Emoji: treat the picker, support detection, and fallback rendering as one system #83032
Jiwoon-Kim
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
The problem
While planning reactions for Notes, #75144 found no existing emoji picker component in Gutenberg. The gap is wider than the picker: WordPress has no shared emoji system. It handles emoji in three places that were built at different times and do not share a model:
wontfixbecause operating systems ship their own). Notes reactions are adding one now: Add emoji reactions as a first class comment type #75144, Add emoji reactions (limited set on notes) #76767, and the full searchable picker in Notes: Open a full searchable emoji picker from the add-reaction button (stacked on #76767) #78176, which lives inpackages/editor/src/components/collab-sidebar/.wp-emoji-loader.jsruns two tests on a canvas:flag(the transgender flag, the Sark flag, and the England flag; any failure fails it) andemoji(the centre pixel of U+1FAC8). The result becomeseverythingoreverythingExceptFlag. It runs on the front end only; the block editor does not load it.wp-emoji.jsreplaces emoji text with images froms.w.org. Core Trac #44001 and wordpress-develop#12252 discuss serving those images locally.Because the three parts do not know about each other, a small mistake in one changes what every site shows, and the picker has to choose its data and storage format without a shared answer to "which sequences does WordPress treat as emoji, and which can this browser draw?". Things I reproduced or read in the source while building a plugin across all three:
emojiis always false and every emoji is replaced by an image, including in browsers that draw Emoji 17 (fixed in trunk for 7.2 in changeset 63755).flagfails andemojipasses, only regional-indicator pairs and the rainbow and pirate flags are replaced. Two of the flags theflagtest draws are not on that list: England (with Scotland and Wales, a tag sequence) stays as a plain black flag, and the transgender flag, a ZWJ sequence, is left as well. That is Core Trac #63451. It likely stopped reproducing because theemojitest began to fail (Emoji 16 in 6.8.2, then Core Trac #66104), which makes WordPress replace everything. With the Core Trac #66104 patch applied, a local test page in Chromium on Windows left the England flag unreplaced again..wp-exclude-emojiis skipped only when it is below the element being parsed. If the excluded element is itself inserted later, or its own text changes, it becomes the parse root and its emoji are replaced. A follow-up to Core Trac #52219, now Core Trac #66120.emojitest checks a single code point. A system that draws U+1FAC8 but not the new Emoji 17 ZWJ sequences counts as supporting Emoji 17.WP_Font_Facedrops a fontsrcthat carries a query string such as?ver=(Core Trac #66119).What I'd like to discuss
Not a plugin to merge. I'd like to discuss where the boundaries should be, using a working implementation as a reference:
Working reference: Axismundi Emoji 0.3.1
Axismundi Emoji is in the Plugin Directory, and its Live Preview installs it and opens a demo page:
Open the Live Preview
The page lists 11 Unicode sequences and the two bundled custom emoji and, after load, says what drew each row: the browser's font, the bundled font, a WordPress.org image, or the site's own image. A panel shows the plugin's mode and WordPress's own test results. In Chromium on Windows with the latest WordPress, WordPress reported
flag: no, emoji: no(Core Trac #66104); the plugin drew the three flags with its font and the other eight became images.What the plugin does:
flagprobe is split into a country-flag profile and a subdivision-flag profile, each probed on its own canvas. A third profile, all RGI emoji, applies only when a site chooses the complete font. Results are cached with a version tied to the font files..wp-exclude-emoji, so WordPress does not replace it as well.:shortcode:and rendered in posts and comments, and declared as FEP-9098Emojitags when a federation plugin is present.Sizes, for the local-assets discussion in Core Trac #44001: the complete font covers all 3,944 RGI emoji in one 1.88 MiB WOFF2 file; the flags subset covers 262 flags in 699 KiB. Twemoji 17.0.2 is 4,009 PNG plus 4,009 SVG files, about 13.7 MiB together. With the complete font chosen and WordPress's image fallback switched off, the demo page made no requests to
s.w.organd its HTML did not mention it: one font file drew all 11 Unicode rows.Reactions. The companion Axismundi Activities plugin (not part of the demo) has emoji reactions that federate as FEP-c0e0 (
EmojiReact, andLikewith content), and its reaction picker reads the same catalogue from the Emoji plugin. Its key rule matches the one #78176 arrived at: only U+FE0E and U+FE0F are removed, so skin tones, ZWJ sequences, and flags stay distinct (unicode:U+1F44Dthere,1f44din Notes). Two things federation adds:custom:example.com:blobcat), because two servers can ship the same shortcode. A shortcode that arrives without itsEmojideclaration is not accepted as a reaction.Notes stores curated slugs and hex keys in
comment_contentof areactioncomment, while Core Trac #64638 registers comment meta for the earlier design, so the storage format is still open. It may be worth settling a key that local reactions, federated reactions, and custom emoji can share before it lands in Core.Where #78176 is ahead: arrow-key navigation over the grid, a skin-tone selector (this plugin leaves skin-tone variants out of the grid), announced search results, translated emoji names, and ordering by frequency. This plugin is not meant to replace that picker; it shows the layers below it.
Known costs of the font approach: the download (the flags subset in automatic mode, the full font only when a site chooses it), a brief swap from the system font while the font loads, and it depends on the browser drawing COLRv1, which is why the plugin probes the font and steps aside when it cannot.
Questions
flagandemoji?Related
All reactions