Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
37 changes: 36 additions & 1 deletion src/js/_enqueues/wp/emoji.js
Original file line number Diff line number Diff line change
Expand Up @@ -110,7 +110,9 @@
// Emoji in a text node are replaced by parsing the element which contains it.
const node = addedNode instanceof Text ? addedNode.parentElement : addedNode;

if ( node instanceof HTMLElement && test( node.textContent ) ) {
if (
node instanceof HTMLElement && test( node.textContent ) && ! isExcludedFromParsing( node )
) {
parse( node );
}
}
Expand All @@ -123,6 +125,39 @@
parse( document.body );
}

/**
* Checks whether a node, or one of its ancestors, is excluded from
* emoji parsing.
*
* The doNotParse() callback passed to Twemoji only excludes descendants
* of the node it's asked to parse, so a node that is itself excluded
* (or nested inside an excluded ancestor) has to be checked here,
* before it's ever handed to parse().
*
* @since 7.2.0
* @private
*
* @param {HTMLElement|null} node The node to check.
*
* @return {boolean} Whether the node or an ancestor has the
* wp-exclude-emoji class.
*/
function isExcludedFromParsing( node ) {
while ( node ) {
if (
node.className &&
typeof node.className === 'string' &&
node.className.indexOf( 'wp-exclude-emoji' ) !== -1
) {
return true;
}

node = node.parentElement;
}

return false;
}

/**
* Tests if a text string contains emoji characters.
*
Expand Down
31 changes: 31 additions & 0 deletions tests/qunit/wp-includes/js/emoji.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
<!DOCTYPE html>
<html>
<head>
<title>wp.emoji QUnit Test Suite</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />

<!-- QUnit -->
<link rel="stylesheet" href="../../../../node_modules/qunit/qunit/qunit.css" type="text/css" media="screen" />
<script src="../../../../node_modules/qunit/qunit/qunit.js"></script>
</head>
<body>
<div id="qunit"></div>
<div id="qunit-fixture"></div>

<script src="../../../../build/wp-includes/js/twemoji.js"></script>
<script>
window._wpemojiSettings = {
baseUrl: 'https://s.w.org/images/core/emoji/17.0.2/72x72/',
ext: '.png',
svgUrl: 'https://s.w.org/images/core/emoji/17.0.2/svg/',
svgExt: '.svg',
supports: {
everything: false,
everythingExceptFlag: false
}
};
</script>
<script src="../../../../build/wp-includes/js/wp-emoji.js"></script>
<script src="emoji.js"></script>
</body>
</html>
52 changes: 52 additions & 0 deletions tests/qunit/wp-includes/js/emoji.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
( function( QUnit ) {
var FLAG = '🇰🇷'; // Flag: South Korea.

QUnit.module( 'wp.emoji' );

function assertNotParsed( assert, container, done ) {
window.setTimeout( function() {
assert.strictEqual( container.querySelector( 'img.emoji' ), null, 'the excluded element should not contain an emoji image' );
container.remove();
done();
}, 50 );
}

QUnit.test( 'does not parse an excluded element appended whole after load', function( assert ) {
var done = assert.async(),
span = document.createElement( 'span' );

span.className = 'wp-exclude-emoji';
span.textContent = FLAG;
document.body.appendChild( span );

assertNotParsed( assert, span, done );
} );

QUnit.test( 'does not parse an excluded element whose text is replaced after load', function( assert ) {
var done = assert.async(),
span = document.createElement( 'span' );

span.className = 'wp-exclude-emoji';
document.body.appendChild( span );

window.setTimeout( function() {
span.textContent = FLAG;
assertNotParsed( assert, span, done );
}, 50 );
} );

QUnit.test( 'does not parse text appended inside an already-excluded ancestor', function( assert ) {
var done = assert.async(),
wrapper = document.createElement( 'span' ),
child = document.createElement( 'em' );

wrapper.className = 'wp-exclude-emoji';
wrapper.appendChild( child );
document.body.appendChild( wrapper );

window.setTimeout( function() {
child.textContent = FLAG;
assertNotParsed( assert, wrapper, done );
}, 50 );
} );
} )( window.QUnit );
Loading