mirror of
https://github.com/svemagie/indiekit-endpoint-activitypub.git
synced 2026-04-02 15:44:58 +02:00
feat: render custom emoji in reader (Release 1)
Extract custom emoji from ActivityPub objects (Fedify Emoji tags) and Mastodon API (status.emojis, account.emojis). Replace :shortcode: patterns with <img> tags in the unified processing pipeline. Emoji rendering applies to post content, author display names, boost attribution, and quote embed authors. Uses the shared postProcessItems() pipeline so both reader and explore views get emoji automatically. Bump version to 2.5.1. Confab-Link: http://localhost:8080/sessions/e9d666ac-3c90-4298-9e92-9ac9d142bc06
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
* @module timeline-store
|
||||
*/
|
||||
|
||||
import { Article, Hashtag, Mention } from "@fedify/fedify/vocab";
|
||||
import { Article, Emoji, Hashtag, Mention } from "@fedify/fedify/vocab";
|
||||
import sanitizeHtml from "sanitize-html";
|
||||
|
||||
/**
|
||||
@@ -82,7 +82,26 @@ export async function extractActorInfo(actor, options = {}) {
|
||||
// Invalid URL, keep handle empty
|
||||
}
|
||||
|
||||
return { name, url, photo, handle };
|
||||
// Extract custom emoji from actor tags
|
||||
const emojis = [];
|
||||
try {
|
||||
if (typeof actor.getTags === "function") {
|
||||
const tags = await actor.getTags(loaderOpts);
|
||||
for await (const tag of tags) {
|
||||
if (tag instanceof Emoji) {
|
||||
const shortcode = (tag.name?.toString() || "").replace(/^:|:$/g, "");
|
||||
const iconUrl = tag.iconId?.href || "";
|
||||
if (shortcode && iconUrl) {
|
||||
emojis.push({ shortcode, url: iconUrl });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch {
|
||||
// Emoji extraction failed — non-critical
|
||||
}
|
||||
|
||||
return { name, url, photo, handle, emojis };
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -190,8 +209,10 @@ export async function extractObjectData(object, options = {}) {
|
||||
// Extract tags — Fedify uses async getTags() which returns typed vocab objects.
|
||||
// Hashtag → category[] (plain strings, # prefix stripped)
|
||||
// Mention → mentions[] ({ name, url } objects for profile linking)
|
||||
// Emoji → emojis[] ({ shortcode, url } for custom emoji rendering)
|
||||
const category = [];
|
||||
const mentions = [];
|
||||
const emojis = [];
|
||||
try {
|
||||
if (typeof object.getTags === "function") {
|
||||
const tags = await object.getTags(loaderOpts);
|
||||
@@ -206,6 +227,13 @@ export async function extractObjectData(object, options = {}) {
|
||||
// tag.href is a URL object — use .href to get the string
|
||||
const mentionUrl = tag.href?.href || "";
|
||||
if (mentionName) mentions.push({ name: mentionName, url: mentionUrl });
|
||||
} else if (tag instanceof Emoji) {
|
||||
// Custom emoji: name is ":shortcode:", icon is an Image with url
|
||||
const shortcode = (tag.name?.toString() || "").replace(/^:|:$/g, "");
|
||||
const iconUrl = tag.iconId?.href || "";
|
||||
if (shortcode && iconUrl) {
|
||||
emojis.push({ shortcode, url: iconUrl });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -259,6 +287,7 @@ export async function extractObjectData(object, options = {}) {
|
||||
author,
|
||||
category,
|
||||
mentions,
|
||||
emojis,
|
||||
photo,
|
||||
video,
|
||||
audio,
|
||||
|
||||
Reference in New Issue
Block a user