mirror of
https://github.com/twitter/twemoji.git
synced 2025-01-27 06:35:16 +00:00
Merge pull request #236 from dvdckl/xhtml-compat
Add XHTML compatibility
This commit is contained in:
commit
0efb650fd3
@ -11,13 +11,13 @@ wru.test([{
|
||||
wru.assert(
|
||||
'default parsing works',
|
||||
twemoji.parse('I \u2764 emoji!') ===
|
||||
'I <img class="emoji" draggable="false" alt="\u2764" src="' + base + '72x72/2764.png"> emoji!'
|
||||
'I <img class="emoji" draggable="false" alt="\u2764" src="' + base + '72x72/2764.png"/> emoji!'
|
||||
);
|
||||
// with "as image" variant
|
||||
wru.assert(
|
||||
'default \uFE0F variant parsing works',
|
||||
twemoji.parse('I \u2764\uFE0F emoji!') ===
|
||||
'I <img class="emoji" draggable="false" alt="\u2764\uFE0F" src="' + base + '72x72/2764.png"> emoji!'
|
||||
'I <img class="emoji" draggable="false" alt="\u2764\uFE0F" src="' + base + '72x72/2764.png"/> emoji!'
|
||||
);
|
||||
// with "as text" variant
|
||||
wru.assert(
|
||||
@ -32,12 +32,12 @@ wru.test([{
|
||||
wru.assert(
|
||||
'number is squared',
|
||||
twemoji.parse('I \u2764 emoji!', {size: 72}) ===
|
||||
'I <img class="emoji" draggable="false" alt="\u2764" src="' + base + '72x72/2764.png"> emoji!'
|
||||
'I <img class="emoji" draggable="false" alt="\u2764" src="' + base + '72x72/2764.png"/> emoji!'
|
||||
);
|
||||
wru.assert(
|
||||
'string is preserved',
|
||||
twemoji.parse('I \u2764 emoji!', {size: 'any-size'}) ===
|
||||
'I <img class="emoji" draggable="false" alt="\u2764" src="' + base + 'any-size/2764.png"> emoji!'
|
||||
'I <img class="emoji" draggable="false" alt="\u2764" src="' + base + 'any-size/2764.png"/> emoji!'
|
||||
);
|
||||
}
|
||||
},{
|
||||
@ -73,7 +73,7 @@ wru.test([{
|
||||
test: function () {
|
||||
wru.assert(
|
||||
'size is overwritten',
|
||||
'I <img class="emoji" draggable="false" alt="\u2764" src="72x72/2764.png"> emoji!' ===
|
||||
'I <img class="emoji" draggable="false" alt="\u2764" src="72x72/2764.png"/> emoji!' ===
|
||||
twemoji.parse(
|
||||
'I \u2764 emoji!',
|
||||
{
|
||||
@ -226,7 +226,7 @@ wru.test([{
|
||||
},{
|
||||
name: 'nested nodes',
|
||||
test: function () {
|
||||
var str = '<img class="emoji" draggable="false" alt="\u2764" src="https://twemoji.maxcdn.com/72x72/2764.png">',
|
||||
var str = '<img class="emoji" draggable="false" alt="\u2764" src="https://twemoji.maxcdn.com/72x72/2764.png"/>',
|
||||
div = document.createElement('div'),
|
||||
p,
|
||||
img;
|
||||
@ -278,7 +278,7 @@ wru.test([{
|
||||
name: 'string parsing + className',
|
||||
test: function () {
|
||||
var className = 'img-' + Math.random();
|
||||
var img = 'I <img class="' + className + '" draggable="false" alt="\u2764" src="72x72/2764.png"> emoji!';
|
||||
var img = 'I <img class="' + className + '" draggable="false" alt="\u2764" src="72x72/2764.png"/> emoji!';
|
||||
wru.assert(
|
||||
'className is overwritten',
|
||||
img ===
|
||||
@ -309,7 +309,7 @@ wru.test([{
|
||||
test: function () {
|
||||
wru.assert(
|
||||
'custom attributes are inserted',
|
||||
'I <img class="emoji" draggable="false" alt="\u2764" src="' + base + '72x72/2764.png" title="Emoji: \u2764" data-test="We all <3 emoji"> emoji!' ===
|
||||
'I <img class="emoji" draggable="false" alt="\u2764" src="' + base + '72x72/2764.png" title="Emoji: \u2764" data-test="We all <3 emoji"/> emoji!' ===
|
||||
twemoji.parse(
|
||||
'I \u2764 emoji!',
|
||||
{
|
||||
@ -328,7 +328,7 @@ wru.test([{
|
||||
test: function () {
|
||||
wru.assert(
|
||||
'custom attributes are inserted',
|
||||
'I <img class="emoji" draggable="false" alt="\u2764" src="' + base + '72x72/2764.png" title="Emoji: 2764" data-test="We all <3 emoji"> emoji!' ===
|
||||
'I <img class="emoji" draggable="false" alt="\u2764" src="' + base + '72x72/2764.png" title="Emoji: 2764" data-test="We all <3 emoji"/> emoji!' ===
|
||||
twemoji.parse(
|
||||
'I \u2764 emoji!',
|
||||
{
|
||||
@ -346,7 +346,7 @@ wru.test([{
|
||||
test: function () {
|
||||
wru.assert(
|
||||
'custom attributes are inserted',
|
||||
'I <img class="emoji" draggable="false" alt="\u2764" src="' + base + '72x72/2764.png" title="&amp;lt;script&amp;gt;alert("yo")&amp;lt;/script&amp;gt;"> emoji!' ===
|
||||
'I <img class="emoji" draggable="false" alt="\u2764" src="' + base + '72x72/2764.png" title="&amp;lt;script&amp;gt;alert("yo")&amp;lt;/script&amp;gt;"/> emoji!' ===
|
||||
twemoji.parse(
|
||||
'I \u2764 emoji!',
|
||||
{
|
||||
@ -364,7 +364,7 @@ wru.test([{
|
||||
test: function () {
|
||||
wru.assert(
|
||||
'custom attributes are inserted',
|
||||
'I <img class="emoji" draggable="false" alt="❤" src="' + base + '72x72/2764.png" title="test"> emoji!' ===
|
||||
'I <img class="emoji" draggable="false" alt="❤" src="' + base + '72x72/2764.png" title="test"/> emoji!' ===
|
||||
twemoji.parse(
|
||||
'I \u2764 emoji!',
|
||||
{
|
||||
@ -421,7 +421,7 @@ wru.test([{
|
||||
},{
|
||||
name: 'folder option',
|
||||
test: function () {
|
||||
var img = 'I <img class="emoji" draggable="false" alt="\u2764" src="svg/2764.svg"> emoji!';
|
||||
var img = 'I <img class="emoji" draggable="false" alt="\u2764" src="svg/2764.svg"/> emoji!';
|
||||
wru.assert(
|
||||
'folder is accepted',
|
||||
img ===
|
||||
@ -542,7 +542,7 @@ wru.test([{
|
||||
twemoji.parse('\u25c0 \u25c0\ufe0e \u25c0\ufe0f', {
|
||||
callback: function(iconId, options){return 'icon';}
|
||||
}) ===
|
||||
'<img class="emoji" draggable="false" alt="\u25c0" src="icon"> \u25c0\ufe0e <img class="emoji" draggable="false" alt="\u25c0\ufe0f" src="icon">'
|
||||
'<img class="emoji" draggable="false" alt="\u25c0" src="icon"/> \u25c0\ufe0e <img class="emoji" draggable="false" alt="\u25c0\ufe0f" src="icon"/>'
|
||||
);
|
||||
}
|
||||
},{
|
||||
@ -567,6 +567,34 @@ wru.test([{
|
||||
wru.assert('correct length', div.getElementsByTagName('img').length === 0);
|
||||
wru.assert('expected html', div.innerHTML === '"\u2b1c\uFE0E"');
|
||||
}
|
||||
}, {
|
||||
name: 'Specific elements are not ignored',
|
||||
test: function () {
|
||||
var innerHTML, div = document.createElement('div');
|
||||
div.innerHTML = '<iframe>\u2764</iframe>';
|
||||
innerHTML = div.innerHTML;
|
||||
twemoji.parse(div);
|
||||
wru.assert('Exclude tags', div.innerHTML === div.innerHTML);
|
||||
div.innerHTML = '<customiframe>\u2764</customiframe>';
|
||||
wru.assert('Avoid false positive',
|
||||
/^<customiframe><img .*?><\/customiframe>$/.test(twemoji.parse(div).innerHTML));
|
||||
}
|
||||
}, {
|
||||
name: 'XHTML parseNode compatibility',
|
||||
test: function () {
|
||||
var frame = document.createElement('iframe');
|
||||
frame.src = 'data:application/xhtml+xml;charset=utf-8,%3Cx%20xmlns%3D%22http%3A%2F%2Fwww.w3.org%2F1999%2Fxhtml%22%3E%E2%9D%A4%3C%2Fx%3E';
|
||||
document.body.appendChild(frame);
|
||||
setTimeout(wru.async(function () {
|
||||
twemoji.parse(frame.contentDocument.documentElement);
|
||||
if (frame.contentDocument.documentElement.outerHTML.indexOf("<html>") == 0) {
|
||||
wru.assert('unable to test XHTML due to iframe not loading');
|
||||
} else {
|
||||
wru.assert('parse XHTML node', /^<x.*?><img .*?><\/x>$/.test(twemoji.parse(frame.contentDocument.documentElement).outerHTML));
|
||||
}
|
||||
document.body.removeChild(frame);
|
||||
}, 10));
|
||||
}
|
||||
}, {
|
||||
name: 'SVG Elements are ignored',
|
||||
test: function () {
|
||||
|
@ -160,13 +160,13 @@ define(function () {
|
||||
* @example
|
||||
*
|
||||
* twemoji.parse("I \u2764\uFE0F emoji!");
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"> emoji!
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"/> emoji!
|
||||
*
|
||||
*
|
||||
* twemoji.parse("I \u2764\uFE0F emoji!", function(iconId, options) {
|
||||
* return '/assets/' + iconId + '.gif';
|
||||
* });
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"> emoji!
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"/> emoji!
|
||||
*
|
||||
*
|
||||
* twemoji.parse("I \u2764\uFE0F emoji!", {
|
||||
@ -175,7 +175,7 @@ define(function () {
|
||||
* return '/assets/' + options.size + '/' + iconId + options.ext;
|
||||
* }
|
||||
* });
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/72x72/2764.png"> emoji!
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/72x72/2764.png"/> emoji!
|
||||
*
|
||||
*/
|
||||
parse: parse,
|
||||
@ -238,8 +238,8 @@ define(function () {
|
||||
// used to find HTML special chars in attributes
|
||||
rescaper = /[&<>'"]/g,
|
||||
|
||||
// nodes with type 1 which should **not** be parsed (including lower case svg)
|
||||
shouldntBeParsed = /IFRAME|NOFRAMES|NOSCRIPT|SCRIPT|SELECT|STYLE|TEXTAREA|[a-z]/,
|
||||
// nodes with type 1 which should **not** be parsed
|
||||
shouldntBeParsed = /^(?:iframe|noframes|noscript|script|select|style|textarea)$/,
|
||||
|
||||
// just a private shortcut
|
||||
fromCharCode = String.fromCharCode;
|
||||
@ -302,9 +302,10 @@ define(function () {
|
||||
// collect them to process emoji later
|
||||
allText.push(subnode);
|
||||
}
|
||||
// ignore all nodes that are not type 1 or that
|
||||
// ignore all nodes that are not type 1, that are svg, or that
|
||||
// should not be parsed as script, style, and others
|
||||
else if (nodeType === 1 && !shouldntBeParsed.test(subnode.nodeName)) {
|
||||
else if (nodeType === 1 && !('ownerSVGElement' in subnode) &&
|
||||
!shouldntBeParsed.test(subnode.nodeName.toLowerCase())) {
|
||||
grabAllTextNodes(subnode, allText);
|
||||
}
|
||||
}
|
||||
@ -460,7 +461,7 @@ define(function () {
|
||||
ret = ret.concat(' ', attrname, '="', escapeHTML(attrib[attrname]), '"');
|
||||
}
|
||||
}
|
||||
ret = ret.concat('>');
|
||||
ret = ret.concat('/>');
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
|
17
2/twemoji.js
17
2/twemoji.js
@ -159,13 +159,13 @@ var twemoji = (function (
|
||||
* @example
|
||||
*
|
||||
* twemoji.parse("I \u2764\uFE0F emoji!");
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"> emoji!
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"/> emoji!
|
||||
*
|
||||
*
|
||||
* twemoji.parse("I \u2764\uFE0F emoji!", function(iconId, options) {
|
||||
* return '/assets/' + iconId + '.gif';
|
||||
* });
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"> emoji!
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"/> emoji!
|
||||
*
|
||||
*
|
||||
* twemoji.parse("I \u2764\uFE0F emoji!", {
|
||||
@ -174,7 +174,7 @@ var twemoji = (function (
|
||||
* return '/assets/' + options.size + '/' + iconId + options.ext;
|
||||
* }
|
||||
* });
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/72x72/2764.png"> emoji!
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/72x72/2764.png"/> emoji!
|
||||
*
|
||||
*/
|
||||
parse: parse,
|
||||
@ -237,8 +237,8 @@ var twemoji = (function (
|
||||
// used to find HTML special chars in attributes
|
||||
rescaper = /[&<>'"]/g,
|
||||
|
||||
// nodes with type 1 which should **not** be parsed (including lower case svg)
|
||||
shouldntBeParsed = /IFRAME|NOFRAMES|NOSCRIPT|SCRIPT|SELECT|STYLE|TEXTAREA|[a-z]/,
|
||||
// nodes with type 1 which should **not** be parsed
|
||||
shouldntBeParsed = /^(?:iframe|noframes|noscript|script|select|style|textarea)$/,
|
||||
|
||||
// just a private shortcut
|
||||
fromCharCode = String.fromCharCode;
|
||||
@ -301,9 +301,10 @@ var twemoji = (function (
|
||||
// collect them to process emoji later
|
||||
allText.push(subnode);
|
||||
}
|
||||
// ignore all nodes that are not type 1 or that
|
||||
// ignore all nodes that are not type 1, that are svg, or that
|
||||
// should not be parsed as script, style, and others
|
||||
else if (nodeType === 1 && !shouldntBeParsed.test(subnode.nodeName)) {
|
||||
else if (nodeType === 1 && !('ownerSVGElement' in subnode) &&
|
||||
!shouldntBeParsed.test(subnode.nodeName.toLowerCase())) {
|
||||
grabAllTextNodes(subnode, allText);
|
||||
}
|
||||
}
|
||||
@ -459,7 +460,7 @@ var twemoji = (function (
|
||||
ret = ret.concat(' ', attrname, '="', escapeHTML(attrib[attrname]), '"');
|
||||
}
|
||||
}
|
||||
ret = ret.concat('>');
|
||||
ret = ret.concat('/>');
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
|
2
2/twemoji.min.js
vendored
2
2/twemoji.min.js
vendored
File diff suppressed because one or more lines are too long
@ -160,13 +160,13 @@ var twemoji = (function (
|
||||
* @example
|
||||
*
|
||||
* twemoji.parse("I \u2764\uFE0F emoji!");
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"> emoji!
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"/> emoji!
|
||||
*
|
||||
*
|
||||
* twemoji.parse("I \u2764\uFE0F emoji!", function(iconId, options) {
|
||||
* return '/assets/' + iconId + '.gif';
|
||||
* });
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"> emoji!
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"/> emoji!
|
||||
*
|
||||
*
|
||||
* twemoji.parse("I \u2764\uFE0F emoji!", {
|
||||
@ -175,7 +175,7 @@ var twemoji = (function (
|
||||
* return '/assets/' + options.size + '/' + iconId + options.ext;
|
||||
* }
|
||||
* });
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/72x72/2764.png"> emoji!
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/72x72/2764.png"/> emoji!
|
||||
*
|
||||
*/
|
||||
parse: parse,
|
||||
@ -238,8 +238,8 @@ var twemoji = (function (
|
||||
// used to find HTML special chars in attributes
|
||||
rescaper = /[&<>'"]/g,
|
||||
|
||||
// nodes with type 1 which should **not** be parsed (including lower case svg)
|
||||
shouldntBeParsed = /IFRAME|NOFRAMES|NOSCRIPT|SCRIPT|SELECT|STYLE|TEXTAREA|[a-z]/,
|
||||
// nodes with type 1 which should **not** be parsed
|
||||
shouldntBeParsed = /^(?:iframe|noframes|noscript|script|select|style|textarea)$/,
|
||||
|
||||
// just a private shortcut
|
||||
fromCharCode = String.fromCharCode;
|
||||
@ -302,9 +302,10 @@ var twemoji = (function (
|
||||
// collect them to process emoji later
|
||||
allText.push(subnode);
|
||||
}
|
||||
// ignore all nodes that are not type 1 or that
|
||||
// ignore all nodes that are not type 1, that are svg, or that
|
||||
// should not be parsed as script, style, and others
|
||||
else if (nodeType === 1 && !shouldntBeParsed.test(subnode.nodeName)) {
|
||||
else if (nodeType === 1 && !('ownerSVGElement' in subnode) &&
|
||||
!shouldntBeParsed.test(subnode.nodeName.toLowerCase())) {
|
||||
grabAllTextNodes(subnode, allText);
|
||||
}
|
||||
}
|
||||
@ -460,7 +461,7 @@ var twemoji = (function (
|
||||
ret = ret.concat(' ', attrname, '="', escapeHTML(attrib[attrname]), '"');
|
||||
}
|
||||
}
|
||||
ret = ret.concat('>');
|
||||
ret = ret.concat('/>');
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
|
@ -647,13 +647,13 @@ function createTwemoji(re) {
|
||||
* @example
|
||||
*
|
||||
* twemoji.parse("I \u2764\uFE0F emoji!");
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"> emoji!
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"/> emoji!
|
||||
*
|
||||
*
|
||||
* twemoji.parse("I \u2764\uFE0F emoji!", function(iconId, options) {
|
||||
* return '/assets/' + iconId + '.gif';
|
||||
* });
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"> emoji!
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/2764.gif"/> emoji!
|
||||
*
|
||||
*
|
||||
* twemoji.parse("I \u2764\uFE0F emoji!", {
|
||||
@ -662,7 +662,7 @@ function createTwemoji(re) {
|
||||
* return '/assets/' + options.size + '/' + iconId + options.ext;
|
||||
* }
|
||||
* });
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/72x72/2764.png"> emoji!
|
||||
* // I <img class="emoji" draggable="false" alt="❤️" src="/assets/72x72/2764.png"/> emoji!
|
||||
*
|
||||
*/
|
||||
parse: parse,
|
||||
@ -725,8 +725,8 @@ function createTwemoji(re) {
|
||||
// used to find HTML special chars in attributes
|
||||
rescaper = /[&<>'"]/g,
|
||||
|
||||
// nodes with type 1 which should **not** be parsed (including lower case svg)
|
||||
shouldntBeParsed = /IFRAME|NOFRAMES|NOSCRIPT|SCRIPT|SELECT|STYLE|TEXTAREA|[a-z]/,
|
||||
// nodes with type 1 which should **not** be parsed
|
||||
shouldntBeParsed = /^(?:iframe|noframes|noscript|script|select|style|textarea)$/,
|
||||
|
||||
// just a private shortcut
|
||||
fromCharCode = String.fromCharCode;
|
||||
@ -789,9 +789,10 @@ function createTwemoji(re) {
|
||||
// collect them to process emoji later
|
||||
allText.push(subnode);
|
||||
}
|
||||
// ignore all nodes that are not type 1 or that
|
||||
// ignore all nodes that are not type 1, that are svg, or that
|
||||
// should not be parsed as script, style, and others
|
||||
else if (nodeType === 1 && !shouldntBeParsed.test(subnode.nodeName)) {
|
||||
else if (nodeType === 1 && !('ownerSVGElement' in subnode) &&
|
||||
!shouldntBeParsed.test(subnode.nodeName.toLowerCase())) {
|
||||
grabAllTextNodes(subnode, allText);
|
||||
}
|
||||
}
|
||||
@ -947,7 +948,7 @@ function createTwemoji(re) {
|
||||
ret = ret.concat(' ', attrname, '="', escapeHTML(attrib[attrname]), '"');
|
||||
}
|
||||
}
|
||||
ret = ret.concat('>');
|
||||
ret = ret.concat('/>');
|
||||
}
|
||||
return ret;
|
||||
});
|
||||
|
Loading…
x
Reference in New Issue
Block a user