github.com/evanw/esbuild@v0.21.4/scripts/dataurl-escapes.html (about) 1 <!DOCTYPE html> 2 <p> 3 This script checks to see what characters need to be escaped in a data URL 4 (in addition to % for percent-encoded hexadecimal escapes) for a browser to 5 parse it correctly. This information is used to implement esbuild's 6 <code>dataurl</code> loader. Here is what your current browser requires: 7 </p> 8 <pre id="result"></pre> 9 <p> 10 The answer that works across Chrome, Firefox, and Safari appears to be: 11 <br> 12 <br>Always percent-encode these values: <code>0x09, 0x0A, 0x0D, 0x23</code> 13 <br>Only percent-encode these values in the trailing position: <code>0x00 to 0x08, 0x0B, 0x0C, 0x0E to 0x20</code> 14 </p> 15 <script> 16 17 function percentEncode(i) { 18 if (i >= 0x80) return encodeURIComponent(String.fromCharCode(i)) 19 return '%' + (0x100 | i).toString(16).slice(-2) 20 } 21 22 async function urlDoesDecodeTo(url, to) { 23 return to === await fetch(url).then(r => r.text()) 24 } 25 26 async function check() { 27 const shouldEncode = [] 28 29 for (let i = 0; i <= 0xFF; i++) { 30 const ch = String.fromCharCode(i) 31 const chPercent = percentEncode(i) 32 33 if (!await urlDoesDecodeTo('data:text/plain,' + chPercent, ch)) { 34 throw new Error('Assertion failed: Cannot decode ' + chPercent) 35 } 36 37 const leading = await urlDoesDecodeTo('data:text/plain,' + ch + 'foo', ch + 'foo') 38 const trailing = await urlDoesDecodeTo('data:text/plain,foo' + ch, 'foo' + ch) 39 const embedded = await urlDoesDecodeTo('data:text/plain,foo' + ch + 'foo', 'foo' + ch + 'foo') 40 41 if (!leading && !trailing && !embedded) { 42 shouldEncode.push('U+' + i.toString(16) + ' (' + ch + ')') 43 } else { 44 if (!leading) shouldEncode.push('U+' + i.toString(16) + ' (' + ch + ') leading') 45 if (!trailing) shouldEncode.push('U+' + i.toString(16) + ' (' + ch + ') trailing') 46 if (!embedded) shouldEncode.push('U+' + i.toString(16) + ' (' + ch + ') embedded') 47 } 48 } 49 50 document.getElementById('result').textContent = 'shouldEncode = ' + JSON.stringify(shouldEncode, null, 2) 51 } 52 53 check() 54 55 </script>