diff --git a/lib/jf2-to-as2.js b/lib/jf2-to-as2.js index d5d402b..7492421 100644 --- a/lib/jf2-to-as2.js +++ b/lib/jf2-to-as2.js @@ -621,10 +621,12 @@ function buildPlainTags(properties, publicationUrl, existing) { const tags = [...(existing || [])]; if (properties.category) { for (const cat of asArray(properties.category)) { + const normalized = cat.split("/").at(-1).replace(/\s+/g, ""); + const segments = cat.split("/").map((s) => encodeURIComponent(s.replace(/\s+/g, ""))); tags.push({ type: "Hashtag", - name: `#${cat.split("/").at(-1).replace(/\s+/g, "")}`, - href: `${publicationUrl}categories/${encodeURIComponent(cat)}`, + name: `#${normalized}`, + href: `${publicationUrl}categories/${segments.join("/")}`, }); } } @@ -643,12 +645,12 @@ function buildFedifyTags(properties, publicationUrl, postType) { } if (properties.category) { for (const cat of asArray(properties.category)) { + const normalized = cat.split("/").at(-1).replace(/\s+/g, ""); + const segments = cat.split("/").map((s) => encodeURIComponent(s.replace(/\s+/g, ""))); tags.push( new Hashtag({ - name: `#${cat.split("/").at(-1).replace(/\s+/g, "")}`, - href: new URL( - `${publicationUrl}categories/${encodeURIComponent(cat)}`, - ), + name: `#${normalized}`, + href: new URL(`${publicationUrl}categories/${segments.join("/")}`), }), ); } diff --git a/lib/mastodon/entities/status.js b/lib/mastodon/entities/status.js index c38fcdd..d8883d5 100644 --- a/lib/mastodon/entities/status.js +++ b/lib/mastodon/entities/status.js @@ -173,11 +173,14 @@ export function serializeStatus(item, { baseUrl, favouritedIds, rebloggedIds, bo // Link preview -> card const card = serializeCard(item.linkPreviews?.[0]); - // Tags from category[] - const tags = (item.category || []).map((tag) => ({ - name: tag, - url: `${baseUrl}/tags/${encodeURIComponent(tag)}`, - })); + // Tags from category[] — normalize nested paths (e.g. "on/tech" → "tech") + const tags = (item.category || []).map((tag) => { + const normalized = tag.split("/").at(-1).replace(/\s+/g, ""); + return { + name: normalized, + url: `${baseUrl}/tags/${encodeURIComponent(normalized)}`, + }; + }); // Mentions — use actorUrl for deterministic ID, parse acct from handle const mentions = (item.mentions || []).map((m) => {