Add emoji rendering to improve post preview accuracy

Install `twemoji` and implement `emojiUtils.ts` to parse and render emojis correctly in the post preview, ensuring consistency with actual published content.

Replit-Commit-Author: Agent
Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda
Replit-Commit-Checkpoint-Type: intermediate_checkpoint
Replit-Commit-Event-Id: 605c7efc-6cfc-498b-bf39-42e925354f36
Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/JcM96XE
This commit is contained in:
michaelschal committed 2025-11-21 14:33:42 +00:00
1 parent 7b8cbbc1e4
commit e596fa298d
3 files changed
+140 -2

No files matched your search

+81
View File
@@ -0,0 +1,81 @@
import twemoji from 'twemoji';
export interface EmojiSegment {
type: 'text' | 'emoji';
content: string;
url?: string;
}
/**
* Parse text and identify emoji segments
* Returns an array of segments with text and emoji parts
*/
export function parseTextWithEmojis(text: string): EmojiSegment[] {
const segments: EmojiSegment[] = [];
let lastIndex = 0;
// Use twemoji to parse and replace emojis
const parsed = twemoji.parse(text, {
callback: (icon: string, options: any) => {
return `https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/72x72/${icon}.png`;
}
});
// Extract emoji positions using a temporary div
const tempDiv = document.createElement('div');
tempDiv.innerHTML = parsed;
const walker = document.createTreeWalker(
tempDiv,
NodeFilter.SHOW_TEXT | NodeFilter.SHOW_ELEMENT,
null
);
let node;
let currentText = '';
while ((node = walker.nextNode())) {
if (node.nodeType === Node.TEXT_NODE) {
if (node.textContent) {
currentText += node.textContent;
}
} else if (node.nodeType === Node.ELEMENT_NODE && (node as Element).tagName === 'IMG') {
// Push any accumulated text before this emoji
if (currentText) {
segments.push({ type: 'text', content: currentText });
currentText = '';
}
const img = node as HTMLImageElement;
segments.push({
type: 'emoji',
content: img.alt || '',
url: img.src
});
}
}
// Push any remaining text
if (currentText) {
segments.push({ type: 'text', content: currentText });
}
// If no emojis were found, return the original text as a single segment
if (segments.length === 0) {
return [{ type: 'text', content: text }];
}
return segments;
}
/**
* Convert text with emojis to HTML string with Twemoji images
*/
export function textToTwemojiHtml(text: string, className?: string): string {
return twemoji.parse(text, {
className: className || 'inline-block align-middle',
callback: (icon: string, options: any) => {
return `https://cdn.jsdelivr.net/gh/twitter/twemoji@14.0.2/assets/72x72/${icon}.png`;
}
});
}