diff options
Diffstat (limited to 'frontend/src/main.ts')
| -rw-r--r-- | frontend/src/main.ts | 63 |
1 files changed, 62 insertions, 1 deletions
diff --git a/frontend/src/main.ts b/frontend/src/main.ts index 099193a..f53632c 100644 --- a/frontend/src/main.ts +++ b/frontend/src/main.ts @@ -1,5 +1,58 @@ +import { marked } from 'marked'; import './style.css' +function renderTextWithFacets(text: string, facets: any[]): string { + if (!facets || facets.length === 0) { + return text; + } + + // convert text to UTF-8 bytes because Bluesky counts bytes in UTF-8 + const encoder = new TextEncoder(); + const postBytes = encoder.encode(text); + + // sort facets by start position + facets.sort((a, b) => a.byteStart - b.byteStart); + + let result = ''; + let lastPos = 0; + + const decoder = new TextDecoder(); + for (const facet of facets) { + // add text before this facet + const beforeBytes = postBytes.slice(lastPos, facet.byteStart); + result += decoder.decode(beforeBytes); + + // add the faceted text as a link + const facetBytes = postBytes.slice(facet.byteStart, facet.byteEnd); + const facetText = decoder.decode(facetBytes); + + switch (facet.type) { + case 'link': + result += `<a href="${facet.value}" target="_blank">${facetText}</a>`; + break; + case 'mention': + result += `<a href="https://bsky.app/profile/${facet.value}" target="_blank">${facetText}</a>`; + break; + case 'tag': + result += `<a href="https://bsky.app/hashtag/${facet.value}" target="_blank">#${facetText}</a>`; + break; + default: // in case Bluesky ever adds other fcaet types + result += facetText; // if we don't recognize the type, just add it as plain text + break; + } + + lastPos = facet.byteEnd; + } + + // add remaining text + const remainingBytes = postBytes.slice(lastPos); + result += decoder.decode(remainingBytes); + + console.log(result); + + return result; +} + async function main() { const app = document.querySelector('#app'); if (!app) { @@ -17,12 +70,20 @@ async function main() { app.innerHTML = ''; for (const post of posts) { + let parsedText = ''; + if(post.facets && post.facets.length > 0) { + parsedText = renderTextWithFacets(post.text || '', post.facets || []); + } else { + parsedText = post.text; + } + const postText = marked.parseInline(parsedText, { breaks: true }); + const postHTML = ` <div class="note"> <img class="note-avatar" src="https://cdn.bsky.app/img/avatar/plain/did:plc:hyyqbqqhpxt2bnn7s2e2iuxd/bafkreidoiynom7v2y5rpsm467l3d2cnr7ozvlfusrchjey3k2jtyquufq4@jpeg" alt="avatar"> <div class="note-content"> <div style="font-weight: bold">@${post.authorHandle}</div> - <div class="note-text">${post.text || '<br>'}</div> + <div class="note-text">${postText || '<br>'}</div> <div style="font-size: 12px; color: #888">${new Date(post.createdAt).toLocaleString()}</div> </div> </div> |
