Skip to content

Commit ad8f950

Browse files
committed
Fix live URL viewer to support Unicode in URLs
Previously, they would work, but inputting them would not update the current URL of the viewer, so the results were not shareable.
1 parent a7ca3ca commit ad8f950

File tree

1 file changed

+25
-5
lines changed

1 file changed

+25
-5
lines changed

live-viewer/live-viewer.js

Lines changed: 25 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,9 @@
33
const urlInput = document.querySelector("#url");
44
const baseInput = document.querySelector("#base");
55

6+
const te = new TextEncoder();
7+
const td = new TextDecoder();
8+
69
// Use an iframe to avoid <base> affecting the main page. This is especially bad in Edge where it
710
// appears to break Edge's DevTools.
811
const browserIframeDocument = document.querySelector("#browser-iframe").contentDocument;
@@ -103,7 +106,7 @@
103106
}
104107

105108
function updateFragmentForSharing() {
106-
location.hash = `url=${btoa(urlInput.value)}&base=${btoa(baseInput.value)}`;
109+
location.hash = `url=${encodeToBase64(urlInput.value)}&base=${encodeToBase64(baseInput.value)}`;
107110
}
108111

109112
function setFromFragment() {
@@ -113,19 +116,36 @@
113116
}
114117
const [, urlEncoded, baseEncoded] = pieces;
115118
try {
116-
urlInput.value = atob(urlEncoded);
119+
urlInput.value = decodeFromBase64(urlEncoded);
117120
} catch (e) {
118121
// 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.");
120123
}
121124

122125
try {
123-
baseInput.value = atob(baseEncoded);
126+
baseInput.value = decodeFromBase64(baseEncoded);
124127
} catch (e) {
125128
// 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.");
127130
}
128131

129132
update();
130133
}
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+
}
131151
})();

0 commit comments

Comments
 (0)