UNPKG

451-tools

Version:

Censorship resilient and distributed publishing: informed by the needs of publishers and their audiences, More Mirrors implements a set of offline fallback strategies for censorship resilient websites.

6 lines 71.2 kB
"use strict";var Z=e=>{throw TypeError(e)};var ee=(e,t,r)=>t.has(e)||Z("Cannot "+r);var D=(e,t,r)=>(ee(e,t,"read from private field"),r?r.call(e):t.get(e)),te=(e,t,r)=>t.has(e)?Z("Cannot add the same private member more than once"):t instanceof WeakSet?t.add(e):t.set(e,r),M=(e,t,r,n)=>(ee(e,t,"write to private field"),n?n.call(e,r):t.set(e,r),r);Object.defineProperty(exports,Symbol.toStringTag,{value:"Module"});try{self["workbox:core:7.0.0"]&&_()}catch{}const ke={"invalid-value":({paramName:e,validValueDescription:t,value:r})=>{if(!e||!t)throw new Error("Unexpected input to 'invalid-value' error.");return`The '${e}' parameter was given a value with an unexpected value. ${t} Received a value of ${JSON.stringify(r)}.`},"not-an-array":({moduleName:e,className:t,funcName:r,paramName:n})=>{if(!e||!t||!r||!n)throw new Error("Unexpected input to 'not-an-array' error.");return`The parameter '${n}' passed into '${e}.${t}.${r}()' must be an array.`},"incorrect-type":({expectedType:e,paramName:t,moduleName:r,className:n,funcName:s})=>{if(!e||!t||!r||!s)throw new Error("Unexpected input to 'incorrect-type' error.");const a=n?`${n}.`:"";return`The parameter '${t}' passed into '${r}.${a}${s}()' must be of type ${e}.`},"incorrect-class":({expectedClassName:e,paramName:t,moduleName:r,className:n,funcName:s,isReturnValueProblem:a})=>{if(!e||!r||!s)throw new Error("Unexpected input to 'incorrect-class' error.");const o=n?`${n}.`:"";return a?`The return value from '${r}.${o}${s}()' must be an instance of class ${e}.`:`The parameter '${t}' passed into '${r}.${o}${s}()' must be an instance of class ${e}.`},"missing-a-method":({expectedMethod:e,paramName:t,moduleName:r,className:n,funcName:s})=>{if(!e||!t||!r||!n||!s)throw new Error("Unexpected input to 'missing-a-method' error.");return`${r}.${n}.${s}() expected the '${t}' parameter to expose a '${e}' method.`},"add-to-cache-list-unexpected-type":({entry:e})=>`An unexpected entry was passed to 'workbox-precaching.PrecacheController.addToCacheList()' The entry '${JSON.stringify(e)}' isn't supported. You must supply an array of strings with one or more characters, objects with a url property or Request objects.`,"add-to-cache-list-conflicting-entries":({firstEntry:e,secondEntry:t})=>{if(!e||!t)throw new Error("Unexpected input to 'add-to-cache-list-duplicate-entries' error.");return`Two of the entries passed to 'workbox-precaching.PrecacheController.addToCacheList()' had the URL ${e} but different revision details. Workbox is unable to cache and version the asset correctly. Please remove one of the entries.`},"plugin-error-request-will-fetch":({thrownErrorMessage:e})=>{if(!e)throw new Error("Unexpected input to 'plugin-error-request-will-fetch', error.");return`An error was thrown by a plugins 'requestWillFetch()' method. The thrown error message was: '${e}'.`},"invalid-cache-name":({cacheNameId:e,value:t})=>{if(!e)throw new Error("Expected a 'cacheNameId' for error 'invalid-cache-name'");return`You must provide a name containing at least one character for setCacheDetails({${e}: '...'}). Received a value of '${JSON.stringify(t)}'`},"unregister-route-but-not-found-with-method":({method:e})=>{if(!e)throw new Error("Unexpected input to 'unregister-route-but-not-found-with-method' error.");return`The route you're trying to unregister was not previously registered for the method type '${e}'.`},"unregister-route-route-not-registered":()=>"The route you're trying to unregister was not previously registered.","queue-replay-failed":({name:e})=>`Replaying the background sync queue '${e}' failed.`,"duplicate-queue-name":({name:e})=>`The Queue name '${e}' is already being used. All instances of backgroundSync.Queue must be given unique names.`,"expired-test-without-max-age":({methodName:e,paramName:t})=>`The '${e}()' method can only be used when the '${t}' is used in the constructor.`,"unsupported-route-type":({moduleName:e,className:t,funcName:r,paramName:n})=>`The supplied '${n}' parameter was an unsupported type. Please check the docs for ${e}.${t}.${r} for valid input types.`,"not-array-of-class":({value:e,expectedClass:t,moduleName:r,className:n,funcName:s,paramName:a})=>`The supplied '${a}' parameter must be an array of '${t}' objects. Received '${JSON.stringify(e)},'. Please check the call to ${r}.${n}.${s}() to fix the issue.`,"max-entries-or-age-required":({moduleName:e,className:t,funcName:r})=>`You must define either config.maxEntries or config.maxAgeSecondsin ${e}.${t}.${r}`,"statuses-or-headers-required":({moduleName:e,className:t,funcName:r})=>`You must define either config.statuses or config.headersin ${e}.${t}.${r}`,"invalid-string":({moduleName:e,funcName:t,paramName:r})=>{if(!r||!e||!t)throw new Error("Unexpected input to 'invalid-string' error.");return`When using strings, the '${r}' parameter must start with 'http' (for cross-origin matches) or '/' (for same-origin matches). Please see the docs for ${e}.${t}() for more info.`},"channel-name-required":()=>"You must provide a channelName to construct a BroadcastCacheUpdate instance.","invalid-responses-are-same-args":()=>"The arguments passed into responsesAreSame() appear to be invalid. Please ensure valid Responses are used.","expire-custom-caches-only":()=>"You must provide a 'cacheName' property when using the expiration plugin with a runtime caching strategy.","unit-must-be-bytes":({normalizedRangeHeader:e})=>{if(!e)throw new Error("Unexpected input to 'unit-must-be-bytes' error.");return`The 'unit' portion of the Range header must be set to 'bytes'. The Range header provided was "${e}"`},"single-range-only":({normalizedRangeHeader:e})=>{if(!e)throw new Error("Unexpected input to 'single-range-only' error.");return`Multiple ranges are not supported. Please use a single start value, and optional end value. The Range header provided was "${e}"`},"invalid-range-values":({normalizedRangeHeader:e})=>{if(!e)throw new Error("Unexpected input to 'invalid-range-values' error.");return`The Range header is missing both start and end values. At least one of those values is needed. The Range header provided was "${e}"`},"no-range-header":()=>"No Range header was found in the Request provided.","range-not-satisfiable":({size:e,start:t,end:r})=>`The start (${t}) and end (${r}) values in the Range are not satisfiable by the cached response, which is ${e} bytes.`,"attempt-to-cache-non-get-request":({url:e,method:t})=>`Unable to cache '${e}' because it is a '${t}' request and only 'GET' requests can be cached.`,"cache-put-with-no-response":({url:e})=>`There was an attempt to cache '${e}' but the response was not defined.`,"no-response":({url:e,error:t})=>{let r=`The strategy could not generate a response for '${e}'.`;return t&&(r+=` The underlying error is ${t}.`),r},"bad-precaching-response":({url:e,status:t})=>`The precaching request for '${e}' failed`+(t?` with an HTTP status of ${t}.`:"."),"non-precached-url":({url:e})=>`createHandlerBoundToURL('${e}') was called, but that URL is not precached. Please pass in a URL that is precached instead.`,"add-to-cache-list-conflicting-integrities":({url:e})=>`Two of the entries passed to 'workbox-precaching.PrecacheController.addToCacheList()' had the URL ${e} with different integrity values. Please remove one of them.`,"missing-precache-entry":({cacheName:e,url:t})=>`Unable to find a precached response in ${e} for ${t}.`,"cross-origin-copy-response":({origin:e})=>`workbox-core.copyResponse() can only be used with same-origin responses. It was passed a response with origin ${e}.`,"opaque-streams-source":({type:e})=>{const t=`One of the workbox-streams sources resulted in an '${e}' response.`;return e==="opaqueredirect"?`${t} Please do not use a navigation request that results in a redirect as a source.`:`${t} Please ensure your sources are CORS-enabled.`}},xe=(e,...t)=>{let r=e;return t.length>0&&(r+=` :: ${JSON.stringify(t)}`),r},Ee=(e,t={})=>{const r=ke[e];if(!r)throw new Error(`Unable to find message for code '${e}'.`);return r(t)},Te=process.env.NODE_ENV==="production"?xe:Ee;let k=class extends Error{constructor(t,r){const n=Te(t,r);super(n),this.name=t,this.details=r}};const $e=(e,t)=>{if(!Array.isArray(e))throw new k("not-an-array",t)},ve=(e,t,r)=>{if(typeof e[t]!=="function")throw r.expectedMethod=t,new k("missing-a-method",r)},Re=(e,t,r)=>{if(typeof e!==t)throw r.expectedType=t,new k("incorrect-type",r)},Ce=(e,t,r)=>{if(!(e instanceof t))throw r.expectedClassName=t.name,new k("incorrect-class",r)},Ne=(e,t,r)=>{if(!t.includes(e))throw r.validValueDescription=`Valid values are ${JSON.stringify(t)}.`,new k("invalid-value",r)},_e=(e,t,r)=>{const n=new k("not-array-of-class",r);if(!Array.isArray(e))throw n;for(const s of e)if(!(s instanceof t))throw n},L=process.env.NODE_ENV==="production"?null:{hasMethod:ve,isArray:$e,isInstance:Ce,isOneOf:Ne,isType:Re,isArrayOfClass:_e};function Ae(e){e.then(()=>{})}const R=process.env.NODE_ENV==="production"?null:(()=>{"__WB_DISABLE_DEV_LOGS"in globalThis||(self.__WB_DISABLE_DEV_LOGS=!1);let e=!1;const t={debug:"#7f8c8d",log:"#2ecc71",warn:"#f39c12",error:"#c0392b",groupCollapsed:"#3498db",groupEnd:null},r=function(a,o){if(self.__WB_DISABLE_DEV_LOGS)return;if(a==="groupCollapsed"&&/^((?!chrome|android).)*safari/i.test(navigator.userAgent)){console[a](...o);return}const i=[`background: ${t[a]}`,"border-radius: 0.5em","color: white","font-weight: bold","padding: 2px 0.5em"],c=e?[]:["%cworkbox",i.join(";")];console[a](...c,...o),a==="groupCollapsed"&&(e=!0),a==="groupEnd"&&(e=!1)},n={},s=Object.keys(t);for(const a of s){const o=a;n[o]=(...i)=>{r(o,i)}}return n})(),De=(e,t)=>t.some(r=>e instanceof r);let re,ne;function Me(){return re||(re=[IDBDatabase,IDBObjectStore,IDBIndex,IDBCursor,IDBTransaction])}function Le(){return ne||(ne=[IDBCursor.prototype.advance,IDBCursor.prototype.continue,IDBCursor.prototype.continuePrimaryKey])}const le=new WeakMap,j=new WeakMap,de=new WeakMap,U=new WeakMap,W=new WeakMap;function Pe(e){const t=new Promise((r,n)=>{const s=()=>{e.removeEventListener("success",a),e.removeEventListener("error",o)},a=()=>{r(w(e.result)),s()},o=()=>{n(e.error),s()};e.addEventListener("success",a),e.addEventListener("error",o)});return t.then(r=>{r instanceof IDBCursor&&le.set(r,e)}).catch(()=>{}),W.set(t,e),t}function Oe(e){if(j.has(e))return;const t=new Promise((r,n)=>{const s=()=>{e.removeEventListener("complete",a),e.removeEventListener("error",o),e.removeEventListener("abort",o)},a=()=>{r(),s()},o=()=>{n(e.error||new DOMException("AbortError","AbortError")),s()};e.addEventListener("complete",a),e.addEventListener("error",o),e.addEventListener("abort",o)});j.set(e,t)}let V={get(e,t,r){if(e instanceof IDBTransaction){if(t==="done")return j.get(e);if(t==="objectStoreNames")return e.objectStoreNames||de.get(e);if(t==="store")return r.objectStoreNames[1]?void 0:r.objectStore(r.objectStoreNames[0])}return w(e[t])},set(e,t,r){return e[t]=r,!0},has(e,t){return e instanceof IDBTransaction&&(t==="done"||t==="store")?!0:t in e}};function Se(e){V=e(V)}function qe(e){return e===IDBDatabase.prototype.transaction&&!("objectStoreNames"in IDBTransaction.prototype)?function(t,...r){const n=e.call(H(this),t,...r);return de.set(n,t.sort?t.sort():[t]),w(n)}:Le().includes(e)?function(...t){return e.apply(H(this),t),w(le.get(this))}:function(...t){return w(e.apply(H(this),t))}}function Ie(e){return typeof e=="function"?qe(e):(e instanceof IDBTransaction&&Oe(e),De(e,Me())?new Proxy(e,V):e)}function w(e){if(e instanceof IDBRequest)return Pe(e);if(U.has(e))return U.get(e);const t=Ie(e);return t!==e&&(U.set(e,t),W.set(t,e)),t}const H=e=>W.get(e);function Ue(e,t,{blocked:r,upgrade:n,blocking:s,terminated:a}={}){const o=indexedDB.open(e,t),i=w(o);return n&&o.addEventListener("upgradeneeded",c=>{n(w(o.result),c.oldVersion,c.newVersion,w(o.transaction),c)}),r&&o.addEventListener("blocked",c=>r(c.oldVersion,c.newVersion,c)),i.then(c=>{a&&c.addEventListener("close",()=>a()),s&&c.addEventListener("versionchange",l=>s(l.oldVersion,l.newVersion,l))}).catch(()=>{}),i}function He(e,{blocked:t}={}){const r=indexedDB.deleteDatabase(e);return t&&r.addEventListener("blocked",n=>t(n.oldVersion,n)),w(r).then(()=>{})}const Be=["get","getKey","getAll","getAllKeys","count"],Fe=["put","add","delete","clear"],B=new Map;function se(e,t){if(!(e instanceof IDBDatabase&&!(t in e)&&typeof t=="string"))return;if(B.get(t))return B.get(t);const r=t.replace(/FromIndex$/,""),n=t!==r,s=Fe.includes(r);if(!(r in(n?IDBIndex:IDBObjectStore).prototype)||!(s||Be.includes(r)))return;const a=async function(o,...i){const c=this.transaction(o,s?"readwrite":"readonly");let l=c.store;return n&&(l=l.index(i.shift())),(await Promise.all([l[r](...i),s&&c.done]))[0]};return B.set(t,a),a}Se(e=>({...e,get:(t,r,n)=>se(t,r)||e.get(t,r,n),has:(t,r)=>!!se(t,r)||e.has(t,r)}));try{self["workbox:expiration:7.0.0"]&&_()}catch{}const je="workbox-expiration",C="cache-entries",ae=e=>{const t=new URL(e,location.href);return t.hash="",t.href};class Ve{constructor(t){this._db=null,this._cacheName=t}_upgradeDb(t){const r=t.createObjectStore(C,{keyPath:"id"});r.createIndex("cacheName","cacheName",{unique:!1}),r.createIndex("timestamp","timestamp",{unique:!1})}_upgradeDbAndDeleteOldDbs(t){this._upgradeDb(t),this._cacheName&&He(this._cacheName)}async setTimestamp(t,r){t=ae(t);const n={url:t,timestamp:r,cacheName:this._cacheName,id:this._getId(t)},a=(await this.getDb()).transaction(C,"readwrite",{durability:"relaxed"});await a.store.put(n),await a.done}async getTimestamp(t){const n=await(await this.getDb()).get(C,this._getId(t));return n==null?void 0:n.timestamp}async expireEntries(t,r){const n=await this.getDb();let s=await n.transaction(C).store.index("timestamp").openCursor(null,"prev");const a=[];let o=0;for(;s;){const c=s.value;c.cacheName===this._cacheName&&(t&&c.timestamp<t||r&&o>=r?a.push(s.value):o++),s=await s.continue()}const i=[];for(const c of a)await n.delete(C,c.id),i.push(c.url);return i}_getId(t){return this._cacheName+"|"+ae(t)}async getDb(){return this._db||(this._db=await Ue(je,1,{upgrade:this._upgradeDbAndDeleteOldDbs.bind(this)})),this._db}}class J{constructor(t,r={}){if(this._isRunning=!1,this._rerunRequested=!1,process.env.NODE_ENV!=="production"){if(L.isType(t,"string",{moduleName:"workbox-expiration",className:"CacheExpiration",funcName:"constructor",paramName:"cacheName"}),!(r.maxEntries||r.maxAgeSeconds))throw new k("max-entries-or-age-required",{moduleName:"workbox-expiration",className:"CacheExpiration",funcName:"constructor"});r.maxEntries&&L.isType(r.maxEntries,"number",{moduleName:"workbox-expiration",className:"CacheExpiration",funcName:"constructor",paramName:"config.maxEntries"}),r.maxAgeSeconds&&L.isType(r.maxAgeSeconds,"number",{moduleName:"workbox-expiration",className:"CacheExpiration",funcName:"constructor",paramName:"config.maxAgeSeconds"})}this._maxEntries=r.maxEntries,this._maxAgeSeconds=r.maxAgeSeconds,this._matchOptions=r.matchOptions,this._cacheName=t,this._timestampModel=new Ve(t)}async expireEntries(){if(this._isRunning){this._rerunRequested=!0;return}this._isRunning=!0;const t=this._maxAgeSeconds?Date.now()-this._maxAgeSeconds*1e3:0,r=await this._timestampModel.expireEntries(t,this._maxEntries),n=await self.caches.open(this._cacheName);for(const s of r)await n.delete(s,this._matchOptions);process.env.NODE_ENV!=="production"&&(r.length>0?(R.groupCollapsed(`Expired ${r.length} ${r.length===1?"entry":"entries"} and removed ${r.length===1?"it":"them"} from the '${this._cacheName}' cache.`),R.log(`Expired the following ${r.length===1?"URL":"URLs"}:`),r.forEach(s=>R.log(` ${s}`)),R.groupEnd()):R.debug("Cache expiration ran and found no entries to remove.")),this._isRunning=!1,this._rerunRequested&&(this._rerunRequested=!1,Ae(this.expireEntries()))}async updateTimestamp(t){process.env.NODE_ENV!=="production"&&L.isType(t,"string",{moduleName:"workbox-expiration",className:"CacheExpiration",funcName:"updateTimestamp",paramName:"url"}),await this._timestampModel.setTimestamp(t,Date.now())}async isURLExpired(t){if(this._maxAgeSeconds){const r=await this._timestampModel.getTimestamp(t),n=Date.now()-this._maxAgeSeconds*1e3;return r!==void 0?r<n:!0}else{if(process.env.NODE_ENV!=="production")throw new k("expired-test-without-max-age",{methodName:"isURLExpired",paramName:"maxAgeSeconds"});return!1}}async delete(){this._rerunRequested=!1,await this._timestampModel.expireEntries(1/0)}}typeof registration<"u"&&registration.scope;const u="451-tools",G=["network-only","network-first","stale-while-revalidate"],he={"network-only":Ge,"network-first":Y,"stale-while-revalidate":We};function Ge({event:e,fetcher:t=fetch}){const{request:r}=e;return t(r)}function Y({cacheName:e,event:t,expirationManager:r,fetcher:n=fetch}){const{request:s}=t;return n(s).then(a=>{const o=a.clone();return a.ok&&caches.open(e).then(i=>i.put(s,o)).then(async()=>{r&&(await r.updateTimestamp(s.url),await r.expireEntries())}),a}).catch(()=>caches.open(e).then(a=>a.match(s,{ignoreSearch:!0})))}function We({cacheName:e,event:t,expirationManager:r,fetcher:n=fetch}){const{request:s}=t;return caches.open(e).then(a=>a.match(s,{ignoreSearch:!0})).then(async a=>a?(t.waitUntil(n(s).then(async o=>{if(o.ok){const i=o.clone();caches.open(e).then(c=>c.put(s.url,i)).then(async()=>{r&&(await r.updateTimestamp(s.url),await r.expireEntries())})}return o})),a):n(s).then(o=>o.ok?caches.open(e).then(i=>i.put(s,o.clone())).then(()=>o):o))}function Je(e){const t=JSON.stringify(e);return self.clients.matchAll().then(r=>Promise.all(r.map(n=>(n.postMessage(t),Promise.resolve("postMessage sent, ",t)))))}const pe="mirrors",fe="/mirrors.json",Ye=10*60*1e3,x="up",z="down";async function q(){return caches.open(pe).then(e=>e.match(fe)).then(e=>e.json())}async function X(e){await caches.open(pe).then(t=>t.put(fe,new Response(JSON.stringify(e),{headers:{"Content-Type":"application/json"}})))}async function oe(e,t){const r=await q(),n=r.find(o=>o.url===e),s={...n,lastModified:Date.now(),status:t},a=[...r.filter(o=>o.url!==e),s];await X(a).then(()=>{n.status!==t&&Je({type:"mirror-status-changed",mirror:e,status:t})})}async function ze(){const e=Date.now(),t=await q(),r=t.every(s=>s.status===z);let n;r?n=t.map(s=>({...s,lastModified:e,status:x})):n=t.map(s=>s.lastModified<e-Ye?{...s,lastModified:e,status:x}:s),await X(n)}async function ie(){const t=(await q()).filter(r=>r.status===x);return t.find(r=>r.isPrimary)||t[0]}async function E(e,t){const r=new URL(e.url),n=r.pathname,s=r.searchParams,a=e.destination==="document",{mirroring:o}=await t.getConfiguration(),i=o.timeout??3e3,c=n.replace(/^\//,"");let l=[];a&&await ze();let f=await ie();for(;f;){const p=f.url,h=new URL(c,p);h.search=s.toString();const $=new AbortController;try{const v=await Promise.race([Xe(i),fetch(new Request(h,{...e,signal:$.signal}))]),I=new Headers(v.headers);return I.append("x-mirror",p),I.append("x-time-cached",Date.now()),await oe(p,x),t.logger(`(mirroring) Request successful on mirror: ${p}, URL: ${h}`),new Response(v.body,{...v,headers:I})}catch(v){$.abort(),l.push(v),await oe(p,z),t.logger(`(mirroring) Request failed on mirror: ${p}, URL: ${h}`)}f=await ie()}return Promise.reject(new Error("networking.js (fetchFromMirrors): Out of mirrors.",{cause:l}))}function Xe(e){return new Promise((t,r)=>{setTimeout(()=>{r(new Response("",{status:408,statusText:"Request Timeout"}))},e)})}function Ke({serviceWorkerController:e}={}){if(!e)throw new Error("You must pass a serviceWorkerController plugin to registerBookmarkApi");e.modules.push("bookmark");const t=({event:s})=>new RegExp(`/${u}/bookmark/?$`).test(s.request.url),r=({event:s})=>ge(u).test(s.request.url),n=new J(`${u}-bookmarks`,{maxEntries:100});e.logger("(bookmark) Module registered."),e.addRoute(t,Qe,"GET"),e.logger(`(bookmark) GET "/${u}/bookmark/" endpoint registered.`),e.addRoute(r,Ze,"GET"),e.logger(`(bookmark) GET "/${u}/bookmark/:path" endpoint registered.`),e.addRoute(r,s=>et({...s,expirationManager:n}),"POST"),e.logger(`(bookmark) POST "/${u}/bookmark/:path" endpoint registered.`),e.addRoute(r,tt,"DELETE"),e.logger(`(bookmark) DELETE "/${u}/bookmark/:path" endpoint registered.`),e.addRoute(rt,s=>nt({...s,expirationManager:n}),"GET")}async function Qe(){const e=`${u}-bookmarks`,t=await caches.open(e),n=(await t.keys()).map(s=>t.match(s).then(async a=>{const o=await a.text(),i=a.headers.get("X-metadata");return{url:s.url,path:new URL(s.url).pathname,html:o,metadata:i?JSON.parse(i):null}}));return Promise.all(n).then(s=>new Response(JSON.stringify(s),{status:200,headers:{"Content-Type":"application/json"}})).catch(s=>new Response(null,{status:500,statusText:s.message}))}async function Ze({event:e}){const t=new URL(e.request.url),r=`${u}-bookmarks`,n=await caches.open(r),s=K(u,t);return s?n.match(s).then(async a=>{if(!a)return new Response(null,{status:404,statusText:"Not Found"});const o=await a.text(),i=a.headers.get("X-metadata"),c=JSON.stringify({url:e.request.url,path:s,html:o,metadata:i?JSON.parse(i):null});return new Response(c,{status:200,headers:{"Content-Type":"application/json"}})}):new Response(null,{status:400,statusText:"Not a valid bookmark path"})}async function et({event:e,serviceWorkerController:t,expirationManager:r}){const n=new URL(e.request.url),s=`${u}-bookmarks`,a=K(u,n);if(!a)return new Response(JSON.stringify({}),{status:400,statusText:"Not a valid bookmark path"});const o=new Request(a),i=await t.fetcher(o);if(!i.ok)return i;let c;try{const{metadata:l}=await e.request.json();c=new Response(i.body,{...i}),c.headers.set("x-metadata",JSON.stringify(l))}catch{c=i}return caches.open(s).then(l=>l.put(a,c)).then(async()=>(await r.updateTimestamp(a),await r.expireEntries(),new Response(null,{status:200}))).catch(l=>new Response(null,{status:500,statusText:l.message}))}async function tt({event:e}){const t=new URL(e.request.url),r=`${u}-bookmarks`,n=K(u,t);return n?caches.open(r).then(s=>s.delete(n)).then(()=>new Response(null,{status:200})).catch(s=>new Response(null,{status:500,statusText:s.message})):new Response(JSON.stringify({}),{status:400,statusText:"Not a valid bookmark path"})}function ge(e){return new RegExp(`/${e}/bookmark/(.{1,})`)}function K(e,t){const r=ge(e);return decodeURIComponent(t.pathname.match(r)[1])}async function rt({event:e}){return caches.open(`${u}-bookmarks`).then(t=>t.match(e.request))}async function nt({serviceWorkerController:e,expirationManager:t,event:r}){const s=e.modules.includes("mirroring")?a=>E(a,e):fetch;return Y({cacheName:`${u}-bookmarks`,expirationManager:t,fetcher:s,event:r})}const st=()=>({});function T(e,t){return t?`${e}?revision=${t}`:e}const at=(e={})=>{const{serviceWorkerController:t}=e;if(!t)throw new Error("You must pass a serviceWorkerController plugin to registerContentBundles");t.modules.push("content-bundles"),t.logger("(content-bundles) Module registered."),t.addInstallHandler(ot),t.addActivateHandler(it);const r=({event:n})=>new RegExp(`/${u}/content-bundles/?$`).test(n.request.url);t.addRoute(r,ct,"GET"),t.logger(`(content-bundles) GET "/${u}/content-bundles/" endpoint registered.`),t.addRoute(ut,lt,"GET")};async function ot({serviceWorkerController:e}){const{contentBundles:t}=await e.getConfiguration();return t.pages.map(r=>{const{metadata:n={}}=r,s=new Request(r.url);return e.fetcher(s).then(a=>{if(!a.ok)throw new Error(`Failed to fetch ${r.url}`);let o;try{o=new Response(a.body,{...a}),o.headers.set("x-metadata",JSON.stringify(n))}catch{o=a}return o}).then(a=>{const o=T(r.url,r.revision);return caches.open(`${u}-content-bundles`).then(i=>i.put(o,a))}).catch(a=>(console.info(a.message,", skipping caching content bundle"),Promise.resolve()))})}async function it({serviceWorkerController:e}){const{contentBundles:t}=await e.getConfiguration(),r=t.pages.map(n=>T(n.url,n.revision));return caches.open(`${u}-content-bundles`).then(n=>n.keys().then(s=>{s.forEach(a=>{const o=a.url.replace(self.location.origin,"");if(!r.includes(o))return n.delete(a)})}))}const ct=async()=>{try{const e=await caches.open(`${u}-content-bundles`),t=await e.keys(),r=await Promise.all(t.map(async n=>{const s=await e.match(n),a=s.headers.get("Content-Type"),o=s.headers.get("X-metadata"),i=await s.text();return{url:n.url,path:new URL(n.url).pathname,metadata:o?JSON.parse(o):null,contentType:a,content:i}}));return new Response(JSON.stringify(r),{status:200,headers:{"Content-Type":"application/json"}})}catch(e){return new Response(null,{status:500,statusText:e.message})}};async function ut({event:e}){return caches.open(`${u}-content-bundles`).then(t=>t.match(e.request,{ignoreSearch:!0}))}async function lt({serviceWorkerController:e,event:t}){const n=e.modules.includes("mirroring")?s=>E(s,e):fetch;return Y({cacheName:`${u}-content-bundles`,fetcher:n,event:t})}const dt=e=>!e||!e.pages?(console.warn("[content-bundles]: No configuration provided"),{pages:[]}):{pages:(Array.isArray(e.pages)?e.pages:[e.pages]).map(n=>{const{metadata:s={}}=n;return typeof n=="string"?{url:n,revision:null,metadata:s}:{url:n.url,revision:n.revision||null,metadata:s}})},ht=(e={})=>{const{serviceWorkerController:t}=e;if(!t)throw new Error("You must pass a serviceWorkerController plugin to registerOfflineAssets");t.modules.push("offline-assets"),t.logger("(offline-assets) Module registered."),t.addInstallHandler(pt),t.addActivateHandler(ft),t.addRoute(gt,mt,"GET")};async function pt({serviceWorkerController:e}){const{offlineAssets:t={}}=await e.getConfiguration();return t.assets.map(r=>{const n=T(r.url,r.revision);return Promise.all([caches.open(`${u}-offline-assets`).then(s=>{const a=new Request(n);return e.fetcher(a).then(o=>{if(o.ok)return s.put(n,o)})})])})}async function ft({serviceWorkerController:e}){const{offlineAssets:t}=await e.getConfiguration(),r=t.assets.map(n=>T(n.url,n.revision));return caches.open(`${u}-offline-assets`).then(n=>n.keys().then(s=>{s.forEach(a=>{const o=a.url.replace(self.location.origin,"");if(!r.includes(o))return n.delete(a)})}))}async function gt({event:e}){return caches.open(`${u}-offline-assets`).then(t=>t.match(e.request,{ignoreSearch:!0}))}function mt({event:e,serviceWorkerController:t}){return caches.open(`${u}-offline-assets`).then(r=>r.match(e.request,{ignoreSearch:!0}).then(n=>(n&&t.logger(`(offline-assets) Match found. Returning cached response for URL path: ${e.request.url}`),n)))}const bt=e=>{if(!e||!e.assets)throw new Error("Missing offlineAssets.assets in configuration.");return{assets:(Array.isArray(e.assets)?e.assets:[e.assets]).map(n=>typeof n=="string"?{url:n,revision:null}:{url:n.url,revision:n.revision||null})}},wt=`<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 640 360"><path fill="#7A7D95" d="M0 0h640v360H0z"/><g fill="#FFF"><path d="M258.649 118.314v122.223h122.223V118.314H258.649zm119.723 2.5v81.901l-33.228-32.793-25.763 24.932-16.711-16.614-41.521 41.038v-98.464h117.223zM261.149 238.037v-15.245l41.517-41.033 33.458 33.265 1.762-1.773-16.73-16.634 23.972-23.2 33.245 32.81v31.81H261.149z"/><path d="M294.185 165.228c8.089 0 14.67-6.581 14.67-14.669s-6.581-14.669-14.67-14.669-14.669 6.581-14.669 14.669 6.58 14.669 14.669 14.669zm0-26.839c6.71 0 12.17 5.459 12.17 12.169s-5.459 12.169-12.17 12.169-12.169-5.459-12.169-12.169 5.458-12.169 12.169-12.169z"/></g></svg> `,yt=(e={})=>{const{serviceWorkerController:t}=e;if(!t)throw new Error("You must pass a serviceWorkerController plugin to registerFallbackImage");t.modules.push("fallback-image"),t.logger("(fallback-image) Module registered."),t.addFallbackHandler(({event:r})=>r.request.destination==="image",({event:r,serviceWorkerController:n})=>(n.logger(`(fallback-image) Returning fallback image for URL: ${r.request.url}`),new Response(wt,{headers:{"Content-Type":"image/svg+xml"}})))},kt=()=>({});function xt({language:e,textDirection:t,templateStrings:r,mainCSS:n,mainJS:s}){return{"{{ language }}":e,"{{ textDirection }}":t,"{{ mainCSS }}":n,"{{ mainJS }}":s,"{{ pageTitle }}":(r==null?void 0:r.pageTitle)||"451 Tools","{{ pageDescription }}":(r==null?void 0:r.pageDescription)||"Censorship Resilient and Distributed Publishing","{{ homeLinkText }}":(r==null?void 0:r.homeLinkText)||"Home","{{ bookmarksTabTitle }}":(r==null?void 0:r.bookmarksTabTitle)||"Bookmarks","{{ editorialTabTitle }}":(r==null?void 0:r.editorialTabTitle)||"Editorial","{{ aboutTabTitle }}":(r==null?void 0:r.aboutTabTitle)||"About","{{ copyright }}":(r==null?void 0:r.copyright)||`Copyright © ${new Date().getFullYear()}, Zamaneh Media. All rights reserved.`,"{{ aboutInnerHTML }}":(r==null?void 0:r.aboutInnerHTML)||` <p>You are on the 451 Tools offline dashboard. This could be because you are experiencing an internet shutdown or your device is not connected to the internet. 451 Tools keeps information available even when the website is censored or when the internet is down.</p> <p>451 Tools helps publishers maintain reach and readership under the most adversarial circumstances. Find out more at <a href="https://451.tools/" target="_blank">https://451.tools/</a>.</p> `}}const Et='<!doctypehtml><html lang="{{ language }}"dir="{{ textDirection }}"><meta charset="UTF-8"><meta name="viewport"content="width=device-width,initial-scale=1"><meta name="description"content="{{ pageDescription }}"><title>{{ pageTitle }}</title><style>{{ mainCSS }}</style><div class="container"><header class="header"><a class="home-link"href="/"><svg xmlns="http://www.w3.org/2000/svg"fill="currentColor"viewBox="0 0 16 16"width="28"height="28"><path d="M8 1.32.66 8.133l.68.734.66-.613V14h5V9h2v5h5V8.254l.66.613.68-.734Zm0 1.36 5 4.648V13h-3V8H6v5H3V7.328Z"/></svg> <span class="link-text">{{ homeLinkText }}</span></a><h1 class="title">{{ pageTitle }}</h1><p class="description">{{ pageDescription }}</p><svg class="offline-icon"xmlns="http://www.w3.org/2000/svg"viewBox="0 0 500 500"aria-hidden="true"><path d="M355.5 105.5c11.4 36.1 17.7 73.6 18.7 111.4 4.3.5 8.5 1.1 12.6 2h69.8c-3.2-52.6-25.4-102.2-62.1-139.9-12.2 10-25.3 18.9-39 26.5M99 405.2c.7.7 1.5 1.3 2.1 1.8 2.1 1.6 4.4 3.1 6.5 4.7 3.2 2.3 6.5 4.5 9.7 6.6 2.3 1.5 4.7 2.8 6.9 4.2 3.4 1.9 6.6 3.9 10 5.6 2.4 1.3 4.9 2.5 7.4 3.7 3.2 1.6 6.8 3.1 10 4.7 2.4 1 4.7 2 7.1 2.8-12.9-16.2-23.6-34.1-31.5-53.4-10 5.7-19.3 12.1-28.2 19.3m171.2-158.9h-19.9v19.2c6-7 12.7-13.4 19.9-19.2m175.6.2c3.6 2.8 7 5.8 10.2 9 .3-3 .6-6 .8-9h-11M250.3 13.8v94.1c24.3-1.5 48-6.9 70.4-16.3-17.6-41.8-42.6-70.5-70.4-77.8m123.9 46.4-2.1-1.8c-2.1-1.6-4.4-3.1-6.5-4.7-3.2-2.3-6.5-4.5-9.7-6.6-2.3-1.5-4.7-2.7-6.9-4.2-3.4-1.9-6.6-3.9-10-5.7-2.5-1.3-4.9-2.5-7.4-3.7-3.2-1.6-6.8-3.2-10-4.7-2.4-1-4.7-1.9-7.1-2.7 13 16.2 23.6 34.1 31.5 53.4 9.9-5.7 19.3-12.2 28.2-19.3M250.3 218.8h78.8c5.7-1.2 11.5-2 17.4-2.4-1.2-33.5-6.6-66.7-16.4-98.8-25.4 10.3-52.4 16.3-79.7 17.8l-.1 83.4m-27.5 232.6v-51.7c-4.1-13.1-6.3-26.7-6.4-40.4V358c-22 2-43.5 7.2-63.9 15.7 17.6 41.6 42.5 70.4 70.3 77.7m-105.1-91.5c-11.6-36.7-18-74.9-18.7-113.4H16.6c3.2 52.6 25.4 102.2 62.1 139.9 12.2-10 25.3-18.9 39-26.5M16.3 218.8h82.5c1-38.5 7.1-76.7 18.7-113.4-13.8-7.6-26.8-16.5-39-26.5-36.7 37.7-58.6 87.4-62.2 139.9m235.3 232.1c-.4-.5-.8-1-1.3-1.5v2c.5-.1.9-.3 1.4-.4 0-.1-.1-.1-.1-.1m-125-204.4c1 34.3 6.5 68.4 16.5 101.3 24.2-9.9 49.9-15.7 75.9-17.5.2-1.2.4-2.4.7-3.5.9-3.9 1.9-7.8 3.1-11.6v-68.7h-96.2M159 26.2c-2.4.8-4.7 1.8-7.1 2.7-3.5 1.5-6.9 2.9-10.3 4.5-2.5 1.2-5 2.4-7.4 3.7-3.4 1.6-6.6 3.6-9.9 5.5-2.4 1.5-4.9 2.9-7.1 4.4-3.3 2.1-6.4 4.3-9.6 6.6-2.1 1.6-4.4 3.2-6.5 4.9-.6.5-1.3 1.1-1.9 1.8 8.9 7.3 18.4 13.6 28.3 19.2 7.8-19.1 18.5-37.1 31.5-53.3m-6.5 65.5c22.4 9.2 46.2 14.7 70.3 16.2v-94c-27.8 7.3-52.7 36.3-70.3 77.8m70.3 43.7c-27.5-1.5-54.3-7.4-79.7-17.8-10 32.8-15.5 66.9-16.5 101.2h96.2v-83.4m246.4 163.3c-6.1-11.7-14-22.4-23.3-31.7-10.7-10.7-23.3-19.4-37.1-25.7l-2.1-.9c-15.7-6.8-33-10.6-51.2-10.6-18.1 0-35.3 3.7-50.9 10.5-37.3 16.1-65.4 49.4-74.3 89.9-2.1 9.7-3.2 19.6-3 29.5.2 13.2 2.4 26.4 6.6 39 5.4 16.2 14 31.2 25.3 44 12.7 14.5 28.5 25.9 46.3 33.5 15.4 6.5 32.3 10.1 50.1 10.1 70.8 0 128.2-57.4 128.2-128.2-.1-21.5-5.3-41.6-14.6-59.4zm-43.9 107-22.1 22.1-47.7-47.7-47.7 47.7-22.1-22.1 47.7-47.7-47.7-47.7 22.1-22.1 47.7 47.7 47.7-47.7 22.1 22.1-47.7 47.7 47.7 47.7z"/></svg></header><main class="main-content"><div class="tabs"role="tablist"><button aria-controls="panel-1"aria-selected="false"class="tab tab__hidden"id="tab-1"role="tab"tabindex="-1"disabled="disabled">{{ bookmarksTabTitle }}</button> <button aria-controls="panel-2"aria-selected="false"class="tab tab__hidden"id="tab-2"role="tab"tabindex="-1"disabled="disabled">{{ editorialTabTitle }}</button> <button aria-controls="panel-3"aria-selected="false"class="tab"id="tab-3"role="tab"tabindex="-1">{{ aboutTabTitle }}</button></div><section aria-labelledby="tab-1"class="tab-content"data-bookmarks hidden id="panel-1"role="tabpanel"tabindex="0"></section><section aria-labelledby="tab-2"class="tab-content"data-editorial hidden id="panel-2"role="tabpanel"tabindex="0"></section><section aria-labelledby="tab-3"class="tab-content rich-text"hidden id="panel-3"role="tabpanel"tabindex="0">{{ aboutInnerHTML }}</section></main><footer><p class="copyright">{{ copyright }}</footer></div><script>{{ mainJS }}<\/script>',ce='*,::after,::before{box-sizing:border-box}*{margin:0}body,html{height:100%}body{-webkit-font-smoothing:antialiased;background-color:var(--background-color,#f9fbfc);color:var(--text-color,#2d2d3b);font-family:system-ui,sans-serif;line-height:1.4}.container{display:flex;flex-direction:column;height:100%;margin:0 auto;max-width:var(--container-width,1200px);padding:0 2rem;width:100%}.header{margin:4rem 0 2.5rem;position:relative}.home-link{display:flex;align-items:center;gap:.5rem;color:var(--primary-color,#1993f6);margin-block-end:1rem;text-decoration:none}.home-link:hover .link-text{text-decoration:underline}.home-link svg{width:28px;height:28px}.title{font-size:2.75rem;line-height:1;margin-block-end:1.5rem}@media screen and (min-width:960px){.title{font-size:5rem}}.description{font-size:1.25rem;max-width:40rem}.offline-icon{display:none;fill:var(--icon-color,#e6e8ec);height:100%;position:absolute;inset-inline-end:0;inset-block-start:0;z-index:-1}@media screen and (min-width:960px){.offline-icon{display:initial}}.main-content{flex-grow:1}.tabs{display:flex;flex-direction:row;flex-wrap:wrap;list-style:none;margin-block-end:2rem;padding:0}@media screen and (min-width:485px){.tabs{border-block-end:1px solid var(--border-color,#e6e8ec);flex-wrap:nowrap;overflow:auto}}.tab{appearance:none;background:0 0;border:none;border-block-end:2px solid transparent;box-shadow:0 1px 0 0 var(--border-color,#e6e8ec);color:var(--tab-text-color,#7a7d95);cursor:pointer;font:inherit;font-size:1.25rem;font-weight:700;padding:.5rem 1rem;transition:border-color .2s ease-in-out;width:50%}@media screen and (min-width:485px){.tab{box-shadow:none;width:initial}}.tab__hidden{display:none}.tab:disabled{cursor:not-allowed;opacity:.5;order:1}.tab:disabled::before{content:"🔒";margin-inline-end:.25rem}.tab[aria-selected=true]{border-color:var(--primary-color,#1993f6);color:var(--primary-color,#1993f6)}.tab:hover:not(:disabled){border-color:var(--primary-color,#1993f6)}.rich-text{max-width:40rem}.rich-text>*+*{margin-block-start:1.5rem}.rich-text h2,.rich-text h3{line-height:1.25}.rich-text h2{font-size:2.25rem}@media screen and (min-width:960px){.rich-text h2{font-size:2.75rem}}.rich-text h3{font-size:1.75rem}@media screen and (min-width:960px){.rich-text h3{font-size:2.25rem}}.rich-text a{color:var(--primary-color,#1993f6)}.rich-text blockquote{border-inline-start:0.25rem solid var(--primary-color,#1993f6);padding-inline-start:1rem}.rich-text cite,.rich-text figcaption{display:block;font-style:italic;margin-block-start:0.5rem}.rich-text figcaption{text-align:center}.rich-text img{display:block;margin-inline-start:auto;margin-inline-end:auto;max-width:100%}.rich-text ol,.rich-text ul{list-style-position:inside;padding:0}.bookmarks,.content-bundles{display:flex;flex-wrap:wrap;gap:1.5rem;list-style:none;padding:0}.card{background-color:var(--card-background-color,#fff);border-radius:.5rem;border:1px solid var(--border-color,#e6e8ec);box-shadow:var(--card-box-shadow,0 8px 24px rgba(149,157,165,.2));width:100%}@media screen and (min-width:960px){.card{width:calc(50% - .75rem)}}.card-link{border-radius:.5rem;color:inherit;display:flex;height:100%;overflow:hidden;text-decoration:none;transition:box-shadow .2s ease-in-out}.card-link:hover{box-shadow:0 0 0 2px var(--primary-color,#1993f6)}.card-image{flex-shrink:0;height:100%;min-height:100px;object-fit:cover;width:100px}.card-image[src=""]{display:none}.card-content{padding:1rem}.card-title{font-size:1.25rem}.card-description,.card-title{-webkit-box-orient:vertical;-webkit-line-clamp:2;display:-webkit-box;overflow-wrap:break-word;overflow:hidden;word-break:break-word}.card-description:not(:empty){-webkit-line-clamp:3;margin-block-start:0.5rem}.copyright{margin:2rem 0;text-align:center}',Tt=`(async function(){const bookmarksPlaceholder=document.querySelector("[data-bookmarks]");const serviceWorkerRegistration=await navigator.serviceWorker.getRegistration();if(!serviceWorkerRegistration){return}let configuration;try{configuration=await caches.open("configuration").then((cache=>cache.match("/configuration.json"))).then((res=>res.json()))}catch{configuration={}}if(configuration.bookmark){const bookmarks=await fetch("/451-tools/bookmark/").then((res=>res.json())).catch((()=>[]));if(bookmarks.length<1){renderNoBookmarks()}else{const bookmarksList=document.createElement("ul");const bookmarksHtml=bookmarks.map(generateCardHtml).join("");bookmarksList.innerHTML=bookmarksHtml;bookmarksList.classList.add("bookmarks");bookmarksPlaceholder.appendChild(bookmarksList)}const bookmarksTab=document.querySelector("#tab-1");bookmarksTab.classList.remove("tab__hidden");bookmarksTab.removeAttribute("disabled")}else if(configuration.fallbackPages.showHiddenTabs){const bookmarksTab=document.querySelector("#tab-1");bookmarksTab.classList.remove("tab__hidden")}function renderNoBookmarks(){const noBookmarksMessage=document.createElement("p");noBookmarksMessage.innerText="You have no bookmarks.";bookmarksPlaceholder.appendChild(noBookmarksMessage)}const contentBundlesPlaceholder=document.querySelector("[data-editorial]");const isContentBundlesUsed=await caches.has("451-tools-content-bundles");if(isContentBundlesUsed){const contentBundles=await caches.open("451-tools-content-bundles").then((cache=>cache.keys())).then((requests=>Promise.all(requests.map((async request=>{const response=await caches.match(request);const html=await response.text();return{path:new URL(request.url).pathname,url:request.url.split("?")[0],html:html}})))));if(contentBundles.length<1){renderNoContentBundles()}else{const contentBundlesList=document.createElement("ul");const contentBundlesHtml=contentBundles.reverse().map(generateCardHtml).join("");contentBundlesList.innerHTML=contentBundlesHtml;contentBundlesList.classList.add("content-bundles");contentBundlesPlaceholder.appendChild(contentBundlesList)}const contentBundlesTab=document.querySelector("#tab-2");contentBundlesTab.classList.remove("tab__hidden");contentBundlesTab.removeAttribute("disabled")}else if(configuration.fallbackPages.showHiddenTabs){const contentBundlesTab=document.querySelector("#tab-2");contentBundlesTab.classList.remove("tab__hidden")}function renderNoContentBundles(){const noContentBundlesMessage=document.createElement("p");noContentBundlesMessage.innerText="You have no content bundles.";contentBundlesPlaceholder.appendChild(noContentBundlesMessage)}function generateCardHtml(response){const cardItem=document.createElement("li");const cardLink=document.createElement("a");const cardImage=document.createElement("img");const cardContent=document.createElement("div");const cardTitle=document.createElement("h2");const cardDescription=document.createElement("p");const html=document.createElement("html");html.innerHTML=response.html;const title=response.metadata?.title||html.querySelector("title")?.innerText||response.url;const description=response.metadata?.description||html.querySelector('meta[name="description"]')?.content||"";const imageSrc=response.metadata?.image?.src||html.querySelector('meta[property="og:image"]')?.content||"";cardItem.classList.add("card");cardLink.classList.add("card-link");cardLink.href=response.path;cardImage.classList.add("card-image");cardImage.src=imageSrc;if(Number.isInteger(response.metadata?.image?.height)){cardImage.height=response.metadata.image.height}if(Number.isInteger(response.metadata?.image?.width)){cardImage.width=response.metadata.image.width}cardImage.alt="";cardContent.classList.add("card-content");cardTitle.classList.add("card-title");cardTitle.innerText=title;cardDescription.classList.add("card-description");cardDescription.innerText=description;cardContent.appendChild(cardTitle);cardContent.appendChild(cardDescription);cardLink.appendChild(cardImage);cardLink.appendChild(cardContent);cardItem.appendChild(cardLink);return cardItem.outerHTML}const activeTabs=Array.from(document.querySelectorAll('[role="tab"]')).filter((tab=>!tab.classList.contains("tab__hidden")&&!tab.hasAttribute("disabled")));const firstActiveTab=activeTabs[0];const firstActivePanel=document.querySelector(\`#\${firstActiveTab.getAttribute("aria-controls")}\`);const tabList=document.querySelector('[role="tablist"]');firstActiveTab.setAttribute("aria-selected",true);firstActiveTab.setAttribute("tabindex",0);firstActivePanel.removeAttribute("hidden");activeTabs.forEach((tab=>tab.addEventListener("click",changeTabs)));let currentTabIndex=0;tabList.addEventListener("keydown",(e=>{if(e.key==="ArrowRight"||e.key==="ArrowLeft"){activeTabs[currentTabIndex].setAttribute("tabindex",-1);if(e.key==="ArrowRight"){currentTabIndex++;if(currentTabIndex>=activeTabs.length){currentTabIndex=0}}else if(e.key==="ArrowLeft"){currentTabIndex--;if(currentTabIndex<0){currentTabIndex=activeTabs.length-1}}activeTabs[currentTabIndex].setAttribute("tabindex",0);activeTabs[currentTabIndex].focus()}}));function changeTabs(e){const target=e.target;const parent=target.parentNode;const grandparent=parent.parentNode;parent.querySelectorAll('[aria-selected="true"]').forEach((t=>t.setAttribute("aria-selected",false)));target.setAttribute("aria-selected",true);grandparent.querySelectorAll('[role="tabpanel"]').forEach((p=>p.setAttribute("hidden",true)));grandparent.parentNode.querySelector(\`#\${target.getAttribute("aria-controls")}\`).removeAttribute("hidden")}})(); `;function Q(e,t){const r=new URL(e.url).pathname;return t.some(n=>{try{return new RegExp(n).test(r)}catch{return!1}})}const $t=async(e={})=>{const{serviceWorkerController:t}=e;if(!t)throw new Error("You must pass a serviceWorkerController plugin to registerFallbackPages");t.modules.push("fallback-pages"),t.logger("(fallback-pages) Module registered."),t.addInstallHandler(vt),t.addActivateHandler(Rt),t.addFallbackHandler(({event:n})=>n.request.destination==="document",Ct);const r=({event:n})=>new RegExp(`/${u}/dashboard/?$`).test(n.request.url);t.addRoute(r,async n=>{const{fallbackPages:s}=await t.getConfiguration(),{language:a,textDirection:o,customProperties:i,templateStrings:c}=s;return new Response(me({language:a,textDirection:o,customProperties:i,templateStrings:c}),{headers:{"Content-Type":"text/html"}})},"GET")};async function vt({serviceWorkerController:e}){const{fallbackPages:t}=await e.getConfiguration();if(t)return t.pages.map(r=>{const n=T(r.url,r.revision);return Promise.all([caches.open(`${u}-fallback-pages`).then(s=>s.add(n))])})}async function Rt({serviceWorkerController:e}){const{fallbackPages:t}=await e.getConfiguration(),r=t==null?void 0:t.pages.map(n=>T(n.url,n.revision));return caches.open(`${u}-fallback-pages`).then(n=>n.keys().then(s=>{s.forEach(a=>{const o=a.url.replace(self.location.origin,"");if(!r.includes(o))return n.delete(a)})}))}async function Ct({event:e,serviceWorkerController:t}){const{fallbackPages:r}=await t.getConfiguration(),{customProperties:n,excludeByPath:s,language:a,pages:o,templateStrings:i,textDirection:c}=r;if(Q(e.request,s))return;if(o.length<1)return t.logger("(fallback-pages) No custom fallback pages configured. Returning the default fallback page."),new Response(me({language:a,textDirection:c,customProperties:n,templateStrings:i}),{headers:{"Content-Type":"text/html"}});const l=o.find(p=>p.refererRegex?new RegExp(p.refererRegex).test(e.request.headers.get("referer")):!1),f=l?l.url:o.find(p=>!p.refererRegex).url;return caches.open(`${u}-fallback-pages`).then(p=>p.match(f,{ignoreSearch:!0}).then(h=>(h&&t.logger("(fallback-pages) Custom fallback page found. Returning cached response."),h)))}function me({language:e,textDirection:t,customProperties:r,templateStrings:n}){const s=r?`:root { ${Object.entries(r).map(([o,i])=>`--${o}: ${i};`).join(" ")} } ${ce}`:ce,a=xt({language:e,textDirection:t,templateStrings:n,mainCSS:s,mainJS:Tt});return Et.replace(/{{\s?(.*?)\s?}}/g,(o,i)=>a[o]||o)}const Nt=e=>{const t=(e==null?void 0:e.customProperties)||{},r=(e==null?void 0:e.templateStrings)||{},n=(e==null?void 0:e.language)||"en",s=(e==null?void 0:e.textDirection)||"ltr",a=(e==null?void 0:e.showHiddenTabs)||!1,o=(e==null?void 0:e.excludeByPath)||[],c=(e!=null&&e.pages?Array.isArray(e.pages)?e.pages:[e.pages]:[]).map(l=>typeof l=="string"?{url:l,revision:null,refererRegex:null}:{url:l.url,revision:l.revision||null,refererRegex:l.refererRegex||null});return{language:n,textDirection:s,customProperties:t,templateStrings:r,showHiddenTabs:a,excludeByPath:o,pages:c}};try{self["workbox:core:7.0.0"]&&_()}catch{}const _t={"invalid-value":({paramName:e,validValueDescription:t,value:r})=>{if(!e||!t)throw new Error("Unexpected input to 'invalid-value' error.");return`The '${e}' parameter was given a value with an unexpected value. ${t} Received a value of ${JSON.stringify(r)}.`},"not-an-array":({moduleName:e,className:t,funcName:r,paramName:n})=>{if(!e||!t||!r||!n)throw new Error("Unexpected input to 'not-an-array' error.");return`The parameter '${n}' passed into '${e}.${t}.${r}()' must be an array.`},"incorrect-type":({expectedType:e,paramName:t,moduleName:r,className:n,funcName:s})=>{if(!e||!t||!r||!s)throw new Error("Unexpected input to 'incorrect-type' error.");const a=n?`${n}.`:"";return`The parameter '${t}' passed into '${r}.${a}${s}()' must be of type ${e}.`},"incorrect-class":({expectedClassName:e,paramName:t,moduleName:r,className:n,funcName:s,isReturnValueProblem:a})=>{if(!e||!r||!s)throw new Error("Unexpected input to 'incorrect-class' error.");const o=n?`${n}.`:"";return a?`The return value from '${r}.${o}${s}()' must be an instance of class ${e}.`:`The parameter '${t}' passed into '${r}.${o}${s}()' must be an instance of class ${e}.`},"missing-a-method":({expectedMethod:e,paramName:t,moduleName:r,className:n,funcName:s})=>{if(!e||!t||!r||!n||!s)throw new Error("Unexpected input to 'missing-a-method' error.");return`${r}.${n}.${s}() expected the '${t}' parameter to expose a '${e}' method.`},"add-to-cache-list-unexpected-type":({entry:e})=>`An unexpected entry was passed to 'workbox-precaching.PrecacheController.addToCacheList()' The entry '${JSON.stringify(e)}' isn't supported. You must supply an array of strings with one or more characters, objects with a url property or Request objects.`,"add-to-cache-list-conflicting-entries":({firstEntry:e,secondEntry:t})=>{if(!e||!t)throw new Error("Unexpected input to 'add-to-cache-list-duplicate-entries' error.");return`Two of the entries passed to 'workbox-precaching.PrecacheController.addToCacheList()' had the URL ${e} but different revision details. Workbox is unable to cache and version the asset correctly. Please remove one of the entries.`},"plugin-error-request-will-fetch":({thrownErrorMessage:e})=>{if(!e)throw new Error("Unexpected input to 'plugin-error-request-will-fetch', error.");return`An error was thrown by a plugins 'requestWillFetch()' method. The thrown error message was: '${e}'.`},"invalid-cache-name":({cacheNameId:e,value:t})=>{if(!e)throw new Error("Expected a 'cacheNameId' for error 'invalid-cache-name'");return`You must provide a name containing at least one character for setCacheDetails({${e}: '...'}). Received a value of '${JSON.stringify(t)}'`},"unregister-route-but-not-found-with-method":({method:e})=>{if(!e)throw new Error("Unexpected input to 'unregister-route-but-not-found-with-method' error.");return`The route you're trying to unregister was not previously registered for the method type '${e}'.`},"unregister-route-route-not-registered":()=>"The route you're trying to unregister was not previously registered.","queue-replay-failed":({name:e})=>`Replaying the background sync queue '${e}' failed.`,"duplicate-queue-name":({name:e})=>`The Queue name '${e}' is already being used. All instances of backgroundSync.Queue must be given unique names.`,"expired-test-without-max-age":({methodName:e,paramName:t})=>`The '${e}()' method can only be used when the '${t}' is used in the constructor.`,"unsupported-route-type":({moduleName:e,className:t,funcName:r,paramName:n})=>`The supplied '${n}' parameter was an unsupported type. Please check the docs for ${e}.${t}.${r} for valid input types.`,"not-array-of-class":({value:e,expectedClass:t,moduleName:r,className:n,funcName:s,paramName:a})=>`The supplied '${a}' parameter must be an array of '${t}' objects. Received '${JSON.stringify(e)},'. Please check the call to ${r}.${n}.${s}() to fix the issue.`,"max-entries-or-age-required":({moduleName:e,className:t,funcName:r})=>`You must define either config.maxEntries or config.maxAgeSecondsin ${e}.${t}.${r}`,"statuses-or-headers-required":({moduleName:e,className:t,funcName:r})=>`You must define either config.statuses or config.headersin ${e}.${t}.${r}`,"invalid-string":({moduleName:e,funcName:t,paramName:r})=>{if(!r||!e||!t)throw new Error("Unexpected input to 'invalid-string' error.");return`When using strings, the '${r}' parameter must start with 'http' (for cross-origin matches) or '/' (for same-origin matches). Please see the do