aboutsummaryrefslogtreecommitdiff
path: root/frontend/src/main.ts
diff options
context:
space:
mode:
Diffstat (limited to 'frontend/src/main.ts')
-rw-r--r--frontend/src/main.ts63
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>