From 87ff1bf6bc746dc21e90b376045b86b6386fc0ce Mon Sep 17 00:00:00 2001 From: Jiwoon-Kim <71701140+Jiwoon-Kim@users.noreply.github.com> Date: Thu, 17 Sep 2026 22:37:59 +0900 Subject: [PATCH] Emoji: Replace subdivision and transgender flags when only the flag test fails. With `everythingExceptFlag`, `wp-emoji.js` replaced only country, rainbow and pirate flags, although the flag support test also checks the transgender flag and the England flag. England, Scotland, Wales and the transgender flag were left as text a browser cannot draw. Adds subdivision tag sequences and the transgender flag to the list, with a QUnit page covering each kind of flag. See #63451. Co-Authored-By: Claude Opus 5 --- src/js/_enqueues/wp/emoji.js | 13 +++- tests/qunit/wp-includes/js/emoji-flags.html | 34 +++++++++ tests/qunit/wp-includes/js/emoji-flags.js | 78 +++++++++++++++++++++ 3 files changed, 123 insertions(+), 2 deletions(-) create mode 100644 tests/qunit/wp-includes/js/emoji-flags.html create mode 100644 tests/qunit/wp-includes/js/emoji-flags.js diff --git a/src/js/_enqueues/wp/emoji.js b/src/js/_enqueues/wp/emoji.js index 274868f52d859..5d6fbcfbc9853 100644 --- a/src/js/_enqueues/wp/emoji.js +++ b/src/js/_enqueues/wp/emoji.js @@ -235,9 +235,18 @@ return false; } + /* + * When only the flag test failed, replace flags and nothing else. The list covers + * every kind of flag that test checks (country, subdivision and ZWJ flags), so a + * failing flag is never left to a font that cannot draw it. + */ if ( settings.supports.everythingExceptFlag && - ! /^1f1(?:e[6-9a-f]|f[0-9a-f])-1f1(?:e[6-9a-f]|f[0-9a-f])$/.test( icon ) && // Country flags. - ! /^(1f3f3-fe0f-200d-1f308|1f3f4-200d-2620-fe0f)$/.test( icon ) // Rainbow and pirate flags. + // Country flags. + ! /^1f1(?:e[6-9a-f]|f[0-9a-f])-1f1(?:e[6-9a-f]|f[0-9a-f])$/.test( icon ) && + // Subdivision flags, such as England: a black flag, tag characters, and a cancel tag. + ! /^1f3f4(?:-e00[2-7][0-9a-f])+-e007f$/.test( icon ) && + // Rainbow, transgender and pirate flags. + ! /^(1f3f3-fe0f-200d-1f308|1f3f3-fe0f-200d-26a7-fe0f|1f3f4-200d-2620-fe0f)$/.test( icon ) ) { return false; } diff --git a/tests/qunit/wp-includes/js/emoji-flags.html b/tests/qunit/wp-includes/js/emoji-flags.html new file mode 100644 index 0000000000000..4e6691398b8ea --- /dev/null +++ b/tests/qunit/wp-includes/js/emoji-flags.html @@ -0,0 +1,34 @@ + + + + wp.emoji flag fallback QUnit Test Suite + + + + + + + +
+
+ + + + + + + diff --git a/tests/qunit/wp-includes/js/emoji-flags.js b/tests/qunit/wp-includes/js/emoji-flags.js new file mode 100644 index 0000000000000..b3cbb87bfe35a --- /dev/null +++ b/tests/qunit/wp-includes/js/emoji-flags.js @@ -0,0 +1,78 @@ +( function( QUnit ) { + /* + * wp-emoji.js is loaded with `everythingExceptFlag`: the browser renders emoji but failed the + * flag test. Every kind of flag that test checks must then be replaced by an image, and nothing + * else. See https://core.trac.wordpress.org/ticket/63451. + */ + QUnit.module( 'wp.emoji flag fallback' ); + + function imageSources( html ) { + var container = document.createElement( 'div' ); + + container.innerHTML = html; + return Array.prototype.map.call( container.querySelectorAll( 'img.emoji' ), function( img ) { + return img.getAttribute( 'src' ); + } ); + } + + QUnit.test( 'replaces a country flag', function( assert ) { + var sources = imageSources( window.wp.emoji.parse( '\uD83C\uDDF0\uD83C\uDDF7' ) ); // Flag: South Korea. + + assert.strictEqual( sources.length, 1, 'one image' ); + assert.ok( /\/1f1f0-1f1f7\.(svg|png)$/.test( sources[0] ), 'for 1f1f0-1f1f7' ); + } ); + + QUnit.test( 'replaces the England flag', function( assert ) { + var sources = imageSources( window.wp.emoji.parse( '\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC65\uDB40\uDC6E\uDB40\uDC67\uDB40\uDC7F' ) ); // Flag: England. + + assert.strictEqual( sources.length, 1, 'one image' ); + assert.ok( /\/1f3f4-e0067-e0062-e0065-e006e-e0067-e007f\.(svg|png)$/.test( sources[0] ), 'for 1f3f4-e0067-e0062-e0065-e006e-e0067-e007f' ); + } ); + + QUnit.test( 'replaces the Scotland flag', function( assert ) { + var sources = imageSources( window.wp.emoji.parse( '\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC73\uDB40\uDC63\uDB40\uDC74\uDB40\uDC7F' ) ); // Flag: Scotland. + + assert.strictEqual( sources.length, 1, 'one image' ); + assert.ok( /\/1f3f4-e0067-e0062-e0073-e0063-e0074-e007f\.(svg|png)$/.test( sources[0] ), 'for 1f3f4-e0067-e0062-e0073-e0063-e0074-e007f' ); + } ); + + QUnit.test( 'replaces the Wales flag', function( assert ) { + var sources = imageSources( window.wp.emoji.parse( '\uD83C\uDFF4\uDB40\uDC67\uDB40\uDC62\uDB40\uDC77\uDB40\uDC6C\uDB40\uDC73\uDB40\uDC7F' ) ); // Flag: Wales. + + assert.strictEqual( sources.length, 1, 'one image' ); + assert.ok( /\/1f3f4-e0067-e0062-e0077-e006c-e0073-e007f\.(svg|png)$/.test( sources[0] ), 'for 1f3f4-e0067-e0062-e0077-e006c-e0073-e007f' ); + } ); + + QUnit.test( 'replaces the transgender flag', function( assert ) { + var sources = imageSources( window.wp.emoji.parse( '\uD83C\uDFF3\uFE0F\u200D\u26A7\uFE0F' ) ); // Transgender flag. + + assert.strictEqual( sources.length, 1, 'one image' ); + assert.ok( /\/1f3f3-fe0f-200d-26a7-fe0f\.(svg|png)$/.test( sources[0] ), 'for 1f3f3-fe0f-200d-26a7-fe0f' ); + } ); + + QUnit.test( 'replaces the rainbow flag', function( assert ) { + var sources = imageSources( window.wp.emoji.parse( '\uD83C\uDFF3\uFE0F\u200D\uD83C\uDF08' ) ); // Rainbow flag. + + assert.strictEqual( sources.length, 1, 'one image' ); + assert.ok( /\/1f3f3-fe0f-200d-1f308\.(svg|png)$/.test( sources[0] ), 'for 1f3f3-fe0f-200d-1f308' ); + } ); + + QUnit.test( 'replaces the pirate flag', function( assert ) { + var sources = imageSources( window.wp.emoji.parse( '\uD83C\uDFF4\u200D\u2620\uFE0F' ) ); // Pirate flag. + + assert.strictEqual( sources.length, 1, 'one image' ); + assert.ok( /\/1f3f4-200d-2620-fe0f\.(svg|png)$/.test( sources[0] ), 'for 1f3f4-200d-2620-fe0f' ); + } ); + + QUnit.test( 'leaves an emoji that is not a flag as text', function( assert ) { + var text = '\uD83D\uDE00'; // Grinning face. + + assert.strictEqual( window.wp.emoji.parse( text ), text ); + } ); + + QUnit.test( 'leaves a black flag on its own as text', function( assert ) { + var text = '\uD83C\uDFF4'; // Black flag. + + assert.strictEqual( window.wp.emoji.parse( text ), text ); + } ); +} )( window.QUnit );