- Add serve.py to resolve clean Quartz URLs to .html files - Regenerate Quartz site with correct baseUrl http://100.118.5.51:9120 - 196 HTML files emitted; all internal links now resolve
2 lines
5.3 KiB
JavaScript
2 lines
5.3 KiB
JavaScript
var S="encrypted-pages-passwords",m="encrypted-pages:decryptedShadowEntries";function v(t){let e=atob(t),n=new Uint8Array(e.length);for(let r=0;r<e.length;r++)n[r]=e.charCodeAt(r);return n}async function b(t,e,n){let r=new TextEncoder,o=await window.crypto.subtle.importKey("raw",r.encode(t),"PBKDF2",!1,["deriveKey"]);return window.crypto.subtle.deriveKey({name:"PBKDF2",salt:e,iterations:n,hash:"SHA-256"},o,{name:"AES-GCM",length:256},!1,["decrypt"])}async function T(t,e,n){let r=v(t),o=r.slice(0,16),i=r.slice(16,28),c=r.slice(28,44),a=r.slice(44),s=new Uint8Array(a.length+c.length);s.set(a,0),s.set(c,a.length);let d=await b(e,o,n),l=await window.crypto.subtle.decrypt({name:"AES-GCM",iv:i},d,s);return new TextDecoder().decode(l)}function h(){try{let t=sessionStorage.getItem(S);if(!t)return[];let e=JSON.parse(t);return Array.isArray(e)?e:[]}catch{return[]}}function A(t){let e=h();e.includes(t)||(e.push(t),sessionStorage.setItem(S,JSON.stringify(e)))}function L(){try{let t=sessionStorage.getItem(m);if(!t)return{};let e=JSON.parse(t);return e&&typeof e=="object"?e:{}}catch{return{}}}function N(t){try{sessionStorage.setItem(m,JSON.stringify(t))}catch{}}function I(t,e){let n=t.querySelector(".encrypted-page-error");n&&(n.textContent=e,n.style.display="block")}function _(t){let e=t.querySelector(".encrypted-page-error");e&&(e.style.display="none",e.textContent="")}function w(t,e){let n=t.querySelector(".encrypted-page-submit"),r=t.querySelector(".encrypted-page-input");n&&(n.disabled=e,n.textContent=e?"Decrypting\u2026":"Unlock"),r&&(r.disabled=e)}function x(){let t=document.querySelectorAll("script");for(let e of t){let r=(e.textContent??"").match(/fetch\(["']([^"']+contentIndex\.json)["']\)/);if(r)return r[1].replace(/contentIndex\.json$/,"encryptedContentIndex.json")}return new URL("static/encryptedContentIndex.json",document.baseURI).toString()}var p=null;async function H(){if(p)return p;let t=x();return p=fetch(t).then(e=>{if(!e.ok)throw new Error(`shadow index HTTP ${e.status}`);return e.json()}).then(e=>!e||e.version!==1||!Array.isArray(e.entries)?{version:1,entries:[]}:e).catch(()=>({version:1,entries:[]})),p}async function D(t,e,n){let r={},o={...n},i=!1;for(let c=0;c<t.entries.length;c++){let a=String(c);if(n[a]){let d=n[a];d&&d.slug&&(r[d.slug]=d.entry);continue}let s=t.entries[c];if(!(!s||typeof s.ciphertext!="string"))for(let d of e)try{let l=await T(s.ciphertext,d,s.iterations),u=JSON.parse(l);u&&typeof u.slug=="string"&&u.entry&&(r[u.slug]=u.entry,o[a]=u,i=!0);break}catch{}}return i&&N(o),r}async function G(t){let e=Object.keys(t);if(e.length!==0){try{let n=await(typeof fetchData<"u"?fetchData:Promise.resolve(null));if(!n||typeof n!="object")return;let r=n.content&&typeof n.content=="object"?n.content:n;for(let o of e)o in r||(r[o]=t[o])}catch{return}document.dispatchEvent(new CustomEvent("content-index-updated",{detail:{slugs:e}})),document.dispatchEvent(new CustomEvent("render"))}}var y=!1;async function f(){if(y)return;let t=h();if(t.length!==0){y=!0;try{let e=await H();if(!e.entries||e.entries.length===0)return;let n=L(),r=await D(e,t,n);await G(r)}finally{y=!1}}}async function E(t,e){let n=t.getAttribute("data-encrypted"),r=parseInt(t.getAttribute("data-iterations")||"600000",10);if(!n)return!1;try{let o=await T(n,e,r);if(t.parentElement){let c=document.createElement("div");c.innerHTML=o,t.replaceWith(...c.childNodes)}return A(e),document.dispatchEvent(new CustomEvent("render")),f(),!0}catch{return!1}}function g(){let t=document.querySelectorAll(".encrypted-page");if(t.length===0){f();return}for(let e of t){if(e.querySelector(".encrypted-page-form")||!e.getAttribute("data-encrypted"))continue;let r=document.createElement("div");r.className="encrypted-page-form",r.innerHTML=['<div class="encrypted-page-icon" aria-hidden="true">','<svg xmlns="http://www.w3.org/2000/svg" width="48" height="48" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="1.5" stroke-linecap="round" stroke-linejoin="round">','<rect x="3" y="11" width="18" height="11" rx="2" ry="2"></rect>','<path d="M7 11V7a5 5 0 0 1 10 0v4"></path>',"</svg>","</div>",'<p class="encrypted-page-label">This page is encrypted. Enter the password to view its content.</p>','<div class="encrypted-page-input-row">','<input type="password" class="encrypted-page-input" placeholder="Password" autocomplete="off" />','<button type="button" class="encrypted-page-submit">Unlock</button>',"</div>",'<p class="encrypted-page-error" style="display:none"></p>'].join(""),e.appendChild(r);let o=r.querySelector(".encrypted-page-input"),i=r.querySelector(".encrypted-page-submit");async function c(){let s=o?.value;if(!s)return;_(e),w(e,!0),await E(e,s)||(w(e,!1),I(e,"Incorrect password. Please try again."),o&&(o.value="",o.focus()))}i&&i.addEventListener("click",c),o&&o.addEventListener("keydown",s=>{s.key==="Enter"&&(s.preventDefault(),c())});let a=h();a.length>0&&(async()=>{for(let s of a)if(await E(e,s))return})()}f()}document.addEventListener("nav",()=>{g()});document.addEventListener("render",()=>{document.querySelectorAll(".encrypted-page").length>0&&g()});var C=new MutationObserver(t=>{for(let e of t)for(let n of e.addedNodes){if(!(n instanceof HTMLElement))continue;if((n.classList?.contains("encrypted-page")?[n]:[...n.querySelectorAll(".encrypted-page")]).filter(i=>!i.querySelector(".encrypted-page-form")).length>0){g();return}}});C.observe(document.body,{childList:!0,subtree:!0});
|