a tool for shared writing and social publishing
1import { RichText, AppBskyFeedPost, AppBskyRichtextFacet } from "@atproto/api";
2
3// this function is ripped straight from the bluesky-social repo
4// https://github.com/bluesky-social/social-app/blob/main/bskyembed/src/components/post.tsx#L119
5export function BlueskyRichText({
6 record,
7}: {
8 record: AppBskyFeedPost.Record | null;
9}) {
10 if (!record) return null;
11
12 const rt = new RichText({
13 text: record.text,
14 facets: record.facets,
15 });
16
17 const richText = [];
18
19 let counter = 0;
20 for (const segment of rt.segments()) {
21 if (
22 segment.link &&
23 AppBskyRichtextFacet.validateLink(segment.link).success
24 ) {
25 richText.push(
26 <a
27 key={counter}
28 href={segment.link.uri}
29 className="text-accent-contrast hover:underline"
30 target="_blank"
31 >
32 {segment.text}
33 </a>,
34 );
35 } else if (
36 segment.mention &&
37 AppBskyRichtextFacet.validateMention(segment.mention).success
38 ) {
39 richText.push(
40 <a
41 key={counter}
42 href={`https://bsky.app/profile/${segment.mention.did}`}
43 className="text-accent-contrast hover:underline"
44 target="_blank"
45 >
46 {segment.text}
47 </a>,
48 );
49 } else if (
50 segment.tag &&
51 AppBskyRichtextFacet.validateTag(segment.tag).success
52 ) {
53 richText.push(
54 <a
55 key={counter}
56 href={`https://bsky.app/tag/${segment.tag.tag}`}
57 className="text-accent-contrast hover:underline"
58 target="_blank"
59 >
60 {segment.text}
61 </a>,
62 );
63 } else {
64 richText.push(segment.text);
65 }
66
67 counter++;
68 }
69
70 return <p className="whitespace-pre-wrap">{richText}</p>;
71}