Skip to content

Commit

Permalink
Merge pull request #3501 from easyops-cn/steve/v3-compress-shared-exa…
Browse files Browse the repository at this point in the history
…mple

fix(playground): compress shared example
  • Loading branch information
qiaofengxi authored Sep 21, 2023
2 parents 5cd16e2 + 177c539 commit 6085788
Showing 1 changed file with 61 additions and 28 deletions.
89 changes: 61 additions & 28 deletions packages/brick-playground/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,8 @@ registerTypeScript(monaco);
registerYaml(monaco);
registerHtml(monaco);

const GZIP_HASH_PREFIX = "#gzip,";

interface Example extends Sources {
key: string;
mode: "html" | "yaml";
Expand Down Expand Up @@ -179,9 +181,23 @@ async function main() {
if (matchedExample) {
initEditorsWith(matchedExample);
} else if (codeFromHash) {
let decompressedExampleString: string | undefined;
if (location.hash.startsWith(GZIP_HASH_PREFIX)) {
try {
decompressedExampleString = await decompress(
location.hash.substring(GZIP_HASH_PREFIX.length)
);
} catch (e) {
// eslint-disable-next-line no-console
console.error("Decompress shared example failed:", e);
}
}

let pastedSources: Example;
try {
pastedSources = JSON.parse(b64DecodeUnicode(location.hash.slice(1)));
pastedSources = JSON.parse(
decompressedExampleString ?? b64DecodeUnicode(location.hash.slice(1))
);
} catch (error) {
// eslint-disable-next-line no-console
console.error("Parse pasted sources failed:", error);
Expand Down Expand Up @@ -238,6 +254,9 @@ async function main() {
previewWin = iframe.contentWindow as unknown as PreviewWindow;
resolve();
});
iframe.addEventListener("error", (reason) => {
reject(reason);
});
});

iframe.src = "./preview/";
Expand Down Expand Up @@ -283,46 +302,60 @@ async function main() {
const shareButton = document.querySelector("#brick-playground-button-share");
const shareResult = document.querySelector("#brick-playground-share-result");
let shareButtonResetTimeout = -1;
shareButton.addEventListener("click", () => {
shareButton.addEventListener("click", async () => {
if (shareButtonResetTimeout !== -1) {
shareResult.textContent = "";
clearTimeout(shareButtonResetTimeout);
}
history.replaceState(
null,
"",
`?mode=${mode}#${b64EncodeUnicode(
JSON.stringify({ [mode]: sources[mode] })
)}`
);
const result = copy(location.href);
shareResult.textContent = result ? "URL copied" : "Failed to copy URL";
let ok = false;
try {
history.replaceState(
null,
"",
`?mode=${mode}${GZIP_HASH_PREFIX}${await compress(
JSON.stringify({ [mode]: sources[mode] })
)}`
);
ok = copy(location.href);
} catch (e) {
// eslint-disable-next-line no-console
console.error("Compress shared example failed:", e);
}
shareResult.textContent = ok ? "URL copied" : "Failed to copy URL";
shareButtonResetTimeout = setTimeout(() => {
shareButtonResetTimeout = -1;
shareResult.textContent = "";
}, 2000) as unknown as number;
});
}

function b64EncodeUnicode(str: string) {
// first we use encodeURIComponent to get percent-encoded UTF-8,
// then we convert the percent encodings into raw bytes which
// can be fed into btoa.
return btoa(
encodeURIComponent(str).replace(/%([0-9A-F]{2})/g, function (match, p1) {
return String.fromCharCode(parseInt(p1, 16));
})
);
function base64ToBytes(base64: string): Uint8Array {
const binString = atob(base64);
return Uint8Array.from(binString, (m) => m.codePointAt(0));
}

function b64DecodeUnicode(str: string) {
return decodeURIComponent(
[...atob(str)]
.map(function (c) {
return "%" + ("00" + c.charCodeAt(0).toString(16)).slice(-2);
})
.join("")
);
function bytesToBase64(bytes: Uint8Array): string {
const binString = Array.from(bytes, (x) => String.fromCodePoint(x)).join("");
return btoa(binString);
}

async function compress(str: string) {
const blob = new Blob([str], { type: "text/plain" });
const stream = blob.stream().pipeThrough(new CompressionStream("gzip"));
const compressedBlob = await new Response(stream).blob();
return bytesToBase64(new Uint8Array(await compressedBlob.arrayBuffer()));
}

async function decompress(str: string) {
const bytes = base64ToBytes(str);
const blob = new Blob([bytes], { type: "text/plain" });
const stream = blob.stream().pipeThrough(new DecompressionStream("gzip"));
const decompressedBlob = await new Response(stream).blob();
return decompressedBlob.text();
}

function b64DecodeUnicode(str: string): string {
return new TextDecoder().decode(base64ToBytes(str));
}

function decorateAltCode(code: string, mode: string, altMode: string): string {
Expand Down

0 comments on commit 6085788

Please sign in to comment.