mirror of
https://github.com/twitter/twemoji.git
synced 2025-03-28 19:20:28 +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
|
||||
);
|
||||
}
|
||||
},{
|
||||
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',
|
||||
test: function () {
|
||||
|
@ -527,6 +527,24 @@ function createTwemoji(re) {
|
||||
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
|
||||
* based on Twitter CDN
|
||||
@ -642,13 +660,15 @@ function createTwemoji(re) {
|
||||
img.onerror = twemoji.onerror;
|
||||
img.className = options.className;
|
||||
img.setAttribute('draggable', 'false');
|
||||
var attrib = options.attributes;
|
||||
if (typeof(attrib) === 'function') {
|
||||
attrib = attrib(alt);
|
||||
}
|
||||
if (attrib) {
|
||||
for (var attrname in attrib) {
|
||||
img.setAttribute(attrname) = attrib[attrname];
|
||||
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||
var attrib = options.attributes(alt);
|
||||
if (attrib) {
|
||||
for (var attrname in attrib) {
|
||||
// don't allow any handlers to be set
|
||||
if (attrname.lastIndexOf('on', 0) === -1) {
|
||||
img.setAttribute(attrname, attrib[attrname]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
img.alt = alt;
|
||||
@ -703,14 +723,16 @@ function createTwemoji(re) {
|
||||
if (src) {
|
||||
// recycle the match string replacing the emoji
|
||||
// with its image counter part
|
||||
var attrib = options.attributes;
|
||||
if (typeof(attrib) === 'function') {
|
||||
attrib = attrib(match);
|
||||
}
|
||||
var attr_text = '';
|
||||
if (attrib) {
|
||||
for (var attrname in attrib) {
|
||||
attr_text = attr_text + ' ' + attrname + '="' + attrib[attrname].replace(/"/g, '"') + '"';
|
||||
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||
var attrib = options.attributes(match);
|
||||
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
|
||||
'alt="',
|
||||
match,
|
||||
'" ',
|
||||
'"',
|
||||
attr_text,
|
||||
'src="',
|
||||
' src="',
|
||||
src,
|
||||
'"',
|
||||
'>'
|
||||
|
@ -250,6 +250,24 @@ define(function () {
|
||||
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
|
||||
* based on Twitter CDN
|
||||
@ -365,13 +383,14 @@ define(function () {
|
||||
img.onerror = twemoji.onerror;
|
||||
img.className = options.className;
|
||||
img.setAttribute('draggable', 'false');
|
||||
var attrib = options.attributes;
|
||||
if (typeof(attrib) === 'function') {
|
||||
attrib = attrib(alt);
|
||||
}
|
||||
if (attrib) {
|
||||
for (var attrname in attrib) {
|
||||
img.setAttribute(attrname) = attrib[attrname];
|
||||
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||
var attrib = options.attributes(alt);
|
||||
if (attrib) {
|
||||
for (var attrname in attrib) {
|
||||
if (attrname.lastIndexOf('on', 0) === -1) {
|
||||
img.setAttribute(attrname, attrib[attrname]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
img.alt = alt;
|
||||
@ -426,14 +445,15 @@ define(function () {
|
||||
if (src) {
|
||||
// recycle the match string replacing the emoji
|
||||
// with its image counter part
|
||||
var attrib = options.attributes;
|
||||
if (typeof(attrib) === 'function') {
|
||||
attrib = attrib(match);
|
||||
}
|
||||
var attr_text = '';
|
||||
if (attrib) {
|
||||
for (var attrname in attrib) {
|
||||
attr_text = attr_text + ' ' + attrname + '="' + attrib[attrname].replace(/"/g, '"') + '"';
|
||||
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||
var attrib = options.attributes(match);
|
||||
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
|
||||
'alt="',
|
||||
match,
|
||||
'" ',
|
||||
'"',
|
||||
attr_text,
|
||||
'src="',
|
||||
' src="',
|
||||
src,
|
||||
'"',
|
||||
'>'
|
||||
|
52
twemoji.js
52
twemoji.js
@ -249,6 +249,24 @@ var twemoji = (function (
|
||||
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
|
||||
* based on Twitter CDN
|
||||
@ -364,13 +382,14 @@ var twemoji = (function (
|
||||
img.onerror = twemoji.onerror;
|
||||
img.className = options.className;
|
||||
img.setAttribute('draggable', 'false');
|
||||
var attrib = options.attributes;
|
||||
if (typeof(attrib) === 'function') {
|
||||
attrib = attrib(alt);
|
||||
}
|
||||
if (attrib) {
|
||||
for (var attrname in attrib) {
|
||||
img.setAttribute(attrname) = attrib[attrname];
|
||||
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||
var attrib = options.attributes(alt);
|
||||
if (attrib) {
|
||||
for (var attrname in attrib) {
|
||||
if (attrname.lastIndexOf('on', 0) === -1) {
|
||||
img.setAttribute(attrname, attrib[attrname]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
img.alt = alt;
|
||||
@ -425,14 +444,15 @@ var twemoji = (function (
|
||||
if (src) {
|
||||
// recycle the match string replacing the emoji
|
||||
// with its image counter part
|
||||
var attrib = options.attributes;
|
||||
if (typeof(attrib) === 'function') {
|
||||
attrib = attrib(match);
|
||||
}
|
||||
var attr_text = '';
|
||||
if (attrib) {
|
||||
for (var attrname in attrib) {
|
||||
attr_text = attr_text + ' ' + attrname + '="' + attrib[attrname].replace(/"/g, '"') + '"';
|
||||
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||
var attrib = options.attributes(match);
|
||||
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
|
||||
'alt="',
|
||||
match,
|
||||
'" ',
|
||||
'"',
|
||||
attr_text,
|
||||
'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);
|
||||
}
|
||||
|
||||
/**
|
||||
* 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
|
||||
* based on Twitter CDN
|
||||
@ -365,13 +383,14 @@ var twemoji = (function (
|
||||
img.onerror = twemoji.onerror;
|
||||
img.className = options.className;
|
||||
img.setAttribute('draggable', 'false');
|
||||
var attrib = options.attributes;
|
||||
if (typeof(attrib) === 'function') {
|
||||
attrib = attrib(alt);
|
||||
}
|
||||
if (attrib) {
|
||||
for (var attrname in attrib) {
|
||||
img.setAttribute(attrname) = attrib[attrname];
|
||||
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||
var attrib = options.attributes(alt);
|
||||
if (attrib) {
|
||||
for (var attrname in attrib) {
|
||||
if (attrname.lastIndexOf('on', 0) === -1) {
|
||||
img.setAttribute(attrname, attrib[attrname]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
img.alt = alt;
|
||||
@ -426,14 +445,15 @@ var twemoji = (function (
|
||||
if (src) {
|
||||
// recycle the match string replacing the emoji
|
||||
// with its image counter part
|
||||
var attrib = options.attributes;
|
||||
if (typeof(attrib) === 'function') {
|
||||
attrib = attrib(match);
|
||||
}
|
||||
var attr_text = '';
|
||||
if (attrib) {
|
||||
for (var attrname in attrib) {
|
||||
attr_text = attr_text + ' ' + attrname + '="' + attrib[attrname].replace(/"/g, '"') + '"';
|
||||
if (options.attributes && typeof(options.attributes) === 'function') {
|
||||
var attrib = options.attributes(match);
|
||||
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
|
||||
'alt="',
|
||||
match,
|
||||
'" ',
|
||||
'"',
|
||||
attr_text,
|
||||
'src="',
|
||||
' src="',
|
||||
src,
|
||||
'"',
|
||||
'>'
|
||||
|
Loading…
x
Reference in New Issue
Block a user