mirror of
https://github.com/twitter/twemoji.git
synced 2024-06-15 03:35:16 +00:00
Update attributes option to only use a callback, more robust html encoding, add tests
This commit is contained in:
parent
13eac7a2d8
commit
3a3efd6063
97
test.js
97
test.js
@ -309,6 +309,103 @@ wru.test([{
|
|||||||
div.getElementsByTagName('img')[0].className === className
|
div.getElementsByTagName('img')[0].className === className
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
},{
|
||||||
|
name: 'string parsing + attributes callback',
|
||||||
|
test: function () {
|
||||||
|
wru.assert(
|
||||||
|
'custom attributes are inserted',
|
||||||
|
'I <img class="emoji" draggable="false" alt="\u2764" title="Emoji: \u2764" data-test="We all <3 emoji" src="' + base + '36x36/2764.png"> emoji!' ===
|
||||||
|
twemoji.parse(
|
||||||
|
'I \u2764 emoji!',
|
||||||
|
{
|
||||||
|
attributes: function(icon) {
|
||||||
|
return {
|
||||||
|
title: 'Emoji: ' + icon,
|
||||||
|
'data-test': 'We all <3 emoji'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
name: 'string parsing + attributes callback content properly encoded',
|
||||||
|
test: function () {
|
||||||
|
wru.assert(
|
||||||
|
'custom attributes are inserted',
|
||||||
|
'I <img class="emoji" draggable="false" alt="\u2764" title="&amp;lt;script&amp;gt;alert("yo")&amp;lt;/script&amp;gt;" src="' + base + '36x36/2764.png"> emoji!' ===
|
||||||
|
twemoji.parse(
|
||||||
|
'I \u2764 emoji!',
|
||||||
|
{
|
||||||
|
attributes: function(icon) {
|
||||||
|
return {
|
||||||
|
title: '&lt;script&gt;alert("yo")&lt;/script&gt;'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
name: 'string parsing + attributes callback "on" attributes are omitted',
|
||||||
|
test: function () {
|
||||||
|
wru.assert(
|
||||||
|
'custom attributes are inserted',
|
||||||
|
'I <img class="emoji" draggable="false" alt="❤" title="test" src="' + base + '36x36/2764.png"> emoji!' ===
|
||||||
|
twemoji.parse(
|
||||||
|
'I \u2764 emoji!',
|
||||||
|
{
|
||||||
|
attributes: function(icon) {
|
||||||
|
return {
|
||||||
|
title: 'test',
|
||||||
|
onsomething: 'whoops!',
|
||||||
|
onclick: 'nope',
|
||||||
|
onmousedown: 'nada'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
},{
|
||||||
|
name: 'DOM parsing + attributes callback',
|
||||||
|
test: function () {
|
||||||
|
var img,
|
||||||
|
// without variant
|
||||||
|
div = document.createElement('div');
|
||||||
|
div.appendChild(document.createTextNode('I \u2764 emoji!'));
|
||||||
|
console.log(div);
|
||||||
|
twemoji.parse(
|
||||||
|
div, {
|
||||||
|
attributes: function(icon) {
|
||||||
|
return {
|
||||||
|
title: 'Emoji: ' + icon,
|
||||||
|
'data-test': 'We all <3 emoji',
|
||||||
|
onclick: 'nope',
|
||||||
|
onmousedown: 'nada'
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
);
|
||||||
|
wru.assert('default parsing works creating 3 nodes', div.childNodes.length === 3);
|
||||||
|
wru.assert('first child is the expected one', div.removeChild(div.firstChild).nodeValue === 'I ');
|
||||||
|
img = div.removeChild(div.firstChild);
|
||||||
|
wru.assert('second child is the image', img.nodeName === 'IMG');
|
||||||
|
wru.assert('img attributes are OK',
|
||||||
|
img.className === 'emoji' &&
|
||||||
|
img.getAttribute('draggable') === 'false' &&
|
||||||
|
img.src === base + '36x36/2764.png' &&
|
||||||
|
img.alt === '\u2764' &&
|
||||||
|
img.onerror === twemoji.onerror &&
|
||||||
|
img.getAttribute('title') === 'Emoji: \u2764' &&
|
||||||
|
img.getAttribute('data-test') === 'We all <3 emoji'
|
||||||
|
);
|
||||||
|
wru.assert('img on attributes are omitted',
|
||||||
|
img.onclick === null &&
|
||||||
|
img.onmousedown === null
|
||||||
|
);
|
||||||
|
}
|
||||||
},{
|
},{
|
||||||
name: 'folder option',
|
name: 'folder option',
|
||||||
test: function () {
|
test: function () {
|
||||||
|
@ -527,6 +527,24 @@ function createTwemoji(re) {
|
|||||||
return document.createTextNode(text);
|
return document.createTextNode(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function to escape html attribute text
|
||||||
|
* @param string text use in HTML attribute
|
||||||
|
* @return string text encoded to use in HTML attribute
|
||||||
|
*/
|
||||||
|
function escape(s) {
|
||||||
|
var escaped = {
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>',
|
||||||
|
"'": ''',
|
||||||
|
'"': '"'
|
||||||
|
};
|
||||||
|
return s.replace(/[&<>'"]/g, function (m) {
|
||||||
|
return escaped[m];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default callback used to generate emoji src
|
* Default callback used to generate emoji src
|
||||||
* based on Twitter CDN
|
* based on Twitter CDN
|
||||||
@ -642,13 +660,15 @@ function createTwemoji(re) {
|
|||||||
img.onerror = twemoji.onerror;
|
img.onerror = twemoji.onerror;
|
||||||
img.className = options.className;
|
img.className = options.className;
|
||||||
img.setAttribute('draggable', 'false');
|
img.setAttribute('draggable', 'false');
|
||||||
var attrib = options.attributes;
|
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||||
if (typeof(attrib) === 'function') {
|
var attrib = options.attributes(alt);
|
||||||
attrib = attrib(alt);
|
if (attrib) {
|
||||||
}
|
for (var attrname in attrib) {
|
||||||
if (attrib) {
|
// don't allow any handlers to be set
|
||||||
for (var attrname in attrib) {
|
if (attrname.lastIndexOf('on', 0) === -1) {
|
||||||
img.setAttribute(attrname) = attrib[attrname];
|
img.setAttribute(attrname, attrib[attrname]);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
img.alt = alt;
|
img.alt = alt;
|
||||||
@ -703,14 +723,16 @@ function createTwemoji(re) {
|
|||||||
if (src) {
|
if (src) {
|
||||||
// recycle the match string replacing the emoji
|
// recycle the match string replacing the emoji
|
||||||
// with its image counter part
|
// with its image counter part
|
||||||
var attrib = options.attributes;
|
|
||||||
if (typeof(attrib) === 'function') {
|
|
||||||
attrib = attrib(match);
|
|
||||||
}
|
|
||||||
var attr_text = '';
|
var attr_text = '';
|
||||||
if (attrib) {
|
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||||
for (var attrname in attrib) {
|
var attrib = options.attributes(match);
|
||||||
attr_text = attr_text + ' ' + attrname + '="' + attrib[attrname].replace(/"/g, '"') + '"';
|
if (attrib) {
|
||||||
|
for (var attrname in attrib) {
|
||||||
|
// don't allow any handlers to be set
|
||||||
|
if (attrname.lastIndexOf('on', 0) === -1) {
|
||||||
|
attr_text = attr_text + ' ' + attrname + '="' + escape(attrib[attrname]) + '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -721,9 +743,9 @@ function createTwemoji(re) {
|
|||||||
// when variants should be copied and pasted too
|
// when variants should be copied and pasted too
|
||||||
'alt="',
|
'alt="',
|
||||||
match,
|
match,
|
||||||
'" ',
|
'"',
|
||||||
attr_text,
|
attr_text,
|
||||||
'src="',
|
' src="',
|
||||||
src,
|
src,
|
||||||
'"',
|
'"',
|
||||||
'>'
|
'>'
|
||||||
|
@ -250,6 +250,24 @@ define(function () {
|
|||||||
return document.createTextNode(text);
|
return document.createTextNode(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function to escape html attribute text
|
||||||
|
* @param string text use in HTML attribute
|
||||||
|
* @return string text encoded to use in HTML attribute
|
||||||
|
*/
|
||||||
|
function escape(s) {
|
||||||
|
var escaped = {
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>',
|
||||||
|
"'": ''',
|
||||||
|
'"': '"'
|
||||||
|
};
|
||||||
|
return s.replace(/[&<>'"]/g, function (m) {
|
||||||
|
return escaped[m];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default callback used to generate emoji src
|
* Default callback used to generate emoji src
|
||||||
* based on Twitter CDN
|
* based on Twitter CDN
|
||||||
@ -365,13 +383,14 @@ define(function () {
|
|||||||
img.onerror = twemoji.onerror;
|
img.onerror = twemoji.onerror;
|
||||||
img.className = options.className;
|
img.className = options.className;
|
||||||
img.setAttribute('draggable', 'false');
|
img.setAttribute('draggable', 'false');
|
||||||
var attrib = options.attributes;
|
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||||
if (typeof(attrib) === 'function') {
|
var attrib = options.attributes(alt);
|
||||||
attrib = attrib(alt);
|
if (attrib) {
|
||||||
}
|
for (var attrname in attrib) {
|
||||||
if (attrib) {
|
if (attrname.lastIndexOf('on', 0) === -1) {
|
||||||
for (var attrname in attrib) {
|
img.setAttribute(attrname, attrib[attrname]);
|
||||||
img.setAttribute(attrname) = attrib[attrname];
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
img.alt = alt;
|
img.alt = alt;
|
||||||
@ -426,14 +445,15 @@ define(function () {
|
|||||||
if (src) {
|
if (src) {
|
||||||
// recycle the match string replacing the emoji
|
// recycle the match string replacing the emoji
|
||||||
// with its image counter part
|
// with its image counter part
|
||||||
var attrib = options.attributes;
|
|
||||||
if (typeof(attrib) === 'function') {
|
|
||||||
attrib = attrib(match);
|
|
||||||
}
|
|
||||||
var attr_text = '';
|
var attr_text = '';
|
||||||
if (attrib) {
|
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||||
for (var attrname in attrib) {
|
var attrib = options.attributes(match);
|
||||||
attr_text = attr_text + ' ' + attrname + '="' + attrib[attrname].replace(/"/g, '"') + '"';
|
if (attrib) {
|
||||||
|
for (var attrname in attrib) {
|
||||||
|
if (attrname.lastIndexOf('on', 0) === -1) {
|
||||||
|
attr_text = attr_text + ' ' + attrname + '="' + escape(attrib[attrname]) + '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,9 +464,9 @@ define(function () {
|
|||||||
// when variants should be copied and pasted too
|
// when variants should be copied and pasted too
|
||||||
'alt="',
|
'alt="',
|
||||||
match,
|
match,
|
||||||
'" ',
|
'"',
|
||||||
attr_text,
|
attr_text,
|
||||||
'src="',
|
' src="',
|
||||||
src,
|
src,
|
||||||
'"',
|
'"',
|
||||||
'>'
|
'>'
|
||||||
|
52
twemoji.js
52
twemoji.js
@ -249,6 +249,24 @@ var twemoji = (function (
|
|||||||
return document.createTextNode(text);
|
return document.createTextNode(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function to escape html attribute text
|
||||||
|
* @param string text use in HTML attribute
|
||||||
|
* @return string text encoded to use in HTML attribute
|
||||||
|
*/
|
||||||
|
function escape(s) {
|
||||||
|
var escaped = {
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>',
|
||||||
|
"'": ''',
|
||||||
|
'"': '"'
|
||||||
|
};
|
||||||
|
return s.replace(/[&<>'"]/g, function (m) {
|
||||||
|
return escaped[m];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default callback used to generate emoji src
|
* Default callback used to generate emoji src
|
||||||
* based on Twitter CDN
|
* based on Twitter CDN
|
||||||
@ -364,13 +382,14 @@ var twemoji = (function (
|
|||||||
img.onerror = twemoji.onerror;
|
img.onerror = twemoji.onerror;
|
||||||
img.className = options.className;
|
img.className = options.className;
|
||||||
img.setAttribute('draggable', 'false');
|
img.setAttribute('draggable', 'false');
|
||||||
var attrib = options.attributes;
|
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||||
if (typeof(attrib) === 'function') {
|
var attrib = options.attributes(alt);
|
||||||
attrib = attrib(alt);
|
if (attrib) {
|
||||||
}
|
for (var attrname in attrib) {
|
||||||
if (attrib) {
|
if (attrname.lastIndexOf('on', 0) === -1) {
|
||||||
for (var attrname in attrib) {
|
img.setAttribute(attrname, attrib[attrname]);
|
||||||
img.setAttribute(attrname) = attrib[attrname];
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
img.alt = alt;
|
img.alt = alt;
|
||||||
@ -425,14 +444,15 @@ var twemoji = (function (
|
|||||||
if (src) {
|
if (src) {
|
||||||
// recycle the match string replacing the emoji
|
// recycle the match string replacing the emoji
|
||||||
// with its image counter part
|
// with its image counter part
|
||||||
var attrib = options.attributes;
|
|
||||||
if (typeof(attrib) === 'function') {
|
|
||||||
attrib = attrib(match);
|
|
||||||
}
|
|
||||||
var attr_text = '';
|
var attr_text = '';
|
||||||
if (attrib) {
|
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||||
for (var attrname in attrib) {
|
var attrib = options.attributes(match);
|
||||||
attr_text = attr_text + ' ' + attrname + '="' + attrib[attrname].replace(/"/g, '"') + '"';
|
if (attrib) {
|
||||||
|
for (var attrname in attrib) {
|
||||||
|
if (attrname.lastIndexOf('on', 0) === -1) {
|
||||||
|
attr_text = attr_text + ' ' + attrname + '="' + escape(attrib[attrname]) + '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -443,9 +463,9 @@ var twemoji = (function (
|
|||||||
// when variants should be copied and pasted too
|
// when variants should be copied and pasted too
|
||||||
'alt="',
|
'alt="',
|
||||||
match,
|
match,
|
||||||
'" ',
|
'"',
|
||||||
attr_text,
|
attr_text,
|
||||||
'src="',
|
' src="',
|
||||||
src,
|
src,
|
||||||
'"',
|
'"',
|
||||||
'>'
|
'>'
|
||||||
|
2
twemoji.min.js
vendored
2
twemoji.min.js
vendored
File diff suppressed because one or more lines are too long
@ -250,6 +250,24 @@ var twemoji = (function (
|
|||||||
return document.createTextNode(text);
|
return document.createTextNode(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Utility function to escape html attribute text
|
||||||
|
* @param string text use in HTML attribute
|
||||||
|
* @return string text encoded to use in HTML attribute
|
||||||
|
*/
|
||||||
|
function escape(s) {
|
||||||
|
var escaped = {
|
||||||
|
'&': '&',
|
||||||
|
'<': '<',
|
||||||
|
'>': '>',
|
||||||
|
"'": ''',
|
||||||
|
'"': '"'
|
||||||
|
};
|
||||||
|
return s.replace(/[&<>'"]/g, function (m) {
|
||||||
|
return escaped[m];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Default callback used to generate emoji src
|
* Default callback used to generate emoji src
|
||||||
* based on Twitter CDN
|
* based on Twitter CDN
|
||||||
@ -365,13 +383,14 @@ var twemoji = (function (
|
|||||||
img.onerror = twemoji.onerror;
|
img.onerror = twemoji.onerror;
|
||||||
img.className = options.className;
|
img.className = options.className;
|
||||||
img.setAttribute('draggable', 'false');
|
img.setAttribute('draggable', 'false');
|
||||||
var attrib = options.attributes;
|
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||||
if (typeof(attrib) === 'function') {
|
var attrib = options.attributes(alt);
|
||||||
attrib = attrib(alt);
|
if (attrib) {
|
||||||
}
|
for (var attrname in attrib) {
|
||||||
if (attrib) {
|
if (attrname.lastIndexOf('on', 0) === -1) {
|
||||||
for (var attrname in attrib) {
|
img.setAttribute(attrname, attrib[attrname]);
|
||||||
img.setAttribute(attrname) = attrib[attrname];
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
img.alt = alt;
|
img.alt = alt;
|
||||||
@ -426,14 +445,15 @@ var twemoji = (function (
|
|||||||
if (src) {
|
if (src) {
|
||||||
// recycle the match string replacing the emoji
|
// recycle the match string replacing the emoji
|
||||||
// with its image counter part
|
// with its image counter part
|
||||||
var attrib = options.attributes;
|
|
||||||
if (typeof(attrib) === 'function') {
|
|
||||||
attrib = attrib(match);
|
|
||||||
}
|
|
||||||
var attr_text = '';
|
var attr_text = '';
|
||||||
if (attrib) {
|
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||||
for (var attrname in attrib) {
|
var attrib = options.attributes(match);
|
||||||
attr_text = attr_text + ' ' + attrname + '="' + attrib[attrname].replace(/"/g, '"') + '"';
|
if (attrib) {
|
||||||
|
for (var attrname in attrib) {
|
||||||
|
if (attrname.lastIndexOf('on', 0) === -1) {
|
||||||
|
attr_text = attr_text + ' ' + attrname + '="' + escape(attrib[attrname]) + '"';
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -444,9 +464,9 @@ var twemoji = (function (
|
|||||||
// when variants should be copied and pasted too
|
// when variants should be copied and pasted too
|
||||||
'alt="',
|
'alt="',
|
||||||
match,
|
match,
|
||||||
'" ',
|
'"',
|
||||||
attr_text,
|
attr_text,
|
||||||
'src="',
|
' src="',
|
||||||
src,
|
src,
|
||||||
'"',
|
'"',
|
||||||
'>'
|
'>'
|
||||||
|
Loading…
Reference in New Issue
Block a user