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;
}