mirror of
https://github.com/R0m1k3/Socialflow.git
synced 2026-10-11 17:26:45 +02:00
Improve emoji handling and text display in previews and generated images
Refactor emoji removal logic into a shared utility and update dependencies. Replit-Commit-Author: Agent Replit-Commit-Session-Id: ae4037a0-2a6f-4530-9bac-79b543286bda Replit-Commit-Checkpoint-Type: intermediate_checkpoint Replit-Commit-Event-Id: 59d8c635-691c-42a3-b368-902e8f16eeee Replit-Commit-Screenshot-Url: https://storage.googleapis.com/screenshot-production-us-central1/397bca8c-984f-43ff-841a-10897aeb8140/ae4037a0-2a6f-4530-9bac-79b543286bda/Q6FJ7Lw
This commit is contained in:
1 parent
e1c6a0ad2a
commit
1bdb7445c3
5 files changed
+30
-32
No files matched your search
@@ -4,6 +4,7 @@ import { Button } from '@/components/ui/button';
|
||||
import { Select, SelectContent, SelectItem, SelectTrigger, SelectValue } from '@/components/ui/select';
|
||||
import { ChevronLeft, ChevronRight, Send, Facebook, Instagram, Heart, MessageCircle, Share2, Bookmark } from 'lucide-react';
|
||||
import type { Media } from '@shared/schema';
|
||||
import { removeEmojis } from '@shared/emoji';
|
||||
|
||||
interface PreviewModalProps {
|
||||
open: boolean;
|
||||
@@ -222,19 +223,6 @@ export function PreviewModal({
|
||||
</div>
|
||||
);
|
||||
|
||||
/**
|
||||
* Removes emojis from text since they don't display well in some contexts
|
||||
*/
|
||||
const removeEmojis = (text: string): string => {
|
||||
return text
|
||||
.replace(/[\u2600-\u26FF]/g, '') // Misc symbols
|
||||
.replace(/[\u2700-\u27BF]/g, '') // Dingbats
|
||||
.replace(/[\uD800-\uDFFF]/g, '') // Surrogate pairs (emoji range)
|
||||
.replace(/[\uFE00-\uFE0F]/g, '') // Variation selectors
|
||||
.replace(/\s+/g, ' ') // Normalize whitespace
|
||||
.trim();
|
||||
};
|
||||
|
||||
const wrapText = (text: string, maxWidth: number, fontSize: number): string[] => {
|
||||
const canvas = document.createElement('canvas');
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
Generated
+10
-3
@@ -58,6 +58,7 @@
|
||||
"drizzle-orm": "^0.39.1",
|
||||
"drizzle-zod": "^0.7.0",
|
||||
"embla-carousel-react": "^8.6.0",
|
||||
"emoji-regex": "^10.6.0",
|
||||
"express": "^4.21.2",
|
||||
"express-session": "^1.18.1",
|
||||
"framer-motion": "^11.13.1",
|
||||
@@ -5341,9 +5342,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/emoji-regex": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||
"version": "10.6.0",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz",
|
||||
"integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/encodeurl": {
|
||||
@@ -8293,6 +8294,12 @@
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/string-width/node_modules/emoji-regex": {
|
||||
"version": "9.2.2",
|
||||
"resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
|
||||
"integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/strip-ansi": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
|
||||
|
||||
@@ -60,6 +60,7 @@
|
||||
"drizzle-orm": "^0.39.1",
|
||||
"drizzle-zod": "^0.7.0",
|
||||
"embla-carousel-react": "^8.6.0",
|
||||
"emoji-regex": "^10.6.0",
|
||||
"express": "^4.21.2",
|
||||
"express-session": "^1.18.1",
|
||||
"framer-motion": "^11.13.1",
|
||||
|
||||
@@ -3,6 +3,7 @@ import { randomUUID } from "crypto";
|
||||
import path from "path";
|
||||
import fs from "fs/promises";
|
||||
import { createCanvas, loadImage, registerFont } from "canvas";
|
||||
import { removeEmojis } from "@shared/emoji";
|
||||
|
||||
interface CropDimensions {
|
||||
width: number;
|
||||
@@ -108,21 +109,6 @@ export class ImageProcessor {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes emojis from text since canvas doesn't support them natively
|
||||
*/
|
||||
private removeEmojis(text: string): string {
|
||||
// Remove emojis and other unicode symbols that canvas can't render
|
||||
// Using a regex that removes emoji-like characters
|
||||
return text
|
||||
.replace(/[\u2600-\u26FF]/g, '') // Misc symbols
|
||||
.replace(/[\u2700-\u27BF]/g, '') // Dingbats
|
||||
.replace(/[\uD800-\uDFFF]/g, '') // Surrogate pairs (emoji range)
|
||||
.replace(/[\uFE00-\uFE0F]/g, '') // Variation selectors
|
||||
.replace(/\s+/g, ' ') // Normalize whitespace
|
||||
.trim();
|
||||
}
|
||||
|
||||
async addTextToStoryImage(imageUrl: string, text: string): Promise<Buffer> {
|
||||
const STORY_WIDTH = 1080;
|
||||
const STORY_HEIGHT = 1920;
|
||||
@@ -133,7 +119,7 @@ export class ImageProcessor {
|
||||
const LINE_HEIGHT_MULTIPLIER = 1.3;
|
||||
|
||||
// Remove emojis from text as canvas doesn't support them
|
||||
const cleanText = this.removeEmojis(text);
|
||||
const cleanText = removeEmojis(text);
|
||||
|
||||
const canvas = createCanvas(STORY_WIDTH, STORY_HEIGHT);
|
||||
const ctx = canvas.getContext('2d');
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import emojiRegex from 'emoji-regex';
|
||||
|
||||
// Cached regex instance for performance
|
||||
const emojiPattern = emojiRegex();
|
||||
|
||||
/**
|
||||
* Removes emojis from text while preserving other Unicode characters
|
||||
* Uses the emoji-regex package which correctly identifies emojis without
|
||||
* removing legitimate astral-plane characters (CJK Extension B, etc.)
|
||||
*/
|
||||
export function removeEmojis(text: string): string {
|
||||
return text
|
||||
.replace(emojiPattern, '')
|
||||
.replace(/\s+/g, ' ') // Normalize whitespace
|
||||
.trim();
|
||||
}
|
||||
Reference in new issue
Block a user