diff --git a/fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasm.test.ts b/fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasm.test.ts index 76d3cf36f..e5269248e 100644 --- a/fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasm.test.ts +++ b/fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasm.test.ts @@ -1,8 +1,17 @@ // SPDX-License-Identifier: AGPL-3.0-or-later +import {initializeEmojiParser} from '@app/features/messaging/utils/markdown/EmojiProviderSetup'; import {ParserFlags} from '@app/features/messaging/utils/markdown/parser/Enums'; import {parseMarkdownAstWithWasm} from '@app/features/messaging/utils/markdown/parser/MarkdownParserWasm'; -import {describe, expect, it} from 'vitest'; +import {beforeAll, describe, expect, it, vi} from 'vitest'; + +vi.mock('@app/features/expressions/utils/EmojiUtils', () => ({ + getEmojiURL: () => null, +})); + +vi.mock('@lingui/core/macro', () => ({ + msg: (descriptor: unknown) => descriptor, +})); describe('markdown parser wasm blockquotes', () => { it('preserves consecutive empty blockquote lines', () => { @@ -62,3 +71,36 @@ describe('markdown parser wasm headings', () => { }); }); }); + +describe('markdown parser wasm default-presentation emoji', () => { + beforeAll(() => { + initializeEmojiParser(); + }); + + it.each([ + ['⌚', 'watch', '231a'], + ['⌛', 'hourglass', '231b'], + ['⏩', 'fast_forward', '23e9'], + ['⏪', 'rewind', '23ea'], + ['⏫', 'arrow_double_up', '23eb'], + ['⏬', 'arrow_double_down', '23ec'], + ['⏰', 'alarm_clock', '23f0'], + ['⏳', 'hourglass_flowing_sand', '23f3'], + ])('renders %s as an emoji without a variation selector', (raw, name, codepoints) => { + expect(parseMarkdownAstWithWasm(raw, 0)).toEqual({ + nodes: [{type: 'Emoji', kind: {kind: 'Standard', raw, codepoints, name}}], + }); + }); + + it('keeps text-presentation symbols as plain text when typed bare', () => { + expect(parseMarkdownAstWithWasm('❤', 0)).toEqual({ + nodes: [{type: 'Text', content: '❤'}], + }); + }); + + it('still renders text-presentation symbols carrying a variation selector', () => { + expect(parseMarkdownAstWithWasm('❤️', 0)).toEqual({ + nodes: [{type: 'Emoji', kind: {kind: 'Standard', raw: '❤️', codepoints: '2764', name: 'heart'}}], + }); + }); +}); diff --git a/fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasm.ts b/fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasm.ts index 97f0afbc1..fa3ef1147 100644 --- a/fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasm.ts +++ b/fluxer_app/src/features/messaging/utils/markdown/parser/MarkdownParserWasm.ts @@ -217,15 +217,6 @@ const SPECIAL_SHORTCODES: Record = { registered: '®', }; -function needsVariationSelector(codePoint: number): boolean { - return ( - (codePoint >= 0x2190 && codePoint <= 0x21ff) || - (codePoint >= 0x2300 && codePoint <= 0x23ff) || - (codePoint >= 0x2600 && codePoint <= 0x27bf) || - (codePoint >= 0x2900 && codePoint <= 0x297f) - ); -} - function appendContextLine(parts: Array): string { return `${parts.join('\t')}\n`; } @@ -244,10 +235,6 @@ function buildEmojiContext(input: string): string { while ((match = emojiRegex.exec(input)) !== null) { const candidate = match[0]; if (!candidate || PLAINTEXT_SYMBOLS.has(candidate)) continue; - const hasVariationSelector = candidate.includes('️'); - const codePoint = candidate.codePointAt(0) || 0; - const isDingbat = codePoint >= 0x2600 && codePoint <= 0x27bf; - if (!isDingbat && needsVariationSelector(codePoint) && !hasVariationSelector) continue; const name = provider.getSurrogateName(candidate); if (!name) continue; const candidateBytes = textEncoder.encode(candidate).byteLength;