interface Facet { index: { byteStart: number; byteEnd: number }; features: Array< | { $type: 'app.bsky.richtext.facet#mention' } | { $type: 'app.bsky.richtext.facet#link'; uri: string } | { $type: 'app.bsky.richtext.facet#tag' } >; } export function renderTextWithFacets(text: string, facets: Facet[]): string { if (!facets || facets.length === 0) return text; // Convert string to a Uint8Array (UTF-8 encoded bytes) const encoder = new TextEncoder(); const decoder = new TextDecoder(); const textBytes = encoder.encode(text); let result = ''; let lastIndex = 0; facets.forEach((facet) => { const { byteStart, byteEnd } = facet.index; // Extract parts of the text using byte offsets const preFacetText = decoder.decode(textBytes.slice(lastIndex, byteStart)); const facetText = decoder.decode(textBytes.slice(byteStart, byteEnd)); let replacedFacetText = facetText; facet.features.forEach((feature) => { if (feature.$type === 'app.bsky.richtext.facet#mention') { replacedFacetText = `${facetText}`; } if (feature.$type === 'app.bsky.richtext.facet#link') { replacedFacetText = `${facetText}`; } if (feature.$type === 'app.bsky.richtext.facet#tag') { replacedFacetText = `${facetText}`; //TODO: Replace with search endpoint when added } }); result += preFacetText + replacedFacetText; lastIndex = byteEnd; }); // Append any remaining text after the last facet result += decoder.decode(textBytes.slice(lastIndex)); return result; }