From 26ffc44ee72522891b4fdacac15134dfcf9c4859 Mon Sep 17 00:00:00 2001 From: Dawid Rycerz Date: Mon, 12 Jan 2026 22:27:17 +0100 Subject: Rework how tags are working and make them native --- src/loaders/pleroma.ts | 52 ++++++++++++++++++++++++++++++++++++++++++-------- 1 file changed, 44 insertions(+), 8 deletions(-) (limited to 'src/loaders/pleroma.ts') diff --git a/src/loaders/pleroma.ts b/src/loaders/pleroma.ts index 0fd839f..975f57e 100644 --- a/src/loaders/pleroma.ts +++ b/src/loaders/pleroma.ts @@ -317,11 +317,9 @@ ${imageAttachments // Join segments with horizontal rule separator let content = segments.join("\n\n---\n\n"); - // Append consolidated tags at the end as markdown links + // Append consolidated tags at the end as plain hashtags if (allTags.size > 0) { - // Get the instance URL from the first post to construct tag URLs - const instanceUrl = chain[0]?.account.url.split("/@")[0] || "https://social.craftknight.com"; - const tagLine = [...allTags].map((t) => `[#${t}](${instanceUrl}/tag/${t})`).join(" "); + const tagLine = [...allTags].map((t) => `#${t}`).join(" "); content = `${content}\n\n${tagLine}`; } @@ -540,6 +538,36 @@ function cleanContent(htmlContent: string): string { return markdown.trim().replace(/\n\s*\n\s*\n/g, "\n\n"); } +/** + * Replace all hashtags in content with internal tag links + * Handles both plain #hashtags and existing markdown links [#tag](url) + * Returns modified content and extracted tags array + */ +function replaceHashtagsWithLinks(content: string): { + content: string; + tags: string[]; +} { + const tags: string[] = []; + + // First, replace existing markdown hashtag links: [#tag](any-url) + let modifiedContent = content.replace(/\[#(\w+)\]\([^)]+\)/g, (_match, tag) => { + tags.push(tag.toLowerCase()); + return `[#${tag}](/micro/tags/${tag.toLowerCase()})`; + }); + + // Then, replace plain #hashtags (not already in markdown link format) + // Negative lookbehind to avoid matching hashtags already in [#tag] format + modifiedContent = modifiedContent.replace(/(? { + tags.push(tag.toLowerCase()); + return `[#${tag}](/micro/tags/${tag.toLowerCase()})`; + }); + + return { + content: modifiedContent, + tags: [...new Set(tags)], // Deduplicate + }; +} + /** * Replace Pleroma notice links with internal links when the post exists in our collection * Handles both markdown links and plain URLs @@ -654,6 +682,7 @@ export function pleromaLoader(config: PleromaFeedConfig): Loader { let attachments: Array<{ url: string; type: string }>; let postId: string; let sourceUrl: string; + let tags: string[]; // Check if this is a thread starter and thread merging is enabled if (config.mergeThreads !== false && isThreadStarter(content)) { @@ -667,15 +696,21 @@ export function pleromaLoader(config: PleromaFeedConfig): Loader { // Merge thread content const merged = mergeThreadContent(chain); - cleanedContent = merged.content; - cleanedContent = replacePleromaLinks(cleanedContent, instanceUrl, allPostIds); + const { content: contentWithTags, tags: extractedTags } = replaceHashtagsWithLinks( + merged.content, + ); + tags = extractedTags; + cleanedContent = replacePleromaLinks(contentWithTags, instanceUrl, allPostIds); attachments = merged.attachments; postId = status.id; sourceUrl = status.url; } else { // Process as single post - cleanedContent = cleanContent(content); - cleanedContent = replacePleromaLinks(cleanedContent, instanceUrl, allPostIds); + const rawContent = cleanContent(content); + const { content: contentWithTags, tags: extractedTags } = + replaceHashtagsWithLinks(rawContent); + tags = extractedTags; + cleanedContent = replacePleromaLinks(contentWithTags, instanceUrl, allPostIds); postId = status.id; sourceUrl = status.url; @@ -711,6 +746,7 @@ export function pleromaLoader(config: PleromaFeedConfig): Loader { author, attachments, language: status.language || undefined, + tags, }, body: cleanedContent, rendered: { -- cgit v1.2.3