|
3 | 3 | const urlInput = document.querySelector("#url"); |
4 | 4 | const baseInput = document.querySelector("#base"); |
5 | 5 |
|
| 6 | + const te = new TextEncoder(); |
| 7 | + const td = new TextDecoder(); |
| 8 | + |
6 | 9 | // Use an iframe to avoid <base> affecting the main page. This is especially bad in Edge where it |
7 | 10 | // appears to break Edge's DevTools. |
8 | 11 | const browserIframeDocument = document.querySelector("#browser-iframe").contentDocument; |
|
103 | 106 | } |
104 | 107 |
|
105 | 108 | function updateFragmentForSharing() { |
106 | | - location.hash = `url=${btoa(urlInput.value)}&base=${btoa(baseInput.value)}`; |
| 109 | + location.hash = `url=${encodeToBase64(urlInput.value)}&base=${encodeToBase64(baseInput.value)}`; |
107 | 110 | } |
108 | 111 |
|
109 | 112 | function setFromFragment() { |
|
113 | 116 | } |
114 | 117 | const [, urlEncoded, baseEncoded] = pieces; |
115 | 118 | try { |
116 | | - urlInput.value = atob(urlEncoded); |
| 119 | + urlInput.value = decodeFromBase64(urlEncoded); |
117 | 120 | } catch (e) { |
118 | 121 | // eslint-disable-next-line no-console |
119 | | - console.warn("url hash parameter was not decodeable as forgiving base64."); |
| 122 | + console.warn("url hash parameter was not deserializable."); |
120 | 123 | } |
121 | 124 |
|
122 | 125 | try { |
123 | | - baseInput.value = atob(baseEncoded); |
| 126 | + baseInput.value = decodeFromBase64(baseEncoded); |
124 | 127 | } catch (e) { |
125 | 128 | // eslint-disable-next-line no-console |
126 | | - console.warn("base hash parameter was not decodeable as forgiving base64."); |
| 129 | + console.warn("base hash parameter was not deserializable."); |
127 | 130 | } |
128 | 131 |
|
129 | 132 | update(); |
130 | 133 | } |
| 134 | + |
| 135 | + // btoa / atob don't work on Unicode. |
| 136 | + // This version is a superset of btoa / atob, so it maintains compatibility with older versions of |
| 137 | + // the live viewer which used btoa / atob directly. |
| 138 | + function encodeToBase64(originalString) { |
| 139 | + const bytes = te.encode(originalString); |
| 140 | + const byteString = Array.from(bytes, byte => String.fromCharCode(byte)).join(""); |
| 141 | + const encoded = btoa(byteString); |
| 142 | + return encoded; |
| 143 | + } |
| 144 | + |
| 145 | + function decodeFromBase64(encoded) { |
| 146 | + const byteString = atob(encoded); |
| 147 | + const bytes = Uint8Array.from(byteString, char => char.charCodeAt(0)); |
| 148 | + const originalString = td.decode(bytes); |
| 149 | + return originalString; |
| 150 | + } |
131 | 151 | })(); |
0 commit comments