this repo has no description
atproto bluesky typescript express
at main 52 lines 1.8 kB view raw
1interface Facet { 2 index: { byteStart: number; byteEnd: number }; 3 features: Array< 4 | { $type: 'app.bsky.richtext.facet#mention' } 5 | { $type: 'app.bsky.richtext.facet#link'; uri: string } 6 | { $type: 'app.bsky.richtext.facet#tag' } 7 >; 8} 9 10export function renderTextWithFacets(text: string, facets: Facet[]): string { 11 if (!facets || facets.length === 0) return text; 12 13 // Convert string to a Uint8Array (UTF-8 encoded bytes) 14 const encoder = new TextEncoder(); 15 const decoder = new TextDecoder(); 16 const textBytes = encoder.encode(text); 17 18 let result = ''; 19 let lastIndex = 0; 20 21 facets.forEach((facet) => { 22 const { byteStart, byteEnd } = facet.index; 23 24 // Extract parts of the text using byte offsets 25 const preFacetText = decoder.decode(textBytes.slice(lastIndex, byteStart)); 26 const facetText = decoder.decode(textBytes.slice(byteStart, byteEnd)); 27 28 let replacedFacetText = facetText; 29 30 facet.features.forEach((feature) => { 31 if (feature.$type === 'app.bsky.richtext.facet#mention') { 32 replacedFacetText = `<a href="../profile/${facetText.replace('@', '')}" class="mention">${facetText}</a>`; 33 } 34 35 if (feature.$type === 'app.bsky.richtext.facet#link') { 36 replacedFacetText = `<a href="${feature.uri}" target="_blank" rel="nofollow">${facetText}</a>`; 37 } 38 39 if (feature.$type === 'app.bsky.richtext.facet#tag') { 40 replacedFacetText = `<a href="https://bsky.app/hashtag/${facetText.replace('#', '')}" class="hashtag">${facetText}</a>`; //TODO: Replace with search endpoint when added 41 } 42 }); 43 44 result += preFacetText + replacedFacetText; 45 lastIndex = byteEnd; 46 }); 47 48 // Append any remaining text after the last facet 49 result += decoder.decode(textBytes.slice(lastIndex)); 50 51 return result; 52}