From 99eb65d7a5ea217e996bc7085e4384d27cf92d6c Mon Sep 17 00:00:00 2001 From: Cyril Date: Thu, 13 Nov 2025 14:34:11 +0100 Subject: [PATCH] =?UTF-8?q?=E2=9C=A8(frontend)=20prevent=20duplicate=20emo?= =?UTF-8?q?ji=20when=20used=20as=20first=20character=20in=20title?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit ensures icon and title are visually distinct in sub-document headers Signed-off-by: Cyril --- CHANGELOG.md | 1 + .../docs/doc-header/components/DocTitle.tsx | 15 +++++++++++---- .../src/features/docs/doc-management/utils.ts | 10 ++++++---- 3 files changed, 18 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index e42e2206a3..861b0cea6c 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -22,6 +22,7 @@ and this project adheres to - 🐛(frontend) make summary button fixed to remain visible during scroll #1581 - 🐛(frontend) fix pdf embed to use full width #1526 - 🐛(pdf) fix table cell alignment issue in exported documents #1582 +- 🐛(frontend) prevent duplicate emoji when used as first character in t… #1595 ## [3.9.0] - 2025-11-10 diff --git a/src/frontend/apps/impress/src/features/docs/doc-header/components/DocTitle.tsx b/src/frontend/apps/impress/src/features/docs/doc-header/components/DocTitle.tsx index 33905caa73..d99a3ee287 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-header/components/DocTitle.tsx +++ b/src/frontend/apps/impress/src/features/docs/doc-header/components/DocTitle.tsx @@ -122,15 +122,22 @@ const DocTitleInput = ({ doc }: DocTitleProps) => { if (isTopRoot) { const sanitizedTitle = updateDocTitle(doc, inputText); setTitleDisplay(sanitizedTitle); + return sanitizedTitle; } else { - const sanitizedTitle = updateDocTitle( - doc, - emoji ? `${emoji} ${inputText}` : inputText, - ); + const { emoji: pastedEmoji } = getEmojiAndTitle(inputText); + const textPreservingPastedEmoji = pastedEmoji + ? `\u200B${inputText}` + : inputText; + const finalTitle = emoji + ? `${emoji} ${textPreservingPastedEmoji}` + : textPreservingPastedEmoji; + + const sanitizedTitle = updateDocTitle(doc, finalTitle); const { titleWithoutEmoji: sanitizedTitleWithoutEmoji } = getEmojiAndTitle(sanitizedTitle); setTitleDisplay(sanitizedTitleWithoutEmoji); + return sanitizedTitleWithoutEmoji; } }, [updateDocTitle, doc, emoji, isTopRoot], diff --git a/src/frontend/apps/impress/src/features/docs/doc-management/utils.ts b/src/frontend/apps/impress/src/features/docs/doc-management/utils.ts index 2d43b68fc2..9e7bef554d 100644 --- a/src/frontend/apps/impress/src/features/docs/doc-management/utils.ts +++ b/src/frontend/apps/impress/src/features/docs/doc-management/utils.ts @@ -26,12 +26,14 @@ export const getEmojiAndTitle = (title: string) => { // Use emoji-regex library for comprehensive emoji detection compatible with ES5 const regex = emojiRegex(); - // Check if the title starts with an emoji - const match = title.match(regex); + // Ignore leading spaces when checking for a leading emoji + const leadingSpacesLength = title.match(/^\s+/)?.[0]?.length ?? 0; + const trimmedStart = title.slice(leadingSpacesLength); + const match = trimmedStart.match(regex); - if (match && title.startsWith(match[0])) { + if (match && trimmedStart.startsWith(match[0])) { const emoji = match[0]; - const titleWithoutEmoji = title.substring(emoji.length).trim(); + const titleWithoutEmoji = trimmedStart.substring(emoji.length).trim(); return { emoji, titleWithoutEmoji }; }