Skip to content

Commit

Permalink
fix(playground): support sharing unicode input (#37)
Browse files Browse the repository at this point in the history
closes #34

This PR updates the base64 encode/decode logic to be done in utf8,
previously it was going straight to `btoa` which only supports ASCII.
This also means that existing links created will be forwards compatible
with the new decoding.

**Testing performed**

`cd website; npm start`

Creating playgrounds with unicode input were sharable. I also took an
existing url from the currently deployed playground and checked that the
new logic is backwards compatible with existing links.

Signed-off-by: Ashley Claymore <[email protected]>
  • Loading branch information
acutmore authored Feb 4, 2025
1 parent 7e13ea9 commit 4a377e2
Showing 1 changed file with 14 additions and 6 deletions.
20 changes: 14 additions & 6 deletions website/play/play.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,10 +47,7 @@ export class C<T> extends Array<T> implements HasField {
};
}
try {
let b64 = urlData.slice(1);
b64 += Array(((4 - (b64.length % 4)) % 4) + 1).join("=");
b64 = b64.replace(/\-/g, "+").replace(/\_/g, "/");
return JSON.parse(atob(b64));
return JSON.parse(utf8base64ToText(urlData.slice(1)));
} catch (_e) {
console.error(_e);
return {
Expand All @@ -65,14 +62,25 @@ function saveURL() {
const text = tsModel.getValue();
const tsx = tsxConfig.enabled;
try {
let encoded = `${btoa(JSON.stringify({ tsx, text } satisfies URLData))}`;
encoded = encoded.replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
const encoded = textToUtf8base64(JSON.stringify({ tsx, text }));
window.history.replaceState(null, "", "#" + encoded);
} catch (err) {
console.error(err);
}
}

function utf8base64ToText(base64: string): string {
base64 += Array(((4 - (base64.length % 4)) % 4) + 1).join("=");
base64 = base64.replace(/\-/g, "+").replace(/\_/g, "/");
return new TextDecoder().decode(Uint8Array.from(atob(base64), (m) => m.codePointAt(0)!));
}

function textToUtf8base64(text: string): string {
const bytes = new TextEncoder().encode(text);
const binString = Array.from(bytes, (byte) => String.fromCodePoint(byte)).join("");
return btoa(binString).replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
}

const tsxConfig = selectBooleanWrapper("lang-select", "tsx", "ts");
const ghostCheckBox = document.getElementById("ghost-check") as HTMLInputElement;

Expand Down

0 comments on commit 4a377e2

Please sign in to comment.