Created
November 29, 2022 18:28
-
-
Save DarrenSem/c9314f9442fa7ce78a39c7305e79ea8c to your computer and use it in GitHub Desktop.
htmlDecode.js htmlEncode.js - using modern browsers' built-in DOM manipulation (plus common escaping for htmlEncode)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// htmlDecode.js htmlEncode.js - using modern browsers' built-in DOM manipulation (plus common escaping for htmlEncode) | |
// let htmlDecode=a=>Object.assign(document.createElement("textarea"),{innerHTML:null==a?"":a.replace(/<\s*br\s*\/?\s*>/gi,"\n")}).value; | |
let htmlDecode = html => Object.assign( | |
document.createElement("textarea"), { | |
innerHTML: html == null ? "" : html.replace(/<\s*br\s*\/?\s*>/gi, "\n") | |
} | |
).value; | |
// let htmlEncode=a=>Object.assign(document.createElement("div"),{innerText:null==a?"":a}).innerHTML.replace(/<br>/g,"\n").replace(/['"\t\f\r\n\u00A0-\u2666]/g,a=>({"'":"'",'"':"""})[a]||`&#${a.charCodeAt(0)};`); | |
let htmlEncode = string => Object.assign( | |
document.createElement("div"), { | |
innerText: string == null ? "" : string | |
} | |
).innerHTML.replace(/<br>/g, "\n").replace( | |
/['"\t\f\r\n\u00A0-\u2666]/g, | |
// \u00A0-\u2666 based on https://stackoverflow.com/questions/1354064/how-to-convert-characters-to-html-entities-using-plain-javascript/1354715#1354715 ("will not properly handle Unicode characters >= U+10000 -- UTF-16 pairs") | |
// cf. http://www.w3.org/TR/html4/sgml/entities.html | |
match => ({ | |
"'": "'", | |
'"': """, | |
}[match] || `&#${match.charCodeAt(0)};`) | |
); | |
console.clear(); | |
// let assert=(...t)=>!!t.reduce((p,f,i,a,m=Array.isArray(f)?f:[f])=>("function"==typeof m[0]?m[0]():m[0])?p:console.assert(0,...m),t.length) | |
let assert = (...tests) => !!tests.reduce( | |
(pass, func, i, ar, messages = Array.isArray(func) ? func : [func]) => ( | |
typeof messages[0] === "function" ? messages[0]() : messages[0] | |
) ? pass : console.assert(0, ...messages) | |
, tests.length | |
); | |
// test via https://stackoverflow.com/questions/7394748/whats-the-right-way-to-decode-a-string-that-has-special-html-entities-in-it/36138117#36138117 | |
assert( | |
() => htmlEncode(`<img src onerror="alert('0','')">`) === '<img src onerror="alert('0','')">', | |
() => htmlDecode('<img src onerror="alert('0','')">') === `<img src onerror="alert('0','')">`, | |
() => htmlDecode(htmlEncode(`<img src onerror="alert('0','')">`)) === `<img src onerror="alert('0','')">`, | |
[() => htmlEncode(`< \xa0'&">`) === `< '&">`, {actual: htmlEncode(`< \xa0'&">`), expected: '< '&">'}], | |
[() => htmlDecode(htmlEncode(`< \xa0'&">`)) === `< \xa0'&">`, {actual: htmlDecode(htmlEncode(`< \xa0'&">`)), expected: `< \xa0'&">`}], | |
[() => htmlEncode(htmlDecode(`< '&">`)) === `< '&">`, {actual: htmlEncode(htmlDecode(`< '&">`)), expected: `< '&">`}], | |
); | |
// test via https://stackoverflow.com/questions/1354064/how-to-convert-characters-to-html-entities-using-plain-javascript | |
assert( | |
[() => htmlDecode("<Übergroße Äpfel mit Würmern>") === "<Übergroße Äpfel mit Würmern>", {actual: htmlDecode("<Übergroße Äpfel mit Würmern>")}], | |
[() => htmlEncode("<Übergroße Äpfel mit Würmern>") === '<Übergroße Äpfel mit Würmern>', {actual: htmlEncode("<Übergroße Äpfel mit Würmern>")}], | |
[() => htmlDecode(htmlEncode("<Übergroße Äpfel mit Würmern>")) === "<Übergroße Äpfel mit Würmern>", {actual: htmlDecode(htmlEncode("<Übergroße Äpfel mit Würmern>"))}], | |
[() => htmlEncode(htmlDecode("<Übergroße Äpfel mit Würmern>")) === '<Übergroße Äpfel mit Würmern>', {actual: htmlEncode(htmlDecode("<Übergroße Äpfel mit Würmern>"))}], | |
); | |
// test via https://stackoverflow.com/questions/7394748/whats-the-right-way-to-decode-a-string-that-has-special-html-entities-in-it/29824550#29824550 | |
let html1 = `	<""&' 高级程序设计 '&">`; | |
let string = `\t\f<""&' 高级程序设计 '&">`; // `<"&' advanced programming '&">` | |
let html2 = "<br>\t\f<""&'   高级程序设计  '&">"; | |
assert( | |
[() => htmlDecode(html1) === string, {"htmlDecode(html1)": htmlDecode(html1), expected: string}], | |
[() => htmlEncode(string) === html1, {"htmlEncode(string)": htmlEncode(string), expected: html1}], | |
[() => htmlDecode(html2) === "\n" + string, {"htmlDecode(html2)": htmlDecode(html2), expected: "\n" + string}], | |
[() => htmlDecode() === "", {"htmlDecode()": htmlDecode()}, ""], | |
[() => htmlEncode() === "", {"htmlEncode()": htmlEncode()}, ""], | |
[() => htmlDecode(null) === "", {"htmlDecode(null)": htmlDecode(null)}, ""], | |
[() => htmlEncode(null) === "", {"htmlEncode(null)": htmlEncode(null)}, ""], | |
[() => htmlDecode('foo\uD800bara&b123;+©>⃒<⃒
fja') | |
=== 'foo\ud800bara&b123;+©>\u20D2<\u20D2\nfja'], | |
); | |
// test via https://stackoverflow.com/questions/1354064/how-to-convert-characters-to-html-entities-using-plain-javascript/42437350#42437350 | |
assert( | |
() => htmlDecode('foo ©©© bar ≠≠≠ baz 𝌆𝌆 qux') === 'foo ©©© bar ≠≠≠ baz 𝌆𝌆 qux', | |
() => htmlEncode('foo ©©© bar ≠≠≠ baz 𝌆𝌆 qux') === 'foo ©©© bar ≠≠≠ baz 𝌆𝌆 qux', | |
[() => htmlEncode('foo ©©© bar ≠≠≠ baz 𝌆𝌆 qux') === htmlEncode(htmlDecode('foo ©©© bar ≠≠≠ baz 𝌆𝌆 qux'))], | |
[() => htmlDecode('foo ©©© bar ≠≠≠ baz 𝌆𝌆 qux') === htmlDecode(htmlEncode('foo ©©© bar ≠≠≠ baz 𝌆𝌆 qux'))], | |
[() => htmlEncode(`&<>\\&'""'\u2646\u2656\u2666`) === '&amp;<>\\&'""'♆♖♦', {actual: htmlEncode(`&<>\\&'""'\u2646\u2656\u2666`)}], | |
); | |
// test via https://sanzon.wordpress.com/2008/05/01/neat-little-html-encoding-trick-in-javascript/#comment-244 | |
assert( | |
[() => htmlEncode(`"\'\`a->\t\n\n\n\t<-b\`\'"`) === '"'`a->	 	<-b`'"', {actual: htmlEncode(`"'\`a->\t\n\n\n\t<-b\`'"`)}], | |
[() => htmlDecode('"'`a->\t<br>\n< Br / >	<-b`'"') === `"\'\`a->\t\n\n\n\t<-b\`\'"`, {actual: htmlDecode('"'`a->\t<br>\n< Br / >	<-b`'"')}], | |
[() => htmlEncode('"\'\`a->\t<br>\t<-b\`\'"') === '"'`a->	<br>	<-b`'"', {actual: htmlEncode('"\'\`a->\t<br>\t<-b\`\'"')}], | |
[() => htmlDecode(htmlEncode('"\'\`a->\t<br>\t<-b\`\'"')) === '"\'\`a->\t<br>\t<-b\`\'"', {actual: htmlDecode(htmlEncode('"\'\`a->\t<br>\t<-b\`\'"'))}], | |
[() => htmlEncode(htmlDecode('"'`a->	<br>	<-b`'"')) === '"'`a->	<br>	<-b`'"', {actual: htmlEncode(htmlDecode('"'`a->	<br>	<-b`'"'))}], | |
); | |
// OTHER tests (lots!) https://github.com/mathiasbynens/he/tree/master/tests | |
// ^ MISTAKES that "he.js" claims to avoid: https://stackoverflow.com/questions/1354064/how-to-convert-characters-to-html-entities-using-plain-javascript/23831239#23831239 | |
assert( | |
() => htmlDecode('≼') === '≼', | |
() => htmlDecode('𝌆𝌆') === '𝌆'.repeat(2), | |
() => htmlDecode('팆') === '팆', | |
() => htmlDecode('€€') === '€'.repeat(2), | |
() => htmlDecode('&amp;gt;') === '&gt;', | |
() => htmlDecode('<img src='x' onerror="prompt(1)"><script>alert(1)</script><img src="x` `<script>alert(1)</script>"` `>') | |
=== '<img src=\'x\' onerror="prompt(1)"><script>alert(1)</script><img src="x` `<script>alert(1)</script>"` `>', | |
() => htmlDecode('aΖba​baζb') === 'a\u0396ba\u200Bba\u03B6b', | |
() => htmlDecode('a𝓏ba‍ba‌b') === 'a\uD835\uDCCFba\u200Dba\u200Cb', | |
() => htmlDecode('a&foololthisdoesntexist;b') === 'a&foololthisdoesntexist;b', | |
() => htmlDecode('foo &lolwat; bar') === 'foo &lolwat; bar', | |
() => htmlDecode('∉ ¬i ¬in ©123') === '\u2209 \xACi \xACin \xA9123', | |
() => htmlDecode('&xxx; &xxx &thorn; &thorn &curren;t &current') === '&xxx; &xxx þ þ ¤t ¤t', | |
() => htmlDecode('&xxx; &xxx &thorn; &thorn &curren;t &current') === '&xxx; &xxx þ þ ¤t ¤t', | |
() => htmlDecode('a𝌆b𝌆c') === 'a\uD834\uDF06b\uD834\uDF06c', | |
() => htmlDecode('a𝌆b©c©d') === 'a\uD834\uDF06b\xA9c\xA9d', | |
() => htmlDecode('a��b��c a�b�c') === 'a\uFFFD\uFFFDb\uFFFD\uFFFDc a\uFFFDb\uFFFDc', | |
() => htmlDecode(''"'&amp;amp;&amp;a�b'') === `'"'&amp;&a\uFFFDb'`, | |
() => htmlDecode('𯿽€�') === '\uDBFF\uDFFF\uD87F\uDFFD\u20AC\uFFFD', | |
[() => htmlEncode('<img src=\'x\' onerror="prompt(1)"><script>alert(1)</script><img src="x` `<script>alert(1)</script>"` `>') | |
=== '<img src='x' onerror="prompt(1)"><script>alert(1)</script><img src="x` `<script>alert(1)</script>"` `>'], | |
); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment