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>