mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-11 17:26:45 +02:00
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:
1 parent
7b8cbbc1e4
commit
e596fa298d
3 files changed
+140
-2
No files matched your search
@@ -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`;
|
||||
}
|
||||
});
|
||||
}
|
||||
Generated
+58
-2
@@ -86,6 +86,7 @@
|
||||
"tailwind-merge": "^2.6.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tw-animate-css": "^1.2.5",
|
||||
"twemoji": "^14.0.2",
|
||||
"twemoji-parser": "^14.0.0",
|
||||
"vaul": "^1.1.2",
|
||||
"wouter": "^3.3.5",
|
||||
@@ -5893,6 +5894,29 @@
|
||||
"integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/fs-extra": {
|
||||
"version": "8.1.0",
|
||||
"resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz",
|
||||
"integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.0",
|
||||
"jsonfile": "^4.0.0",
|
||||
"universalify": "^0.1.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=6 <7 || >=8"
|
||||
}
|
||||
},
|
||||
"node_modules/fs-extra/node_modules/jsonfile": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
|
||||
"integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
|
||||
"license": "MIT",
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/fsevents": {
|
||||
"version": "2.3.3",
|
||||
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
|
||||
@@ -6037,8 +6061,7 @@
|
||||
"node_modules/graceful-fs": {
|
||||
"version": "4.2.11",
|
||||
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==",
|
||||
"dev": true
|
||||
"integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
|
||||
},
|
||||
"node_modules/has-property-descriptors": {
|
||||
"version": "1.0.2",
|
||||
@@ -6325,6 +6348,18 @@
|
||||
"node": ">=6"
|
||||
}
|
||||
},
|
||||
"node_modules/jsonfile": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-5.0.0.tgz",
|
||||
"integrity": "sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"universalify": "^0.1.2"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"graceful-fs": "^4.1.6"
|
||||
}
|
||||
},
|
||||
"node_modules/lightningcss": {
|
||||
"version": "1.29.2",
|
||||
"resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.29.2.tgz",
|
||||
@@ -8715,6 +8750,18 @@
|
||||
"url": "https://github.com/sponsors/Wombosvideo"
|
||||
}
|
||||
},
|
||||
"node_modules/twemoji": {
|
||||
"version": "14.0.2",
|
||||
"resolved": "https://registry.npmjs.org/twemoji/-/twemoji-14.0.2.tgz",
|
||||
"integrity": "sha512-BzOoXIe1QVdmsUmZ54xbEH+8AgtOKUiG53zO5vVP2iUu6h5u9lN15NcuS6te4OY96qx0H7JK9vjjl9WQbkTRuA==",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"fs-extra": "^8.0.1",
|
||||
"jsonfile": "^5.0.0",
|
||||
"twemoji-parser": "14.0.0",
|
||||
"universalify": "^0.1.2"
|
||||
}
|
||||
},
|
||||
"node_modules/twemoji-parser": {
|
||||
"version": "14.0.0",
|
||||
"resolved": "https://registry.npmjs.org/twemoji-parser/-/twemoji-parser-14.0.0.tgz",
|
||||
@@ -8772,6 +8819,15 @@
|
||||
"integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/universalify": {
|
||||
"version": "0.1.2",
|
||||
"resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
|
||||
"integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
|
||||
"license": "MIT",
|
||||
"engines": {
|
||||
"node": ">= 4.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/unpipe": {
|
||||
"version": "1.0.0",
|
||||
"resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
|
||||
|
||||
@@ -88,6 +88,7 @@
|
||||
"tailwind-merge": "^2.6.0",
|
||||
"tailwindcss-animate": "^1.0.7",
|
||||
"tw-animate-css": "^1.2.5",
|
||||
"twemoji": "^14.0.2",
|
||||
"twemoji-parser": "^14.0.0",
|
||||
"vaul": "^1.1.2",
|
||||
"wouter": "^3.3.5",
|
||||
|
||||
Reference in new issue
Block a user