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