@aiquants/markdown-explorer 0.1.0 → 0.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (43) hide show
  1. package/CHANGELOG.md +53 -1
  2. package/README.md +53 -16
  3. package/dist/{ExplorerSplit-DwEFmvQM.js → ExplorerSplit-B7pmzR8t.js} +3 -3
  4. package/dist/{ExplorerSplit-BESGFcu6.cjs → ExplorerSplit-Bi3yU6NG.cjs} +1 -1
  5. package/dist/MultiLayout-BxeXOLX1.js +909 -0
  6. package/dist/MultiLayout-DtFrFRmS.cjs +1 -0
  7. package/dist/TreeLayout-BQUfVNlA.cjs +1 -0
  8. package/dist/TreeLayout-D6hCSihW.js +22 -0
  9. package/dist/core/config.d.cts +8 -0
  10. package/dist/core/config.d.ts +8 -0
  11. package/dist/core/labels.d.cts +6 -1
  12. package/dist/core/labels.d.ts +6 -1
  13. package/dist/{dataRoute-CKbdwkQ7.cjs → dataRoute-B9Wk-G7A.cjs} +1 -1
  14. package/dist/{dataRoute-Bkfwfp1R.js → dataRoute-zUX-oR9j.js} +39 -38
  15. package/dist/{index-BgkZ9ATV.js → index-BJTmp0lR.js} +947 -901
  16. package/dist/index-DkiGlM7C.cjs +3 -0
  17. package/dist/index.cjs +1 -1
  18. package/dist/index.js +13 -13
  19. package/dist/location-DfYTzfFS.cjs +1 -0
  20. package/dist/{location-Cb2Ak55B.js → location-V5BKeWNs.js} +189 -162
  21. package/dist/sanitizeWorker.cjs +1 -1
  22. package/dist/sanitizeWorker.js +196 -206
  23. package/dist/server/anonymous.d.cts +2 -2
  24. package/dist/server/anonymous.d.ts +2 -2
  25. package/dist/server/ports.d.cts +4 -1
  26. package/dist/server/ports.d.ts +4 -1
  27. package/dist/server.cjs +1 -1
  28. package/dist/server.d.cts +1 -1
  29. package/dist/server.d.ts +1 -1
  30. package/dist/server.js +631 -603
  31. package/dist/styles/markdown-explorer.css +1 -1
  32. package/docs/behavior/dom-hooks.md +4 -4
  33. package/docs/behavior/layout.md +21 -9
  34. package/docs/behavior/localization.md +4 -3
  35. package/docs/behavior/security.md +23 -5
  36. package/docs/behavior/url-contract.md +8 -2
  37. package/package.json +5 -5
  38. package/dist/MultiLayout-DxPiARsv.js +0 -896
  39. package/dist/MultiLayout-r_qx1Mfz.cjs +0 -1
  40. package/dist/TreeLayout-9-20bbSM.cjs +0 -1
  41. package/dist/TreeLayout-CW7lgV_e.js +0 -19
  42. package/dist/index-y9tVvDW7.cjs +0 -3
  43. package/dist/location-DWHQYntR.cjs +0 -1
package/dist/server.cjs CHANGED
@@ -1 +1 @@
1
- "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("./dataRoute-CKbdwkQ7.cjs"),Ze=require("node:crypto"),Se=require("react-router"),ee=require("./location-DWHQYntR.cjs"),te=require("node:fs"),q=require("node:path"),Te=require("node:url"),mt=require("node:worker_threads"),fe=require("node:fs/promises"),pt=require("node:stream");var xe=typeof document<"u"?document.currentScript:null;const Me=Object.freeze({kind:"anonymous"}),ht=Object.freeze({authenticate:async()=>({status:"signed-in",principal:Me}),principalKey:()=>Me.kind,signedOutPage:(e,t)=>new Response(null,{status:401,headers:t})}),wt="application/octet-stream",qe="application/pdf",gt=new Set(["image/png","image/apng","image/jpeg","image/gif","image/webp","image/avif","image/bmp","image/x-icon","image/vnd.microsoft.icon","audio/mpeg","audio/mp4","audio/aac","audio/ogg","audio/opus","audio/wav","audio/wave","audio/x-wav","audio/webm","audio/flac","audio/x-flac","audio/x-m4a","video/mp4","video/webm","video/ogg","video/quicktime",qe]),et="default-src 'none'; media-src 'self'; style-src 'unsafe-inline'",Et=`${et}; sandbox`,yt=`${et}; sandbox allow-same-origin`,ve=/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u,bt=/^[\t\n\r ]+|[\t\n\r ]+$/gu,Ne=/^[\t ]+|[\t ]+$/gu,St=e=>{const t=[];let r="",n=0;for(;;){for(;n<e.length&&e[n]!=='"'&&e[n]!==",";)r+=e[n],n+=1;if(n<e.length&&e[n]==='"'){const s=n;for(n+=1;n<e.length&&e[n]!=='"';)n+=e[n]==="\\"?2:1;if(n=Math.min(n+1,e.length),r+=e.slice(s,n),n<e.length)continue}if(t.push(r.replace(Ne,"")),r="",n>=e.length)return t;n+=1}},Tt=e=>{const t=e.replace(bt,""),r=t.indexOf("/");if(r<0)return null;const n=t.slice(0,r),s=t.indexOf(";",r+1),o=t.slice(r+1,s<0?t.length:s).replace(/[\t\n\r ]+$/u,"");return ve.test(n)&&ve.test(o)?`${n}/${o}`.toLowerCase():null},xt=e=>{let t=null;for(const r of St(e)){const n=Tt(r);n!==null&&n!=="*/*"&&(t=n)}return t},Ot=/['()*]/gu,Rt=e=>encodeURIComponent(e).replace(Ot,t=>`%${t.charCodeAt(0).toString(16).toUpperCase()}`),_t=Object.freeze({"Cache-Control":"private, max-age=60, stale-while-revalidate=600, no-transform",Vary:"Cookie"}),kt=(e,t)=>{const r=xt(e),n=r!==null&&gt.has(r),s=n&&(r.startsWith("audio/")||r.startsWith("video/"));return{contentType:r===null?wt:r,inline:n,headers:{"X-Content-Type-Options":"nosniff","Content-Disposition":`${n?"inline":"attachment"}; filename*=UTF-8''${Rt(t)}`,...r===qe?{}:{"Content-Security-Policy":s?yt:Et},"Cross-Origin-Resource-Policy":"same-origin"}}},At=/^bytes=(?:(\d+)-(\d*)|-(\d+))$/iu,pe=Object.freeze({kind:"whole"}),Le=Object.freeze({kind:"unsatisfiable"}),Nt=(e,t,r)=>{const n=e.get("Range");if(n===null)return pe;const s=e.get("If-Range");if(s!==null&&s!==r)return pe;const o=At.exec(n);if(o===null)return pe;const[,c,m,g]=o;if(g!==void 0){const h=Number(g);if(h===0)return Le;const A=Math.max(0,t-h);return{kind:"partial",range:{offset:A,length:t-A}}}const x=Number(c),l=m===""?Number.POSITIVE_INFINITY:Number(m);return l<x?pe:x>=t?Le:{kind:"partial",range:{offset:x,length:Math.min(l,t-1)-x+1}}},$e="W/",Pt=e=>{const t=[];let r=0,n=!1;for(let s=0;s<e.length;s+=1)e[s]==='"'?n=!n:e[s]===","&&!n&&(t.push(e.slice(r,s).replace(Ne,"")),r=s+1);return t.push(e.slice(r).replace(Ne,"")),t},je=e=>e.startsWith($e)?e.slice($e.length):e,It=(e,t)=>{if(e===null)return!1;const r=Pt(e);if(r.length===1&&r[0]==="*")return!0;const n=je(t);return r.some(s=>je(s)===n)},Mt=(e,t)=>{let r=t;return e.pipeThrough(new TransformStream({transform:(n,s)=>{const o=n.byteLength>r?n.subarray(0,r):n;r-=o.byteLength,s.enqueue(o),r===0&&s.terminate()},flush:n=>{r>0&&n.error(new RangeError("[markdown-explorer] the asset ended before its declared length"))}}))},Oe=async(e,t,r,n,s)=>{if(n!==null&&r.set("Content-Length",String(n)),e.method.toUpperCase()==="HEAD")return new Response(null,{status:t,headers:r});const o=await s();return new Response(n===null?o:Mt(o,n),{status:t,headers:r})},vt=(e,t)=>{const r=new Headers(e);for(const[n,s]of Object.entries({"Accept-Ranges":"bytes","Content-Range":`bytes */${t}`,"Cache-Control":"private, no-store","X-Content-Type-Options":"nosniff"}))r.set(n,s);return new Response(null,{status:416,headers:r})},Lt=async(e,t,r)=>{const n=`"${t.version}"`,s=kt(t.contentType,t.name),o=new Headers(r);for(const[g,x]of Object.entries({...s.headers,..._t,ETag:n}))o.set(g,x);if(It(e.headers.get("If-None-Match"),n))return new Response(null,{status:304,headers:o});if(o.set("Content-Type",s.contentType),t.size===null)return Oe(e,200,o,null,()=>t.open(null));if(t.size===0)return o.set("Content-Length","0"),new Response(null,{status:200,headers:o});o.set("Accept-Ranges","bytes");const c=Nt(e.headers,t.size,n);if(c.kind==="unsatisfiable")return vt(r,t.size);if(c.kind==="whole")return Oe(e,200,o,t.size,()=>t.open(null));const{range:m}=c;return o.set("Content-Range",`bytes ${m.offset}-${m.offset+m.length-1}/${t.size}`),Oe(e,206,o,m.length,()=>t.open(m))},Re=(e,t)=>{const r=new AbortController,n=t(AbortSignal.any([e.signal,r.signal]));return new Promise(s=>{let o;const c=setTimeout(()=>{s(e.late),o=setTimeout(()=>r.abort(),e.handOverMs)},e.timeoutMs),m=()=>{clearTimeout(c),clearTimeout(o)};n.then(g=>{m(),s(g)},()=>{m(),s(e.late)})})},$t=Object.freeze({error:(e,t)=>{console.error(e,t)}}),tt=Symbol.for("@aiquants/markdown-explorer:ExplorerError");class me extends Error{reason;code;constructor(t,r={}){if(!y.isExplorerFailureReason(t))throw new RangeError(`[markdown-explorer] ExplorerError needs a failure reason; got ${JSON.stringify(t)}`);if(r.code!==void 0&&!y.isExplorerFailureCode(r.code))throw new RangeError(`[markdown-explorer] an ExplorerError code must be 1 to 64 lowercase letters, digits or hyphens; got ${JSON.stringify(r.code)}`);super(`[markdown-explorer] ${t}`,r.cause===void 0?void 0:{cause:r.cause}),this.name="ExplorerError",this.reason=t,this.code=r.code,Object.defineProperty(this,tt,{value:!0})}}const jt=e=>e instanceof Error&&Object.hasOwn(e,tt)&&y.isExplorerFailureReason(e.reason),Dt=e=>typeof e=="object"&&e!==null&&e.name==="AbortError",Pe=(e,t,r)=>{try{e.error(t,r)}catch(n){console.error("[markdown-explorer] the logger threw while reporting a failure",{operation:r.operation,error:n})}},ne=(e,t)=>Pe(e,`[markdown-explorer] ${t.operation} failed`,t),zt=(e,t)=>Pe(e,`[markdown-explorer] ${t.operation} left out an entry`,t),Ct=(e,t)=>Pe(e,`[markdown-explorer] ${t.operation} refused a path the deny rules match`,{...t,error:new RangeError("[markdown-explorer] the path matches a deny rule")}),De=(e,t)=>{e===null||typeof e!="object"&&typeof e!="function"||Promise.resolve(e).then(void 0,t)},re=(e,t,r,n)=>jt(e)?y.failureOf(e.reason,e.code):(Dt(e)||r.aborted||ne(n,{...t,error:e}),{reason:"failed"}),ze=(e,t)=>{if(!Number.isSafeInteger(t)||t<=0)throw new RangeError(`[markdown-explorer] a cache ${e} must be a positive integer; got ${String(t)}`)},rt=(e,t)=>{ze("capacity",e),t!==void 0&&ze("weight budget",t.max);const r=new Map;let n=0;const s=o=>{const c=r.get(o);c!==void 0&&(r.delete(o),n-=c.weight)};return{get:o=>{const c=r.get(o);if(c!==void 0)return r.delete(o),r.set(o,c),c.value},set:(o,c)=>{s(o);const m=t===void 0?0:t.of(o,c);if(!(t!==void 0&&m>t.max)){r.set(o,{value:c,weight:m}),n+=m;for(const g of r.keys()){if(r.size<=e&&(t===void 0||n<=t.max))break;s(g)}}},delete:s,size:()=>r.size,weight:()=>n}},nt=e=>Math.max(1,e-1),Ht=2147483647,Ce=Object.freeze({status:"aborted"}),se=(e,t,r)=>{const n=(e.get(t)??0)+r;n===0?e.delete(t):e.set(t,n)},ce=(e,t,r)=>{if(!Number.isSafeInteger(t)||t<=0||t>r)throw new RangeError(`[markdown-explorer] a worker pool's ${e} must be an integer in 1..${String(r)}; got ${String(t)}`)},Bt=e=>e!==null&&typeof e=="object"&&e.ready===!0&&!("id"in e),Ft=(e,t)=>e!==null&&typeof e=="object"&&e.id===t&&"output"in e,Ut=({url:e,size:t,deadlineMs:r,jobsPerScope:n,maxQueuedJobs:s,heapLimits:o})=>{ce("size",t,Number.MAX_SAFE_INTEGER),ce("deadline",r,Ht),ce("jobsPerScope",n,Number.MAX_SAFE_INTEGER),ce("maxQueuedJobs",s,Number.MAX_SAFE_INTEGER),ce("maxOldGenerationSizeMb",o.maxOldGenerationSizeMb,Number.MAX_SAFE_INTEGER),ce("maxYoungGenerationSizeMb",o.maxYoungGenerationSizeMb,Number.MAX_SAFE_INTEGER);const c=Object.freeze({maxOldGenerationSizeMb:o.maxOldGenerationSizeMb,maxYoungGenerationSizeMb:o.maxYoungGenerationSizeMb}),m=new Set,g=[],x=new Map,l=new Map,h=nt(t);let A=0;const k=(u,a)=>{const{job:E}=u;u.timer!==null&&clearTimeout(u.timer),u.timer=null,u.job=null,u.sent=!1,E!==null&&(se(x,E.scope,-1),se(l,E.scope,-1),E.settle(a))},I=u=>{const[a]=g.splice(u,1);a?.detach()},R=()=>{let u=-1,a=h,E=Number.POSITIVE_INFINITY;for(const[S,_]of g.entries()){const P=x.get(_.scope)??0,C=l.get(_.scope)??0;(P<a||P===a&&u>=0&&C<E)&&(u=S,a=P,E=C)}return u},O=(u,a)=>{m.has(u)&&(m.delete(u),k(u,a),u.worker.terminate().catch(()=>{}),D())},L=u=>{u.timer=setTimeout(()=>{O(u,{status:"timeout"})},r)},b=(u,a)=>u.sent?{status:"crashed",error:a}:{status:"unavailable",error:a},N=(u,a)=>{u.sent=!0,L(u);try{u.worker.postMessage({id:a.id,input:a.input})}catch(E){k(u,{status:"crashed",error:E}),u.worker.unref()}},z=()=>{const u={worker:new mt.Worker(e,{resourceLimits:c}),job:null,sent:!1,timer:null,ready:!1};return u.worker.unref(),u.timer=setTimeout(()=>{O(u,{status:"unavailable",error:new Error(`[markdown-explorer] a worker did not start within ${String(r)} ms`)})},r),u.worker.on("message",a=>{if(!u.ready&&Bt(a)){u.ready=!0,u.timer!==null&&clearTimeout(u.timer),u.timer=null,u.job===null?u.worker.unref():N(u,u.job),u.job===null&&D();return}const{job:E}=u;if(E===null||!Ft(a,E.id)){O(u,b(u,new Error("[markdown-explorer] a worker sent a message that answers no job")));return}k(u,{status:"done",output:a.output}),u.worker.unref(),D()}),u.worker.on("error",a=>{O(u,b(u,a))}),u.worker.on("messageerror",a=>{O(u,b(u,a))}),u.worker.on("exit",a=>{O(u,b(u,new Error(`[markdown-explorer] a worker exited with code ${String(a)}`)))}),m.add(u),u},D=()=>{for(;;){const u=R(),a=g[u];if(a===void 0)return;let E;for(const _ of m)if(_.job===null){E=_;break}if(E===void 0&&m.size<t)try{E=z()}catch(_){I(u),se(l,a.scope,-1),a.settle({status:"unavailable",error:_});continue}if(E===void 0)return;I(u),se(x,a.scope,1);const S=E;S.job=a,S.worker.ref(),S.ready&&N(S,a)}};return{run:(u,{scope:a,signal:E})=>new Promise(S=>{if(E.aborted){S(Ce);return}if((l.get(a)??0)>=n){S({status:"refused",limit:"scope"});return}A+=1;const _={id:A,input:u,scope:a,settle:S,detach:()=>{}};g.push(_),se(l,a,1),D();const P=g.indexOf(_);if(P<0)return;if(g.length>s){I(P),se(l,a,-1),S({status:"refused",limit:"queue"});return}const C=()=>{const M=g.indexOf(_);M<0||(I(M),se(l,a,-1),S(Ce))};E.addEventListener("abort",C,{once:!0}),_.detach=()=>{E.removeEventListener("abort",C)}}),workers:()=>m.size}},Ie=1024*1024,Xt=3e4,Gt=4*Ie,Jt=64*Ie,Yt=3,Wt=2,Kt=(e,t)=>e+nt(t)+Yt,Vt=4,Qt=32,Zt=512,qt=64,er=4096,tr=32,He=4096,rr=4,ot=({workerHeapMb:e,maxHtmlBytes:t})=>Math.floor(((e-qt)*Ie-t*tr)/er),nr=({maxHtmlBytes:e})=>e,or=({maxHtmlBytes:e})=>rr*e,sr=1024,ir=2147483647,ar=64,cr=2**29,ur=1024*1024,lr=64,Be=Object.freeze({status:"rejected",reason:"too-large",cause:null}),_e=Object.freeze({status:"rejected",reason:"failed",cause:null}),ie=(e,t,r,n)=>{if(t===void 0)return r;if(typeof t!="number")throw new TypeError(`[markdown-explorer] sanitizer.${e} must be a number; got ${typeof t}`);if(!Number.isSafeInteger(t)||t<=0||t>n)throw new RangeError(`[markdown-explorer] sanitizer.${e} must be an integer in 1..${String(n)}; got ${String(t)}`);return t},dr=(e,t)=>{if(e!==void 0&&(e===null||typeof e!="object"))throw new TypeError("[markdown-explorer] sanitizer must be an object of { workers, deadlineMs, maxHtmlBytes, cacheBytes, workerHeapMb, jobsPerScope, maxQueuedJobs }");const{workers:r,deadlineMs:n,maxHtmlBytes:s,cacheBytes:o,workerHeapMb:c,jobsPerScope:m,maxQueuedJobs:g}=e??{},x=ie("workers",r,Wt,ar),l=ie("jobsPerScope",m,Kt(t,x),Number.MAX_SAFE_INTEGER),h=Object.freeze({workers:x,deadlineMs:ie("deadlineMs",n,Xt,ir),maxHtmlBytes:ie("maxHtmlBytes",s,Gt,cr),cacheBytes:ie("cacheBytes",o,Jt,Number.MAX_SAFE_INTEGER),workerHeapMb:ie("workerHeapMb",c,Zt,ur),jobsPerScope:l,maxQueuedJobs:ie("maxQueuedJobs",g,Vt*l,Number.MAX_SAFE_INTEGER)});if(h.jobsPerScope<t)throw new RangeError(`[markdown-explorer] sanitizer.jobsPerScope must be at least multiView.maxPanels (${String(t)}), because a page sends the document of every panel to the sanitizer at once for one reader; got ${String(h.jobsPerScope)}`);if(h.maxQueuedJobs<t)throw new RangeError(`[markdown-explorer] sanitizer.maxQueuedJobs must be at least multiView.maxPanels (${String(t)}), because a reader whose page finds every worker busy waits with the document of every panel; got ${String(h.maxQueuedJobs)}`);if(ot(h)<He)throw new RangeError(`[markdown-explorer] sanitizer.workerHeapMb (${String(h.workerHeapMb)} MiB) must leave room for ${String(He)} parsed nodes beside HTML of sanitizer.maxHtmlBytes (${String(h.maxHtmlBytes)} bytes); raise workerHeapMb or lower maxHtmlBytes`);return h},fr=()=>{const e=typeof document>"u"?require("url").pathToFileURL(__filename).href:xe&&xe.tagName.toUpperCase()==="SCRIPT"&&xe.src||new URL("server.cjs",document.baseURI).href,t=new URL(`./sanitizeWorker${q.extname(Te.fileURLToPath(e))}`,e);if(!te.existsSync(Te.fileURLToPath(t)))throw new Error(`[markdown-explorer] the HTML sanitizer worker is missing: ${Te.fileURLToPath(t)}`);return t},Fe=new Map,mr=(e,t)=>{const r=[e.href,t.workers,t.deadlineMs,t.workerHeapMb,t.jobsPerScope,t.maxQueuedJobs].map(String).join("\0");let n=Fe.get(r);return n===void 0&&(n=Ut({url:e,size:t.workers,deadlineMs:t.deadlineMs,jobsPerScope:t.jobsPerScope,maxQueuedJobs:t.maxQueuedJobs,heapLimits:{maxOldGenerationSizeMb:t.workerHeapMb,maxYoungGenerationSizeMb:Qt}}),Fe.set(r,n)),n},pr=e=>{if(e===null||typeof e!="object")return!1;const{status:t,html:r,message:n}=e;return t==="sanitized"&&typeof r=="string"||t==="too-large"||t==="error"&&typeof n=="string"},hr=e=>e instanceof Error&&e.code==="ERR_WORKER_OUT_OF_MEMORY",wr=({iframeHosts:e,dataPath:t,options:r,pool:n})=>{const s=Object.freeze([...e]),o=ot(r),c=nr(r),m=or(r),g=rt(sr,{max:r.cacheBytes,of:(R,O)=>2*R.length+(O.status==="sanitized"?2*O.html.length:lr)}),x=new Map,l=new Map,h=R=>{x.get(R.key)===R&&x.delete(R.key);const O=l.get(R.hash);O?.delete(R),O?.size===0&&l.delete(R.hash)},A=async(R,O,L)=>{const b=await n.run({html:R,iframeHosts:s,dataPath:t,maxNodes:o,maxAttributeChars:c,maxSanitizedChars:m},{scope:O,signal:L});if(b.status==="refused"){const z=b.limit==="scope"?`its reader already has ${String(r.jobsPerScope)} documents being sanitized or waiting`:`${String(r.maxQueuedJobs)} documents are already waiting`;return{outcome:{status:"rejected",reason:"failed",cause:new Error(`[markdown-explorer] the HTML sanitizer refused a document: ${z}`)},lasting:!1}}if(b.status==="aborted")return{outcome:_e,lasting:!1};if(b.status==="timeout")return{outcome:{status:"rejected",reason:"too-large",cause:new Error(`[markdown-explorer] the HTML sanitizer did not finish within ${String(r.deadlineMs)} ms`)},lasting:!0};if(b.status==="unavailable")return{outcome:{status:"rejected",reason:"failed",cause:new Error("[markdown-explorer] the HTML sanitizer worker could not start",{cause:b.error})},lasting:!1};if(b.status==="crashed"&&hr(b.error))return{outcome:{status:"rejected",reason:"too-large",cause:new Error(`[markdown-explorer] the HTML sanitizer ran out of its ${String(r.workerHeapMb)} MiB worker heap`,{cause:b.error})},lasting:!0};if(b.status==="crashed")return{outcome:{status:"rejected",reason:"failed",cause:new Error("[markdown-explorer] the HTML sanitizer worker failed",{cause:b.error})},lasting:!0};const{output:N}=b;return pr(N)?N.status==="too-large"?{outcome:Be,lasting:!0}:N.status==="error"?{outcome:{status:"rejected",reason:"failed",cause:new Error(`[markdown-explorer] the HTML sanitizer failed: ${N.message}`)},lasting:!0}:N.html.length>m?{outcome:{status:"rejected",reason:"too-large",cause:new Error(`[markdown-explorer] the HTML sanitizer's output of ${String(N.html.length)} characters exceeds its limit of ${String(m)}`)},lasting:!0}:{outcome:{status:"sanitized",html:N.html},lasting:!0}:{outcome:{status:"rejected",reason:"failed",cause:new Error("[markdown-explorer] the HTML sanitizer worker answered something that is not an outcome")},lasting:!0}},k=(R,O,L,b)=>{let N=()=>{};const z=new Promise(a=>{N=a}),D={hash:O,key:L,outcome:z,answer:N,controller:new AbortController,waiters:0};x.set(L,D);const u=l.get(O);return u===void 0?l.set(O,new Set([D])):u.add(D),A(R,b,D.controller.signal).catch(a=>({outcome:{status:"rejected",reason:"failed",cause:a instanceof Error?a:new Error(String(a))},lasting:!0})).then(({outcome:a,lasting:E})=>{if(h(D),D.answer(a),!E)return;const S=g.get(O),_=S??(a.status==="rejected"?{...a,cause:null}:a);S===void 0&&g.set(O,_);for(const P of l.get(O)??[])h(P),P.answer(_),P.controller.abort()}),D},I=(R,O)=>new Promise(L=>{R.waiters+=1;const b=()=>{R.waiters-=1,L(_e),!(R.waiters>0)&&(h(R),R.controller.abort())};O.addEventListener("abort",b,{once:!0}),R.outcome.then(N=>{O.removeEventListener("abort",b),L(N)})});return(R,{scope:O,signal:L})=>{if(R.length>r.maxHtmlBytes||Buffer.byteLength(R,"utf8")>r.maxHtmlBytes)return Promise.resolve(Be);const b=Ze.createHash("sha256").update(R,"utf8").digest("base64"),N=g.get(b);if(N!==void 0)return Promise.resolve(N);if(L.aborted)return Promise.resolve(_e);const z=`${b}\0${O}`,D=x.get(z);return I(D===void 0?k(R,b,z,O):D,L)}},be=e=>({result:e,json:JSON.stringify(e)}),ke=Object.freeze(be(Object.freeze({status:"error",failure:Object.freeze({reason:"failed"})}))),gr=e=>e.status==="ok"&&e.entries.length>0,Er=({ttlMs:e,maxEntries:t,maxBytes:r,now:n})=>{const s=rt(t,{max:r,of:(l,h)=>2*h.tree.json.length}),o=new Map,c=new Map,m=(l,h)=>{const A=new AbortController,k={waiters:0,superseded:!1,started:!1,loadTree:h},I=c.get(l),R=(z,D)=>{const u=be(z);return!(k.superseded||A.signal.aborted)&&gr(z)&&s.set(l,{tree:u,loadedAt:D}),u},L=(async()=>{if(I!==void 0&&await I,A.signal.aborted)return ke;const z=n();return k.started=!0,R(await k.loadTree(A.signal,z),z)})().finally(()=>{o.get(l)===b&&o.delete(l)}),b={promise:L,controller:A,state:k};o.set(l,b);const N=L.then(()=>{},()=>{});return c.set(l,N),N.then(()=>{c.get(l)===N&&c.delete(l)}),b},g=(l,h,A)=>{h.state.waiters+=1;const k=()=>{h.state.waiters-=1,!(h.state.waiters>0)&&(o.get(l)===h&&o.delete(l),h.controller.abort())};return A.addEventListener("abort",k,{once:!0}),h.promise.finally(()=>{A.removeEventListener("abort",k)})},x=l=>{s.delete(l);const h=o.get(l);h?.state.started&&(h.state.superseded=!0,o.delete(l))};return{load:(l,h,A)=>{if(h.aborted)return Promise.resolve(ke);const k=s.get(l);if(k!==void 0){if(n()-k.loadedAt<e)return Promise.resolve(k.tree);s.delete(l)}const I=o.get(l);return g(l,I===void 0?m(l,A):I,h)},refresh:(l,h,A)=>{if(h.aborted)return Promise.resolve(ke);x(l);const k=o.get(l);return k===void 0?g(l,m(l,A),h):(k.state.loadTree=A,g(l,k,h))},forget:x}},yr=e=>({load:(t,r,n)=>n(r,e()).then(be),refresh:(t,r,n)=>n(r,e()).then(be),forget:()=>{}}),v=e=>{throw new TypeError(`[markdown-explorer] ${e}`)},br=e=>{if(e===null||typeof e!="object")return null;const{name:t,path:r}=e;return typeof t!="string"||typeof r!="string"?null:t===""?{path:r,reason:"an empty name"}:y.isAcceptableDocumentPath(r)?null:{path:r,reason:"a path the browser cannot address (empty, too long, a lone surrogate, a control character or a backslash)"}},Sr=(e,t,r,n,s)=>{const o=new Set,c=g=>{if(!Array.isArray(g))return v("a source returned entries that are not an array");const x=[];for(const l of g){const h=m(l);h!==null&&x.push(h)}return x},m=g=>{const x=br(g);if(x!==null)return n(x),null;const l=y.entryViolation(g);if(l!==null)return v(l);const h=g;if(o.has(h))return v("a source returned entries that contain themselves");const{name:A,path:k,type:I,mimeType:R,children:O,lazy:L}=h;if(t.deniesName(A)||t.deniesPath(k))return null;if(!s(k))return n({path:k,reason:"a path outside the source's boundary"}),null;const b=R===void 0?{name:A,path:k}:{name:A,path:k,mimeType:R};if(I==="file")return{...b,type:I};if(L===!0)return r?{...b,type:I,lazy:!0,children:[]}:v("a lazy directory came from a source without a children function");if(O===void 0)return{...b,type:I};o.add(h);const N=c(O);return o.delete(h),{...b,type:I,children:N}};return c(e)},Tr=/^[\x21\x23-\x7E]{1,256}$/u,st=e=>typeof e=="string"&&Tr.test(e),xr=new Set(["text","image","media","file"]),Or=e=>typeof e=="string"&&xr.has(e),Rr=(e,t)=>{if(e!==null&&typeof e=="object"){const s=e,{kind:o}=s;if(Or(o)){if(Object.hasOwn(s,"url"))return v(`a ${o} document carries its version, not a url`);if(typeof s.name!="string")return v("a document needs a name string");if(!st(s.version))return v(`a ${o} document needs a version of 1 to 256 visible ASCII characters other than '"'`);const c=t(s.version);switch(o){case"image":case"file":return{kind:o,name:s.name,url:c};case"media":{const{mediaType:m}=s;return y.isExplorerMediaType(m)?{kind:o,name:s.name,url:c,mediaType:m}:v(`unknown media type ${typeof m=="string"?JSON.stringify(m.slice(0,64)):typeof m}`)}case"text":return typeof s.text!="string"||typeof s.truncated!="boolean"?v("a text document needs text and truncated"):{kind:o,name:s.name,text:s.text,truncated:s.truncated,url:c}}}}const r=y.documentViolation(e);if(r!==null)return v(r);const n=e;switch(n.kind){case"failure":{const{reason:s,code:o}=n.failure;return{kind:"failure",failure:y.failureOf(s,o)}}case"markdown":return n.headings.length>y.EXPLORER_MAX_HEADINGS?{kind:"failure",failure:y.failureOf("too-large")}:{kind:"unsanitized-markdown",name:n.name,html:n.htmlContent,headings:n.headings.map(({text:s,depth:o,id:c})=>({text:s,depth:o,id:c}))}}},_r=e=>{if(e===null||typeof e!="object")return v("an asset file must be an object");const{name:t,contentType:r,size:n,version:s,open:o}=e;return typeof t!="string"||t===""?v("an asset file needs a non-empty name"):typeof r!="string"?v("an asset file needs a contentType string ('' when unknown)"):n!==null&&!(typeof n=="number"&&Number.isSafeInteger(n)&&n>=0)?v("an asset file's size must be null or a non-negative safe integer"):st(s)?typeof o!="function"?v("an asset file needs an open function"):Object.freeze({name:t,contentType:r,size:n,version:s,open:o}):v(`an asset file needs a version of 1 to 256 visible ASCII characters other than '"'`)},kr=e=>Array.isArray(e)?e.map(t=>{if(t===null||typeof t!="object")return v("a notice must be an object");const{id:r,tone:n,title:s,body:o,action:c}=t;if(typeof r!="string"||r===""||typeof s!="string")return v("a notice needs an id and a title");if(!y.isExplorerNoticeTone(n))return v(`unknown notice tone ${typeof n=="string"?JSON.stringify(n.slice(0,64)):typeof n}`);if(o!==void 0&&typeof o!="string")return v("a notice body must be a string");const g={id:r,tone:n,title:s,...o===void 0?{}:{body:o}};if(c===void 0)return g;if(c===null||typeof c!="object")return v("a notice action must be an object");const{label:x,href:l}=c;return typeof x!="string"||!y.isAcceptableUrl(l,y.EXPLORER_LINK_PROTOCOLS)?v("a notice action needs a label and an http(s), mailto or relative href"):{...g,action:{label:x,href:l}}}):v("notices must be an array"),Ar=4e3,he=Object.freeze({ttlMs:3e5,maxEntries:64,maxBytes:64*1024*1024}),Ue=32,it="private, no-store",Nr=Object.freeze({"Content-Type":"application/json; charset=utf-8","Cache-Control":it,"X-Content-Type-Options":"nosniff","Content-Security-Policy":"default-src 'none'; frame-ancestors 'none'; sandbox","Cross-Origin-Resource-Policy":"same-origin"}),Pr=22,Ir=2147483647,Ae=Object.freeze([]),Xe=Object.freeze(["contains","confirm"]),J=(e,t,r)=>{if(!(r&&t===void 0)&&typeof t!="function")throw new TypeError(`[markdown-explorer] ${e} must be a function; got ${typeof t}`)},ye=(e,t,r)=>{if(typeof t!="number")throw new TypeError(`[markdown-explorer] ${e} must be a number; got ${typeof t}`);if(!Number.isSafeInteger(t)||t<=0||t>r)throw new RangeError(`[markdown-explorer] ${e} must be an integer in 1..${String(r)}; got ${String(t)}`);return t},Mr=e=>{if(e===null||typeof e!="object"||!Object.isFrozen(e))throw new TypeError("[markdown-explorer] config must be the value returned by defineExplorerConfig");return ee.defineExplorerConfig(e)},vr=e=>{if(typeof e!="string")throw new TypeError(`[markdown-explorer] scopeSecret must be a string; got ${typeof e}`);if(e.length<Ue)throw new RangeError(`[markdown-explorer] scopeSecret must have at least ${String(Ue)} characters; got ${String(e.length)}`);return e},Lr=(e,t)=>{if(!ee.isPlainObject(t))throw new TypeError(`[markdown-explorer] ${e}.boundary must be a plain object { contains, confirm? }`);for(const r of Object.keys(t))if(!Xe.includes(r))throw new RangeError(`[markdown-explorer] ${e}.boundary.${r} is not an option; expected ${Xe.join(", ")}`);J(`${e}.boundary.contains`,t.contains,!1),J(`${e}.boundary.confirm`,t.confirm,!0)},$r=e=>{if(!Array.isArray(e))throw new TypeError("[markdown-explorer] sources must be an array");const t=e;if(t.length===0)throw new RangeError("[markdown-explorer] sources must hold at least one source");const r=new Set;for(const[n,s]of t.entries()){if(s===null||typeof s!="object")throw new TypeError(`[markdown-explorer] sources[${String(n)}] must be an object`);const{id:o,label:c,boundary:m,tree:g,children:x,cacheScope:l}=s;if(!ee.isExplorerSourceId(o))throw new RangeError(`[markdown-explorer] sources[${String(n)}].id must use lowercase letters, digits and "-" and start with a letter or digit; got ${typeof o=="string"?JSON.stringify(o):typeof o}`);const h=`source ${JSON.stringify(o)}`;if(r.has(o))throw new RangeError(`[markdown-explorer] source ids must be unique; ${JSON.stringify(o)} repeats at sources[${String(n)}]`);if(r.add(o),typeof c!="string"&&typeof c!="function")throw new TypeError(`[markdown-explorer] ${h}.label must be a string or a function`);if(typeof c=="string"&&c.trim()==="")throw new RangeError(`[markdown-explorer] ${h}.label must not be blank`);if(Lr(h,m),J(`${h}.tree`,g,!1),J(`${h}.children`,x,!0),l!==void 0&&l!=="principal"&&l!=="shared")throw new RangeError(`[markdown-explorer] ${h}.cacheScope must be "principal" or "shared"; got ${JSON.stringify(l)}`)}return t},jr=e=>{if(e===!1)return!1;if(e===void 0)return he;if(e===null||typeof e!="object")throw new TypeError("[markdown-explorer] treeCache must be { ttlMs, maxEntries, maxBytes } or false");const{ttlMs:t,maxEntries:r,maxBytes:n}=e;return{ttlMs:t===void 0?he.ttlMs:ye("treeCache.ttlMs",t,Number.MAX_SAFE_INTEGER),maxEntries:r===void 0?he.maxEntries:ye("treeCache.maxEntries",r,Number.MAX_SAFE_INTEGER),maxBytes:n===void 0?he.maxBytes:ye("treeCache.maxBytes",n,Number.MAX_SAFE_INTEGER)}},Ge=e=>{if(e===null||typeof e!="object")throw new TypeError("[markdown-explorer] authenticate must resolve to { status, ... }");const{status:t}=e;if(t!=="signed-in"&&t!=="signed-out"&&t!=="forbidden")throw new TypeError(`[markdown-explorer] authenticate resolved to an unknown status ${JSON.stringify(t)}`);return e},Je=(e,t)=>{if(!(t instanceof Response))throw new TypeError(`[markdown-explorer] ${e} must return a Response`);return t},Ye=(e,t)=>{if(typeof t!="string"||t==="")throw new TypeError("[markdown-explorer] principalKey must return a non-empty string");return Ze.createHmac("sha256",e).update(t,"utf8").digest("base64url").slice(0,Pr)},Dr=e=>e.view==="multi"?e.docs:e.doc===null?[]:[e.doc],we=(e,t)=>{const r=e.getAll(t),[n]=r;return r.length===1&&n!==void 0&&n!==""?n:null},ue=(e,t,r,n={})=>{const s=new Headers(r);for(const[o,c]of Object.entries({...Nr,...n}))s.set(o,c);return new Response(t,{status:e,headers:s})},U=(e,t,r)=>ue(y.EXPLORER_FAILURE_STATUS[e.reason],JSON.stringify({failure:e}),t,r),We=e=>{if(e.headers.get(y.EXPLORER_REFRESH_HEADER)!==y.EXPLORER_REFRESH_HEADER_VALUE)return!1;const t=e.headers.get("Sec-Fetch-Site");return t===null||t==="same-origin"},zr=({parentHeaders:e,loaderHeaders:t,errorHeaders:r})=>{const n=new Headers,s=r===void 0?[e,t]:[e,t,r];for(const o of s)for(const[c,m]of o)c!=="set-cookie"&&n.set(c,m);return n},Cr=e=>{if(e===null||typeof e!="object")throw new TypeError("[markdown-explorer] the server configuration must be an object");const t=Mr(e.config),r=vr(e.scopeSecret);J("authenticate",e.authenticate,!1),J("principalKey",e.principalKey,!1),J("document",e.document,!1),J("asset",e.asset,!1),J("signedOutPage",e.signedOutPage,!1),J("forbiddenPage",e.forbiddenPage,!0),J("notices",e.notices,!0),J("onTreeRefreshed",e.onTreeRefreshed,!0);const n=$r(e.sources),s=ee.withExplorerSources(t,n.map(i=>i.id)),o=e.logger;if(o!==void 0&&(o===null||typeof o!="object"||typeof o.error!="function"))throw new TypeError("[markdown-explorer] logger must be an object with an error function");const c=e.logger===void 0?$t:e.logger,m=y.resolvePathRules(e.deny),g=e.deferredTimeoutMs===void 0?Ar:ye("deferredTimeoutMs",e.deferredTimeoutMs,Ir),x=jr(e.treeCache),l=()=>Date.now(),h=x===!1?yr(l):Er({...x,now:l}),A=dr(e.sanitizer,t.multiView.maxPanels),k=wr({iframeHosts:t.iframeHosts,dataPath:t.dataPath,options:A,pool:mr(fr(),A)}),I=new Map(n.map(i=>[i.id,i])),R=ee.documentStyleNames(t),{authenticate:O,principalKey:L,signedOutPage:b,forbiddenPage:N,onTreeRefreshed:z}=e,D=(i,w)=>{if(typeof i.label=="string")return i.label;const d=i.label(w);if(typeof d!="string"||d.trim()==="")throw new TypeError(`[markdown-explorer] the label of source ${JSON.stringify(i.id)} must be a non-blank string`);return d},u=(i,w)=>i.cacheScope==="shared"?i.id:`${i.id}\0${w}`,a=(i,w)=>{const d=f=>ne(c,{operation:"boundary",sourceId:i.id,path:w,error:f});let p;try{p=i.boundary.contains(w)}catch(f){return d(f),!1}return typeof p=="boolean"?p:(De(p,d),d(new TypeError(`[markdown-explorer] boundary.contains of source ${JSON.stringify(i.id)} must return a boolean; got ${typeof p}`)),!1)},E=async(i,w,d)=>{const{confirm:p}=i.boundary;if(p===void 0)return{status:"inside",readPath:d};let f;try{f=await p(w,d)}catch(V){return{status:"error",failure:re(V,{operation:"boundary",sourceId:i.id,path:d},w.signal,c)}}const T=V=>(ne(c,{operation:"boundary",sourceId:i.id,path:d,error:new TypeError(`[markdown-explorer] boundary.confirm of source ${JSON.stringify(i.id)} ${V}`)}),{status:"outside"});if(f===null||typeof f!="object")return T(`must resolve to { inside, readPath? }; got ${f===null?"null":typeof f}`);const{inside:j,readPath:H}=f;return j===!1?{status:"outside"}:j!==!0||typeof H!="string"?T("must resolve to { inside: false } or { inside: true, readPath: string }"):!y.isAcceptableDocumentPath(H)||m.deniesPath(H)?(ne(c,{operation:"boundary",sourceId:i.id,path:d,error:new RangeError(`[markdown-explorer] boundary.confirm of source ${JSON.stringify(i.id)} answered a readPath the explorer does not serve (unacceptable or denied)`)}),{status:"error",failure:{reason:"failed"}}):{status:"inside",readPath:H}},S=async(i,w)=>{const d=n.filter(f=>a(f,w));if(d.length===0)return{status:"error",failure:{reason:"forbidden"}};if(d.some(f=>f.boundary.confirm===void 0))return{status:"inside",readPath:w};let p=null;for(const f of d){const T=await E(f,i,w);if(T.status==="inside")return T;T.status==="error"&&p===null&&(p=T.failure)}return{status:"error",failure:p===null?{reason:"forbidden"}:p}},_=(i,w,d)=>{const p=({path:f,reason:T})=>zt(c,{operation:d.operation,sourceId:d.sourceId,path:f,error:new TypeError(`[markdown-explorer] an entry with ${T} was left out`)});try{return{status:"ok",entries:Sr(i,m,w.children!==void 0,p,f=>a(w,f))}}catch(f){return ne(c,{...d,error:f}),{status:"error",failure:{reason:"failed"}}}},P=async(i,w,d)=>{let p;try{p=await i.tree(w)}catch(T){return{status:"error",failure:re(T,{operation:"tree",sourceId:i.id},w.signal,c)}}const f=_(p,i,{operation:"tree",sourceId:i.id});return f.status==="ok"?{status:"ok",entries:f.entries,loadedAt:d}:f},C=(i,w,d,p)=>(f,T)=>P(i,{principal:w,request:d,signal:f,refresh:p},T),M=(i,w,d,p,f)=>h.load(u(i,d),f,C(i,w,p,!1)),X=(i,w,d,p)=>h.refresh(u(i,d),p.signal,C(i,w,p,!0)),G=(i,w)=>{if(z===void 0)return;const d=p=>ne(c,{operation:"refresh",sourceId:i.id,error:p});try{De(z(w),d)}catch(p){d(p)}},F=async(i,w,d,p)=>{if(m.deniesPath(p)||!a(i,p))return{status:"error",failure:{reason:"forbidden"}};const f=await E(i,d,p);if(f.status==="outside")return{status:"error",failure:{reason:"forbidden"}};if(f.status==="error")return{status:"error",failure:f.failure};let T;try{T=await w(d,p,f.readPath)}catch(j){return{status:"error",failure:re(j,{operation:"children",sourceId:i.id,path:p},d.signal,c)}}return _(T,i,{operation:"children",sourceId:i.id,path:p})},Z=async(i,w,d)=>{if(m.deniesPath(d))return y.failureDocument("forbidden");const p=await S(i,d);if(p.status==="error")return{kind:"failure",failure:p.failure};let f;try{f=await e.document(i,d,p.readPath)}catch(H){return{kind:"failure",failure:re(H,{operation:"document",path:d},i.signal,c)}}let T;try{T=Rr(f,H=>y.explorerAssetHref(t.dataPath,d,H))}catch(H){return ne(c,{operation:"document",path:d,error:H}),y.failureDocument("failed")}if(T.kind!=="unsanitized-markdown")return T;const j=await k(T.html,{scope:w,signal:i.signal});return j.status==="sanitized"?{kind:"markdown",name:T.name,htmlContent:j.html,headings:T.headings}:(j.cause!==null&&ne(c,{operation:"document",path:d,error:j.cause}),y.failureDocument(j.reason))},$=async i=>{if(e.notices===void 0)return Ae;try{return kr(await e.notices(i))}catch(w){return re(w,{operation:"notices"},i.signal,c),Ae}},Y=async(i,w,d)=>{const p=we(w,y.EXPLORER_DATA_QUERY.path);if(p===null||!y.isAcceptableDocumentPath(p))return U({reason:"invalid"},d);if(m.deniesPath(p))return Ct(c,{operation:"asset",path:p}),U({reason:"forbidden"},d);const f=await S(i,p);if(f.status==="error")return U(f.failure,d);try{const T=_r(await e.asset(i,p,f.readPath));return await Lt(i.request,T,d)}catch(T){return U(re(T,{operation:"asset",path:p},i.signal,c),d)}},W=async({request:i,url:w,params:d})=>{const p=Ge(await O(i)),f=new Headers(p.headers);if(f.set("Cache-Control",it),p.status==="signed-out")throw Je("signedOutPage",b(i,f));if(p.status==="forbidden")throw N===void 0?Se.data(null,{status:403,headers:f}):Je("forbiddenPage",N(i,f));const T=ee.resolveExplorerLocation(s,d["*"],w.searchParams);if(T.kind==="redirect")throw Se.redirect(T.href,{headers:f});const{location:j}=T,{principal:H}=p,V=Ye(r,L(H)),de=I.get(j.source);if(de===void 0)throw new RangeError(`[markdown-explorer] no source for ${JSON.stringify(j.source)}`);const oe={signal:i.signal,timeoutMs:g,late:null,handOverMs:g},Q={scope:V,sources:n.map(B=>({id:B.id,label:D(B,H)})),settings:ee.parseViewSettings(ee.readCookieValue(i.headers.get("Cookie"),t.settingsCookie),R),tree:j.view==="single"?null:{sourceId:j.source,result:Re(oe,B=>M(de,H,V,i,B).then(ae=>ae.result))},documents:Dr(j).map(B=>({path:B,document:Re(oe,ae=>Z({principal:H,request:i,signal:ae,refresh:!1},V,B))})),notices:Re({signal:i.signal,timeoutMs:g,late:Ae,handOverMs:0},B=>$({principal:H,request:i,signal:B,refresh:!1}))};return Se.data(Q,{headers:f})},K=async(i,w,d)=>{let p;try{p=Ge(await O(w))}catch(B){return U(re(B,{operation:"authenticate"},w.signal,c))}const f=new Headers(p.headers);if(p.status==="signed-out")return U({reason:"unauthorized"},f);if(p.status==="forbidden")return U({reason:"forbidden"},f);const{principal:T}=p;if(i==="asset")return Y({principal:T,request:w,signal:w.signal,refresh:!1},d,f);const j=Ye(r,L(T));f.set(y.EXPLORER_SCOPE_HEADER,j);const H={principal:T,request:w,signal:w.signal,refresh:!1},V=()=>U({reason:"invalid"},f);if(i==="document"){const B=we(d,y.EXPLORER_DATA_QUERY.path);if(B===null||!y.isAcceptableDocumentPath(B))return V();const ae=w.headers.has(y.EXPLORER_REFRESH_HEADER);return ae&&!We(w)?U({reason:"forbidden"},f):ue(200,JSON.stringify(await Z({...H,refresh:ae},j,B)),f)}const de=we(d,y.EXPLORER_DATA_QUERY.source),oe=we(d,y.EXPLORER_DATA_QUERY.path);if(de===null||i==="children"&&(oe===null||!y.isAcceptableDocumentPath(oe)))return V();const Q=I.get(de);if(Q===void 0)return U({reason:"not-found"},f);if(i==="tree")return ue(200,(await M(Q,T,j,w,w.signal)).json,f);if(i==="refresh"){const B=await X(Q,T,j,w);return w.signal.aborted||G(Q,u(Q,j)),ue(200,B.json,f)}return Q.children===void 0||oe===null?U({reason:"not-found"},f):ue(200,JSON.stringify(await F(Q,Q.children,H,oe)),f)},le=async(i,w,d)=>{if(new URL(i.url).pathname.endsWith(".data"))return U({reason:"not-found"});if(!y.isExplorerDataOperation(d))return U({reason:"not-found"});const p=i.method.toUpperCase(),f=d==="refresh";if(f?p!=="POST":p!=="GET"&&p!=="HEAD")return ue(405,JSON.stringify({failure:{reason:"invalid"}}),void 0,{Allow:f?"POST":"GET, HEAD"});if(f&&!We(i))return U({reason:"forbidden"});try{return await K(d,i,w.searchParams)}catch(T){return U(re(T,{operation:d},i.signal,c))}};return Object.freeze({loader:W,headers:zr,dataLoader:({request:i,url:w,params:d})=>le(i,w,d["*"]),dataAction:({request:i,url:w,params:d})=>le(i,w,d["*"]),forgetTree:i=>{if(typeof i!="string")throw new TypeError(`[markdown-explorer] forgetTree needs the string key onTreeRefreshed received; got ${typeof i}`);h.forget(i)}})},ge=Object.freeze({maxEntries:2e4,maxDocumentBytes:2*1024*1024,textPreviewBytes:8*1024,walkConcurrency:8}),Hr=new Set(["md","markdown","mdx"]),at=new Map([...[["png","image/png"],["jpg","image/jpeg"],["jpeg","image/jpeg"],["gif","image/gif"],["svg","image/svg+xml"],["webp","image/webp"],["ico","image/x-icon"],["bmp","image/bmp"],["tif","image/tiff"],["tiff","image/tiff"],["avif","image/avif"]].map(([e,t])=>[e,{kind:"image",contentType:t}]),...[["mp4","video/mp4"],["m4v","video/mp4"],["webm","video/webm"],["mov","video/quicktime"],["avi","video/x-msvideo"],["mkv","video/x-matroska"],["ogv","video/ogg"]].map(([e,t])=>[e,{kind:"media",mediaType:"video",contentType:t}]),...[["mp3","audio/mpeg"],["wav","audio/wav"],["ogg","audio/ogg"],["oga","audio/ogg"],["opus","audio/ogg"],["m4a","audio/mp4"],["flac","audio/flac"],["aac","audio/aac"],["wma","audio/x-ms-wma"]].map(([e,t])=>[e,{kind:"media",mediaType:"audio",contentType:t}]),["pdf",{kind:"media",mediaType:"pdf",contentType:"application/pdf"}]]),Br=new Set(["txt","text","log","csv","tsv","json","jsonc","json5","ndjson","yaml","yml","toml","ini","cfg","conf","properties","xml","xsl","xsd","dtd","html","htm","xhtml","css","scss","sass","less","styl","js","mjs","cjs","jsx","ts","mts","cts","tsx","vue","svelte","astro","py","pyi","rb","go","rs","java","kt","kts","scala","groovy","gradle","c","h","cc","cpp","cxx","hpp","hh","hxx","cs","fs","vb","swift","m","mm","php","pl","pm","r","jl","lua","dart","ex","exs","erl","hrl","hs","ml","mli","clj","cljs","elm","nim","zig","v","sol","tf","hcl","nix","sh","bash","zsh","fish","ps1","psm1","bat","cmd","sql","graphql","gql","proto","thrift","avsc","rst","adoc","asciidoc","tex","bib","org","textile","diff","patch","srt","vtt","ics","vcf","gitignore","gitattributes","editorconfig","dockerignore","npmignore","prettierrc","eslintrc","babelrc","mailmap"]),Fr=new Set(["readme","license","licence","copying","notice","authors","contributors","changelog","changes","todo","makefile","dockerfile","containerfile","procfile","gemfile","rakefile","vagrantfile","jenkinsfile","brewfile","codeowners"]),ct=typeof te.constants.O_NOFOLLOW=="number"?te.constants.O_NOFOLLOW:0,ut=typeof te.constants.O_NONBLOCK=="number"?te.constants.O_NONBLOCK:0,Ke=e=>`${e.size}-${e.mtimeNs}`,Ur=e=>e!==""&&e!=="."&&e!==".."&&!e.includes(":")&&!e.endsWith(".")&&!e.endsWith(" "),Ve=e=>y.isAcceptableDocumentPath(e)&&e===e.normalize("NFC")&&e.split("/").every(Ur),lt=e=>{const t=e.toLowerCase(),r=t.lastIndexOf(".");return r<0?"":t.slice(r+1)},Xr=e=>{const t=lt(e);if(Hr.has(t))return{kind:"markdown"};const r=at.get(t);if(r!==void 0)return r.kind==="image"?{kind:"image"}:{kind:"media",mediaType:r.mediaType};const n=e.toLowerCase();return Br.has(t)||!n.includes(".")&&Fr.has(n)?{kind:"text"}:{kind:"file"}},dt=e=>{switch(typeof e=="object"&&e!==null?e.code:void 0){case"ENOENT":case"ENOTDIR":return"not-found";case"ELOOP":case"EACCES":case"EPERM":return"forbidden";case"ENAMETOOLONG":return"invalid";case"EISDIR":return"unsupported";default:return null}},ft=e=>{const t=dt(e);return t===null?e:new me(t)},Gr=e=>{const t=typeof e=="object"&&e!==null?e.code:void 0;return t==="EACCES"||t==="EPERM"||t==="ENOENT"||t==="ENOTDIR"},Qe=async(e,t)=>{const r=[];for await(const n of e.createReadStream({start:0,end:t-1,autoClose:!1}))r.push(n);return Buffer.concat(r)},Jr=(e,t)=>e!==null?{start:e.offset,end:e.offset+e.length-1}:t===0n?{}:{start:0,end:Number(t)-1},Yr=async(e,t,r,n)=>{let s;try{s=await fe.open(e,te.constants.O_RDONLY|ct|ut);const g=await s.stat({bigint:!0});if(!g.isFile()||g.ino!==t.ino||g.dev!==t.dev||g.size!==t.size||g.mtimeNs!==t.mtimeNs)throw new me("not-found")}catch(g){throw await s?.close(),ft(g)}const o=s.createReadStream(Jr(r,t.size)),c=pt.Readable.toWeb(o),m=()=>{o.destroy(n.reason)};return n.aborted?m():n.addEventListener("abort",m,{once:!0}),c},Wr=(e,t)=>{const r=ee.NAME_COLLATOR.compare(e,t);return r!==0?r:e===t?0:e<t?-1:1},Kr=e=>{let t=0;const r=[];return async n=>{t<e?t+=1:await new Promise(s=>r.push(s));try{return await n()}finally{const s=r.shift();s===void 0?t-=1:s()}}},Vr=(e,t)=>{if(e.isSymbolicLink())return"symbolic-link";if(!(e.isDirectory()||e.isFile()))return"special-file";const{name:r}=e;return r!==r.normalize("NFC")?"not-nfc":r.includes(":")?"colon":r.endsWith(".")||r.endsWith(" ")?"trailing-dot-or-space":y.isAcceptableDocumentPath(r)?y.isAcceptableDocumentPath(t)?null:"path-too-long":"control-character-or-backslash"},Qr=new Set(["id","label","root","pathPrefix","parse","deny","maxEntries","maxDocumentBytes","textPreviewBytes","walkConcurrency","cacheScope","reportSkipped"]),Ee=(e,t,r)=>{if(t===void 0)return r;if(typeof t!="number"||!Number.isSafeInteger(t)||t<=0)throw new RangeError(`[markdown-explorer] ${e} must be a positive integer; got ${String(t)}`);return t},Zr=e=>{if(e===null||typeof e!="object")throw new TypeError("[markdown-explorer] createFileSystemSource needs an options object");for(const a of Object.keys(e))if(!Qr.has(a))throw new TypeError(`[markdown-explorer] createFileSystemSource does not know the option ${JSON.stringify(a)}`);const{id:t,label:r,root:n,parse:s}=e;if(typeof t!="string"||t==="")throw new TypeError("[markdown-explorer] a file-system source needs a non-empty id");if(typeof r!="string"||r.trim()==="")throw new TypeError("[markdown-explorer] a file-system source needs a non-blank label");if(typeof s!="function")throw new TypeError("[markdown-explorer] a file-system source needs a parse function");if(typeof n!="string"||!q.isAbsolute(n))throw new RangeError(`[markdown-explorer] root must be an absolute path; got ${JSON.stringify(n)}`);let o;try{o=te.statSync(n).isDirectory()}catch(a){throw new RangeError(`[markdown-explorer] root does not exist: ${n}`,{cause:a})}if(!o)throw new RangeError(`[markdown-explorer] root is not a directory: ${n}`);const c=te.realpathSync(n),m=e.pathPrefix;if(typeof m!="string")throw new TypeError('[markdown-explorer] pathPrefix is required: "" for a source over the whole root, or relative segments ending with "/"');if(m!==""&&!(m.endsWith("/")&&Ve(m.slice(0,-1))))throw new RangeError(`[markdown-explorer] pathPrefix must be empty or relative segments ending with "/"; got ${JSON.stringify(m)}`);const g=y.resolvePathRules(e.deny),x=Ee("maxEntries",e.maxEntries,ge.maxEntries),l=Ee("maxDocumentBytes",e.maxDocumentBytes,ge.maxDocumentBytes),h=Ee("textPreviewBytes",e.textPreviewBytes,ge.textPreviewBytes),A=Ee("walkConcurrency",e.walkConcurrency,ge.walkConcurrency),k=e.cacheScope===void 0?"principal":e.cacheScope;if(k!=="principal"&&k!=="shared")throw new RangeError(`[markdown-explorer] cacheScope must be "principal" or "shared"; got ${JSON.stringify(k)}`);const I=e.reportSkipped;if(I!==void 0&&typeof I!="function")throw new TypeError("[markdown-explorer] reportSkipped must be a function");const R=I===void 0?a=>{console.warn(`[markdown-explorer] the file-system source ${JSON.stringify(a.sourceId)} does not list ${JSON.stringify(a.path)}: ${a.reason}`)}:I,O=new Set,L=a=>{const E=q.resolve(c,...a.split("/")),S=q.relative(c,E);return S===""||S===".."||S.startsWith(`..${q.sep}`)||q.isAbsolute(S)?null:E},b=(a,E)=>{const S=`${E}\0${a}`;O.has(S)||O.size>=x||(O.add(S),R({sourceId:t,path:a,reason:E}))},N=async({signal:a})=>{a.throwIfAborted();const E=new AbortController,S=()=>{E.abort(a.reason)};a.addEventListener("abort",S,{once:!0});const _=Kr(A);let P=0;const C=async(M,X)=>{const G=await _(async()=>{E.signal.throwIfAborted();try{return await fe.readdir(M,{withFileTypes:!0})}catch($){if(X===""||!Gr($))throw $;return null}});if(E.signal.throwIfAborted(),G===null)return b(`${m}${X}`,"unreadable-directory"),null;const F=[];for(const $ of G){if(g.deniesName($.name))continue;const Y=X===""?$.name:`${X}/${$.name}`,W=`${m}${Y}`,K=Vr($,W);if(K!==null){b(W,K);continue}F.push({dirent:$,relativePath:Y,path:W})}if(P+=F.length,P>x)throw new me("too-large");return F.sort(($,Y)=>Wr($.dirent.name,Y.dirent.name)),(await Promise.all(F.map(async({dirent:$,relativePath:Y,path:W})=>{if(!$.isDirectory())return{name:$.name,path:W,type:"file"};const K=await C(q.join(M,$.name),Y);return K===null?null:{name:$.name,path:W,type:"directory",children:K}}))).filter($=>$!==null)};try{const M=await C(c,"");if(M===null)throw new Error("[markdown-explorer] the source's root could not be listed");return M}catch(M){throw E.abort(),M}finally{a.removeEventListener("abort",S)}},z=async a=>{if(!a.startsWith(m))return{status:"refused",reason:"not-found"};const E=a.slice(m.length);if(!Ve(E))return{status:"refused",reason:"invalid"};if(g.deniesPath(E))return{status:"refused",reason:"forbidden"};const S=L(E);if(S===null)return{status:"refused",reason:"forbidden"};const _=await fe.lstat(S,{bigint:!0});if(_.isSymbolicLink())return{status:"refused",reason:"forbidden"};if(!_.isFile())return{status:"refused",reason:"unsupported"};const P=await fe.realpath(S);return P!==S||g.deniesPath(q.relative(c,P).split(q.sep).join("/"))?{status:"refused",reason:"forbidden"}:{status:"file",target:S,name:E.slice(E.lastIndexOf("/")+1),stats:_}},D=async(a,E,S)=>{let _;try{const P=await z(S);if(P.status==="refused")return y.failureDocument(P.reason);const{target:C,name:M,stats:X}=P,G=Xr(M),F=Ke(X);if(G.kind==="image")return{kind:"image",name:M,version:F};if(G.kind==="media")return{kind:"media",name:M,mediaType:G.mediaType,version:F};if(G.kind==="file")return{kind:"file",name:M,version:F};_=await fe.open(C,te.constants.O_RDONLY|ct|ut);const Z=await _.stat({bigint:!0});if(!Z.isFile()||Z.ino!==X.ino||Z.dev!==X.dev)return y.failureDocument("forbidden");if(G.kind==="markdown"){if(Z.size>BigInt(l))return y.failureDocument("too-large");const K=await Qe(_,l+1);if(K.length>l)return y.failureDocument("too-large");const le=await s(new TextDecoder("utf-8").decode(K),E);return{kind:"markdown",name:M,htmlContent:le.htmlContent,headings:le.headings}}const $=await Qe(_,h);if($.includes(0))return{kind:"file",name:M,version:F};const Y=Z.size>BigInt(h),W=new TextDecoder("utf-8").decode($,{stream:Y});return{kind:"text",name:M,text:W,truncated:Y,version:F}}catch(P){const C=dt(P);if(C===null)throw P;return y.failureDocument(C)}finally{await _?.close()}},u=async(a,E,S)=>{let _;try{_=await z(S)}catch(F){throw ft(F)}if(_.status==="refused")throw new me(_.reason);const{target:P,name:C,stats:M}=_,X=at.get(lt(C)),G=X===void 0?"":X.contentType;return{name:C,contentType:G,size:Number(M.size),version:Ke(M),open:F=>Yr(P,M,F,a.signal)}};return Object.freeze({id:t,label:r,cacheScope:k,boundary:Object.freeze({contains:a=>a.startsWith(m)}),tree:N,document:D,asset:u})};exports.DEFAULT_DENIED_PATH_SEGMENTS=y.DEFAULT_DENIED_PATH_SEGMENTS;exports.MAX_DOCUMENT_PATH_LENGTH=y.MAX_DOCUMENT_PATH_LENGTH;exports.isAcceptableDocumentPath=y.isAcceptableDocumentPath;exports.isDeniedPath=y.isDeniedPath;exports.ExplorerError=me;exports.anonymousAccess=ht;exports.createFileSystemSource=Zr;exports.createMarkdownExplorer=Cr;
1
+ "use strict";Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});const y=require("./dataRoute-B9Wk-G7A.cjs"),st=require("node:crypto"),Tt=require("@aiquants/markdown/server"),Se=require("react-router"),te=require("./location-DfYTzfFS.cjs"),re=require("node:fs"),ee=require("node:path"),Te=require("node:url"),xt=require("node:worker_threads"),de=require("node:fs/promises"),Ot=require("node:stream");var xe=typeof document<"u"?document.currentScript:null;const $e=Object.freeze({kind:"anonymous"}),Rt=Object.freeze({authenticate:async()=>({status:"signed-in",principal:$e}),principalKey:()=>$e.kind,signedOutPage:(e,t)=>new Response(null,{status:401,headers:t})}),kt="application/octet-stream",at="application/pdf",_t=new Set(["image/png","image/apng","image/jpeg","image/gif","image/webp","image/avif","image/bmp","image/x-icon","image/vnd.microsoft.icon","audio/mpeg","audio/mp4","audio/aac","audio/ogg","audio/opus","audio/wav","audio/wave","audio/x-wav","audio/webm","audio/flac","audio/x-flac","audio/x-m4a","video/mp4","video/webm","video/ogg","video/quicktime",at]),it="default-src 'none'; media-src 'self'; style-src 'unsafe-inline'",At=`${it}; sandbox`,Nt=`${it}; sandbox allow-same-origin`,je=/^[!#$%&'*+\-.^_`|~0-9A-Za-z]+$/u,It=/^[\t\n\r ]+|[\t\n\r ]+$/gu,Ne=/^[\t ]+|[\t ]+$/gu,Pt=e=>{const t=[];let r="",n=0;for(;;){for(;n<e.length&&e[n]!=='"'&&e[n]!==",";)r+=e[n],n+=1;if(n<e.length&&e[n]==='"'){const a=n;for(n+=1;n<e.length&&e[n]!=='"';)n+=e[n]==="\\"?2:1;if(n=Math.min(n+1,e.length),r+=e.slice(a,n),n<e.length)continue}if(t.push(r.replace(Ne,"")),r="",n>=e.length)return t;n+=1}},Mt=e=>{const t=e.replace(It,""),r=t.indexOf("/");if(r<0)return null;const n=t.slice(0,r),a=t.indexOf(";",r+1),o=t.slice(r+1,a<0?t.length:a).replace(/[\t\n\r ]+$/u,"");return je.test(n)&&je.test(o)?`${n}/${o}`.toLowerCase():null},vt=e=>{let t=null;for(const r of Pt(e)){const n=Mt(r);n!==null&&n!=="*/*"&&(t=n)}return t},Lt=/['()*]/gu,$t=e=>encodeURIComponent(e).replace(Lt,t=>`%${t.charCodeAt(0).toString(16).toUpperCase()}`),jt=Object.freeze({"Cache-Control":"private, max-age=60, stale-while-revalidate=600, no-transform",Vary:"Cookie"}),Dt=(e,t)=>{const r=vt(e),n=r!==null&&_t.has(r),a=n&&(r.startsWith("audio/")||r.startsWith("video/"));return{contentType:r===null?kt:r,inline:n,headers:{"X-Content-Type-Options":"nosniff","Content-Disposition":`${n?"inline":"attachment"}; filename*=UTF-8''${$t(t)}`,...r===at?{}:{"Content-Security-Policy":a?Nt:At},"Cross-Origin-Resource-Policy":"same-origin"}}},zt=/^bytes=(?:(\d+)-(\d*)|-(\d+))$/iu,pe=Object.freeze({kind:"whole"}),De=Object.freeze({kind:"unsatisfiable"}),Ct=(e,t,r)=>{const n=e.get("Range");if(n===null)return pe;const a=e.get("If-Range");if(a!==null&&a!==r)return pe;const o=zt.exec(n);if(o===null)return pe;const[,c,f,g]=o;if(g!==void 0){const p=Number(g);if(p===0)return De;const A=Math.max(0,t-p);return{kind:"partial",range:{offset:A,length:t-A}}}const x=Number(c),d=f===""?Number.POSITIVE_INFINITY:Number(f);return d<x?pe:x>=t?De:{kind:"partial",range:{offset:x,length:Math.min(d,t-1)-x+1}}},ze="W/",Ht=e=>{const t=[];let r=0,n=!1;for(let a=0;a<e.length;a+=1)e[a]==='"'?n=!n:e[a]===","&&!n&&(t.push(e.slice(r,a).replace(Ne,"")),r=a+1);return t.push(e.slice(r).replace(Ne,"")),t},Ce=e=>e.startsWith(ze)?e.slice(ze.length):e,Bt=(e,t)=>{if(e===null)return!1;const r=Ht(e);if(r.length===1&&r[0]==="*")return!0;const n=Ce(t);return r.some(a=>Ce(a)===n)},Ft=(e,t)=>{let r=t;return e.pipeThrough(new TransformStream({transform:(n,a)=>{const o=n.byteLength>r?n.subarray(0,r):n;r-=o.byteLength,a.enqueue(o),r===0&&a.terminate()},flush:n=>{r>0&&n.error(new RangeError("[markdown-explorer] the asset ended before its declared length"))}}))},Oe=async(e,t,r,n,a)=>{if(n!==null&&r.set("Content-Length",String(n)),e.method.toUpperCase()==="HEAD")return new Response(null,{status:t,headers:r});const o=await a();return new Response(n===null?o:Ft(o,n),{status:t,headers:r})},Ut=(e,t)=>{const r=new Headers(e);for(const[n,a]of Object.entries({"Accept-Ranges":"bytes","Content-Range":`bytes */${t}`,"Cache-Control":"private, no-store","X-Content-Type-Options":"nosniff"}))r.set(n,a);return new Response(null,{status:416,headers:r})},Xt=async(e,t,r)=>{const n=`"${t.version}"`,a=Dt(t.contentType,t.name),o=new Headers(r);for(const[g,x]of Object.entries({...a.headers,...jt,ETag:n}))o.set(g,x);if(Bt(e.headers.get("If-None-Match"),n))return new Response(null,{status:304,headers:o});if(o.set("Content-Type",a.contentType),t.size===null)return Oe(e,200,o,null,()=>t.open(null));if(t.size===0)return o.set("Content-Length","0"),new Response(null,{status:200,headers:o});o.set("Accept-Ranges","bytes");const c=Ct(e.headers,t.size,n);if(c.kind==="unsatisfiable")return Ut(r,t.size);if(c.kind==="whole")return Oe(e,200,o,t.size,()=>t.open(null));const{range:f}=c;return o.set("Content-Range",`bytes ${f.offset}-${f.offset+f.length-1}/${t.size}`),Oe(e,206,o,f.length,()=>t.open(f))},Re=(e,t)=>{const r=new AbortController,n=t(AbortSignal.any([e.signal,r.signal]));return new Promise(a=>{let o;const c=setTimeout(()=>{a(e.late),o=setTimeout(()=>r.abort(),e.handOverMs)},e.timeoutMs),f=()=>{clearTimeout(c),clearTimeout(o)};n.then(g=>{f(),a(g)},()=>{f(),a(e.late)})})},Gt=Object.freeze({error:(e,t)=>{console.error(e,t)}}),ct=Symbol.for("@aiquants/markdown-explorer:ExplorerError");class fe extends Error{reason;code;constructor(t,r={}){if(!y.isExplorerFailureReason(t))throw new RangeError(`[markdown-explorer] ExplorerError needs a failure reason; got ${JSON.stringify(t)}`);if(r.code!==void 0&&!y.isExplorerFailureCode(r.code))throw new RangeError(`[markdown-explorer] an ExplorerError code must be 1 to 64 lowercase letters, digits or hyphens; got ${JSON.stringify(r.code)}`);super(`[markdown-explorer] ${t}`,r.cause===void 0?void 0:{cause:r.cause}),this.name="ExplorerError",this.reason=t,this.code=r.code,Object.defineProperty(this,ct,{value:!0})}}const Jt=e=>e instanceof Error&&Object.hasOwn(e,ct)&&y.isExplorerFailureReason(e.reason),Yt=e=>typeof e=="object"&&e!==null&&e.name==="AbortError",Ie=(e,t,r)=>{try{e.error(t,r)}catch(n){console.error("[markdown-explorer] the logger threw while reporting a failure",{operation:r.operation,error:n})}},ne=(e,t)=>Ie(e,`[markdown-explorer] ${t.operation} failed`,t),Wt=(e,t)=>Ie(e,`[markdown-explorer] ${t.operation} left out an entry`,t),Kt=(e,t)=>Ie(e,`[markdown-explorer] ${t.operation} refused a path the deny rules match`,{...t,error:new RangeError("[markdown-explorer] the path matches a deny rule")}),He=(e,t)=>{e===null||typeof e!="object"&&typeof e!="function"||Promise.resolve(e).then(void 0,t)},q=(e,t,r,n)=>Jt(e)?y.failureOf(e.reason,e.code):(Yt(e)||r.aborted||ne(n,{...t,error:e}),{reason:"failed"}),Be=(e,t)=>{if(!Number.isSafeInteger(t)||t<=0)throw new RangeError(`[markdown-explorer] a cache ${e} must be a positive integer; got ${String(t)}`)},ut=(e,t)=>{Be("capacity",e),t!==void 0&&Be("weight budget",t.max);const r=new Map;let n=0;const a=o=>{const c=r.get(o);c!==void 0&&(r.delete(o),n-=c.weight)};return{get:o=>{const c=r.get(o);if(c!==void 0)return r.delete(o),r.set(o,c),c.value},set:(o,c)=>{a(o);const f=t===void 0?0:t.of(o,c);if(!(t!==void 0&&f>t.max)){r.set(o,{value:c,weight:f}),n+=f;for(const g of r.keys()){if(r.size<=e&&(t===void 0||n<=t.max))break;a(g)}}},delete:a,size:()=>r.size,weight:()=>n}},lt=e=>Math.max(1,e-1),Vt=2147483647,Fe=Object.freeze({status:"aborted"}),oe=(e,t,r)=>{const n=(e.get(t)??0)+r;n===0?e.delete(t):e.set(t,n)},ie=(e,t,r)=>{if(!Number.isSafeInteger(t)||t<=0||t>r)throw new RangeError(`[markdown-explorer] a worker pool's ${e} must be an integer in 1..${String(r)}; got ${String(t)}`)},Qt=e=>e!==null&&typeof e=="object"&&e.ready===!0&&!("id"in e),Zt=(e,t)=>e!==null&&typeof e=="object"&&e.id===t&&"output"in e,qt=({url:e,size:t,deadlineMs:r,jobsPerScope:n,maxQueuedJobs:a,heapLimits:o})=>{ie("size",t,Number.MAX_SAFE_INTEGER),ie("deadline",r,Vt),ie("jobsPerScope",n,Number.MAX_SAFE_INTEGER),ie("maxQueuedJobs",a,Number.MAX_SAFE_INTEGER),ie("maxOldGenerationSizeMb",o.maxOldGenerationSizeMb,Number.MAX_SAFE_INTEGER),ie("maxYoungGenerationSizeMb",o.maxYoungGenerationSizeMb,Number.MAX_SAFE_INTEGER);const c=Object.freeze({maxOldGenerationSizeMb:o.maxOldGenerationSizeMb,maxYoungGenerationSizeMb:o.maxYoungGenerationSizeMb}),f=new Set,g=[],x=new Map,d=new Map,p=lt(t);let A=0;const _=(u,i)=>{const{job:E}=u;u.timer!==null&&clearTimeout(u.timer),u.timer=null,u.job=null,u.sent=!1,E!==null&&(oe(x,E.scope,-1),oe(d,E.scope,-1),E.settle(i))},P=u=>{const[i]=g.splice(u,1);i?.detach()},R=()=>{let u=-1,i=p,E=Number.POSITIVE_INFINITY;for(const[T,k]of g.entries()){const I=x.get(k.scope)??0,H=d.get(k.scope)??0;(I<i||I===i&&u>=0&&H<E)&&(u=T,i=I,E=H)}return u},O=(u,i)=>{f.has(u)&&(f.delete(u),_(u,i),u.worker.terminate().catch(()=>{}),z())},L=u=>{u.timer=setTimeout(()=>{O(u,{status:"timeout"})},r)},S=(u,i)=>u.sent?{status:"crashed",error:i}:{status:"unavailable",error:i},N=(u,i)=>{u.sent=!0,L(u);try{u.worker.postMessage({id:i.id,input:i.input})}catch(E){_(u,{status:"crashed",error:E}),u.worker.unref()}},C=()=>{const u={worker:new xt.Worker(e,{resourceLimits:c}),job:null,sent:!1,timer:null,ready:!1};return u.worker.unref(),u.timer=setTimeout(()=>{O(u,{status:"unavailable",error:new Error(`[markdown-explorer] a worker did not start within ${String(r)} ms`)})},r),u.worker.on("message",i=>{if(!u.ready&&Qt(i)){u.ready=!0,u.timer!==null&&clearTimeout(u.timer),u.timer=null,u.job===null?u.worker.unref():N(u,u.job),u.job===null&&z();return}const{job:E}=u;if(E===null||!Zt(i,E.id)){O(u,S(u,new Error("[markdown-explorer] a worker sent a message that answers no job")));return}_(u,{status:"done",output:i.output}),u.worker.unref(),z()}),u.worker.on("error",i=>{O(u,S(u,i))}),u.worker.on("messageerror",i=>{O(u,S(u,i))}),u.worker.on("exit",i=>{O(u,S(u,new Error(`[markdown-explorer] a worker exited with code ${String(i)}`)))}),f.add(u),u},z=()=>{for(;;){const u=R(),i=g[u];if(i===void 0)return;let E;for(const k of f)if(k.job===null){E=k;break}if(E===void 0&&f.size<t)try{E=C()}catch(k){P(u),oe(d,i.scope,-1),i.settle({status:"unavailable",error:k});continue}if(E===void 0)return;P(u),oe(x,i.scope,1);const T=E;T.job=i,T.worker.ref(),T.ready&&N(T,i)}};return{run:(u,{scope:i,signal:E})=>new Promise(T=>{if(E.aborted){T(Fe);return}if((d.get(i)??0)>=n){T({status:"refused",limit:"scope"});return}A+=1;const k={id:A,input:u,scope:i,settle:T,detach:()=>{}};g.push(k),oe(d,i,1),z();const I=g.indexOf(k);if(I<0)return;if(g.length>a){P(I),oe(d,i,-1),T({status:"refused",limit:"queue"});return}const H=()=>{const M=g.indexOf(k);M<0||(P(M),oe(d,i,-1),T(Fe))};E.addEventListener("abort",H,{once:!0}),k.detach=()=>{E.removeEventListener("abort",H)}}),workers:()=>f.size}},Pe=1024*1024,er=3e4,tr=4*Pe,rr=64*Pe,nr=3,or=2,sr=(e,t)=>e+lt(t)+nr,ar=4,ir=32,cr=512,ur=64,lr=4096,dr=32,Ue=4096,fr=4,dt=({workerHeapMb:e,maxHtmlBytes:t})=>Math.floor(((e-ur)*Pe-t*dr)/lr),mr=({maxHtmlBytes:e})=>e,pr=({maxHtmlBytes:e})=>fr*e,hr=1024,wr=2147483647,gr=64,Er=2**29,yr=1024*1024,br=64,Xe=Object.freeze({status:"rejected",reason:"too-large",cause:null}),ke=Object.freeze({status:"rejected",reason:"failed",cause:null}),se=(e,t,r,n)=>{if(t===void 0)return r;if(typeof t!="number")throw new TypeError(`[markdown-explorer] sanitizer.${e} must be a number; got ${typeof t}`);if(!Number.isSafeInteger(t)||t<=0||t>n)throw new RangeError(`[markdown-explorer] sanitizer.${e} must be an integer in 1..${String(n)}; got ${String(t)}`);return t},Sr=(e,t)=>{if(e!==void 0&&(e===null||typeof e!="object"))throw new TypeError("[markdown-explorer] sanitizer must be an object of { workers, deadlineMs, maxHtmlBytes, cacheBytes, workerHeapMb, jobsPerScope, maxQueuedJobs }");const{workers:r,deadlineMs:n,maxHtmlBytes:a,cacheBytes:o,workerHeapMb:c,jobsPerScope:f,maxQueuedJobs:g}=e??{},x=se("workers",r,or,gr),d=se("jobsPerScope",f,sr(t,x),Number.MAX_SAFE_INTEGER),p=Object.freeze({workers:x,deadlineMs:se("deadlineMs",n,er,wr),maxHtmlBytes:se("maxHtmlBytes",a,tr,Er),cacheBytes:se("cacheBytes",o,rr,Number.MAX_SAFE_INTEGER),workerHeapMb:se("workerHeapMb",c,cr,yr),jobsPerScope:d,maxQueuedJobs:se("maxQueuedJobs",g,ar*d,Number.MAX_SAFE_INTEGER)});if(p.jobsPerScope<t)throw new RangeError(`[markdown-explorer] sanitizer.jobsPerScope must be at least multiView.maxPanels (${String(t)}), because a page sends the document of every panel to the sanitizer at once for one reader; got ${String(p.jobsPerScope)}`);if(p.maxQueuedJobs<t)throw new RangeError(`[markdown-explorer] sanitizer.maxQueuedJobs must be at least multiView.maxPanels (${String(t)}), because a reader whose page finds every worker busy waits with the document of every panel; got ${String(p.maxQueuedJobs)}`);if(dt(p)<Ue)throw new RangeError(`[markdown-explorer] sanitizer.workerHeapMb (${String(p.workerHeapMb)} MiB) must leave room for ${String(Ue)} parsed nodes beside HTML of sanitizer.maxHtmlBytes (${String(p.maxHtmlBytes)} bytes); raise workerHeapMb or lower maxHtmlBytes`);return p},Tr=()=>{const e=typeof document>"u"?require("url").pathToFileURL(__filename).href:xe&&xe.tagName.toUpperCase()==="SCRIPT"&&xe.src||new URL("server.cjs",document.baseURI).href,t=new URL(`./sanitizeWorker${ee.extname(Te.fileURLToPath(e))}`,e);if(!re.existsSync(Te.fileURLToPath(t)))throw new Error(`[markdown-explorer] the HTML sanitizer worker is missing: ${Te.fileURLToPath(t)}`);return t},Ge=new Map,xr=(e,t)=>{const r=[e.href,t.workers,t.deadlineMs,t.workerHeapMb,t.jobsPerScope,t.maxQueuedJobs].map(String).join("\0");let n=Ge.get(r);return n===void 0&&(n=qt({url:e,size:t.workers,deadlineMs:t.deadlineMs,jobsPerScope:t.jobsPerScope,maxQueuedJobs:t.maxQueuedJobs,heapLimits:{maxOldGenerationSizeMb:t.workerHeapMb,maxYoungGenerationSizeMb:ir}}),Ge.set(r,n)),n},Or=e=>{if(e===null||typeof e!="object")return!1;const{status:t,html:r,message:n}=e;return t==="sanitized"&&typeof r=="string"||t==="too-large"||t==="error"&&typeof n=="string"},Rr=e=>e instanceof Error&&e.code==="ERR_WORKER_OUT_OF_MEMORY",kr=({iframeHosts:e,dataPath:t,options:r,pool:n})=>{const a=Object.freeze([...e]),o=dt(r),c=mr(r),f=pr(r),g=ut(hr,{max:r.cacheBytes,of:(R,O)=>2*R.length+(O.status==="sanitized"?2*O.html.length:br)}),x=new Map,d=new Map,p=R=>{x.get(R.key)===R&&x.delete(R.key);const O=d.get(R.hash);O?.delete(R),O?.size===0&&d.delete(R.hash)},A=async(R,O,L)=>{const S=await n.run({html:R,iframeHosts:a,dataPath:t,maxNodes:o,maxAttributeChars:c,maxSanitizedChars:f},{scope:O,signal:L});if(S.status==="refused"){const C=S.limit==="scope"?`its reader already has ${String(r.jobsPerScope)} documents being sanitized or waiting`:`${String(r.maxQueuedJobs)} documents are already waiting`;return{outcome:{status:"rejected",reason:"failed",cause:new Error(`[markdown-explorer] the HTML sanitizer refused a document: ${C}`)},lasting:!1}}if(S.status==="aborted")return{outcome:ke,lasting:!1};if(S.status==="timeout")return{outcome:{status:"rejected",reason:"too-large",cause:new Error(`[markdown-explorer] the HTML sanitizer did not finish within ${String(r.deadlineMs)} ms`)},lasting:!0};if(S.status==="unavailable")return{outcome:{status:"rejected",reason:"failed",cause:new Error("[markdown-explorer] the HTML sanitizer worker could not start",{cause:S.error})},lasting:!1};if(S.status==="crashed"&&Rr(S.error))return{outcome:{status:"rejected",reason:"too-large",cause:new Error(`[markdown-explorer] the HTML sanitizer ran out of its ${String(r.workerHeapMb)} MiB worker heap`,{cause:S.error})},lasting:!0};if(S.status==="crashed")return{outcome:{status:"rejected",reason:"failed",cause:new Error("[markdown-explorer] the HTML sanitizer worker failed",{cause:S.error})},lasting:!0};const{output:N}=S;return Or(N)?N.status==="too-large"?{outcome:Xe,lasting:!0}:N.status==="error"?{outcome:{status:"rejected",reason:"failed",cause:new Error(`[markdown-explorer] the HTML sanitizer failed: ${N.message}`)},lasting:!0}:N.html.length>f?{outcome:{status:"rejected",reason:"too-large",cause:new Error(`[markdown-explorer] the HTML sanitizer's output of ${String(N.html.length)} characters exceeds its limit of ${String(f)}`)},lasting:!0}:{outcome:{status:"sanitized",html:N.html},lasting:!0}:{outcome:{status:"rejected",reason:"failed",cause:new Error("[markdown-explorer] the HTML sanitizer worker answered something that is not an outcome")},lasting:!0}},_=(R,O,L,S)=>{let N=()=>{};const C=new Promise(i=>{N=i}),z={hash:O,key:L,outcome:C,answer:N,controller:new AbortController,waiters:0};x.set(L,z);const u=d.get(O);return u===void 0?d.set(O,new Set([z])):u.add(z),A(R,S,z.controller.signal).catch(i=>({outcome:{status:"rejected",reason:"failed",cause:i instanceof Error?i:new Error(String(i))},lasting:!0})).then(({outcome:i,lasting:E})=>{if(p(z),z.answer(i),!E)return;const T=g.get(O),k=T??(i.status==="rejected"?{...i,cause:null}:i);T===void 0&&g.set(O,k);for(const I of d.get(O)??[])p(I),I.answer(k),I.controller.abort()}),z},P=(R,O)=>new Promise(L=>{R.waiters+=1;const S=()=>{R.waiters-=1,L(ke),!(R.waiters>0)&&(p(R),R.controller.abort())};O.addEventListener("abort",S,{once:!0}),R.outcome.then(N=>{O.removeEventListener("abort",S),L(N)})});return(R,{scope:O,signal:L})=>{if(R.length>r.maxHtmlBytes||Buffer.byteLength(R,"utf8")>r.maxHtmlBytes)return Promise.resolve(Xe);const S=st.createHash("sha256").update(R,"utf8").digest("base64"),N=g.get(S);if(N!==void 0)return Promise.resolve(N);if(L.aborted)return Promise.resolve(ke);const C=`${S}\0${O}`,z=x.get(C);return P(z===void 0?_(R,S,C,O):z,L)}},be=e=>({result:e,json:JSON.stringify(e)}),_e=Object.freeze(be(Object.freeze({status:"error",failure:Object.freeze({reason:"failed"})}))),_r=e=>e.status==="ok"&&e.entries.length>0,Ar=({ttlMs:e,maxEntries:t,maxBytes:r,now:n})=>{const a=ut(t,{max:r,of:(d,p)=>2*p.tree.json.length}),o=new Map,c=new Map,f=(d,p)=>{const A=new AbortController,_={waiters:0,superseded:!1,started:!1,loadTree:p},P=c.get(d),R=(C,z)=>{const u=be(C);return!(_.superseded||A.signal.aborted)&&_r(C)&&a.set(d,{tree:u,loadedAt:z}),u},L=(async()=>{if(P!==void 0&&await P,A.signal.aborted)return _e;const C=n();return _.started=!0,R(await _.loadTree(A.signal,C),C)})().finally(()=>{o.get(d)===S&&o.delete(d)}),S={promise:L,controller:A,state:_};o.set(d,S);const N=L.then(()=>{},()=>{});return c.set(d,N),N.then(()=>{c.get(d)===N&&c.delete(d)}),S},g=(d,p,A)=>{p.state.waiters+=1;const _=()=>{p.state.waiters-=1,!(p.state.waiters>0)&&(o.get(d)===p&&o.delete(d),p.controller.abort())};return A.addEventListener("abort",_,{once:!0}),p.promise.finally(()=>{A.removeEventListener("abort",_)})},x=d=>{a.delete(d);const p=o.get(d);p?.state.started&&(p.state.superseded=!0,o.delete(d))};return{load:(d,p,A)=>{if(p.aborted)return Promise.resolve(_e);const _=a.get(d);if(_!==void 0){if(n()-_.loadedAt<e)return Promise.resolve(_.tree);a.delete(d)}const P=o.get(d);return g(d,P===void 0?f(d,A):P,p)},refresh:(d,p,A)=>{if(p.aborted)return Promise.resolve(_e);x(d);const _=o.get(d);return _===void 0?g(d,f(d,A),p):(_.state.loadTree=A,g(d,_,p))},forget:x}},Nr=e=>({load:(t,r,n)=>n(r,e()).then(be),refresh:(t,r,n)=>n(r,e()).then(be),forget:()=>{}}),v=e=>{throw new TypeError(`[markdown-explorer] ${e}`)},Ir=e=>{if(e===null||typeof e!="object")return null;const{name:t,path:r}=e;return typeof t!="string"||typeof r!="string"?null:t===""?{path:r,reason:"an empty name"}:y.isAcceptableDocumentPath(r)?null:{path:r,reason:"a path the browser cannot address (empty, too long, a lone surrogate, a control character or a backslash)"}},Pr=(e,t,r,n,a)=>{const o=new Set,c=g=>{if(!Array.isArray(g))return v("a source returned entries that are not an array");const x=[];for(const d of g){const p=f(d);p!==null&&x.push(p)}return x},f=g=>{const x=Ir(g);if(x!==null)return n(x),null;const d=y.entryViolation(g);if(d!==null)return v(d);const p=g;if(o.has(p))return v("a source returned entries that contain themselves");const{name:A,path:_,type:P,mimeType:R,children:O,lazy:L}=p;if(t.deniesName(A)||t.deniesPath(_))return null;if(!a(_))return n({path:_,reason:"a path outside the source's boundary"}),null;const S=R===void 0?{name:A,path:_}:{name:A,path:_,mimeType:R};if(P==="file")return{...S,type:P};if(L===!0)return r?{...S,type:P,lazy:!0,children:[]}:v("a lazy directory came from a source without a children function");if(O===void 0)return{...S,type:P};o.add(p);const N=c(O);return o.delete(p),{...S,type:P,children:N}};return c(e)},Mr=/^[\x21\x23-\x7E]{1,256}$/u,ft=e=>typeof e=="string"&&Mr.test(e),vr=new Set(["text","image","media","file"]),Lr=e=>typeof e=="string"&&vr.has(e),$r=(e,t)=>{if(e!==null&&typeof e=="object"){const a=e,{kind:o}=a;if(Lr(o)){if(Object.hasOwn(a,"url"))return v(`a ${o} document carries its version, not a url`);if(typeof a.name!="string")return v("a document needs a name string");if(!ft(a.version))return v(`a ${o} document needs a version of 1 to 256 visible ASCII characters other than '"'`);const c=t(a.version);switch(o){case"image":case"file":return{kind:o,name:a.name,url:c};case"media":{const{mediaType:f}=a;return y.isExplorerMediaType(f)?{kind:o,name:a.name,url:c,mediaType:f}:v(`unknown media type ${typeof f=="string"?JSON.stringify(f.slice(0,64)):typeof f}`)}case"text":return typeof a.text!="string"||typeof a.truncated!="boolean"?v("a text document needs text and truncated"):{kind:o,name:a.name,text:a.text,truncated:a.truncated,url:c}}}}const r=y.documentViolation(e);if(r!==null)return v(r);const n=e;switch(n.kind){case"failure":{const{reason:a,code:o}=n.failure;return{kind:"failure",failure:y.failureOf(a,o)}}case"markdown":return n.headings.length>y.EXPLORER_MAX_HEADINGS?{kind:"failure",failure:y.failureOf("too-large")}:{kind:"unsanitized-markdown",name:n.name,html:n.htmlContent,headings:n.headings.map(({text:a,depth:o,id:c})=>({text:a,depth:o,id:c}))}}},jr=e=>{if(e===null||typeof e!="object")return v("an asset file must be an object");const{name:t,contentType:r,size:n,version:a,open:o}=e;return typeof t!="string"||t===""?v("an asset file needs a non-empty name"):typeof r!="string"?v("an asset file needs a contentType string ('' when unknown)"):n!==null&&!(typeof n=="number"&&Number.isSafeInteger(n)&&n>=0)?v("an asset file's size must be null or a non-negative safe integer"):ft(a)?typeof o!="function"?v("an asset file needs an open function"):Object.freeze({name:t,contentType:r,size:n,version:a,open:o}):v(`an asset file needs a version of 1 to 256 visible ASCII characters other than '"'`)},Dr=e=>Array.isArray(e)?e.map(t=>{if(t===null||typeof t!="object")return v("a notice must be an object");const{id:r,tone:n,title:a,body:o,action:c}=t;if(typeof r!="string"||r===""||typeof a!="string")return v("a notice needs an id and a title");if(!y.isExplorerNoticeTone(n))return v(`unknown notice tone ${typeof n=="string"?JSON.stringify(n.slice(0,64)):typeof n}`);if(o!==void 0&&typeof o!="string")return v("a notice body must be a string");const g={id:r,tone:n,title:a,...o===void 0?{}:{body:o}};if(c===void 0)return g;if(c===null||typeof c!="object")return v("a notice action must be an object");const{label:x,href:d}=c;return typeof x!="string"||!y.isAcceptableUrl(d,y.EXPLORER_LINK_PROTOCOLS)?v("a notice action needs a label and an http(s), mailto or relative href"):{...g,action:{label:x,href:d}}}):v("notices must be an array"),zr=4e3,he=Object.freeze({ttlMs:3e5,maxEntries:64,maxBytes:64*1024*1024}),Je=32,mt="private, no-store",Cr=Object.freeze({"Content-Type":"application/json; charset=utf-8","Cache-Control":mt,"X-Content-Type-Options":"nosniff","Content-Security-Policy":"default-src 'none'; frame-ancestors 'none'; sandbox","Cross-Origin-Resource-Policy":"same-origin"}),Hr=22,Br=2147483647,Ae=Object.freeze([]),Ye=Object.freeze(["contains","confirm"]),We=Object.freeze({readOnly:!1}),Fr=Object.freeze({readOnly:!0}),J=(e,t,r)=>{if(!(r&&t===void 0)&&typeof t!="function")throw new TypeError(`[markdown-explorer] ${e} must be a function; got ${typeof t}`)},ye=(e,t,r)=>{if(typeof t!="number")throw new TypeError(`[markdown-explorer] ${e} must be a number; got ${typeof t}`);if(!Number.isSafeInteger(t)||t<=0||t>r)throw new RangeError(`[markdown-explorer] ${e} must be an integer in 1..${String(r)}; got ${String(t)}`);return t},Ur=e=>{if(e===null||typeof e!="object"||!Object.isFrozen(e))throw new TypeError("[markdown-explorer] config must be the value returned by defineExplorerConfig");return te.revalidateExplorerConfig(e)},Ke=e=>{try{return new Headers(e)}catch{throw new TypeError("[markdown-explorer] authenticate returned headers that are not a valid headers init (their values are not logged)")}},Ve=e=>e instanceof Response?new TypeError(`[markdown-explorer] authenticate threw a Response (status ${String(e.status)}), which a data request does not follow`):e,Xr=e=>{if(typeof e!="string")throw new TypeError(`[markdown-explorer] scopeSecret must be a string; got ${typeof e}`);if(e.length<Je)throw new RangeError(`[markdown-explorer] scopeSecret must have at least ${String(Je)} characters; got ${String(e.length)}`);return e},Gr=(e,t)=>{if(!te.isPlainObject(t))throw new TypeError(`[markdown-explorer] ${e}.boundary must be a plain object { contains, confirm? }`);for(const r of Object.keys(t))if(!Ye.includes(r))throw new RangeError(`[markdown-explorer] ${e}.boundary.${r} is not an option; expected ${Ye.join(", ")}`);J(`${e}.boundary.contains`,t.contains,!1),J(`${e}.boundary.confirm`,t.confirm,!0)},Jr=e=>{if(!Array.isArray(e))throw new TypeError("[markdown-explorer] sources must be an array");const t=e;if(t.length===0)throw new RangeError("[markdown-explorer] sources must hold at least one source");const r=new Set;for(const[n,a]of t.entries()){if(a===null||typeof a!="object")throw new TypeError(`[markdown-explorer] sources[${String(n)}] must be an object`);const{id:o,label:c,boundary:f,tree:g,children:x,cacheScope:d}=a;if(!te.isExplorerSourceId(o))throw new RangeError(`[markdown-explorer] sources[${String(n)}].id must use lowercase letters, digits and "-" and start with a letter or digit; got ${typeof o=="string"?JSON.stringify(o):typeof o}`);const p=`source ${JSON.stringify(o)}`;if(r.has(o))throw new RangeError(`[markdown-explorer] source ids must be unique; ${JSON.stringify(o)} repeats at sources[${String(n)}]`);if(r.add(o),typeof c!="string"&&typeof c!="function")throw new TypeError(`[markdown-explorer] ${p}.label must be a string or a function`);if(typeof c=="string"&&c.trim()==="")throw new RangeError(`[markdown-explorer] ${p}.label must not be blank`);if(Gr(p,f),J(`${p}.tree`,g,!1),J(`${p}.children`,x,!0),d!==void 0&&d!=="principal"&&d!=="shared")throw new RangeError(`[markdown-explorer] ${p}.cacheScope must be "principal" or "shared"; got ${JSON.stringify(d)}`)}return t},Yr=e=>{if(e===!1)return!1;if(e===void 0)return he;if(e===null||typeof e!="object")throw new TypeError("[markdown-explorer] treeCache must be { ttlMs, maxEntries, maxBytes } or false");const{ttlMs:t,maxEntries:r,maxBytes:n}=e;return{ttlMs:t===void 0?he.ttlMs:ye("treeCache.ttlMs",t,Number.MAX_SAFE_INTEGER),maxEntries:r===void 0?he.maxEntries:ye("treeCache.maxEntries",r,Number.MAX_SAFE_INTEGER),maxBytes:n===void 0?he.maxBytes:ye("treeCache.maxBytes",n,Number.MAX_SAFE_INTEGER)}},Qe=e=>{if(e===null||typeof e!="object")throw new TypeError("[markdown-explorer] authenticate must resolve to { status, ... }");const{status:t}=e;if(t!=="signed-in"&&t!=="signed-out"&&t!=="forbidden")throw new TypeError(`[markdown-explorer] authenticate resolved to an unknown status ${JSON.stringify(t)}`);return e},Ze=(e,t)=>{if(!(t instanceof Response))throw new TypeError(`[markdown-explorer] ${e} must return a Response`);return t},qe=(e,t)=>{if(typeof t!="string"||t==="")throw new TypeError("[markdown-explorer] principalKey must return a non-empty string");return st.createHmac("sha256",e).update(t,"utf8").digest("base64url").slice(0,Hr)},Wr=e=>e.view==="multi"?e.docs:e.doc===null?[]:[e.doc],we=(e,t)=>{const r=e.getAll(t),[n]=r;return r.length===1&&n!==void 0&&n!==""?n:null},ce=(e,t,r,n={})=>{const a=new Headers(r);for(const[o,c]of Object.entries({...Cr,...n}))a.set(o,c);return new Response(t,{status:e,headers:a})},F=(e,t,r)=>ce(y.EXPLORER_FAILURE_STATUS[e.reason],JSON.stringify({failure:e}),t,r),et=(e,t)=>{const r=t==="refresh"?["POST"]:["GET","HEAD"];return r.includes(e.method.toUpperCase())?null:ce(405,JSON.stringify({failure:{reason:"invalid"}}),void 0,{Allow:r.join(", ")})},tt=e=>{if(e.headers.get(y.EXPLORER_REFRESH_HEADER)!==y.EXPLORER_REFRESH_HEADER_VALUE)return!1;const t=e.headers.get("Sec-Fetch-Site");return t===null||t==="same-origin"},Kr=({parentHeaders:e,loaderHeaders:t,errorHeaders:r})=>{const n=new Headers,a=r===void 0?[e,t]:[e,t,r];for(const o of a)for(const[c,f]of o)c!=="set-cookie"&&n.set(c,f);return n},Vr=e=>{if(e===null||typeof e!="object")throw new TypeError("[markdown-explorer] the server configuration must be an object");const t=Ur(e.config),r=Xr(e.scopeSecret);J("authenticate",e.authenticate,!1),J("principalKey",e.principalKey,!1),J("document",e.document,!1),J("asset",e.asset,!1),J("signedOutPage",e.signedOutPage,!1),J("forbiddenPage",e.forbiddenPage,!0),J("notices",e.notices,!0),J("onTreeRefreshed",e.onTreeRefreshed,!0);const n=Jr(e.sources),a=te.withExplorerSources(t,n.map(s=>s.id)),o=e.logger;if(o!==void 0&&(o===null||typeof o!="object"||typeof o.error!="function"))throw new TypeError("[markdown-explorer] logger must be an object with an error function");const c=e.logger===void 0?Gt:e.logger,f=y.resolvePathRules(e.deny),g=e.deferredTimeoutMs===void 0?zr:ye("deferredTimeoutMs",e.deferredTimeoutMs,Br),x=Yr(e.treeCache),d=()=>Date.now(),p=x===!1?Nr(d):Ar({...x,now:d}),A=Sr(e.sanitizer,t.multiView.maxPanels),_=kr({iframeHosts:t.iframeHosts,dataPath:t.dataPath,options:A,pool:xr(Tr(),A)}),P=new Map(n.map(s=>[s.id,s])),R=te.documentStyleNames(t),{authenticate:O,principalKey:L,signedOutPage:S,forbiddenPage:N,onTreeRefreshed:C}=e,z=(s,m)=>{if(typeof s.label=="string")return s.label;const l=s.label(m);if(typeof l!="string"||l.trim()==="")throw new TypeError(`[markdown-explorer] the label of source ${JSON.stringify(s.id)} must be a non-blank string`);return l},u=(s,m)=>s.cacheScope==="shared"?s.id:`${s.id}\0${m}`,i=(s,m)=>{const l=w=>ne(c,{operation:"boundary",sourceId:s.id,path:m,error:w});let h;try{h=s.boundary.contains(m)}catch(w){return l(w),!1}return typeof h=="boolean"?h:(He(h,l),l(new TypeError(`[markdown-explorer] boundary.contains of source ${JSON.stringify(s.id)} must return a boolean; got ${typeof h}`)),!1)},E=async(s,m,l)=>{const{confirm:h}=s.boundary;if(h===void 0)return{status:"inside",readPath:l};let w;try{w=await h(m,l)}catch(Q){return{status:"error",failure:q(Q,{operation:"boundary",sourceId:s.id,path:l},m.signal,c)}}const b=Q=>(ne(c,{operation:"boundary",sourceId:s.id,path:l,error:new TypeError(`[markdown-explorer] boundary.confirm of source ${JSON.stringify(s.id)} ${Q}`)}),{status:"outside"});if(w===null||typeof w!="object")return b(`must resolve to { inside, readPath? }; got ${w===null?"null":typeof w}`);const{inside:j,readPath:D}=w;return j===!1?{status:"outside"}:j!==!0||typeof D!="string"?b("must resolve to { inside: false } or { inside: true, readPath: string }"):!y.isAcceptableDocumentPath(D)||f.deniesPath(D)?(ne(c,{operation:"boundary",sourceId:s.id,path:l,error:new RangeError(`[markdown-explorer] boundary.confirm of source ${JSON.stringify(s.id)} answered a readPath the explorer does not serve (unacceptable or denied)`)}),{status:"error",failure:{reason:"failed"}}):{status:"inside",readPath:D}},T=async(s,m)=>{const l=n.filter(w=>i(w,m));if(l.length===0)return{status:"error",failure:{reason:"forbidden"}};if(l.some(w=>w.boundary.confirm===void 0))return{status:"inside",readPath:m};let h=null;for(const w of l){const b=await E(w,s,m);if(b.status==="inside")return b;b.status==="error"&&h===null&&(h=b.failure)}return{status:"error",failure:h===null?{reason:"forbidden"}:h}},k=(s,m,l)=>{const h=({path:w,reason:b})=>Wt(c,{operation:l.operation,sourceId:l.sourceId,path:w,error:new TypeError(`[markdown-explorer] an entry with ${b} was left out`)});try{return{status:"ok",entries:Pr(s,f,m.children!==void 0,h,w=>i(m,w))}}catch(w){return ne(c,{...l,error:w}),{status:"error",failure:{reason:"failed"}}}},I=async(s,m,l)=>{let h;try{h=await s.tree(m)}catch(b){return{status:"error",failure:q(b,{operation:"tree",sourceId:s.id},m.signal,c)}}const w=k(h,s,{operation:"tree",sourceId:s.id});return w.status==="ok"?{status:"ok",entries:w.entries,loadedAt:l}:w},H=(s,m,l,h)=>(w,b)=>I(s,{principal:m,request:l,signal:w,refresh:h},b),M=(s,m,l,h,w)=>p.load(u(s,l),w,H(s,m,h,!1)),X=(s,m,l,h)=>p.refresh(u(s,l),h.signal,H(s,m,h,!0)),G=(s,m)=>{if(C===void 0)return;const l=h=>ne(c,{operation:"refresh",sourceId:s.id,error:h});try{He(C(m),l)}catch(h){l(h)}},U=async(s,m,l,h)=>{if(f.deniesPath(h)||!i(s,h))return{status:"error",failure:{reason:"forbidden"}};const w=await E(s,l,h);if(w.status==="outside")return{status:"error",failure:{reason:"forbidden"}};if(w.status==="error")return{status:"error",failure:w.failure};let b;try{b=await m(l,h,w.readPath)}catch(j){return{status:"error",failure:q(j,{operation:"children",sourceId:s.id,path:h},l.signal,c)}}return k(b,s,{operation:"children",sourceId:s.id,path:h})},Z=async(s,m,l)=>{if(f.deniesPath(l))return y.failureDocument("forbidden");const h=await T(s,l);if(h.status==="error")return{kind:"failure",failure:h.failure};let w;try{w=await e.document(s,l,h.readPath)}catch(D){return{kind:"failure",failure:q(D,{operation:"document",path:l},s.signal,c)}}let b;try{b=$r(w,D=>y.explorerAssetHref(t.dataPath,l,D))}catch(D){return ne(c,{operation:"document",path:l,error:D}),y.failureDocument("failed")}if(b.kind!=="unsanitized-markdown")return b;const j=await _(b.html,{scope:m,signal:s.signal});return j.status==="sanitized"?{kind:"markdown",name:b.name,htmlContent:j.html,headings:b.headings}:(j.cause!==null&&ne(c,{operation:"document",path:l,error:j.cause}),y.failureDocument(j.reason))},$=async s=>{if(e.notices===void 0)return Ae;try{return Dr(await e.notices(s))}catch(m){return q(m,{operation:"notices"},s.signal,c),Ae}},Y=async(s,m,l)=>{const h=we(m,y.EXPLORER_DATA_QUERY.path);if(h===null||!y.isAcceptableDocumentPath(h))return F({reason:"invalid"},l);if(f.deniesPath(h))return Kt(c,{operation:"asset",path:h}),F({reason:"forbidden"},l);const w=await T(s,h);if(w.status==="error")return F(w.failure,l);try{const b=jr(await e.asset(s,h,w.readPath));return await Xt(s.request,b,l)}catch(b){return F(q(b,{operation:"asset",path:h},s.signal,c),l)}},V=async({request:s,url:m,params:l})=>{const h=Qe(await O(s,We)),w=Ke(h.headers);if(w.set("Cache-Control",mt),h.status==="signed-out")throw Ze("signedOutPage",S(s,w));if(h.status==="forbidden")throw N===void 0?Se.data(null,{status:403,headers:w}):Ze("forbiddenPage",N(s,w));const b=te.resolveExplorerLocation(a,l["*"],m.searchParams);if(b.kind==="redirect")throw Se.redirect(b.href,{headers:w});const{location:j}=b,{principal:D}=h,Q=qe(r,L(D)),ue=P.get(j.source);if(ue===void 0)throw new RangeError(`[markdown-explorer] no source for ${JSON.stringify(j.source)}`);const le={signal:s.signal,timeoutMs:g,late:null,handOverMs:g},ae={scope:Q,sources:n.map(B=>({id:B.id,label:z(B,D)})),settings:te.parseViewSettings(te.readCookieValue(s.headers.get("Cookie"),t.settingsCookie),R),tree:j.view==="single"?null:{sourceId:j.source,result:Re(le,B=>M(ue,D,Q,s,B).then(K=>K.result))},documents:Wr(j).map(B=>({path:B,document:Re(le,K=>Z({principal:D,request:s,signal:K,refresh:!1},Q,B))})),notices:Re({signal:s.signal,timeoutMs:g,late:Ae,handOverMs:0},B=>$({principal:D,request:s,signal:B,refresh:!1}))};return Se.data(ae,{headers:w})},W=async(s,m)=>{const l=Qe(await O(s,m));return{authentication:l,headers:Ke(l.headers)}},me=async(s,m,l)=>{let h;try{h=await W(m,We)}catch(K){return F(q(Ve(K),{operation:"authenticate"},m.signal,c))}const{authentication:w,headers:b}=h;if(w.status==="signed-out")return F({reason:"unauthorized"},b);if(w.status==="forbidden")return F({reason:"forbidden"},b);const{principal:j}=w;if(s==="asset")return Y({principal:j,request:m,signal:m.signal,refresh:!1},l,b);const D=qe(r,L(j));b.set(y.EXPLORER_SCOPE_HEADER,D);const Q={principal:j,request:m,signal:m.signal,refresh:!1},ue=()=>F({reason:"invalid"},b);if(s==="document"){const K=we(l,y.EXPLORER_DATA_QUERY.path);if(K===null||!y.isAcceptableDocumentPath(K))return ue();const Le=m.headers.has(y.EXPLORER_REFRESH_HEADER);return Le&&!tt(m)?F({reason:"forbidden"},b):ce(200,JSON.stringify(await Z({...Q,refresh:Le},D,K)),b)}const le=we(l,y.EXPLORER_DATA_QUERY.source),ae=we(l,y.EXPLORER_DATA_QUERY.path);if(le===null||s==="children"&&(ae===null||!y.isAcceptableDocumentPath(ae)))return ue();const B=P.get(le);if(B===void 0)return F({reason:"not-found"},b);if(s==="tree")return ce(200,(await M(B,j,D,m,m.signal)).json,b);if(s==="refresh"){const K=await X(B,j,D,m);return m.signal.aborted||G(B,u(B,D)),ce(200,K.json,b)}return B.children===void 0||ae===null?F({reason:"not-found"},b):ce(200,JSON.stringify(await U(B,B.children,Q,ae)),b)},bt=async s=>{const{authentication:m,headers:l}=await W(s,Fr);if(!l.keys().next().done)throw new TypeError("[markdown-explorer] authenticate returned headers in read-only mode; a read-only authentication must only read the session (none was forwarded)");return m.status==="signed-in"},Me=t.embeds.linkCardEndpoint===null?null:Tt.createLinkCardHandler({authorize:bt}),St=async(s,m)=>{try{return await s(m)}catch(l){return F(q(Ve(l),{operation:"authenticate"},m.signal,c))}},ve=async(s,m,l)=>{if(new URL(s.url).pathname.endsWith(".data"))return F({reason:"not-found"});if(!y.isExplorerDataOperation(l))return F({reason:"not-found"});if(l==="link-card"){if(Me===null)return F({reason:"not-found"});const w=et(s,l);return w!==null?w:St(Me,s)}const h=et(s,l);if(h!==null)return h;if(l==="refresh"&&!tt(s))return F({reason:"forbidden"});try{return await me(l,s,m.searchParams)}catch(w){return F(q(w,{operation:l},s.signal,c))}};return Object.freeze({loader:V,headers:Kr,dataLoader:({request:s,url:m,params:l})=>ve(s,m,l["*"]),dataAction:({request:s,url:m,params:l})=>ve(s,m,l["*"]),forgetTree:s=>{if(typeof s!="string")throw new TypeError(`[markdown-explorer] forgetTree needs the string key onTreeRefreshed received; got ${typeof s}`);p.forget(s)}})},ge=Object.freeze({maxEntries:2e4,maxDocumentBytes:2*1024*1024,textPreviewBytes:8*1024,walkConcurrency:8}),Qr=new Set(["md","markdown","mdx"]),pt=new Map([...[["png","image/png"],["jpg","image/jpeg"],["jpeg","image/jpeg"],["gif","image/gif"],["svg","image/svg+xml"],["webp","image/webp"],["ico","image/x-icon"],["bmp","image/bmp"],["tif","image/tiff"],["tiff","image/tiff"],["avif","image/avif"]].map(([e,t])=>[e,{kind:"image",contentType:t}]),...[["mp4","video/mp4"],["m4v","video/mp4"],["webm","video/webm"],["mov","video/quicktime"],["avi","video/x-msvideo"],["mkv","video/x-matroska"],["ogv","video/ogg"]].map(([e,t])=>[e,{kind:"media",mediaType:"video",contentType:t}]),...[["mp3","audio/mpeg"],["wav","audio/wav"],["ogg","audio/ogg"],["oga","audio/ogg"],["opus","audio/ogg"],["m4a","audio/mp4"],["flac","audio/flac"],["aac","audio/aac"],["wma","audio/x-ms-wma"]].map(([e,t])=>[e,{kind:"media",mediaType:"audio",contentType:t}]),["pdf",{kind:"media",mediaType:"pdf",contentType:"application/pdf"}]]),Zr=new Set(["txt","text","log","csv","tsv","json","jsonc","json5","ndjson","yaml","yml","toml","ini","cfg","conf","properties","xml","xsl","xsd","dtd","html","htm","xhtml","css","scss","sass","less","styl","js","mjs","cjs","jsx","ts","mts","cts","tsx","vue","svelte","astro","py","pyi","rb","go","rs","java","kt","kts","scala","groovy","gradle","c","h","cc","cpp","cxx","hpp","hh","hxx","cs","fs","vb","swift","m","mm","php","pl","pm","r","jl","lua","dart","ex","exs","erl","hrl","hs","ml","mli","clj","cljs","elm","nim","zig","v","sol","tf","hcl","nix","sh","bash","zsh","fish","ps1","psm1","bat","cmd","sql","graphql","gql","proto","thrift","avsc","rst","adoc","asciidoc","tex","bib","org","textile","diff","patch","srt","vtt","ics","vcf","gitignore","gitattributes","editorconfig","dockerignore","npmignore","prettierrc","eslintrc","babelrc","mailmap"]),qr=new Set(["readme","license","licence","copying","notice","authors","contributors","changelog","changes","todo","makefile","dockerfile","containerfile","procfile","gemfile","rakefile","vagrantfile","jenkinsfile","brewfile","codeowners"]),ht=typeof re.constants.O_NOFOLLOW=="number"?re.constants.O_NOFOLLOW:0,wt=typeof re.constants.O_NONBLOCK=="number"?re.constants.O_NONBLOCK:0,rt=e=>`${e.size}-${e.mtimeNs}`,en=e=>e!==""&&e!=="."&&e!==".."&&!e.includes(":")&&!e.endsWith(".")&&!e.endsWith(" "),nt=e=>y.isAcceptableDocumentPath(e)&&e===e.normalize("NFC")&&e.split("/").every(en),gt=e=>{const t=e.toLowerCase(),r=t.lastIndexOf(".");return r<0?"":t.slice(r+1)},tn=e=>{const t=gt(e);if(Qr.has(t))return{kind:"markdown"};const r=pt.get(t);if(r!==void 0)return r.kind==="image"?{kind:"image"}:{kind:"media",mediaType:r.mediaType};const n=e.toLowerCase();return Zr.has(t)||!n.includes(".")&&qr.has(n)?{kind:"text"}:{kind:"file"}},Et=e=>{switch(typeof e=="object"&&e!==null?e.code:void 0){case"ENOENT":case"ENOTDIR":return"not-found";case"ELOOP":case"EACCES":case"EPERM":return"forbidden";case"ENAMETOOLONG":return"invalid";case"EISDIR":return"unsupported";default:return null}},yt=e=>{const t=Et(e);return t===null?e:new fe(t)},rn=e=>{const t=typeof e=="object"&&e!==null?e.code:void 0;return t==="EACCES"||t==="EPERM"||t==="ENOENT"||t==="ENOTDIR"},ot=async(e,t)=>{const r=[];for await(const n of e.createReadStream({start:0,end:t-1,autoClose:!1}))r.push(n);return Buffer.concat(r)},nn=(e,t)=>e!==null?{start:e.offset,end:e.offset+e.length-1}:t===0n?{}:{start:0,end:Number(t)-1},on=async(e,t,r,n)=>{let a;try{a=await de.open(e,re.constants.O_RDONLY|ht|wt);const g=await a.stat({bigint:!0});if(!g.isFile()||g.ino!==t.ino||g.dev!==t.dev||g.size!==t.size||g.mtimeNs!==t.mtimeNs)throw new fe("not-found")}catch(g){throw await a?.close(),yt(g)}const o=a.createReadStream(nn(r,t.size)),c=Ot.Readable.toWeb(o),f=()=>{o.destroy(n.reason)};return n.aborted?f():n.addEventListener("abort",f,{once:!0}),c},sn=(e,t)=>{const r=te.NAME_COLLATOR.compare(e,t);return r!==0?r:e===t?0:e<t?-1:1},an=e=>{let t=0;const r=[];return async n=>{t<e?t+=1:await new Promise(a=>r.push(a));try{return await n()}finally{const a=r.shift();a===void 0?t-=1:a()}}},cn=(e,t)=>{if(e.isSymbolicLink())return"symbolic-link";if(!(e.isDirectory()||e.isFile()))return"special-file";const{name:r}=e;return r!==r.normalize("NFC")?"not-nfc":r.includes(":")?"colon":r.endsWith(".")||r.endsWith(" ")?"trailing-dot-or-space":y.isAcceptableDocumentPath(r)?y.isAcceptableDocumentPath(t)?null:"path-too-long":"control-character-or-backslash"},un=new Set(["id","label","root","pathPrefix","parse","deny","maxEntries","maxDocumentBytes","textPreviewBytes","walkConcurrency","cacheScope","reportSkipped"]),Ee=(e,t,r)=>{if(t===void 0)return r;if(typeof t!="number"||!Number.isSafeInteger(t)||t<=0)throw new RangeError(`[markdown-explorer] ${e} must be a positive integer; got ${String(t)}`);return t},ln=e=>{if(e===null||typeof e!="object")throw new TypeError("[markdown-explorer] createFileSystemSource needs an options object");for(const i of Object.keys(e))if(!un.has(i))throw new TypeError(`[markdown-explorer] createFileSystemSource does not know the option ${JSON.stringify(i)}`);const{id:t,label:r,root:n,parse:a}=e;if(typeof t!="string"||t==="")throw new TypeError("[markdown-explorer] a file-system source needs a non-empty id");if(typeof r!="string"||r.trim()==="")throw new TypeError("[markdown-explorer] a file-system source needs a non-blank label");if(typeof a!="function")throw new TypeError("[markdown-explorer] a file-system source needs a parse function");if(typeof n!="string"||!ee.isAbsolute(n))throw new RangeError(`[markdown-explorer] root must be an absolute path; got ${JSON.stringify(n)}`);let o;try{o=re.statSync(n).isDirectory()}catch(i){throw new RangeError(`[markdown-explorer] root does not exist: ${n}`,{cause:i})}if(!o)throw new RangeError(`[markdown-explorer] root is not a directory: ${n}`);const c=re.realpathSync(n),f=e.pathPrefix;if(typeof f!="string")throw new TypeError('[markdown-explorer] pathPrefix is required: "" for a source over the whole root, or relative segments ending with "/"');if(f!==""&&!(f.endsWith("/")&&nt(f.slice(0,-1))))throw new RangeError(`[markdown-explorer] pathPrefix must be empty or relative segments ending with "/"; got ${JSON.stringify(f)}`);const g=y.resolvePathRules(e.deny),x=Ee("maxEntries",e.maxEntries,ge.maxEntries),d=Ee("maxDocumentBytes",e.maxDocumentBytes,ge.maxDocumentBytes),p=Ee("textPreviewBytes",e.textPreviewBytes,ge.textPreviewBytes),A=Ee("walkConcurrency",e.walkConcurrency,ge.walkConcurrency),_=e.cacheScope===void 0?"principal":e.cacheScope;if(_!=="principal"&&_!=="shared")throw new RangeError(`[markdown-explorer] cacheScope must be "principal" or "shared"; got ${JSON.stringify(_)}`);const P=e.reportSkipped;if(P!==void 0&&typeof P!="function")throw new TypeError("[markdown-explorer] reportSkipped must be a function");const R=P===void 0?i=>{console.warn(`[markdown-explorer] the file-system source ${JSON.stringify(i.sourceId)} does not list ${JSON.stringify(i.path)}: ${i.reason}`)}:P,O=new Set,L=i=>{const E=ee.resolve(c,...i.split("/")),T=ee.relative(c,E);return T===""||T===".."||T.startsWith(`..${ee.sep}`)||ee.isAbsolute(T)?null:E},S=(i,E)=>{const T=`${E}\0${i}`;O.has(T)||O.size>=x||(O.add(T),R({sourceId:t,path:i,reason:E}))},N=async({signal:i})=>{i.throwIfAborted();const E=new AbortController,T=()=>{E.abort(i.reason)};i.addEventListener("abort",T,{once:!0});const k=an(A);let I=0;const H=async(M,X)=>{const G=await k(async()=>{E.signal.throwIfAborted();try{return await de.readdir(M,{withFileTypes:!0})}catch($){if(X===""||!rn($))throw $;return null}});if(E.signal.throwIfAborted(),G===null)return S(`${f}${X}`,"unreadable-directory"),null;const U=[];for(const $ of G){if(g.deniesName($.name))continue;const Y=X===""?$.name:`${X}/${$.name}`,V=`${f}${Y}`,W=cn($,V);if(W!==null){S(V,W);continue}U.push({dirent:$,relativePath:Y,path:V})}if(I+=U.length,I>x)throw new fe("too-large");return U.sort(($,Y)=>sn($.dirent.name,Y.dirent.name)),(await Promise.all(U.map(async({dirent:$,relativePath:Y,path:V})=>{if(!$.isDirectory())return{name:$.name,path:V,type:"file"};const W=await H(ee.join(M,$.name),Y);return W===null?null:{name:$.name,path:V,type:"directory",children:W}}))).filter($=>$!==null)};try{const M=await H(c,"");if(M===null)throw new Error("[markdown-explorer] the source's root could not be listed");return M}catch(M){throw E.abort(),M}finally{i.removeEventListener("abort",T)}},C=async i=>{if(!i.startsWith(f))return{status:"refused",reason:"not-found"};const E=i.slice(f.length);if(!nt(E))return{status:"refused",reason:"invalid"};if(g.deniesPath(E))return{status:"refused",reason:"forbidden"};const T=L(E);if(T===null)return{status:"refused",reason:"forbidden"};const k=await de.lstat(T,{bigint:!0});if(k.isSymbolicLink())return{status:"refused",reason:"forbidden"};if(!k.isFile())return{status:"refused",reason:"unsupported"};const I=await de.realpath(T);return I!==T||g.deniesPath(ee.relative(c,I).split(ee.sep).join("/"))?{status:"refused",reason:"forbidden"}:{status:"file",target:T,name:E.slice(E.lastIndexOf("/")+1),stats:k}},z=async(i,E,T)=>{let k;try{const I=await C(T);if(I.status==="refused")return y.failureDocument(I.reason);const{target:H,name:M,stats:X}=I,G=tn(M),U=rt(X);if(G.kind==="image")return{kind:"image",name:M,version:U};if(G.kind==="media")return{kind:"media",name:M,mediaType:G.mediaType,version:U};if(G.kind==="file")return{kind:"file",name:M,version:U};k=await de.open(H,re.constants.O_RDONLY|ht|wt);const Z=await k.stat({bigint:!0});if(!Z.isFile()||Z.ino!==X.ino||Z.dev!==X.dev)return y.failureDocument("forbidden");if(G.kind==="markdown"){if(Z.size>BigInt(d))return y.failureDocument("too-large");const W=await ot(k,d+1);if(W.length>d)return y.failureDocument("too-large");const me=await a(new TextDecoder("utf-8").decode(W),E);return{kind:"markdown",name:M,htmlContent:me.htmlContent,headings:me.headings}}const $=await ot(k,p);if($.includes(0))return{kind:"file",name:M,version:U};const Y=Z.size>BigInt(p),V=new TextDecoder("utf-8").decode($,{stream:Y});return{kind:"text",name:M,text:V,truncated:Y,version:U}}catch(I){const H=Et(I);if(H===null)throw I;return y.failureDocument(H)}finally{await k?.close()}},u=async(i,E,T)=>{let k;try{k=await C(T)}catch(U){throw yt(U)}if(k.status==="refused")throw new fe(k.reason);const{target:I,name:H,stats:M}=k,X=pt.get(gt(H)),G=X===void 0?"":X.contentType;return{name:H,contentType:G,size:Number(M.size),version:rt(M),open:U=>on(I,M,U,i.signal)}};return Object.freeze({id:t,label:r,cacheScope:_,boundary:Object.freeze({contains:i=>i.startsWith(f)}),tree:N,document:z,asset:u})};exports.DEFAULT_DENIED_PATH_SEGMENTS=y.DEFAULT_DENIED_PATH_SEGMENTS;exports.MAX_DOCUMENT_PATH_LENGTH=y.MAX_DOCUMENT_PATH_LENGTH;exports.isAcceptableDocumentPath=y.isAcceptableDocumentPath;exports.isDeniedPath=y.isDeniedPath;exports.ExplorerError=fe;exports.anonymousAccess=Rt;exports.createFileSystemSource=ln;exports.createMarkdownExplorer=Vr;
package/dist/server.d.cts CHANGED
@@ -3,5 +3,5 @@ export { type AnonymousAccess, type AnonymousPrincipal, anonymousAccess } from "
3
3
  export { createMarkdownExplorer } from "./server/createMarkdownExplorer.cjs";
4
4
  export { ExplorerError, type ExplorerLogDetail, type ExplorerLogger, type ExplorerOperation } from "./server/errors.cjs";
5
5
  export { createFileSystemSource, type FileSystemSkippedEntry, type FileSystemSkipReason, type FileSystemSource, type FileSystemSourceOptions } from "./server/fileSystemSource.cjs";
6
- export type { ExplorerAssetFile, ExplorerAuthentication, ExplorerBoundaryAnswer, ExplorerByteRange, ExplorerHostDocument, ExplorerPageLoaderResult, ExplorerSource, ExplorerSourceBoundary, ExplorerSourceContext, MarkdownExplorerServer, MarkdownExplorerServerConfig, } from "./server/ports.cjs";
6
+ export type { ExplorerAssetFile, ExplorerAuthentication, ExplorerAuthenticationMode, ExplorerBoundaryAnswer, ExplorerByteRange, ExplorerHostDocument, ExplorerPageLoaderResult, ExplorerSource, ExplorerSourceBoundary, ExplorerSourceContext, MarkdownExplorerServer, MarkdownExplorerServerConfig, } from "./server/ports.cjs";
7
7
  export type { HtmlSanitizerOptions } from "./server/sanitizer.cjs";
package/dist/server.d.ts CHANGED
@@ -3,5 +3,5 @@ export { type AnonymousAccess, type AnonymousPrincipal, anonymousAccess } from "
3
3
  export { createMarkdownExplorer } from "./server/createMarkdownExplorer.js";
4
4
  export { ExplorerError, type ExplorerLogDetail, type ExplorerLogger, type ExplorerOperation } from "./server/errors.js";
5
5
  export { createFileSystemSource, type FileSystemSkippedEntry, type FileSystemSkipReason, type FileSystemSource, type FileSystemSourceOptions } from "./server/fileSystemSource.js";
6
- export type { ExplorerAssetFile, ExplorerAuthentication, ExplorerBoundaryAnswer, ExplorerByteRange, ExplorerHostDocument, ExplorerPageLoaderResult, ExplorerSource, ExplorerSourceBoundary, ExplorerSourceContext, MarkdownExplorerServer, MarkdownExplorerServerConfig, } from "./server/ports.js";
6
+ export type { ExplorerAssetFile, ExplorerAuthentication, ExplorerAuthenticationMode, ExplorerBoundaryAnswer, ExplorerByteRange, ExplorerHostDocument, ExplorerPageLoaderResult, ExplorerSource, ExplorerSourceBoundary, ExplorerSourceContext, MarkdownExplorerServer, MarkdownExplorerServerConfig, } from "./server/ports.js";
7
7
  export type { HtmlSanitizerOptions } from "./server/sanitizer.js";