diff --git a/lib/syndicator.js b/lib/syndicator.js index 4c7c960..8bf29c3 100644 --- a/lib/syndicator.js +++ b/lib/syndicator.js @@ -224,7 +224,7 @@ export function createSyndicator(plugin) { // timelines (Phanpy/Moshidon). Uses $setOnInsert — idempotent. try { const profile = await plugin._collections.ap_profile?.findOne({}); - const content = normalizeContent(properties.content); + const content = buildTimelineContent(properties); const timelineItem = { uid: properties.url, url: properties.url, @@ -289,13 +289,51 @@ export function createSyndicator(plugin) { // ─── Timeline helpers ─────────────────────────────────────────────────────── -function normalizeContent(content) { - if (!content) return { text: "", html: "" }; - if (typeof content === "string") return { text: content, html: `
${content}
` }; - return { - text: content.text || content.value || "", - html: content.html || content.text || content.value || "", - }; +/** + * Build content from JF2 properties. Synthesizes content for interaction + * types (likes, bookmarks, reposts) that have no body text. + */ +function buildTimelineContent(properties) { + const content = properties.content; + if (content) { + if (typeof content === "string") return { text: content, html: `${content}
` }; + if (content.text || content.html) { + return { + text: content.text || content.value || "", + html: content.html || content.text || content.value || "", + }; + } + } + + // Synthesize for interaction types + const esc = (s) => s.replace(/&/g, "&").replace(//g, ">").replace(/"/g, """); + const likeOf = properties["like-of"]; + if (likeOf) { + return { + text: `Liked: ${likeOf}`, + html: `Liked: ${esc(likeOf)}
`, + }; + } + const bookmarkOf = properties["bookmark-of"]; + if (bookmarkOf) { + const label = properties.name || bookmarkOf; + return { + text: `Bookmarked: ${label}`, + html: `Bookmarked: ${esc(label)}
`, + }; + } + const repostOf = properties["repost-of"]; + if (repostOf) { + const label = properties.name || repostOf; + return { + text: `Reposted: ${label}`, + html: `Reposted: ${esc(label)}
`, + }; + } + if (properties.name) { + return { text: properties.name, html: `${esc(properties.name)}
` }; + } + return { text: "", html: "" }; } function mapPostType(postType) { diff --git a/package.json b/package.json index 3db4f2a..f08d620 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@rmdes/indiekit-endpoint-activitypub", - "version": "3.10.1", + "version": "3.10.2", "description": "ActivityPub federation endpoint for Indiekit via Fedify. Adds full fediverse support: actor, inbox, outbox, followers, following, syndication, and Mastodon migration.", "keywords": [ "indiekit",