mirror of
https://github.com/fluxerapp/fluxer
synced 2026-10-17 13:05:32 +09:00
fix(markdown): render default-presentation emoji without variation selectors
This commit is contained in:
1 parent
f7ebc1492c
commit
f98a40062a
2 files changed
+43
-14
No files matched your search
@@ -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'}}],
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -217,15 +217,6 @@ const SPECIAL_SHORTCODES: Record<string, string> = {
|
||||
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>): 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;
|
||||
|
||||
Reference in new issue
Block a user