@@ -242,12 +242,62 @@ let boilerplateSrc;
242242if ( boilerplate ) {
243243 boilerplateSrc = await fetch ( boilerplate ) . then ( ( p ) => p . text ( ) ) ;
244244}
245- let src = urlParams . get ( 'src' ) ;
245+
246+ function base64ToBytes ( b64 ) {
247+ const bin = atob ( b64 ) ;
248+ return Uint8Array . from ( bin , c => c . charCodeAt ( 0 ) ) ;
249+ }
250+
251+ function base64ToUtf8 ( b64 ) {
252+ const bytes = base64ToBytes ( b64 ) ;
253+ return new TextDecoder ( ) . decode ( bytes ) ;
254+ }
255+
256+ function bytesToBase64 ( bytes ) {
257+ let binary = '' ;
258+ const len = bytes . length ;
259+ for ( let i = 0 ; i < len ; i ++ ) binary += String . fromCharCode ( bytes [ i ] ) ;
260+ return btoa ( binary ) ;
261+ }
262+
263+ async function gzipUtf8ToBytes ( str ) {
264+ const encoder = new TextEncoder ( ) ;
265+ const data = encoder . encode ( str ) ;
266+ const cs = new CompressionStream ( 'gzip' ) ;
267+ const compressedStream = new Response ( data ) . body . pipeThrough ( cs ) ;
268+ const compressedArrayBuffer = await new Response ( compressedStream ) . arrayBuffer ( ) ;
269+ return new Uint8Array ( compressedArrayBuffer ) ;
270+ }
271+
272+ async function gunzipBytesToUtf8 ( uint8arr ) {
273+ const ds = new DecompressionStream ( 'gzip' ) ;
274+ const decompressedStream = new Blob ( [ uint8arr ] ) . stream ( ) . pipeThrough ( ds ) ;
275+ const decompressedArrayBuffer = await new Response ( decompressedStream ) . arrayBuffer ( ) ;
276+ return new TextDecoder ( ) . decode ( decompressedArrayBuffer ) ;
277+ }
278+
279+ async function zipCode ( code ) {
280+ const zippedBytes = await gzipUtf8ToBytes ( code ) ;
281+ const base64 = bytesToBase64 ( zippedBytes ) ;
282+ return 'gzip:' + base64 ;
283+ }
284+
285+ let src = urlParams . get ( 'src' ) , isGzip = false ;
286+
246287if ( src ) {
247288 if ( / h t t p ( s ) ? : \/ \/ .* / . test ( src ) ) {
248289 src = await fetch ( src ) . then ( ( p ) => p . text ( ) ) ;
249290 } else {
250- src = atob ( src ) ;
291+ if ( src . startsWith ( 'gzip:' ) ) {
292+ isGzip = true ;
293+ src = src . substring ( 5 ) ;
294+ }
295+ if ( isGzip ) {
296+ const bytes = base64ToBytes ( src ) ;
297+ src = await gunzipBytesToUtf8 ( bytes ) ;
298+ } else {
299+ src = base64ToUtf8 ( src ) ;
300+ }
251301 }
252302 doc = src ;
253303} else {
@@ -279,35 +329,36 @@ window.compile = () => {
279329 code = ( boilerplateSrc || '' ) + '\n\n' + code ;
280330 evalCode ( code ) ;
281331} ;
282- window . share = ( ) => {
283- let code = editor . state . doc . toString ( ) . trim ( ) ;
284- code = btoa ( code ) ;
285- url . searchParams . set ( 'src' , code ) ;
332+
333+ window . share = async ( ) => {
334+ const code = editor . state . doc . toString ( ) . trim ( ) ;
335+ const src = await zipCode ( code ) ;
336+ url . searchParams . set ( 'src' , src ) ;
286337 window . location = url ;
287338} ;
288- window . blankAOC = ( ) => {
289- const code = btoa ( aocDoc ) ;
339+ window . blankAOC = async ( ) => {
340+ const code = await zipCode ( aocDoc ) ;
290341 const url = new URL ( window . location ) ;
291342 url . searchParams . set ( 'src' , code ) ;
292343 url . searchParams . set ( 'boilerplate' , aocBoilerplateUrl ) ;
293344 url . searchParams . set ( 'repl' , true ) ;
294345
295346 window . location = url ;
296- }
347+ } ;
297348
298349window . changeREPL = ( target ) => {
299350 document . getElementById ( 'result' ) . innerText = '' ;
300351 if ( target . checked ) {
301352 repl = true ;
302- compile ( ) ;
353+ window . compile ( ) ;
303354 } else {
304355 repl = false ;
305- compile ( ) ;
356+ window . compile ( ) ;
306357 }
307358 url . searchParams . set ( 'repl' , repl ) ;
308359 window . history . replaceState ( null , null , url ) ;
309360} ;
310361if ( repl ) {
311362 document . getElementById ( 'replCheckBox' ) . checked = true ;
312363}
313- compile ( ) ;
364+ window . compile ( ) ;
0 commit comments