diff --git a/README.md b/README.md index 9b7c488..8c763fc 100644 --- a/README.md +++ b/README.md @@ -56,11 +56,18 @@ You can configure which emojis are supported for rating interactions by going to **Default emojis**: `🎥🏆⭐💎🔥⚡🎯🚀💰🎖️` +**ZWJ Sequence Support**: The plugin fully supports complex emojis including ZWJ (Zero Width Joiner) sequences such as: +- 🏴‍☠️ (Pirate Flag) +- 👨‍🚒 (Man Firefighter) +- 🏳️‍🌈 (Rainbow Flag) +- And other compound emojis + **Example usage**: - `🎥🎥🎥🎥🎥 (4/5)` Movie rating - `🏆🏆🏆 3/5` Achievement level - `🔥🔥🔥🔥 80%` Spice level - `🎯🎯🎯🎯🎯🎯 (5/6)` Accuracy rating +- `🏴‍☠️🏴‍☠️🏴‍☠️ (3/5)` Pirate movie rating ## Installation diff --git a/src/utils/getUnicodeCharLength.ts b/src/utils/getUnicodeCharLength.ts index 7683ea8..7d268e9 100644 --- a/src/utils/getUnicodeCharLength.ts +++ b/src/utils/getUnicodeCharLength.ts @@ -1,6 +1,8 @@ /** - * Get the length of a string in Unicode characters + * Get the length of a string in Unicode grapheme clusters + * This properly handles ZWJ sequences, variation selectors, and complex emoji */ export function getUnicodeCharLength(str: string): number { - return [...str].length; + const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' }); + return Array.from(segmenter.segment(str)).length; } \ No newline at end of file diff --git a/src/utils/getUnicodeSubstring.ts b/src/utils/getUnicodeSubstring.ts index 13dd136..704418e 100644 --- a/src/utils/getUnicodeSubstring.ts +++ b/src/utils/getUnicodeSubstring.ts @@ -1,6 +1,8 @@ /** - * Get a substring with proper Unicode character handling + * Get a substring with proper Unicode grapheme cluster handling + * This properly handles ZWJ sequences, variation selectors, and complex emoji */ export function getUnicodeSubstring(str: string, start: number, end: number): string { - return [...str].slice(start, end).join(''); + const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' }); + return Array.from(segmenter.segment(str), segment => segment.segment).slice(start, end).join(''); } \ No newline at end of file diff --git a/src/utils/updateSymbolPatternsFromSettings.ts b/src/utils/updateSymbolPatternsFromSettings.ts index 0206c3d..28697ae 100644 --- a/src/utils/updateSymbolPatternsFromSettings.ts +++ b/src/utils/updateSymbolPatternsFromSettings.ts @@ -10,11 +10,12 @@ export function updateSymbolPatternsFromSettings(settings: InteractiveRatingsSet // Add emoji patterns from settings if (settings.supportedEmojis) { - // Split the emoji string into individual characters (handling Unicode properly) - const emojis = [...settings.supportedEmojis]; + // Split the emoji string into individual grapheme clusters (handling ZWJ sequences properly) + const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' }); + const emojis = Array.from(segmenter.segment(settings.supportedEmojis), segment => segment.segment); for (const emoji of emojis) { - if (emoji.trim()) { // Skip empty characters + if (emoji.trim()) { // Skip empty characters and whitespace newPatterns.push({ full: emoji, empty: emoji, @@ -28,8 +29,10 @@ export function updateSymbolPatternsFromSettings(settings: InteractiveRatingsSet updateSymbolPatterns(newPatterns); if (LOGGING_ENABLED) { + const segmenter = new Intl.Segmenter('en', { granularity: 'grapheme' }); console.debug('[InteractiveRatings] Updated symbol patterns from settings', { supportedEmojis: settings.supportedEmojis, + parsedEmojis: settings.supportedEmojis ? Array.from(segmenter.segment(settings.supportedEmojis), segment => segment.segment) : [], totalPatterns: newPatterns.length }); }