summaryrefslogtreecommitdiff
path: root/src/loaders/pleroma.ts
diff options
context:
space:
mode:
authorDawid Rycerz <dawid@rycerz.xyz>2026-01-12 22:27:17 +0100
committerDawid Rycerz <dawid@rycerz.xyz>2026-01-12 22:27:17 +0100
commit26ffc44ee72522891b4fdacac15134dfcf9c4859 (patch)
tree0a4014f93f35b348f9e5062904e17d724f228a69 /src/loaders/pleroma.ts
parent686ccbfd2ed51723f4df79ba0b976e0f5fafce2f (diff)
Rework how tags are working and make them native
Diffstat (limited to 'src/loaders/pleroma.ts')
-rw-r--r--src/loaders/pleroma.ts52
1 files changed, 44 insertions, 8 deletions
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}`;
}
@@ -541,6 +539,36 @@ function cleanContent(htmlContent: string): string {
}
/**
+ * 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(/(?<!\[)#(\w+)(?!\])/g, (_match, tag) => {
+ 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: {