itty-bitty/docs/index.min.html
2022-10-19 21:47:36 -07:00

24 lines
29 KiB
HTML
Raw Permalink Blame History

This file contains invisible Unicode characters

This file contains invisible Unicode characters that are indistinguishable to humans but may be processed differently by a computer. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<meta name="viewport" content="width=device-width, viewport-fit=cover">
<meta name="description" content="itty bitty things can be conveyed in a link.">
<link id="favicon" rel="icon" href="/favicon.svg">
<style>body{font-family:sans-serif}@media(prefers-color-scheme:dark){body{color:white;background-color:#121212}}#iframe{border:0;position:absolute;top:0;left:0;width:100%;height:100%}#edit{font-family:monospace;font-weight:bold;color:rgba(0,0,0,0.54);position:absolute;z-index:100;position:absolute;top:.85em;right:1em;display:none}#edit:not(:hover){text-decoration:none}#warning{position:absolute;border-radius:4px;background-color:#feecc2;padding:1em;font-size:16px;width:20em;z-index:100;top:10vh;left:50vw;margin-left:-10em}#warning:empty{display:none}body.toasting #iframe,body.toasting #edit{opacity:.5;pointer-events:none}body.toasting #toast{box-sizing:border-box;background-color:#feecc2;border-radius:4px;font-size:13px;left:50%;top:10px;margin-left:-160px;padding:1em;position:absolute;max-width:320px;z-index:101}body:not(.toasting) #toast,body.toasting #warning{display:none}body:not(.download) #download{display:none}#download{background:#fafafa;width:100vw;height:100vh;position:absolute;top:0;left:0;display:flex;text-decoration:none;color:black;justify-content:center;align-items:center;flex-direction:column;font-size:14px}#dl-image{width:128px;height:128px;background-position:center;background-repeat:no-repeat;background-image:url("data:image/svg+xml,%0A%3Csvg width='128' height='128' viewBox='0 0 128 128' fill='none' xmlns='http://www.w3.org/2000/svg'%3E%3Cmask id='path-1-outside-1_116_2' maskUnits='userSpaceOnUse' x='27' y='15' width='74' height='98' fill='black'%3E%3Crect fill='white' x='27' y='15' width='74' height='98'/%3E%3Cpath d='M80 16H28V112H100V36L80 16Z'/%3E%3C/mask%3E%3Cpath d='M80 16H28V112H100V36L80 16Z' fill='white'/%3E%3Cpath d='M28 16V15H27V16H28ZM80 16L80.7071 15.2929L80.4142 15H80V16ZM28 112H27V113H28V112ZM100 112V113H101V112H100ZM100 36H101V35.5858L100.707 35.2929L100 36ZM28 17H80V15H28V17ZM29 112V16H27V112H29ZM100 111H28V113H100V111ZM99 36V112H101V36H99ZM100.707 35.2929L80.7071 15.2929L79.2929 16.7071L99.2929 36.7071L100.707 35.2929Z' fill='black' fill-opacity='0.15' mask='url(%23path-1-outside-1_116_2)'/%3E%3C/svg%3E%0A");padding:20px 32px;box-sizing:border-box;display:flex;justify-content:center;align-items:center;color:rgba(0,0,0,0.3);font-weight:bold}#dl-button{text-decoration:none;background:gray;color:white;padding:.5em 1em;border-radius:2em;display:none}#dl-button:hover{background:black}#dl-name{margin-bottom:2em}body:not(.loading) #loader{opacity:.0}#loader{border-radius:50%;width:1em;height:1em;font-size:10px;margin:0 auto;position:relative;text-indent:-9999em;color:white;opacity:1;transition:opacity 500ms;-webkit-animation-fill-mode:both;animation-fill-mode:both;-webkit-animation:turntable 2.8s infinite ease-in-out;animation:turntable 2.8s infinite ease-in-out;-webkit-transform:translateZ(0);-ms-transform:translateZ(0);transform:translateZ(0);-webkit-animation-delay:-0.16s;animation-delay:-0.16s;animation-timing-function:ease-in-out;--ld0:.00em 2.25em 0 .20em rgba(127,127,127,1.50);--ld1:.93em 2.24em 0 .20em rgba(127,127,127,1.45);--ld2:1.76em 2.20em 0 .18em rgba(127,127,127,1.31);--ld3:2.43em 2.15em 0 .16em rgba(127,127,127,1.09);--ld4:2.85em 2.08em 0 .13em rgba(127,127,127,0.81);--ld5:3.00em 2.00em 0 .10em rgba(127,127,127,0.50);--ld6:2.85em 1.92em 0 .07em rgba(127,127,127,0.19);--ld7:2.43em 1.85em 0 .04em rgba(127,127,127,-0.09);--ld8:1.76em 1.80em 0 .02em rgba(127,127,127,-0.31);--ld9:.93em 1.76em 0 .00em rgba(127,127,127,-0.45);--ld10:.00em 1.75em 0 .00em rgba(127,127,127,-0.50);--ld11:-0.93em 1.76em 0 .00em rgba(127,127,127,-0.45);--ld12:-1.76em 1.80em 0 .02em rgba(127,127,127,-0.31);--ld13:-2.43em 1.85em 0 .04em rgba(127,127,127,-0.09);--ld14:-2.85em 1.92em 0 .07em rgba(127,127,127,0.19);--ld15:-3.00em 2.00em 0 .10em rgba(127,127,127,0.50);--ld16:-2.85em 2.08em 0 .13em rgba(127,127,127,0.81);--ld17:-2.43em 2.15em 0 .16em rgba(127,127,127,1.09);--ld18:-1.76em 2.20em 0 .18em rgba(127,127,127,1.31);--ld19:-0.93em 2.24em 0 .20em rgba(127,127,127,1.45)}@keyframes turntable{100%,0%{box-shadow:var(--ld0),var(--ld4),var(--ld8),var(--ld12),var(--ld16)}5%{box-shadow:var(--ld1),var(--ld5),var(--ld9),var(--ld13),var(--ld17)}10%{box-shadow:var(--ld2),var(--ld6),var(--ld10),var(--ld14),var(--ld18)}15%{box-shadow:var(--ld3),var(--ld7),var(--ld11),var(--ld15),var(--ld19)}20%{box-shadow:var(--ld4),var(--ld8),var(--ld12),var(--ld16),var(--ld0)}25%{box-shadow:var(--ld5),var(--ld9),var(--ld13),var(--ld17),var(--ld1)}30%{box-shadow:var(--ld6),var(--ld10),var(--ld14),var(--ld18),var(--ld2)}35%{box-shadow:var(--ld7),var(--ld11),var(--ld15),var(--ld19),var(--ld3)}40%{box-shadow:var(--ld8),var(--ld12),var(--ld16),var(--ld0),var(--ld4)}45%{box-shadow:var(--ld9),var(--ld13),var(--ld17),var(--ld1),var(--ld5)}50%{box-shadow:var(--ld10),var(--ld14),var(--ld18),var(--ld2),var(--ld6)}55%{box-shadow:var(--ld11),var(--ld15),var(--ld19),var(--ld3),var(--ld7)}60%{box-shadow:var(--ld12),var(--ld16),var(--ld0),var(--ld4),var(--ld8)}65%{box-shadow:var(--ld13),var(--ld17),var(--ld1),var(--ld5),var(--ld9)}70%{box-shadow:var(--ld14),var(--ld18),var(--ld2),var(--ld6),var(--ld10)}75%{box-shadow:var(--ld15),var(--ld19),var(--ld3),var(--ld7),var(--ld11)}80%{box-shadow:var(--ld16),var(--ld0),var(--ld4),var(--ld8),var(--ld12)}85%{box-shadow:var(--ld17),var(--ld1),var(--ld5),var(--ld9),var(--ld13)}90%{box-shadow:var(--ld18),var(--ld2),var(--ld6),var(--ld10),var(--ld14)}95%{box-shadow:var(--ld19),var(--ld3),var(--ld7),var(--ld11),var(--ld15)}}
</style>
<link rel="preload" href="render/recipe.js" as="script" />
<meta id="themeColor" name="theme-color" content="white" media="(prefers-color-scheme: light)">
<meta id="themeColorDark" name="theme-color" content="#121212" media="(prefers-color-scheme: dark)">
<!-- <link rel="manifest" href="/manifest.json"> -->
<script src="/js/lzma/lzma-d-min.js"></script>
<script type="module" >const padForBase64=(s,c=" ")=>s.padEnd(s.length+(3-s.length%3)%3,c);const HEAD_TAGS=()=>btoa(padForBase64('<base target="_top">\n'));const HEAD_TAGS_EXTENDED=()=>btoa(padForBase64(`<meta charset="utf-8"><meta name="viewport" content="width=device-width"><base target="_top"><style type="text/css">body{margin:0 auto;padding:12vmin 10vmin;max-width:35em;line-height:1.5em;font-family:-apple-system,BlinkMacSystemFont,sans-serif;word-wrap:break-word;}@media(prefers-color-scheme: dark){body{color:white;background-color:black;}}</style>`));const dataUrlRE=/^data:(?<mediatype>(?<type>[a-z]+)\/(?<subtype>[a-z+\-]+))?(?<params>(?:;[^;,]+=[^;,]+)*)?(?:;(?<encoding>\w+64))?,(?<data>.*)$/;let schemeMappings={r:"application/ld+json;charset=utf-8;format=gz;base64,",h:"text/html;charset=utf-8;format=gz;base64,",t:","};class DataURL{constructor(url){this.initString=url;var colon=url.substring(0,15).indexOf(":");if(colon!=-1){this.scheme=url.substring(0,colon);if(schemeMappings[this.scheme]){url=`data:${schemeMappings[this.scheme]},${url}`}}else{if(url.charAt(0)=="?"){this.editable=true;url=url.substring(1)}this.dataPrefix=HEAD_TAGS_EXTENDED();let encoding=url.startsWith("XQA")?bitty.LZMA_MARKER:bitty.GZIP_MARKER;url=`data:text/html;charset=utf-8;format=${encoding};base64,${url}`}let match=url.match(dataUrlRE);this.params={};if(match){let info=match.groups;Object.assign(this,info);this.params=info.params?JSON.parse('{"'+decodeURI(info.params?.substring(1)).replace(/"/g,'\\"').replace(/;/g,'","').replace(/=/g,'":"')+'"}'):{}}if(this.encoding){this.data=this.data.replace(/=/g,"")}else{this.data=decodeURIComponent(this.data)}}get href(){let urlString="data:";if(this.mediatype)urlString+=this.mediatype;if(this.params)Object.entries(this.params).forEach((e=>urlString+=`;${e[0]}=${e[1]}`));if(this.encoding)urlString+=";"+this.encoding;if(!this.encoding&&this.dataPrefix){this.dataPrefix=atob(this.dataPrefix)}urlString+=","+(this.dataPrefix||"")+this.data;return urlString}get format(){return this.params.format||this.encoding}clone=()=>{var clone=Object.assign(Object.create(Object.getPrototypeOf(this)),this);clone.params={...this.params};return clone};decompress=async()=>{if(this.params.cipher){console.log(this.params.cipher,decryptData);this.data=await decryptData(this.params.cipher,this.data)}if(this.format&&this.format!="base64"){let bytes=base64ToByteArray(this.data);this.rawData=await decompressData(bytes,this.format);this.data=await dataToBase64(this.rawData);delete this.params.format;this.encoding=BASE64_MARKER}return this};compress=async(format=GZIP_MARKER)=>{let rawData=this.encoding?await base64ToByteArray(this.data):stringToByteArray(this.data);let compressedData=await compressData(rawData,format);var base64String=dataToBase64(compressedData);base64String=base64String.replace(/=+$/,"");this.data=base64String;this.params.format=format;return this};parseDom=async()=>{try{const parser=new DOMParser;const doc=parser.parseFromString(`<?xml version="1.0" encoding="UTF-8"?>`+atob(this.data),this.mediatype);return doc}catch(e){}}}function parseBittyURL(url){if(typeof url==="string")url=new URL(url);let location=url.location;let fragment=url.hash;let path=url.pathname;var slashIndex=fragment.indexOf("/");var hashTitle=decodePrettyComponent(fragment.substring(1,slashIndex));var hashData=fragment.substring(slashIndex+1);return{path:path,hashTitle:hashTitle,hashData:hashData}}async function testCompression(rawData){let gz=await compressData(rawData,GZIP_MARKER);console.log(gz.length,typeof gz,dataToBase64(gz).length);let xz=await compressData(rawData,LZMA_MARKER);console.log(xz.length,typeof xz,dataToBase64(xz).length);let ungz=await decompressData(gz,GZIP_MARKER);let unxz=await decompressData(xz,LZMA_MARKER);console.log("unzip",ungz==rawData,unxz==rawData,{ungz:ungz,unxz:unxz,rawData:rawData,raw:byteArrayToString(rawData).substring(684),ungzs:byteArrayToString(ungz).substring(684),unxzs:byteArrayToString(unxz).substring(684)},byteArrayToString(ungz)==byteArrayToString(unxz))}async function compressData(data,encoding=GZIP_MARKER,callback){console.debug("Compressing with",encoding);if(encoding==GZIP_MARKER){return import("/js/gzip/pako.min.js").then((module=>pako.deflate(data,{level:"9"})))}else if(encoding==BROT_MARKER){}else if(encoding==LZMA_MARKER){return new Promise((function(resolve,reject){console.log({xz:data});LZMA.compress(data,9,(function(result,error){if(error)reject(error);resolve(result)}))}))}}function stringToByteArray(string){return(new TextEncoder).encode(string);return Uint8Array.from(string,(c=>c.charCodeAt(0)))}function byteArrayToString(bytes){return(new TextDecoder).decode(bytes);return String.fromCharCode.apply(null,new Uint8Array(bytes))}function browserDecompressData(data){const cs=new DecompressionStream("gzip");const writer=cs.writable.getWriter();writer.write(data);writer.close();return new Response(cs.readable).arrayBuffer().then((function(arrayBuffer){return(new TextDecoder).decode(arrayBuffer)}))}async function decompressData(data,encoding,callback){if(encoding==GZIP_MARKER){return import("/js/gzip/pako.min.js").then((module=>{let byteArray=pako.inflate(data);return byteArray}))}else if(encoding==BROT_MARKER){return import("/js/brotli/decode.js").then((module=>module.BrotliDecode(data)))}else if(encoding==LZMA_MARKER||encoding==LZMA64_MARKER){return new Promise((function(resolve,reject){LZMA.decompress(data,((result,error)=>{if(error)reject(error);resolve(stringToByteArray(result))}))}))}}async function decryptData(cipher,base64){return new Promise(((resolve,reject)=>{loadScript("/js/crypto-js.min.js",(()=>{console.log("decrypting",cipher);let pass=prompt("This page is encrypted. What's the passcode?");if(!pass)resolve(base64);let decrypted=CryptoJS[cipher.toUpperCase()].decrypt(base64,pass);return resolve(CryptoJS.enc.Base64.stringify(decrypted))}))}))}function infoForDataURL(url){return new DataURL(url)}var BASE64_MARKER="base64";var LZMA64_MARKER="bxze64";var BASE_MARKER="bs";var LZMA_MARKER="xz";var GZIP_MARKER="gz";var BROT_MARKER="br";function base64ToByteArray(base64){return Uint8Array.from(atob(base64),(c=>c.charCodeAt(0)))}function loadScript(src,callback){let script=el("script",{src:src});script.addEventListener("load",(function(e){console.debug("Loaded script",src);if(callback)callback(e)}));document.head.appendChild(script)}function escapeStringForIMessage(str){var matches=str.match(/[^\/+=]{1,300}/g);if(matches)str=matches.join("=");return str}async function hashString(string,base=36){const arrayBuffer=await(new TextEncoder).encode(string);const hashAsArrayBuffer=await crypto.subtle.digest("SHA-256",arrayBuffer);const uint8ViewOfHash=new Uint8Array(hashAsArrayBuffer);const hashAsHex=Array.from(uint8ViewOfHash).map((b=>b.toString(16).padStart(2,"0"))).join("");if(base==16)return hashAsHex;if(base==36){const guid=BigInt("0x"+hashAsHex);const asBase36=guid.toString(36).toLowerCase();return asBase36}const hashAsBase64=btoa(String.fromCharCode.apply(null,uint8ViewOfHash));hashAsBase64.replace(/=/g,"").replace(/[\+\/+]/g,"-").toLowerCase();return hashAsBase64}function dataToBase64(data){return btoa(String.fromCharCode.apply(null,new Uint8Array(data)))}function dataToBase64FR(data){return new Promise(((resolve,reject)=>{if(!data||!data.length)return resolve("");var fr=new FileReader;fr.onload=()=>resolve(fr.result.split(",")[1]);fr.onerror=reject;fr.readAsDataURL(new Blob([data],{encoding:"UTF-8",type:"text/html;charset=UTF-8"}))}))}function dataURLToString(durl){return fetch(durl).then((r=>r.blob())).then((blob=>new Promise(((resolve,reject)=>{var fr=new FileReader;fr.onload=()=>resolve(fr.result);fr.onerror=reject;fr.readAsText(blob)}))))}function stringToData(string,callback){if(!string.length)return callback("");var a=new FileReader;a.onload=function(e){callback(e.target.result.replace())};a.readAsDataURL(new Blob([string],{encoding:"UTF-8",type:"text/html;charset=UTF-8"}))}function dataToString(data,callback){return newDataURLtoBlob(data).then((blob=>{var reader=new FileReader;reader.onload=function(e){callback(reader.result)};reader.readAsText(blob)}))}function newDataURLtoBlob(dataURL){return fetch(dataURL).then((r=>r.blob()))}function dataURLtoBlob(dataURL){var byteString=window.atob(dataURL.split(",")[1]);var mimeString=dataURL.split(",")[0].split(":")[1].split(";")[0];var arrayBuffer=new ArrayBuffer(byteString.length);var _ia=new Uint8Array(arrayBuffer);for(var i=0;i<byteString.length;i++){_ia[i]=byteString.charCodeAt(i)}var dataView=new DataView(arrayBuffer);var blob=new Blob([dataView.buffer],{type:mimeString});return blob}function encodePrettyComponent(s){let replacements={" - ":"---","-":"--"," ":"-"};let re=new RegExp("("+Object.keys(replacements).join("|")+")","g");return encodeURIComponent(s.replace(re,(e=>replacements[e]??"-"))).replace(/[!'()*]/g,(c=>"%"+c.charCodeAt(0).toString(16)))}function decodePrettyComponent(s){let replacements={"---":" - ","--":"-","-":" "};return decodeURIComponent(s.replace(/-+/g,(e=>replacements[e]??"-")))}function pathToMetadata(path){let components=path.substring(1).split("/");let info={title:decodePrettyComponent(components.shift())};for(let i=0;i<components.length;i+=2){let key=components[i];let value=components[i+1];if(!value)continue;if(key=="d"){value=decodePrettyComponent(value)}else if(value.includes("%")){value=decodeURIComponent(value)}if(key.length&&value.length)info[key]=value}return info}function metadataToPath(data){if(!data||!data.title)return"/";let path=["/"+encodePrettyComponent(data.title)];if(data.description)path.push("d/"+encodePrettyComponent(data.description.substring(0,200).split(". ").shift()));if(data.favicon)path.push("f/"+encodeURIComponent(data.favicon));if(data.image)path.push("i/"+encodeURIComponent(btoa(data.image).replace(/=/g,"")));return path.join("/")+"/"}const el=(selector,...args)=>{var attrs=args[0]&&typeof args[0]==="object"&&!Array.isArray(args[0])&&!(args[0]instanceof HTMLElement)?args.shift():{};let classes=selector.split(".");if(classes.length>0)selector=classes.shift();if(classes.length)attrs.className=classes.join(" ");let id=selector.split("#");if(id.length>0)selector=id.shift();if(id.length)attrs.id=id[0];var node=document.createElement(selector.length>0?selector:"div");for(let prop in attrs){if(attrs.hasOwnProperty(prop)&&attrs[prop]!=undefined){if(prop.indexOf("data-")==0){let dataProp=prop.substring(5).replace(/-([a-z])/g,(function(g){return g[1].toUpperCase()}));node.dataset[dataProp]=attrs[prop]}else{node[prop]=attrs[prop]}}}const append=child=>{if(Array.isArray(child))return child.forEach(append);if(typeof child=="string")child=document.createTextNode(child);if(child)node.appendChild(child)};args.forEach(append);return node};export{DataURL,infoForDataURL,stringToData,dataToString,hashString,encodePrettyComponent,decodePrettyComponent,metadataToPath,pathToMetadata,parseBittyURL,el,BASE64_MARKER,LZMA64_MARKER,BASE_MARKER,LZMA_MARKER,GZIP_MARKER,BROT_MARKER,HEAD_TAGS,HEAD_TAGS_EXTENDED};
</script>
<script type="module" >import*as bitty from"/bitty.js";window.bitty=bitty;const isFramed=window.self!==window.top;function addToast(){}function showLoader(state){let loader=document.getElementById("loader");if(state){if(!loader){loader=document.createElement("div");loader.id="loader";document.body.appendChild(loader)}}else if(loader){setTimeout((()=>loader?.parentElement?.removeChild(loader)),500)}setTimeout((()=>document.body.classList.toggle("loading",state)),1)}window.showLoader=showLoader;function setThemeColor(color){let el=document.getElementById("themeColor");if(!el){el=document.createElement("meta");el.name="theme-color";el.id="themeColor";document.head.appendChild(el)}el.content=color}function setFavicon(favicon){document.getElementById("favicon").href='data:image/svg+xml,<svg xmlns="http://www.w3.org/2000/svg" width="1em" height="1em"><text y=".9em">'+favicon+"</text></svg>"}window.el=function(tagName,attrs,...children){let l=document.createElement(tagName);Object.entries(attrs).forEach((([k,v])=>l[k]=v));children.forEach((c=>l.appendChild(c)));return l};const renderers={"application/ld+json":{script:"/render/recipe.html"},"text/canvas+javascript":{script:"canvas"},"text/javascript":{script:"script"},"application/bitsy":{script:"/render/bitsy.html",sandbox:"bitsy"},c:{script:"color"},"text/rawhtml":{script:"parse"},javascript:{script:"bookmarklet"},ipfs:{script:"ipfs",sandbox:"ipfs"},web3:{script:"web3"},"text/directory":{script:"download",args:{extension:"vcf",filename:"contact"}}};function share(info){if(!info.url)info={title:document.title,text:document.title,url:location.href};console.log("Share",info);if(navigator.share){navigator.share(info).then((()=>{console.log("Thanks for sharing!")})).catch(console.error)}else{copyLink(info)}}function copyLink(info){var text=info.url;var dummy=document.createElement("input");document.body.appendChild(dummy);dummy.value=text;dummy.select();document.execCommand("copy");document.body.removeChild(dummy);document.body.classList.add("copied");setTimeout((function(){document.body.classList.remove("copied")}),2e3)}let wakeLock;const getWakeLock=async()=>{try{if(navigator.wakeLock){wakeLock=await navigator.wakeLock.request();wakeLock.addEventListener("release",(()=>{}));console.log("Keeping Screen Awake:",!wakeLock.released)}else{}}catch(err){console.error(`${err.name}, ${err.message}`)}};function keepAwake(){let ctx=new AudioContext;let bufferSize=2*ctx.sampleRate,emptyBuffer=ctx.createBuffer(1,bufferSize,ctx.sampleRate),output=emptyBuffer.getChannelData(0);for(let i=0;i<bufferSize;i++)output[i]=0;let source=ctx.createBufferSource();source.buffer=emptyBuffer;source.loop=true;let node=ctx.createMediaStreamDestination();source.connect(node);let audio=document.createElement("audio");audio.style.display="none";document.body.appendChild(audio);audio.srcObject=node.stream;audio.play()}const handleVisibilityChange=async()=>{if(wakeLock!==null&&document.visibilityState==="visible"){await getWakeLock()}};document.addEventListener("visibilitychange",handleVisibilityChange);window.addEventListener("message",(function(e){console.debug("Message:",e.origin,e.data);showLoader(false);if(e.data.loading!=undefined)showLoader(e.data.loading);if(e.data.title)document.title=e.data.title;if(e.data.favicon)setFavicon(e.data.favicon);if(e.data.themeColor)setThemeColor(e.data.themeColor);if(e.data.updateURL){let path=bitty.metadataToPath(e.data)+window.location.hash;window.history.replaceState(null,null,path)}if(e.data.share){share(e.data.share)}if(e.data.wakeLock){getWakeLock()}if(e.data.updateHash){window.history.replaceState(null,null,e.data.updateHash)}if(e.data.replaceURL){if(e.data.compressURL){let durl=new bitty.DataURL(e.data.replaceURL);durl.compress().then((arg=>{window.history.replaceState(null,null,"/#/"+arg.href);renderContent()}))}else{window.history.replaceState(null,null,e.data.replaceURL);renderContent()}}if(e.data.setStorage)document.localStorage.setItem(contentHash,e.data.set);if(e.data.getStorage)document.getElementById("iframe").postMessage(document.localStorage.getItem(contentHash),e.origin)}),false);async function renderContent(){showLoader(true);var fragment=window.location.hash.substring(1);if(fragment.length<3&&!isFramed){return location.href="/edit"}if(window.location.search){window.history.replaceState(null,null,window.location.search.substring(1)+"#"+fragment)}var isIE=navigator.userAgent.match(/rv:11/);var isEdge=navigator.userAgent.match(/Edge\//);var isWatch=window.outerWidth<220;let bittyInfo=bitty.parseBittyURL(location);let durl=new bitty.DataURL(bittyInfo.hashData);if(durl.params.compress){console.log("Compressing URL",durl);delete durl.params.compress;durl.compress(bitty.GZIP_MARKER).then((arg=>{window.history.replaceState(null,null,"/#/"+arg.href);renderContent()}));return}var iframe=document.getElementById("iframe");var dataPrefix=undefined;var renderMode="data";var renderer;let components=window.location.pathname.substring(1).split("/");let info={};info.title=decodeURIComponent(components.shift()).replace(/-/g," ").replace(//g,"-");let i;for(i=0;i<components.length;i+=2){let key=components[i];let value=decodeURIComponent(components[i+1]);if(key.length&&value.length)info[key]=value}info.d=info.d?.replace(/-/g," ").replace(//g,"-");if(info.f)setFavicon(info.f);var slashIndex=fragment.indexOf("/");var title=fragment.substring(0,slashIndex)||info.title;if(title)title=decodeURIComponent(title.replace(/_/g," "));var type=undefined;var description=undefined;document.title=title??location.hostname;fragment=fragment.substring(slashIndex+1);var editable=fragment.charAt(0)=="?";var link=document.getElementById("edit");if(editable){fragment=fragment.substring(1);document.body.appendChild(el("a",{id:"edit",onclick:function(){location.href="/edit"+location.hash}}))}if(fragment.startsWith("data:")){renderer=durl.params?.render?{script:durl.params.render,sandbox:"hash"}:renderers[durl.mediatype];type="data:"+durl.mediaype;if(durl.mediatype=="text/html"){dataPrefix=bitty.HEAD_TAGS()}else if(durl.mediatype=="text/plain"||durl.mediatype==undefined){dataPrefix=bitty.HEAD_TAGS_EXTENDED();durl.mediatype="text/html";renderMode="data"}else if(durl.type=="text"){}else if(durl.type=="image"){}else if(durl.type==undefined){}else if(!renderer){console.log("unknown type, rendering as download");renderMode="download"}if(renderer){var script=renderer.script;if(script.indexOf("/")==-1)script=location.origin+"/render/"+script+".js";renderMode="script"}}else{var colon=fragment.indexOf(":");if(colon>0&&colon<15){document.body.classList.remove("toasting");let scheme=fragment.substring(0,colon);type=scheme;let renderer=renderers[scheme];if(renderer){return renderContentWithScript({renderer:renderer,title:title,info:info,body:fragment,url:fragment})}return window.location.replace(fragment)}var compressed=true;dataPrefix=bitty.HEAD_TAGS_EXTENDED();let encoding=!compressed?"base64,":fragment.startsWith("XQA")?bitty.LZMA_MARKER:bitty.GZIP_MARKER;durl=new bitty.DataURL(`data:text/html;charset=utf-8;format=${encoding};base64,${fragment}`)}if((isEdge||isIE)&&location.href.length==2083){let element=document.getElementById("warning")||document.body.appendChild(el("div",{id:"warning"}));element.innerHTML='Edge only supports shorter URLs (maximum 2083 bytes).<br>Larger sites may require a different browser.<br><a href="http://reference.bitty.site">Learn more</a>'}await durl.decompress();durl.dataPrefix=dataPrefix;let dataURL=durl.href;let dataContent=durl.rawData;if(!dataURL)return;iframe.sandbox="allow-same-origin allow-downloads allow-scripts allow-forms allow-top-navigation allow-popups allow-modals allow-popups-to-escape-sandbox";if(isIE&&renderMode=="data")renderMode="frame";let contentTarget;if(isWatch){console.log("Rendering for watch");contentTarget=document}console.log("🖋 Rendering mode: "+""+renderMode,{url:durl});if(renderMode=="download"){try{let extension=title.split(".");let dl=el("a",{id:"download",href:dataURL,download:title},el("div",{id:"dl-image",innerText:extension.pop()??""}),el("div",{id:"dl-name",innerText:"title"}),el("div",{id:"dl-button"}));document.body.append(dl);document.body.classList.add("download");dl.click();return}catch(e){console.log("DL error",e);iframe.src=dataURL;showLoader(false)}}else if(renderMode=="data"){iframe.src=dataURL;showLoader(false)}else{bitty.dataToString(dataURL,(function(content){if(renderMode=="frame"){writeDocContent(contentTarget,content)}else if(renderMode=="script"){renderContentWithScript({renderer:renderer,title:title,info:info,body:content,url:dataURL,overwrite:contentTarget==document})}}))}let recordHistory=true;if(!isFramed&&recordHistory)recordToHistory(durl)}window.addEventListener("DOMContentLoaded",renderContent);window.addEventListener("hashchange",renderContent);const SCRIPT_LOADER=`<!doctype html><meta charset=utf-8><script src="${location.origin}/render.js"><\/script>`;async function renderContentWithScript(params){params.script=params.renderer.script;params.originalURL=location.href;if(params.script.indexOf("/")==-1)params.script=location.origin+"/render/"+params.script+".js";if(params.overwrite){let scriptEl=document.createElement("script");scriptEl.src="/render.js";scriptEl.addEventListener("load",(function(e){console.log("Loaded script",scriptEl.src);renderScriptContent(params,"*")}));document.head.appendChild(scriptEl)}else{iframe.onload=()=>{iframe.contentWindow.postMessage(params,"*");delete iframe.onload;iframe.contentWindow.focus()};let src=window.scriptDomain??location.origin;src+="/render";let sandbox=params.renderer?.sandbox;if(params.script.endsWith(".html")){src=params.script;if(!sandbox)sandbox="none"}if(sandbox=="none"){}else if(sandbox=="hash"){let hash=await bitty.hashString(params.body);src=src.replace("https://","https://script-"+hash+".")}else if(sandbox){src=src.replace("https://","https://"+sandbox+".")}else{src="data:text/html,"+SCRIPT_LOADER}console.log("📜Loading script with source:",src);iframe.src=src}}function writeDocContent(doc,content){doc.open();doc.write(content);doc.close()}function extractTerms(...args){let wordSet={};args.forEach((string=>{if(string)string.split(/\s/).forEach((word=>{if(word.length>2)wordSet[word.toLowerCase()]=true}))}));return Object.keys(wordSet)}async function recordToHistory(){let location=window.location;let fragment=location.hash;fragment=fragment.substring(fragment.indexOf("/")+1);let hash=await bitty.hashString(fragment);let durl=new bitty.DataURL(fragment);let type=durl.mediatype;let metadata=bitty.pathToMetadata(location.pathname);if(!metadata.title){let dom=await(await durl.decompress()).parseDom();if(dom){for(let el of dom.getElementsByTagName("script")){el.parentNode.removeChild(el)}metadata.title=dom.title;metadata.description=dom.body?.innerText.trim();if(!metadata.title.length){metadata.title=dom.body?.children[0]?.innerText.trim()?.split("\n").pop()}metadata.description=metadata.description?.replace(metadata.title,"").trim()}console.debug("Extracting metadata from content",metadata)}if(navigator.storage&&navigator.storage.persist)navigator.storage.persist().then((granted=>{if(granted)console.debug("Storage will not be cleared except by explicit user action");else console.debug("Storage may be cleared by the UA under storage pressure.")}));let openRequest=indexedDB.open("history",3);openRequest.onupgradeneeded=function(event){console.log("Upgrading Database",event);const db=event.target.result;const transaction=event.target.transaction;let objectStore;if(!db.objectStoreNames.contains("urls")){objectStore=db.createObjectStore("urls",{keyPath:"id"})}else{objectStore=transaction.objectStore("urls")}objectStore.createIndex("created","created");objectStore.createIndex("type","type");objectStore.createIndex("terms","terms",{multiEntry:true})};openRequest.onerror=function(){console.error("Error",openRequest.error)};openRequest.onsuccess=()=>{let db=openRequest.result;let transaction=db.transaction("urls","readwrite");let history=transaction.objectStore("urls");let hashCode=s=>s.split("").reduce(((a,b)=>{a=(a<<5)-a+b.charCodeAt(0);return a&a}),0);let terms=extractTerms(metadata.title,metadata.description);let entry={id:hash,url:location.href,title:metadata.title||"",text:metadata.description?.substring(0,256),type:type,terms:terms,created:new Date};console.log("🕙Adding history",{entry:entry});let request=history.put(entry);request.onsuccess=function(){console.debug("entry added to the history",request.result)};request.onerror=function(){console.log("Error",request.error)}}}
</script>
<script type="module" src="/js/gzip/pako.min.js" ></script>
<script nomodule> location.href = "/v1/" + location.hash </script>
<noscript>itty.bitty requires JavaScript.</noscript>
</head>
<iframe id="iframe" sandbox="allow-same-origin allow-downloads allow-scripts allow-forms allow-top-navigation allow-popups allow-modals allow-popups-to-escape-sandbox"></iframe>
</html>