From 30ed87377419225f4b7c972dfbe35172a1670d5c Mon Sep 17 00:00:00 2001 From: Andrew Lilley Brinker Date: Thu, 5 Dec 2024 08:07:11 -0800 Subject: [PATCH] chore: Update site to new URL Signed-off-by: Andrew Lilley Brinker --- CHANGELOG.md | 10 +++++----- README.md | 8 ++++---- dist/dockerhub/README.md | 7 +++---- hipcheck/Cargo.toml | 2 +- site/config.toml | 2 +- site/content/docs/rfds/0004-plugin-api.md | 2 +- site/content/docs/rfds/0006-rust-plugin-sdk.md | 2 +- .../rfds/0008-policy-expr-typing-refactor.md | 7 +++++++ site/content/docs/rfds/0009-batch-queries.md | 3 +++ site/content/docs/rfds/0010-submit-chunking.md | 3 +++ site/scripts/src/footer/installer.ts | 4 +--- site/static/js/footer.mjs | 2 +- site/static/js/footer.mjs.map | 6 +++--- 13 files changed, 34 insertions(+), 24 deletions(-) rename site/content/{ => docs}/rfds/0008-policy-expr-typing-refactor.md (98%) diff --git a/CHANGELOG.md b/CHANGELOG.md index 41f73412..13d65f9a 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,7 +8,7 @@ project adheres to [Semantic Versioning]. ## UPCOMING: We Will No Longer Publish to Crates.io starting with 3.8.0 -We recently merged [RFD #7, "Simplified Release Procedures"](https://mitre.github.io/hipcheck/rfds/0007/), +We recently merged [RFD #7, "Simplified Release Procedures"](https://hipcheck.mitre.org/docs/rfds/0007/), which explains that starting with version 3.8.0 (the next minor version), we'll no longer be publishing Hipcheck itself to Crates.io. The reasons for this are explained in the RFD, but essentially the need to publish to Crates.io has been @@ -169,7 +169,7 @@ to modify Hipcheck itself. This placed some limitations on our ability to grow Hipcheck, and more importantly it conflicted with a core design philosophy of Hipcheck: that it should *empower* uses to express their policies about using open source software (this is one of our Product Values, as expressed in -[RFD #2](https://mitre.github.io/hipcheck/rfds/0002/)). +[RFD #2](https://hipcheck.mitre.org/rfds/0002/)). With `3.6.1` users can now define custom plugins to provide new sources of data and new analyses. There's a lot more for us to do with this, including @@ -179,7 +179,7 @@ distribute, and use plugins, and more! For now though, this launch is our official starting point where users _can_ create, distribute, and run plugins. For more details on the design of the new plugin system, check out -[RFD #4](https://mitre.github.io/hipcheck/rfds/0004/). If you have questions +[RFD #4](https://hipcheck.mitre.org/rfds/0004/). If you have questions on how to work with plugins, you can always ask us in our [GitHub Discussions forum](https://github.com/mitre/hipcheck/discussions)! @@ -309,7 +309,7 @@ And finally, many dependency version bumps: __Full Changelog__: [3.6.0]: https://github.com/mitre/hipcheck/compare/hipcheck-v3.5.0..hipcheck-v3.6.0 -[rfd_4]: https://mitre.github.io/hipcheck/rfds/0004/ +[rfd_4]: https://hipcheck.mitre.org/rfds/0004/ ## [3.5.0] - 2024-08-05 @@ -423,7 +423,7 @@ Hipcheck 3.4.0 is an exciting release featuring 3 new subcommands! out exactly how much each analysis contributes to the overall score. This command does that math for you to make it easier. -Hipcheck also now has an [official website](https://mitre.github.io/hipcheck)! +Hipcheck also now has an [official website](https://hipcheck.mitre.org)! Feel free to check it out, and let us know if you encounter any issues with it. ### Added diff --git a/README.md b/README.md index 250e8474..e545f5b3 100644 --- a/README.md +++ b/README.md @@ -72,9 +72,9 @@ found in the [`LICENSE`](LICENSE) file in this repository. > (FEB 2014)][dfars]. [dfars]: https://www.acquisition.gov/dfars/252.227-7014-rights-other-commercial-computer-software-and-other-commercial-computer-software-documentation. -[quickstart]: https://mitre.github.io/hipcheck/docs/getting-started/first-run/ -[install]: https://mitre.github.io/hipcheck/docs/getting-started/install/ +[quickstart]: https://hipcheck.mitre.org/docs/getting-started/first-run/ +[install]: https://hipcheck.mitre.org/docs/getting-started/install/ [license]: https://github.com/mitre/hipcheck/blob/main/LICENSE [release]: https://github.com/mitre/hipcheck/releases/latest -[rfd_2]: https://mitre.github.io/hipcheck/docs/rfds/0002/ -[website]: https://mitre.github.io/hipcheck +[rfd_2]: https://hipcheck.mitre.org/docs/rfds/0002/ +[website]: https://hipcheck.mitre.org diff --git a/dist/dockerhub/README.md b/dist/dockerhub/README.md index f3c05fcf..71729e8d 100644 --- a/dist/dockerhub/README.md +++ b/dist/dockerhub/README.md @@ -23,9 +23,9 @@ Hipcheck currently provides images for the following architectures: ## Helpful Links -* [Website](https://mitre.github.io/hipcheck) -* [Quickstart Guide](https://mitre.github.io/hipcheck/docs/quickstart/) -* [Complete Guide](https://mitre.github.io/hipcheck/docs/guide/) +* [Website](https://hipcheck.mitre.org) +* [Quickstart Guide](https://hipcheck.mitre.org/docs/quickstart/) +* [Complete Guide](https://hipcheck.mitre.org/docs/guide/) * [Github](https://github.com/mitre/hipcheck) * [Report an Issue](https://github.com/mitre/hipcheck/issues/new) @@ -33,4 +33,3 @@ Hipcheck currently provides images for the following architectures: Hipcheck's software is licensed under the Apache 2.0 license, which can be found [here](https://github.com/mitre/hipcheck/blob/main/LICENSE) - diff --git a/hipcheck/Cargo.toml b/hipcheck/Cargo.toml index 1e134c7b..e44d0cae 100644 --- a/hipcheck/Cargo.toml +++ b/hipcheck/Cargo.toml @@ -9,7 +9,7 @@ readme = "../README.md" version = "3.7.0" edition = "2021" license = "Apache-2.0" -homepage = "https://mitre.github.io/hipcheck" +homepage = "https://hipcheck.mitre.org" repository = "https://github.com/mitre/hipcheck" include = ["src/**", "../LICENSE", "../README.md", "build.rs", "proto/**"] diff --git a/site/config.toml b/site/config.toml index 88861256..70ed028c 100644 --- a/site/config.toml +++ b/site/config.toml @@ -1,5 +1,5 @@ # The URL of the side. -base_url = "https://mitre.github.io/hipcheck" +base_url = "https://hipcheck.mitre.org" # Generate an Atom feed for the blog. generate_feeds = true diff --git a/site/content/docs/rfds/0004-plugin-api.md b/site/content/docs/rfds/0004-plugin-api.md index 4c3121bf..602bf2f0 100644 --- a/site/content/docs/rfds/0004-plugin-api.md +++ b/site/content/docs/rfds/0004-plugin-api.md @@ -1030,6 +1030,6 @@ architectures. [cargo_semver]: https://doc.rust-lang.org/cargo/reference/specifying-dependencies.html#version-requirement-syntax [rust_platforms]: https://doc.rust-lang.org/beta/rustc/platform-support.html [gRPC]: https://grpc.io/ -[hipcheck_scoring]: https://mitre.github.io/hipcheck/docs/guide/concepts/#scoring +[hipcheck_scoring]: https://hipcheck.mitre.org/docs/guide/concepts/#scoring [rfd_3]: ./003-plugin-architecture-vision.md [grpc]: https://grpc.io/ diff --git a/site/content/docs/rfds/0006-rust-plugin-sdk.md b/site/content/docs/rfds/0006-rust-plugin-sdk.md index cf9ec8ec..61910729 100644 --- a/site/content/docs/rfds/0006-rust-plugin-sdk.md +++ b/site/content/docs/rfds/0006-rust-plugin-sdk.md @@ -326,4 +326,4 @@ Where `InputType` and `OutputType` are types defined by the user of the SDK which implement the `schemars::JsonSchema` trait. This macro could generate a `DoThing` type implementing `Query`. -[RFD 4]: https://mitre.github.io/hipcheck/rfds/0004/ +[RFD 4]: https://hipcheck.mitre.org/rfds/0004/ diff --git a/site/content/rfds/0008-policy-expr-typing-refactor.md b/site/content/docs/rfds/0008-policy-expr-typing-refactor.md similarity index 98% rename from site/content/rfds/0008-policy-expr-typing-refactor.md rename to site/content/docs/rfds/0008-policy-expr-typing-refactor.md index 7abf2032..4287b354 100644 --- a/site/content/rfds/0008-policy-expr-typing-refactor.md +++ b/site/content/docs/rfds/0008-policy-expr-typing-refactor.md @@ -1,5 +1,12 @@ --- title: "Policy Expression Typing" +weight: 8 +slug: 0008 +extra: + rfd: 8 + primary_author: Julian Lanson + primary_author_link: https://github.com/j-lanson + status: Accepted --- ## The Current Situation diff --git a/site/content/docs/rfds/0009-batch-queries.md b/site/content/docs/rfds/0009-batch-queries.md index 6f7ee2ce..10617b4f 100644 --- a/site/content/docs/rfds/0009-batch-queries.md +++ b/site/content/docs/rfds/0009-batch-queries.md @@ -4,6 +4,9 @@ weight: 9 slug: 0009 extra: rfd: 9 + primary_author: Julian Lanson + primary_author_link: https://github.com/j-lanson + status: Accepted --- # Batched Plugin Queries diff --git a/site/content/docs/rfds/0010-submit-chunking.md b/site/content/docs/rfds/0010-submit-chunking.md index 495c12e6..51d89e0c 100644 --- a/site/content/docs/rfds/0010-submit-chunking.md +++ b/site/content/docs/rfds/0010-submit-chunking.md @@ -4,6 +4,9 @@ weight: 10 slug: 0010 extra: rfd: 10 + primary_author: Julian Lanson + primary_author_link: https://github.com/j-lanson + status: Accepted --- # Submit Chunking diff --git a/site/scripts/src/footer/installer.ts b/site/scripts/src/footer/installer.ts index cac897db..87b53cbd 100644 --- a/site/scripts/src/footer/installer.ts +++ b/site/scripts/src/footer/installer.ts @@ -85,9 +85,7 @@ function installerForPlatform(platform: string | undefined): string { function resolve_host(): string { const protocol = globalThis.window.location.protocol; const host = globalThis.window.location.host; - // If we're on GitHub Pages, append the `/hipcheck` path. - const amendedHost = (host === "mitre.github.io") ? `${host}/hipcheck` : host; - return `${protocol}//${amendedHost}`; + return `${protocol}//${host}`; } /** diff --git a/site/static/js/footer.mjs b/site/static/js/footer.mjs index 1b32aca1..ad1a1e59 100644 --- a/site/static/js/footer.mjs +++ b/site/static/js/footer.mjs @@ -1,2 +1,2 @@ -function g(e,t,o){let r=z(e).replace(`#icon-${t}`,`#icon-${o}`);V(e,r)}function z(e){let t=e.getAttributeNS(R,"href");if(t===null)throw new S;return t}function V(e,t){e.setAttributeNS(R,"href",t)}var R="http://www.w3.org/1999/xlink",S=class extends Error{constructor(){super("could not find copy icon")}};function a(e){let t=document.querySelector(e);if(t===null)throw new k(`could not find ${e}`);return t}function m(e){let t=document.querySelectorAll(e);if(t===null)throw new k(`could not find all '${e}'`);return Array.from(t)}function D(e){navigator.clipboard.writeText(e).then(null,t=>{throw new H(t)})}var H=class extends Error{constructor(t){super(`clipboard copy rejected: '${t}'`)}},k=class extends Error{constructor(t){super(t)}};function $(){let e;try{e=m(".docs-nav-toggle")}catch{return}e.forEach(t=>{let o=t.querySelector(".toggle-icon use");if(o===null){console.log(`no icon found for toggle: '${t}'`);return}t.addEventListener("click",s=>{s.preventDefault();let r=t.parentElement?.parentElement;if(r==null)return;let l=r.querySelector(".docs-nav-section");l!==null&&(l.classList.toggle("hidden"),Y(l)?g(o,"chevron-right","chevron-down"):g(o,"chevron-down","chevron-right"))})})}function Y(e){return e.classList.contains("hidden")}function P(){let e,t,o,s;try{e=m(".installer-button"),t=a("#installer-cmd"),o=a("#installer-copy"),s=a("#installer-copy > svg > use")}catch{return}e.forEach(r=>{r.addEventListener("click",l=>{l.preventDefault(),e.forEach(n=>delete n.dataset.active),r.dataset.active="true",t.innerText=N(r.dataset.platform)}),r.dataset.active&&r.dataset.active==="true"&&(t.innerText=N(r.dataset.platform))}),o.addEventListener("click",r=>{r.preventDefault(),D(t.innerText),g(s,"clipboard","check"),setTimeout(()=>g(s,"check","clipboard"),1500)})}function N(e){if(e===void 0)throw new x(e);let t=J();switch(e){case"macos":return K(t);case"linux":return K(t);case"windows":return Z(t);default:throw new x(e)}}function J(){let e=globalThis.window.location.protocol,t=globalThis.window.location.host,o=t==="mitre.github.io"?`${t}/hipcheck`:t;return`${e}//${o}`}function K(e){return`curl -LsSf ${e}/dl/install.sh | sh`}function Z(e){return`irm ${e}/dl/install.ps1 | iex`}var x=class extends Error{constructor(t){super(`could not determine platform: '${t||"undefined"}'`)}};function W(){m('a[href^="#"]').forEach(e=>{e.addEventListener("click",t=>{if(t.preventDefault(),t.currentTarget===null)return;let o=t.currentTarget.getAttribute("href");if(o===null)return;let r=a(o).getBoundingClientRect().top,l=globalThis.window.scrollY,n=r+l;globalThis.window.scrollTo({top:n,behavior:"smooth"})})})}function q(e,t){let o;return(...s)=>{clearTimeout(o),o=setTimeout(()=>t(...s),e)}}function Q(e){let t=Object.entries(e).filter(([o,s])=>s!==void 0);return Object.fromEntries(t)}function p(e,t={},o={},s=[]){let r=document.createElement(e);Object.assign(r,Q(t)),o.classList&&o.classList.forEach(n=>r.classList.add(n)),o.dataset&&Object.entries(o.dataset).filter(([n,d])=>d!==void 0).forEach(([n,d])=>r.dataset[n]=d);let l=s.map(n=>typeof n=="string"?document.createTextNode(n):n);return r.append(...l),r}function O(){let e=a("#search-button"),t=a("#search-modal"),o=a("#search-modal-close"),s=a("#search-modal-shroud"),r=a("#search-modal-box"),l=a("#search-input");e.addEventListener("click",n=>I(n,t,l)),s.addEventListener("click",n=>I(n,t,l)),o.addEventListener("click",n=>I(n,t,l)),r.addEventListener("click",n=>n.stopPropagation()),document.addEventListener("keydown",n=>{if(n.metaKey===!0&&n.shiftKey===!1&&n.key==="k"){n.preventDefault(),e.click();return}if(C(t))switch(n.key){case"Escape":n.preventDefault(),s.click();return;case"ArrowDown":break;case"ArrowUp":break;default:break}})}function I(e,t,o){e.preventDefault(),t.classList.toggle("hidden"),C(t)&&o.focus()}function C(e){return!e.classList.contains("hidden")}var ee="/search_index.en.json",te=6;function F(){let e=a("#search-input"),t=a("#search-results"),o=a("#search-results-items"),s,r="",l=async function(){return s===void 0&&(s=fetch(ee).then(async function(n){return await elasticlunr.Index.load(await n.json())})),await s};e.addEventListener("keyup",q(150,async function(){let n=e.value.trim();if(n===r||(t.style.display=n===""?"none":"block",o.innerHTML="",r=n,r===""))return;let d=(await l()).search(n,{bool:"AND",fields:{title:{boost:2},body:{boost:1}}});if(d.length===0){t.style.display="none";return}for(let f=0;f0){for(let B in n)elasticlunr.stemmer(L).startsWith(n[B])&&(v=40,d=!0);u.push([L,v,f]),v=2}f+=L.length,f+=1}f+=1}if(u.length===0){let c=e,i=p("span",{},{},[]);return i.innerHTML=c,i}let E=[],y=Math.min(u.length,15),T=0;for(let c=0;c=0;i--)E[i]>c&&(c=E[i],b=i)}let h=[],w=u[b][2];for(let c=b;c"),w=i[2]+i[0].length,h.push(e.substring(i[2],w)),i[1]===40&&h.push("")}h.push("\u2026");let U=h.join(""),_=p("span",{},{},[]);return _.innerHTML=U,_}function j(e){if(e===void 0)throw new M(e);switch(e){case"system":switch(localStorage.removeItem("theme"),se()){case"dark":document.documentElement.classList.add("dark");break;case"light":document.documentElement.classList.remove("dark");break}break;case"light":localStorage.setItem("theme",e),document.documentElement.classList.remove("dark");break;case"dark":localStorage.setItem("theme",e),document.documentElement.classList.add("dark");break;default:throw new M(e)}oe(e)}function oe(e){m(".theme-option").forEach(t=>{t.dataset.theme===e?t.dataset.active="true":delete t.dataset.active})}function se(){return globalThis.window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}var M=class extends Error{constructor(t){super(`could not determine theme: '${t||"undefined"}'`)}};function G(){m(".theme-option").forEach(e=>{e.addEventListener("click",t=>{t.preventDefault(),j(e.dataset.theme)})})}function ce(){G(),P(),O(),F(),W(),$()}(function(){try{ce()}catch(e){console.error(e)}})(); +function g(e,t,o){let r=z(e).replace(`#icon-${t}`,`#icon-${o}`);V(e,r)}function z(e){let t=e.getAttributeNS(R,"href");if(t===null)throw new S;return t}function V(e,t){e.setAttributeNS(R,"href",t)}var R="http://www.w3.org/1999/xlink",S=class extends Error{constructor(){super("could not find copy icon")}};function a(e){let t=document.querySelector(e);if(t===null)throw new x(`could not find ${e}`);return t}function m(e){let t=document.querySelectorAll(e);if(t===null)throw new x(`could not find all '${e}'`);return Array.from(t)}function D(e){navigator.clipboard.writeText(e).then(null,t=>{throw new I(t)})}var I=class extends Error{constructor(t){super(`clipboard copy rejected: '${t}'`)}},x=class extends Error{constructor(t){super(t)}};function $(){let e;try{e=m(".docs-nav-toggle")}catch{return}e.forEach(t=>{let o=t.querySelector(".toggle-icon use");if(o===null){console.log(`no icon found for toggle: '${t}'`);return}t.addEventListener("click",s=>{s.preventDefault();let r=t.parentElement?.parentElement;if(r==null)return;let l=r.querySelector(".docs-nav-section");l!==null&&(l.classList.toggle("hidden"),Y(l)?g(o,"chevron-right","chevron-down"):g(o,"chevron-down","chevron-right"))})})}function Y(e){return e.classList.contains("hidden")}function P(){let e,t,o,s;try{e=m(".installer-button"),t=a("#installer-cmd"),o=a("#installer-copy"),s=a("#installer-copy > svg > use")}catch{return}e.forEach(r=>{r.addEventListener("click",l=>{l.preventDefault(),e.forEach(n=>delete n.dataset.active),r.dataset.active="true",t.innerText=N(r.dataset.platform)}),r.dataset.active&&r.dataset.active==="true"&&(t.innerText=N(r.dataset.platform))}),o.addEventListener("click",r=>{r.preventDefault(),D(t.innerText),g(s,"clipboard","check"),setTimeout(()=>g(s,"check","clipboard"),1500)})}function N(e){if(e===void 0)throw new k(e);let t=J();switch(e){case"macos":return K(t);case"linux":return K(t);case"windows":return Z(t);default:throw new k(e)}}function J(){let e=globalThis.window.location.protocol,t=globalThis.window.location.host;return`${e}//${t}`}function K(e){return`curl -LsSf ${e}/dl/install.sh | sh`}function Z(e){return`irm ${e}/dl/install.ps1 | iex`}var k=class extends Error{constructor(t){super(`could not determine platform: '${t||"undefined"}'`)}};function W(){m('a[href^="#"]').forEach(e=>{e.addEventListener("click",t=>{if(t.preventDefault(),t.currentTarget===null)return;let o=t.currentTarget.getAttribute("href");if(o===null)return;let r=a(o).getBoundingClientRect().top,l=globalThis.window.scrollY,n=r+l;globalThis.window.scrollTo({top:n,behavior:"smooth"})})})}function q(e,t){let o;return(...s)=>{clearTimeout(o),o=setTimeout(()=>t(...s),e)}}function Q(e){let t=Object.entries(e).filter(([o,s])=>s!==void 0);return Object.fromEntries(t)}function p(e,t={},o={},s=[]){let r=document.createElement(e);Object.assign(r,Q(t)),o.classList&&o.classList.forEach(n=>r.classList.add(n)),o.dataset&&Object.entries(o.dataset).filter(([n,d])=>d!==void 0).forEach(([n,d])=>r.dataset[n]=d);let l=s.map(n=>typeof n=="string"?document.createTextNode(n):n);return r.append(...l),r}function O(){let e=a("#search-button"),t=a("#search-modal"),o=a("#search-modal-close"),s=a("#search-modal-shroud"),r=a("#search-modal-box"),l=a("#search-input");e.addEventListener("click",n=>H(n,t,l)),s.addEventListener("click",n=>H(n,t,l)),o.addEventListener("click",n=>H(n,t,l)),r.addEventListener("click",n=>n.stopPropagation()),document.addEventListener("keydown",n=>{if(n.metaKey===!0&&n.shiftKey===!1&&n.key==="k"){n.preventDefault(),e.click();return}if(C(t))switch(n.key){case"Escape":n.preventDefault(),s.click();return;case"ArrowDown":break;case"ArrowUp":break;default:break}})}function H(e,t,o){e.preventDefault(),t.classList.toggle("hidden"),C(t)&&o.focus()}function C(e){return!e.classList.contains("hidden")}var ee="/search_index.en.json",te=6;function F(){let e=a("#search-input"),t=a("#search-results"),o=a("#search-results-items"),s,r="",l=async function(){return s===void 0&&(s=fetch(ee).then(async function(n){return await elasticlunr.Index.load(await n.json())})),await s};e.addEventListener("keyup",q(150,async function(){let n=e.value.trim();if(n===r||(t.style.display=n===""?"none":"block",o.innerHTML="",r=n,r===""))return;let d=(await l()).search(n,{bool:"AND",fields:{title:{boost:2},body:{boost:1}}});if(d.length===0){t.style.display="none";return}for(let f=0;f0){for(let B in n)elasticlunr.stemmer(b).startsWith(n[B])&&(v=40,d=!0);u.push([b,v,f]),v=2}f+=b.length,f+=1}f+=1}if(u.length===0){let c=e,i=p("span",{},{},[]);return i.innerHTML=c,i}let E=[],y=Math.min(u.length,15),T=0;for(let c=0;c=0;i--)E[i]>c&&(c=E[i],L=i)}let h=[],w=u[L][2];for(let c=L;c"),w=i[2]+i[0].length,h.push(e.substring(i[2],w)),i[1]===40&&h.push("")}h.push("\u2026");let U=h.join(""),_=p("span",{},{},[]);return _.innerHTML=U,_}function j(e){if(e===void 0)throw new M(e);switch(e){case"system":switch(localStorage.removeItem("theme"),se()){case"dark":document.documentElement.classList.add("dark");break;case"light":document.documentElement.classList.remove("dark");break}break;case"light":localStorage.setItem("theme",e),document.documentElement.classList.remove("dark");break;case"dark":localStorage.setItem("theme",e),document.documentElement.classList.add("dark");break;default:throw new M(e)}oe(e)}function oe(e){m(".theme-option").forEach(t=>{t.dataset.theme===e?t.dataset.active="true":delete t.dataset.active})}function se(){return globalThis.window.matchMedia("(prefers-color-scheme: dark)").matches?"dark":"light"}var M=class extends Error{constructor(t){super(`could not determine theme: '${t||"undefined"}'`)}};function G(){m(".theme-option").forEach(e=>{e.addEventListener("click",t=>{t.preventDefault(),j(e.dataset.theme)})})}function ce(){G(),P(),O(),F(),W(),$()}(function(){try{ce()}catch(e){console.error(e)}})(); //# sourceMappingURL=footer.mjs.map diff --git a/site/static/js/footer.mjs.map b/site/static/js/footer.mjs.map index f230209e..bd5898ae 100644 --- a/site/static/js/footer.mjs.map +++ b/site/static/js/footer.mjs.map @@ -1,7 +1,7 @@ { "version": 3, "sources": ["../../scripts/src/util/icon.ts", "../../scripts/src/util/web.ts", "../../scripts/src/footer/docs.ts", "../../scripts/src/footer/installer.ts", "../../scripts/src/footer/scroll.ts", "../../scripts/src/util/event.ts", "../../scripts/src/util/html.ts", "../../scripts/src/footer/search.ts", "../../scripts/src/util/theme.ts", "../../scripts/src/footer/theme.ts", "../../scripts/src/footer/main.ts"], - "sourcesContent": ["export function updateIcon(\n $node: HTMLElement,\n oldName: string,\n newName: string,\n) {\n const iconUrl = getIconUrl($node);\n const newIconUrl = iconUrl.replace(`#icon-${oldName}`, `#icon-${newName}`);\n setIconUrl($node, newIconUrl);\n}\n\n/**\n * Get the URL out of an icon `use` element.\n */\nfunction getIconUrl($node: HTMLElement): string {\n const iconUrl = $node.getAttributeNS(XLINK_NS, \"href\");\n if (iconUrl === null) throw new IconError();\n return iconUrl;\n}\n\n/**\n * Get the URL on an icon `use` element.\n */\nfunction setIconUrl($node: HTMLElement, url: string) {\n $node.setAttributeNS(XLINK_NS, \"href\", url);\n}\n\n/**\n * The namespace URL for the Xlink namespace\n */\nconst XLINK_NS: string = \"http://www.w3.org/1999/xlink\";\n\n/**\n * Error arising when trying to update the copy-to-clipboard icon.\n */\nclass IconError extends Error {\n constructor() {\n super(`could not find copy icon`);\n }\n}\n", "/**\n * document.querySelector with type conversion and error handling.\n */\nexport function querySelector(selector: string): HTMLElement {\n const $elem = document.querySelector(selector);\n if ($elem === null) throw new QueryError(`could not find ${selector}`);\n return $elem as HTMLElement;\n}\n\n/**\n * document.querySelectorAll with type conversions and error handling.\n */\nexport function querySelectorAll(selector: string): Array {\n const $elems = document.querySelectorAll(selector);\n if ($elems === null) throw new QueryError(`could not find all '${selector}'`);\n return Array.from($elems) as Array;\n}\n\n/**\n * navigator.clipboard.writeText with error handling.\n */\nexport function copyToClipboard(text: string) {\n navigator.clipboard.writeText(text).then(null, (reason) => {\n throw new ClipboardError(reason);\n });\n}\n\n/**\n * Indicates an error while attempting to put data into the clipboard.\n */\nclass ClipboardError extends Error {\n constructor(source: unknown) {\n super(`clipboard copy rejected: '${source}'`);\n }\n}\n\n/**\n * Indicates an error while trying to select one or more elements on the page.\n */\nclass QueryError extends Error {\n constructor(msg: string) {\n super(msg);\n }\n}\n", "import { updateIcon } from \"../util/icon.ts\";\nimport { querySelectorAll } from \"../util/web.ts\";\n\n/**\n * Sets up the collapse/expand functionality for docs navigation.\n */\nexport function setupDocsNav() {\n let $toggles;\n\n try {\n $toggles = querySelectorAll(\".docs-nav-toggle\");\n } catch (_e) {\n // Swallow these errors.\n return;\n }\n\n $toggles.forEach(($toggle) => {\n // Get the icon inside the toggle.\n const $toggleIcon = $toggle.querySelector(\n \".toggle-icon use\",\n ) as HTMLElement;\n if ($toggleIcon === null) {\n console.log(`no icon found for toggle: '${$toggle}'`);\n return;\n }\n\n $toggle.addEventListener(\"click\", (e) => {\n e.preventDefault();\n\n // Find the subsection list associated with the current toggle.\n const $parent = $toggle.parentElement?.parentElement;\n if ($parent === null || $parent === undefined) return;\n const $subsection = $parent.querySelector(\n \".docs-nav-section\",\n ) as HTMLElement;\n if ($subsection === null) return;\n\n // Hide or show it.\n $subsection.classList.toggle(\"hidden\");\n\n if (sectionIsHidden($subsection)) {\n updateIcon($toggleIcon, \"chevron-right\", \"chevron-down\");\n } else {\n updateIcon($toggleIcon, \"chevron-down\", \"chevron-right\");\n }\n });\n });\n}\n\nfunction sectionIsHidden($subsection: HTMLElement): boolean {\n return $subsection.classList.contains(\"hidden\");\n}\n", "import { updateIcon } from \"../util/icon.ts\";\nimport {\n copyToClipboard,\n querySelector,\n querySelectorAll,\n} from \"../util/web.ts\";\n\n/**\n * Setup behavior for the install picker.\n *\n * This makes sure the platform buttons are clickable and update the install\n * command appropriately, and that the copy-to-clipboard button works.\n */\nexport function setupInstallerPicker() {\n // The buttons used to select the platform.\n let $buttons: Array;\n\n // The block containing the install command.\n let $cmd: HTMLElement;\n\n // The copy-to-clipboard button.\n let $copy: HTMLElement;\n\n // The icon inside the copy-to-clipboard button.\n let $copyIcon: HTMLElement;\n\n try {\n $buttons = querySelectorAll(\".installer-button\");\n $cmd = querySelector(\"#installer-cmd\");\n $copy = querySelector(\"#installer-copy\");\n $copyIcon = querySelector(\"#installer-copy > svg > use\");\n } catch (_e) {\n // Swallow these errors.\n return;\n }\n\n $buttons.forEach(($button) => {\n $button.addEventListener(\"click\", (e) => {\n e.preventDefault();\n $buttons.forEach(($button) => delete $button.dataset.active);\n $button.dataset.active = \"true\";\n $cmd.innerText = installerForPlatform($button.dataset.platform);\n });\n\n if ($button.dataset.active && $button.dataset.active === \"true\") {\n $cmd.innerText = installerForPlatform($button.dataset.platform);\n }\n });\n\n $copy.addEventListener(\"click\", (e) => {\n e.preventDefault();\n copyToClipboard($cmd.innerText);\n updateIcon($copyIcon, \"clipboard\", \"check\");\n // Set the icon back on a timer.\n setTimeout(() => updateIcon($copyIcon, \"check\", \"clipboard\"), 1_500);\n });\n}\n\n/**\n * Get the install script based on the chosen platform.\n */\nfunction installerForPlatform(platform: string | undefined): string {\n if (platform === undefined) throw new UnknownPlatformError(platform);\n\n const host = resolve_host();\n\n switch (platform) {\n case \"macos\":\n return unix_installer(host);\n case \"linux\":\n return unix_installer(host);\n case \"windows\":\n return windows_installer(host);\n default:\n throw new UnknownPlatformError(platform);\n }\n}\n\n/**\n * Get the host of the site.\n *\n * This is intended to correctly handle deployment locally in development and\n * deployment in production on GitHub Pages.\n */\nfunction resolve_host(): string {\n const protocol = globalThis.window.location.protocol;\n const host = globalThis.window.location.host;\n // If we're on GitHub Pages, append the `/hipcheck` path.\n const amendedHost = (host === \"mitre.github.io\") ? `${host}/hipcheck` : host;\n return `${protocol}//${amendedHost}`;\n}\n\n/**\n * The install script to use for Unix (macOS and Linux) platforms.\n */\nfunction unix_installer(host: string): string {\n return `curl -LsSf ${host}/dl/install.sh | sh`;\n}\n\n/**\n * The install script to use for Windows.\n */\nfunction windows_installer(host: string): string {\n return `irm ${host}/dl/install.ps1 | iex`;\n}\n\n/**\n * Indicates an error while trying to detect the user's install platform.\n */\nclass UnknownPlatformError extends Error {\n constructor(platform: string | undefined) {\n super(\n `could not determine platform: '${platform || \"undefined\"}'`,\n );\n }\n}\n", "import { querySelector, querySelectorAll } from \"../util/web.ts\";\n\nexport function setupSmoothScrolling() {\n /*\n * This code from: https://stackoverflow.com/a/7717572\n * Used under the CC BY-SA 3.0 license with modifications.\n */\n querySelectorAll('a[href^=\"#\"]').forEach((anchor) => {\n anchor.addEventListener(\"click\", (e) => {\n e.preventDefault();\n if (e.currentTarget === null) return;\n\n const targetHeader = (e.currentTarget as HTMLElement).getAttribute(\"href\");\n if (targetHeader === null) return;\n\n const $header = querySelector(targetHeader);\n const headerPosition = $header.getBoundingClientRect().top;\n const scrollAmount = globalThis.window.scrollY;\n const offsetPosition = headerPosition + scrollAmount;\n\n globalThis.window.scrollTo({\n top: offsetPosition,\n behavior: \"smooth\",\n });\n });\n });\n}\n", "/**\n * Debounce an event handler by waiting `waitFor` number of milliseconds before\n * permitting the event to be triggered again.\n */\nexport function debounce) => ReturnType>(\n waitFor: number,\n func: F,\n): (...args: Parameters) => void {\n let timeout: number;\n return (...args: Parameters): void => {\n clearTimeout(timeout);\n timeout = setTimeout(() => func(...args), waitFor);\n };\n}\n", "/**\n * This code adapted from char's \"rainbow\" project.\n *\n * https://github.com/char/rainbow/blob/47721ad574c61d59921435a2bff41b9fd582540d/src/util/elem.ts\n *\n * It's licensed under the terms of the WTFPL.\n *\n * https://bsky.app/profile/pet.bun.how/post/3l7vv6ddjn426\n */\n\n// deno-lint-ignore-file ban-types\n\nexport type ElemProps = {\n [K in keyof E as E[K] extends Function ? never : K]?: E[K];\n};\n\n// Just a shorthand for a long type name.\ntype HTMLElemTagNameMap = HTMLElementTagNameMap;\n\n// Children can be built from an existing element, string, or text.\ntype IntoChild = Element | string | Text;\n\n// We permit adding classes and data attributes.\ntype Extras = {\n classList?: string[];\n dataset?: Partial>;\n};\n\n// Attributes to add.\ntype Attrs =\n | ElemProps\n | ElemProps[];\n\n// A little way to reduce an object down to only defined entries, since\n// entries can have a key but an undefined value.\nfunction removeUndefinedValues(x: object): object {\n const entries = Object.entries(x).filter(([_k, v]) => v !== undefined);\n return Object.fromEntries(entries);\n}\n\n/**\n * Construct a new HTMLElement\n */\nexport function elem(\n tag: K,\n attrs: Attrs = {},\n extras: Extras = {},\n children: IntoChild[] = [],\n): HTMLElemTagNameMap[K] {\n // Create the new element.\n const element = document.createElement(tag);\n\n // Assign any defined values from `attrs`.\n Object.assign(element, removeUndefinedValues(attrs));\n\n // Fill in any provided classes.\n if (extras.classList) {\n extras.classList.forEach((c) => element.classList.add(c));\n }\n\n // Fill in any assigned data attributes.\n if (extras.dataset) {\n Object.entries(extras.dataset)\n .filter(([_k, v]) => v !== undefined)\n .forEach(([k, v]) => (element.dataset[k] = v));\n }\n\n // Populate any children.\n const nodes = children.map(\n (e) => (typeof e === \"string\" ? document.createTextNode(e) : e)\n );\n element.append(...nodes);\n\n return element;\n}\n", "import { debounce } from \"../util/event.ts\";\nimport { elem } from \"../util/html.ts\";\nimport { querySelector } from \"../util/web.ts\";\n\n/**\n * Sets up functionality for opening and closing the search modal.\n */\nexport function setupSearchModal() {\n const $button = querySelector(\"#search-button\");\n const $modal = querySelector(\"#search-modal\");\n const $modalClose = querySelector(\"#search-modal-close\");\n const $modalShroud = querySelector(\"#search-modal-shroud\");\n const $modalBox = querySelector(\"#search-modal-box\");\n const $searchInput = querySelector(\"#search-input\");\n\n // Need all of these together to make sure clicking the *background* closes\n // the search modal, but clicking inside the box (anywhere other than the\n // close button) does *not* close the modal.\n $button.addEventListener(\n \"click\",\n (e) => toggleModal(e, $modal, $searchInput),\n );\n $modalShroud.addEventListener(\n \"click\",\n (e) => toggleModal(e, $modal, $searchInput),\n );\n $modalClose.addEventListener(\n \"click\",\n (e) => toggleModal(e, $modal, $searchInput),\n );\n $modalBox.addEventListener(\"click\", (e) => e.stopPropagation());\n\n // Keyboard shortcuts.\n document.addEventListener(\"keydown\", (e) => {\n // 'Meta+K' to open or close the modal.\n if (e.metaKey === true && e.shiftKey === false && e.key === \"k\") {\n e.preventDefault();\n $button.click();\n return;\n }\n\n if (modalIsOpen($modal)) {\n switch (e.key) {\n case \"Escape\":\n e.preventDefault();\n $modalShroud.click();\n return;\n case \"ArrowDown\":\n // TODO: Focus the next result in the search results.\n break;\n case \"ArrowUp\":\n // TODO: Focus the prior result in the search result.\n break;\n default:\n break;\n }\n }\n });\n}\n\n/**\n * Toggle whether the modal is open or not.\n */\nfunction toggleModal(\n e: MouseEvent,\n $modal: HTMLElement,\n $searchInput: HTMLElement,\n) {\n e.preventDefault();\n $modal.classList.toggle(\"hidden\");\n if (modalIsOpen($modal)) $searchInput.focus();\n}\n\n/**\n * Check if the modal is open.\n */\nfunction modalIsOpen($modal: HTMLElement): boolean {\n return !$modal.classList.contains(\"hidden\");\n}\n\n/**\n * Elasticlunr is the library Zola uses for search integration, and it doesn't\n * provide TypeScript type definitions. So the definitions here are just enough\n * to get Deno's linter to stop complaining, but they do mean we don't really\n * get type-checking protection for interacting with the Elasticluner API.\n *\n * In the future if we wanted type-checking for this API we could replace the\n * 'any' with an actual description of the relevant types.\n */\n\n// Define the Index type.\ntype Index = {\n // deno-lint-ignore no-explicit-any\n load: (data: Promise) => Promise;\n // deno-lint-ignore no-explicit-any\n search: (query: string, options?: any) => SearchResult;\n};\n\n/**\n * Data returned from the Elasticlunr search function\n */\ntype SearchResult = {\n ref: string;\n score: number;\n doc: {\n body: string;\n id: string;\n title: string;\n };\n};\n\n// Define the \"elasticlunr\" global.\ndeclare global {\n let elasticlunr: {\n Index: Index;\n // deno-lint-ignore no-explicit-any\n stemmer: any;\n };\n}\n\n/**\n * The path to the search index created by Zola.\n */\nconst SEARCH_INDEX: string = \"/search_index.en.json\";\n\n/**\n * The maximum number of results to show in searches.\n */\nconst MAX_ITEMS: number = 6;\n\n/**\n * Setup the search operation within the search modal.\n */\nexport function setupSearch() {\n const $searchInput = querySelector(\"#search-input\") as HTMLInputElement;\n const $searchResults = querySelector(\"#search-results\");\n const $searchResultsItems = querySelector(\"#search-results-items\");\n\n // The search index, representing the content of the site.\n let index: Promise;\n\n // The current term being searched by the user.\n let currentTerm = \"\";\n\n const initIndex = async function () {\n // If no index, then asynchronously load it from the index file.\n if (index === undefined) {\n index = fetch(SEARCH_INDEX)\n .then(\n async function (response) {\n return await elasticlunr.Index.load(await response.json());\n },\n );\n }\n\n return await index;\n };\n\n $searchInput.addEventListener(\n \"keyup\",\n debounce(150, async function () {\n const term = $searchInput.value.trim();\n if (term === currentTerm) return;\n\n $searchResults.style.display = term === \"\" ? \"none\" : \"block\";\n $searchResultsItems.innerHTML = \"\";\n\n currentTerm = term;\n if (currentTerm === \"\") return;\n\n const results: SearchResult[] = (await initIndex())\n .search(term, {\n bool: \"AND\",\n fields: {\n title: { boost: 2 },\n body: { boost: 1 },\n },\n });\n\n if (results.length === 0) {\n $searchResults.style.display = \"none\";\n return;\n }\n\n for (let i = 0; i < Math.min(results.length, MAX_ITEMS); ++i) {\n const entry = buildListEntry(results[i], currentTerm.split(\" \"));\n $searchResultsItems.appendChild(entry);\n }\n }),\n );\n}\n\n/**\n * Build an HTML element for each item in the search results.\n */\nfunction buildListEntry(data: SearchResult, terms: string[]): HTMLElement {\n return elem(\"li\", {}, {\n classList: [\"border-t\", \"border-neutral-300\", \"dark:border-neutral-500\"],\n }, [\n elem(\"div\", {}, {}, [\n elem(\"a\", { href: data.ref }, {\n classList: [\n \"block\",\n \"px-5\",\n \"py-2\",\n \"hover:bg-blue-50\",\n \"dark:hover:bg-blue-500\",\n \"hover:text-blue-500\",\n \"dark:hover:text-white\",\n \"group\",\n ],\n }, [\n elem(\"span\", {}, {\n classList: [\"block\", \"text-base\", \"mb-1\", \"font-medium\"],\n }, [\n data.doc.title,\n ]),\n elem(\"span\", {}, {\n classList: [\n \"block\",\n \"text-neutral-500\",\n \"text-sm\",\n \"group-hover:text-blue-500\",\n ],\n }, [\n makeTeaser(data.doc.body, terms),\n ]),\n ]),\n ]),\n ]);\n}\n\n/**\n * Construct a usable preview of the body that matched the search term.\n *\n * This code adapted from Zola's sample search code, itself adapted from mdbook.\n * Licensed under the terms of the MIT license.\n *\n * https://github.com/getzola/zola/blob/master/LICENSE\n */\nfunction makeTeaser(body: string, terms: string[]): HTMLElement {\n const TERM_WEIGHT = 40;\n const NORMAL_WORD_WEIGHT = 2;\n const FIRST_WORD_WEIGHT = 8;\n const TEASER_MAX_WORDS = 15;\n\n const stemmedTerms = terms.map(function (w) {\n return elasticlunr.stemmer(w.toLowerCase());\n });\n\n let termFound = false;\n let index = 0;\n // contains elements of [\"word\", weight, index_in_document]\n const weighted: ([string, number, number])[] = [];\n\n // split in sentences, then words\n const sentences = body.toLowerCase().split(\". \");\n\n for (const i in sentences) {\n const words = sentences[i].split(\" \");\n let value = FIRST_WORD_WEIGHT;\n\n for (const j in words) {\n const word = words[j];\n\n if (word.length > 0) {\n for (const k in stemmedTerms) {\n if (elasticlunr.stemmer(word).startsWith(stemmedTerms[k])) {\n value = TERM_WEIGHT;\n termFound = true;\n }\n }\n\n weighted.push([word, value, index]);\n value = NORMAL_WORD_WEIGHT;\n }\n\n index += word.length;\n // ' ' or '.' if last word in sentence\n index += 1;\n }\n\n // because we split at a two-char boundary '. '\n index += 1;\n }\n\n if (weighted.length === 0) {\n const final = body;\n const span = elem(\"span\", {}, {}, []);\n span.innerHTML = final;\n return span;\n }\n\n const windowWeights: number[] = [];\n const windowSize = Math.min(weighted.length, TEASER_MAX_WORDS);\n // We add a window with all the weights first\n let curSum = 0;\n for (let i = 0; i < windowSize; i++) {\n curSum += weighted[i][1];\n }\n windowWeights.push(curSum);\n\n for (let i = 0; i < weighted.length - windowSize; i++) {\n curSum -= weighted[i][1];\n curSum += weighted[i + windowSize][1];\n windowWeights.push(curSum);\n }\n\n // If we didn't find the term, just pick the first window\n let maxSumIndex = 0;\n if (termFound) {\n let maxFound = 0;\n // backwards\n for (let i = windowWeights.length - 1; i >= 0; i--) {\n if (windowWeights[i] > maxFound) {\n maxFound = windowWeights[i];\n maxSumIndex = i;\n }\n }\n }\n\n const teaser: string[] = [];\n let startIndex = weighted[maxSumIndex][2];\n for (let i = maxSumIndex; i < maxSumIndex + windowSize; i++) {\n const word = weighted[i];\n if (startIndex < word[2]) {\n // missing text from index to start of `word`\n teaser.push(body.substring(startIndex, word[2]));\n startIndex = word[2];\n }\n\n // add around search terms\n if (word[1] === TERM_WEIGHT) {\n teaser.push(\"\");\n }\n startIndex = word[2] + word[0].length;\n teaser.push(body.substring(word[2], startIndex));\n\n if (word[1] === TERM_WEIGHT) {\n teaser.push(\"\");\n }\n }\n teaser.push(\"\u2026\");\n const final = teaser.join(\"\");\n const span = elem(\"span\", {}, {}, []);\n span.innerHTML = final;\n return span;\n}\n", "import { querySelectorAll } from \"./web.ts\";\n\n/**\n * Get the theme that's currently set by the user.\n */\nexport function getConfiguredTheme(): KnownTheme {\n const theme = localStorage.getItem(\"theme\") ?? \"system\";\n\n switch (theme) {\n case \"dark\":\n return theme;\n case \"light\":\n return theme;\n case \"system\":\n return theme;\n default:\n throw new ThemeError(theme);\n }\n}\n\n/**\n * Update the theme on the page and in local storage.\n */\nexport function setPageTheme(theme: string | undefined) {\n if (theme === undefined) throw new ThemeError(theme);\n\n switch (theme) {\n case \"system\":\n localStorage.removeItem(\"theme\");\n switch (preferredTheme()) {\n case \"dark\":\n document.documentElement.classList.add(\"dark\");\n break;\n case \"light\":\n document.documentElement.classList.remove(\"dark\");\n break;\n }\n\n break;\n\n case \"light\":\n localStorage.setItem(\"theme\", theme);\n document.documentElement.classList.remove(\"dark\");\n break;\n\n case \"dark\":\n localStorage.setItem(\"theme\", theme);\n document.documentElement.classList.add(\"dark\");\n break;\n\n default:\n throw new ThemeError(theme);\n }\n\n setButtons(theme);\n}\n\n/**\n * The known theme selector options.\n */\ntype KnownTheme = \"dark\" | \"light\" | \"system\";\n\n/**\n * A theme that can be pulled explicitly from local storage.\n */\ntype StoredTheme = \"dark\" | \"light\";\n\n/**\n * Set as active the button that matches the theme.\n *\n * Make sure to set all another buttons as inactive.\n */\nfunction setButtons(theme: KnownTheme) {\n querySelectorAll(\".theme-option\").forEach(($option) => {\n if ($option.dataset.theme === theme) $option.dataset.active = \"true\";\n else delete $option.dataset.active;\n });\n}\n\n/**\n * Get the user's preferred theme based on a media query.\n */\nfunction preferredTheme(): StoredTheme {\n const prefersDark =\n globalThis.window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n\n if (prefersDark) return \"dark\";\n return \"light\";\n}\n\n/**\n * Indicates an error during theme selection.\n */\nclass ThemeError extends Error {\n constructor(theme: string | undefined) {\n super(\n `could not determine theme: '${theme || \"undefined\"}'`,\n );\n }\n}\n", "import { querySelectorAll } from \"../util/web.ts\";\nimport { setPageTheme } from \"../util/theme.ts\";\n\n/**\n * Sets up the logic for updating theme post-load.\n *\n * Note that this does _not_ handle setting the theme initially on page load.\n * That's done in a separate file since it needs to happen in the head, whereas\n * this code runs at the end of the body.\n */\nexport function setupThemeController() {\n querySelectorAll(\".theme-option\").forEach(($option) => {\n $option.addEventListener(\"click\", (e) => {\n e.preventDefault();\n setPageTheme($option.dataset.theme);\n });\n });\n}\n", "import { setupDocsNav } from \"./docs.ts\";\nimport { setupInstallerPicker } from \"./installer.ts\";\nimport { setupSmoothScrolling } from \"./scroll.ts\";\nimport { setupSearch, setupSearchModal } from \"./search.ts\";\nimport { setupThemeController } from \"./theme.ts\";\n\n/**\n * Run all page setup operations, initializing all interactive widgets.\n *\n * There are currently three widgets:\n *\n * - Theme Controller in the navigation bar.\n * - Installer Picker on the homepage.\n * - Search button in the navigation bar.\n */\nfunction setup() {\n setupThemeController();\n setupInstallerPicker();\n setupSearchModal();\n setupSearch();\n setupSmoothScrolling();\n setupDocsNav();\n}\n\n/**\n * Do setup, logging errors to the console.\n */\n(function () {\n try {\n setup();\n } catch (e) {\n console.error(e);\n }\n})();\n"], - "mappings": "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", - "names": ["updateIcon", "$node", "oldName", "newName", "newIconUrl", "getIconUrl", "setIconUrl", "iconUrl", "XLINK_NS", "IconError", "url", "querySelector", "selector", "$elem", "QueryError", "querySelectorAll", "$elems", "copyToClipboard", "text", "reason", "ClipboardError", "source", "msg", "setupDocsNav", "$toggles", "querySelectorAll", "$toggle", "$toggleIcon", "e", "$parent", "$subsection", "sectionIsHidden", "updateIcon", "setupInstallerPicker", "$buttons", "$cmd", "$copy", "$copyIcon", "querySelectorAll", "querySelector", "$button", "e", "installerForPlatform", "copyToClipboard", "updateIcon", "platform", "UnknownPlatformError", "host", "resolve_host", "unix_installer", "windows_installer", "protocol", "amendedHost", "setupSmoothScrolling", "querySelectorAll", "anchor", "e", "targetHeader", "headerPosition", "querySelector", "scrollAmount", "offsetPosition", "debounce", "waitFor", "func", "timeout", "args", "removeUndefinedValues", "x", "entries", "_k", "v", "elem", "tag", "attrs", "extras", "children", "element", "c", "k", "nodes", "e", "setupSearchModal", "$button", "querySelector", "$modal", "$modalClose", "$modalShroud", "$modalBox", "$searchInput", "e", "toggleModal", "modalIsOpen", "SEARCH_INDEX", "MAX_ITEMS", "setupSearch", "$searchResults", "$searchResultsItems", "index", "currentTerm", "initIndex", "response", "debounce", "term", "results", "i", "entry", "buildListEntry", "data", "terms", "elem", "makeTeaser", "body", "stemmedTerms", "w", "termFound", "weighted", "sentences", "words", "value", "j", "word", "k", "final", "span", "windowWeights", "windowSize", "curSum", "maxSumIndex", "maxFound", "teaser", "startIndex", "setPageTheme", "theme", "ThemeError", "preferredTheme", "setButtons", "querySelectorAll", "$option", "setupThemeController", "querySelectorAll", "$option", "e", "setPageTheme", "setup", "setupThemeController", "setupInstallerPicker", "setupSearchModal", "setupSearch", "setupSmoothScrolling", "setupDocsNav"] + "sourcesContent": ["export function updateIcon(\n $node: HTMLElement,\n oldName: string,\n newName: string,\n) {\n const iconUrl = getIconUrl($node);\n const newIconUrl = iconUrl.replace(`#icon-${oldName}`, `#icon-${newName}`);\n setIconUrl($node, newIconUrl);\n}\n\n/**\n * Get the URL out of an icon `use` element.\n */\nfunction getIconUrl($node: HTMLElement): string {\n const iconUrl = $node.getAttributeNS(XLINK_NS, \"href\");\n if (iconUrl === null) throw new IconError();\n return iconUrl;\n}\n\n/**\n * Get the URL on an icon `use` element.\n */\nfunction setIconUrl($node: HTMLElement, url: string) {\n $node.setAttributeNS(XLINK_NS, \"href\", url);\n}\n\n/**\n * The namespace URL for the Xlink namespace\n */\nconst XLINK_NS: string = \"http://www.w3.org/1999/xlink\";\n\n/**\n * Error arising when trying to update the copy-to-clipboard icon.\n */\nclass IconError extends Error {\n constructor() {\n super(`could not find copy icon`);\n }\n}\n", "/**\n * document.querySelector with type conversion and error handling.\n */\nexport function querySelector(selector: string): HTMLElement {\n const $elem = document.querySelector(selector);\n if ($elem === null) throw new QueryError(`could not find ${selector}`);\n return $elem as HTMLElement;\n}\n\n/**\n * document.querySelectorAll with type conversions and error handling.\n */\nexport function querySelectorAll(selector: string): Array {\n const $elems = document.querySelectorAll(selector);\n if ($elems === null) throw new QueryError(`could not find all '${selector}'`);\n return Array.from($elems) as Array;\n}\n\n/**\n * navigator.clipboard.writeText with error handling.\n */\nexport function copyToClipboard(text: string) {\n navigator.clipboard.writeText(text).then(null, (reason) => {\n throw new ClipboardError(reason);\n });\n}\n\n/**\n * Indicates an error while attempting to put data into the clipboard.\n */\nclass ClipboardError extends Error {\n constructor(source: unknown) {\n super(`clipboard copy rejected: '${source}'`);\n }\n}\n\n/**\n * Indicates an error while trying to select one or more elements on the page.\n */\nclass QueryError extends Error {\n constructor(msg: string) {\n super(msg);\n }\n}\n", "import { updateIcon } from \"../util/icon.ts\";\nimport { querySelectorAll } from \"../util/web.ts\";\n\n/**\n * Sets up the collapse/expand functionality for docs navigation.\n */\nexport function setupDocsNav() {\n let $toggles;\n\n try {\n $toggles = querySelectorAll(\".docs-nav-toggle\");\n } catch (_e) {\n // Swallow these errors.\n return;\n }\n\n $toggles.forEach(($toggle) => {\n // Get the icon inside the toggle.\n const $toggleIcon = $toggle.querySelector(\n \".toggle-icon use\",\n ) as HTMLElement;\n if ($toggleIcon === null) {\n console.log(`no icon found for toggle: '${$toggle}'`);\n return;\n }\n\n $toggle.addEventListener(\"click\", (e) => {\n e.preventDefault();\n\n // Find the subsection list associated with the current toggle.\n const $parent = $toggle.parentElement?.parentElement;\n if ($parent === null || $parent === undefined) return;\n const $subsection = $parent.querySelector(\n \".docs-nav-section\",\n ) as HTMLElement;\n if ($subsection === null) return;\n\n // Hide or show it.\n $subsection.classList.toggle(\"hidden\");\n\n if (sectionIsHidden($subsection)) {\n updateIcon($toggleIcon, \"chevron-right\", \"chevron-down\");\n } else {\n updateIcon($toggleIcon, \"chevron-down\", \"chevron-right\");\n }\n });\n });\n}\n\nfunction sectionIsHidden($subsection: HTMLElement): boolean {\n return $subsection.classList.contains(\"hidden\");\n}\n", "import { updateIcon } from \"../util/icon.ts\";\nimport {\n copyToClipboard,\n querySelector,\n querySelectorAll,\n} from \"../util/web.ts\";\n\n/**\n * Setup behavior for the install picker.\n *\n * This makes sure the platform buttons are clickable and update the install\n * command appropriately, and that the copy-to-clipboard button works.\n */\nexport function setupInstallerPicker() {\n // The buttons used to select the platform.\n let $buttons: Array;\n\n // The block containing the install command.\n let $cmd: HTMLElement;\n\n // The copy-to-clipboard button.\n let $copy: HTMLElement;\n\n // The icon inside the copy-to-clipboard button.\n let $copyIcon: HTMLElement;\n\n try {\n $buttons = querySelectorAll(\".installer-button\");\n $cmd = querySelector(\"#installer-cmd\");\n $copy = querySelector(\"#installer-copy\");\n $copyIcon = querySelector(\"#installer-copy > svg > use\");\n } catch (_e) {\n // Swallow these errors.\n return;\n }\n\n $buttons.forEach(($button) => {\n $button.addEventListener(\"click\", (e) => {\n e.preventDefault();\n $buttons.forEach(($button) => delete $button.dataset.active);\n $button.dataset.active = \"true\";\n $cmd.innerText = installerForPlatform($button.dataset.platform);\n });\n\n if ($button.dataset.active && $button.dataset.active === \"true\") {\n $cmd.innerText = installerForPlatform($button.dataset.platform);\n }\n });\n\n $copy.addEventListener(\"click\", (e) => {\n e.preventDefault();\n copyToClipboard($cmd.innerText);\n updateIcon($copyIcon, \"clipboard\", \"check\");\n // Set the icon back on a timer.\n setTimeout(() => updateIcon($copyIcon, \"check\", \"clipboard\"), 1_500);\n });\n}\n\n/**\n * Get the install script based on the chosen platform.\n */\nfunction installerForPlatform(platform: string | undefined): string {\n if (platform === undefined) throw new UnknownPlatformError(platform);\n\n const host = resolve_host();\n\n switch (platform) {\n case \"macos\":\n return unix_installer(host);\n case \"linux\":\n return unix_installer(host);\n case \"windows\":\n return windows_installer(host);\n default:\n throw new UnknownPlatformError(platform);\n }\n}\n\n/**\n * Get the host of the site.\n *\n * This is intended to correctly handle deployment locally in development and\n * deployment in production on GitHub Pages.\n */\nfunction resolve_host(): string {\n const protocol = globalThis.window.location.protocol;\n const host = globalThis.window.location.host;\n return `${protocol}//${host}`;\n}\n\n/**\n * The install script to use for Unix (macOS and Linux) platforms.\n */\nfunction unix_installer(host: string): string {\n return `curl -LsSf ${host}/dl/install.sh | sh`;\n}\n\n/**\n * The install script to use for Windows.\n */\nfunction windows_installer(host: string): string {\n return `irm ${host}/dl/install.ps1 | iex`;\n}\n\n/**\n * Indicates an error while trying to detect the user's install platform.\n */\nclass UnknownPlatformError extends Error {\n constructor(platform: string | undefined) {\n super(\n `could not determine platform: '${platform || \"undefined\"}'`,\n );\n }\n}\n", "import { querySelector, querySelectorAll } from \"../util/web.ts\";\n\nexport function setupSmoothScrolling() {\n /*\n * This code from: https://stackoverflow.com/a/7717572\n * Used under the CC BY-SA 3.0 license with modifications.\n */\n querySelectorAll('a[href^=\"#\"]').forEach((anchor) => {\n anchor.addEventListener(\"click\", (e) => {\n e.preventDefault();\n if (e.currentTarget === null) return;\n\n const targetHeader = (e.currentTarget as HTMLElement).getAttribute(\"href\");\n if (targetHeader === null) return;\n\n const $header = querySelector(targetHeader);\n const headerPosition = $header.getBoundingClientRect().top;\n const scrollAmount = globalThis.window.scrollY;\n const offsetPosition = headerPosition + scrollAmount;\n\n globalThis.window.scrollTo({\n top: offsetPosition,\n behavior: \"smooth\",\n });\n });\n });\n}\n", "/**\n * Debounce an event handler by waiting `waitFor` number of milliseconds before\n * permitting the event to be triggered again.\n */\nexport function debounce) => ReturnType>(\n waitFor: number,\n func: F,\n): (...args: Parameters) => void {\n let timeout: number;\n return (...args: Parameters): void => {\n clearTimeout(timeout);\n timeout = setTimeout(() => func(...args), waitFor);\n };\n}\n", "/**\n * This code adapted from char's \"rainbow\" project.\n *\n * https://github.com/char/rainbow/blob/47721ad574c61d59921435a2bff41b9fd582540d/src/util/elem.ts\n *\n * It's licensed under the terms of the WTFPL.\n *\n * https://bsky.app/profile/pet.bun.how/post/3l7vv6ddjn426\n */\n\n// deno-lint-ignore-file ban-types\n\nexport type ElemProps = {\n [K in keyof E as E[K] extends Function ? never : K]?: E[K];\n};\n\n// Just a shorthand for a long type name.\ntype HTMLElemTagNameMap = HTMLElementTagNameMap;\n\n// Children can be built from an existing element, string, or text.\ntype IntoChild = Element | string | Text;\n\n// We permit adding classes and data attributes.\ntype Extras = {\n classList?: string[];\n dataset?: Partial>;\n};\n\n// Attributes to add.\ntype Attrs =\n | ElemProps\n | ElemProps[];\n\n// A little way to reduce an object down to only defined entries, since\n// entries can have a key but an undefined value.\nfunction removeUndefinedValues(x: object): object {\n const entries = Object.entries(x).filter(([_k, v]) => v !== undefined);\n return Object.fromEntries(entries);\n}\n\n/**\n * Construct a new HTMLElement\n */\nexport function elem(\n tag: K,\n attrs: Attrs = {},\n extras: Extras = {},\n children: IntoChild[] = [],\n): HTMLElemTagNameMap[K] {\n // Create the new element.\n const element = document.createElement(tag);\n\n // Assign any defined values from `attrs`.\n Object.assign(element, removeUndefinedValues(attrs));\n\n // Fill in any provided classes.\n if (extras.classList) {\n extras.classList.forEach((c) => element.classList.add(c));\n }\n\n // Fill in any assigned data attributes.\n if (extras.dataset) {\n Object.entries(extras.dataset)\n .filter(([_k, v]) => v !== undefined)\n .forEach(([k, v]) => (element.dataset[k] = v));\n }\n\n // Populate any children.\n const nodes = children.map(\n (e) => (typeof e === \"string\" ? document.createTextNode(e) : e)\n );\n element.append(...nodes);\n\n return element;\n}\n", "import { debounce } from \"../util/event.ts\";\nimport { elem } from \"../util/html.ts\";\nimport { querySelector } from \"../util/web.ts\";\n\n/**\n * Sets up functionality for opening and closing the search modal.\n */\nexport function setupSearchModal() {\n const $button = querySelector(\"#search-button\");\n const $modal = querySelector(\"#search-modal\");\n const $modalClose = querySelector(\"#search-modal-close\");\n const $modalShroud = querySelector(\"#search-modal-shroud\");\n const $modalBox = querySelector(\"#search-modal-box\");\n const $searchInput = querySelector(\"#search-input\");\n\n // Need all of these together to make sure clicking the *background* closes\n // the search modal, but clicking inside the box (anywhere other than the\n // close button) does *not* close the modal.\n $button.addEventListener(\n \"click\",\n (e) => toggleModal(e, $modal, $searchInput),\n );\n $modalShroud.addEventListener(\n \"click\",\n (e) => toggleModal(e, $modal, $searchInput),\n );\n $modalClose.addEventListener(\n \"click\",\n (e) => toggleModal(e, $modal, $searchInput),\n );\n $modalBox.addEventListener(\"click\", (e) => e.stopPropagation());\n\n // Keyboard shortcuts.\n document.addEventListener(\"keydown\", (e) => {\n // 'Meta+K' to open or close the modal.\n if (e.metaKey === true && e.shiftKey === false && e.key === \"k\") {\n e.preventDefault();\n $button.click();\n return;\n }\n\n if (modalIsOpen($modal)) {\n switch (e.key) {\n case \"Escape\":\n e.preventDefault();\n $modalShroud.click();\n return;\n case \"ArrowDown\":\n // TODO: Focus the next result in the search results.\n break;\n case \"ArrowUp\":\n // TODO: Focus the prior result in the search result.\n break;\n default:\n break;\n }\n }\n });\n}\n\n/**\n * Toggle whether the modal is open or not.\n */\nfunction toggleModal(\n e: MouseEvent,\n $modal: HTMLElement,\n $searchInput: HTMLElement,\n) {\n e.preventDefault();\n $modal.classList.toggle(\"hidden\");\n if (modalIsOpen($modal)) $searchInput.focus();\n}\n\n/**\n * Check if the modal is open.\n */\nfunction modalIsOpen($modal: HTMLElement): boolean {\n return !$modal.classList.contains(\"hidden\");\n}\n\n/**\n * Elasticlunr is the library Zola uses for search integration, and it doesn't\n * provide TypeScript type definitions. So the definitions here are just enough\n * to get Deno's linter to stop complaining, but they do mean we don't really\n * get type-checking protection for interacting with the Elasticluner API.\n *\n * In the future if we wanted type-checking for this API we could replace the\n * 'any' with an actual description of the relevant types.\n */\n\n// Define the Index type.\ntype Index = {\n // deno-lint-ignore no-explicit-any\n load: (data: Promise) => Promise;\n // deno-lint-ignore no-explicit-any\n search: (query: string, options?: any) => SearchResult;\n};\n\n/**\n * Data returned from the Elasticlunr search function\n */\ntype SearchResult = {\n ref: string;\n score: number;\n doc: {\n body: string;\n id: string;\n title: string;\n };\n};\n\n// Define the \"elasticlunr\" global.\ndeclare global {\n let elasticlunr: {\n Index: Index;\n // deno-lint-ignore no-explicit-any\n stemmer: any;\n };\n}\n\n/**\n * The path to the search index created by Zola.\n */\nconst SEARCH_INDEX: string = \"/search_index.en.json\";\n\n/**\n * The maximum number of results to show in searches.\n */\nconst MAX_ITEMS: number = 6;\n\n/**\n * Setup the search operation within the search modal.\n */\nexport function setupSearch() {\n const $searchInput = querySelector(\"#search-input\") as HTMLInputElement;\n const $searchResults = querySelector(\"#search-results\");\n const $searchResultsItems = querySelector(\"#search-results-items\");\n\n // The search index, representing the content of the site.\n let index: Promise;\n\n // The current term being searched by the user.\n let currentTerm = \"\";\n\n const initIndex = async function () {\n // If no index, then asynchronously load it from the index file.\n if (index === undefined) {\n index = fetch(SEARCH_INDEX)\n .then(\n async function (response) {\n return await elasticlunr.Index.load(await response.json());\n },\n );\n }\n\n return await index;\n };\n\n $searchInput.addEventListener(\n \"keyup\",\n debounce(150, async function () {\n const term = $searchInput.value.trim();\n if (term === currentTerm) return;\n\n $searchResults.style.display = term === \"\" ? \"none\" : \"block\";\n $searchResultsItems.innerHTML = \"\";\n\n currentTerm = term;\n if (currentTerm === \"\") return;\n\n const results: SearchResult[] = (await initIndex())\n .search(term, {\n bool: \"AND\",\n fields: {\n title: { boost: 2 },\n body: { boost: 1 },\n },\n });\n\n if (results.length === 0) {\n $searchResults.style.display = \"none\";\n return;\n }\n\n for (let i = 0; i < Math.min(results.length, MAX_ITEMS); ++i) {\n const entry = buildListEntry(results[i], currentTerm.split(\" \"));\n $searchResultsItems.appendChild(entry);\n }\n }),\n );\n}\n\n/**\n * Build an HTML element for each item in the search results.\n */\nfunction buildListEntry(data: SearchResult, terms: string[]): HTMLElement {\n return elem(\"li\", {}, {\n classList: [\"border-t\", \"border-neutral-300\", \"dark:border-neutral-500\"],\n }, [\n elem(\"div\", {}, {}, [\n elem(\"a\", { href: data.ref }, {\n classList: [\n \"block\",\n \"px-5\",\n \"py-2\",\n \"hover:bg-blue-50\",\n \"dark:hover:bg-blue-500\",\n \"hover:text-blue-500\",\n \"dark:hover:text-white\",\n \"group\",\n ],\n }, [\n elem(\"span\", {}, {\n classList: [\"block\", \"text-base\", \"mb-1\", \"font-medium\"],\n }, [\n data.doc.title,\n ]),\n elem(\"span\", {}, {\n classList: [\n \"block\",\n \"text-neutral-500\",\n \"text-sm\",\n \"group-hover:text-blue-500\",\n ],\n }, [\n makeTeaser(data.doc.body, terms),\n ]),\n ]),\n ]),\n ]);\n}\n\n/**\n * Construct a usable preview of the body that matched the search term.\n *\n * This code adapted from Zola's sample search code, itself adapted from mdbook.\n * Licensed under the terms of the MIT license.\n *\n * https://github.com/getzola/zola/blob/master/LICENSE\n */\nfunction makeTeaser(body: string, terms: string[]): HTMLElement {\n const TERM_WEIGHT = 40;\n const NORMAL_WORD_WEIGHT = 2;\n const FIRST_WORD_WEIGHT = 8;\n const TEASER_MAX_WORDS = 15;\n\n const stemmedTerms = terms.map(function (w) {\n return elasticlunr.stemmer(w.toLowerCase());\n });\n\n let termFound = false;\n let index = 0;\n // contains elements of [\"word\", weight, index_in_document]\n const weighted: ([string, number, number])[] = [];\n\n // split in sentences, then words\n const sentences = body.toLowerCase().split(\". \");\n\n for (const i in sentences) {\n const words = sentences[i].split(\" \");\n let value = FIRST_WORD_WEIGHT;\n\n for (const j in words) {\n const word = words[j];\n\n if (word.length > 0) {\n for (const k in stemmedTerms) {\n if (elasticlunr.stemmer(word).startsWith(stemmedTerms[k])) {\n value = TERM_WEIGHT;\n termFound = true;\n }\n }\n\n weighted.push([word, value, index]);\n value = NORMAL_WORD_WEIGHT;\n }\n\n index += word.length;\n // ' ' or '.' if last word in sentence\n index += 1;\n }\n\n // because we split at a two-char boundary '. '\n index += 1;\n }\n\n if (weighted.length === 0) {\n const final = body;\n const span = elem(\"span\", {}, {}, []);\n span.innerHTML = final;\n return span;\n }\n\n const windowWeights: number[] = [];\n const windowSize = Math.min(weighted.length, TEASER_MAX_WORDS);\n // We add a window with all the weights first\n let curSum = 0;\n for (let i = 0; i < windowSize; i++) {\n curSum += weighted[i][1];\n }\n windowWeights.push(curSum);\n\n for (let i = 0; i < weighted.length - windowSize; i++) {\n curSum -= weighted[i][1];\n curSum += weighted[i + windowSize][1];\n windowWeights.push(curSum);\n }\n\n // If we didn't find the term, just pick the first window\n let maxSumIndex = 0;\n if (termFound) {\n let maxFound = 0;\n // backwards\n for (let i = windowWeights.length - 1; i >= 0; i--) {\n if (windowWeights[i] > maxFound) {\n maxFound = windowWeights[i];\n maxSumIndex = i;\n }\n }\n }\n\n const teaser: string[] = [];\n let startIndex = weighted[maxSumIndex][2];\n for (let i = maxSumIndex; i < maxSumIndex + windowSize; i++) {\n const word = weighted[i];\n if (startIndex < word[2]) {\n // missing text from index to start of `word`\n teaser.push(body.substring(startIndex, word[2]));\n startIndex = word[2];\n }\n\n // add around search terms\n if (word[1] === TERM_WEIGHT) {\n teaser.push(\"\");\n }\n startIndex = word[2] + word[0].length;\n teaser.push(body.substring(word[2], startIndex));\n\n if (word[1] === TERM_WEIGHT) {\n teaser.push(\"\");\n }\n }\n teaser.push(\"\u2026\");\n const final = teaser.join(\"\");\n const span = elem(\"span\", {}, {}, []);\n span.innerHTML = final;\n return span;\n}\n", "import { querySelectorAll } from \"./web.ts\";\n\n/**\n * Get the theme that's currently set by the user.\n */\nexport function getConfiguredTheme(): KnownTheme {\n const theme = localStorage.getItem(\"theme\") ?? \"system\";\n\n switch (theme) {\n case \"dark\":\n return theme;\n case \"light\":\n return theme;\n case \"system\":\n return theme;\n default:\n throw new ThemeError(theme);\n }\n}\n\n/**\n * Update the theme on the page and in local storage.\n */\nexport function setPageTheme(theme: string | undefined) {\n if (theme === undefined) throw new ThemeError(theme);\n\n switch (theme) {\n case \"system\":\n localStorage.removeItem(\"theme\");\n switch (preferredTheme()) {\n case \"dark\":\n document.documentElement.classList.add(\"dark\");\n break;\n case \"light\":\n document.documentElement.classList.remove(\"dark\");\n break;\n }\n\n break;\n\n case \"light\":\n localStorage.setItem(\"theme\", theme);\n document.documentElement.classList.remove(\"dark\");\n break;\n\n case \"dark\":\n localStorage.setItem(\"theme\", theme);\n document.documentElement.classList.add(\"dark\");\n break;\n\n default:\n throw new ThemeError(theme);\n }\n\n setButtons(theme);\n}\n\n/**\n * The known theme selector options.\n */\ntype KnownTheme = \"dark\" | \"light\" | \"system\";\n\n/**\n * A theme that can be pulled explicitly from local storage.\n */\ntype StoredTheme = \"dark\" | \"light\";\n\n/**\n * Set as active the button that matches the theme.\n *\n * Make sure to set all another buttons as inactive.\n */\nfunction setButtons(theme: KnownTheme) {\n querySelectorAll(\".theme-option\").forEach(($option) => {\n if ($option.dataset.theme === theme) $option.dataset.active = \"true\";\n else delete $option.dataset.active;\n });\n}\n\n/**\n * Get the user's preferred theme based on a media query.\n */\nfunction preferredTheme(): StoredTheme {\n const prefersDark =\n globalThis.window.matchMedia(\"(prefers-color-scheme: dark)\").matches;\n\n if (prefersDark) return \"dark\";\n return \"light\";\n}\n\n/**\n * Indicates an error during theme selection.\n */\nclass ThemeError extends Error {\n constructor(theme: string | undefined) {\n super(\n `could not determine theme: '${theme || \"undefined\"}'`,\n );\n }\n}\n", "import { querySelectorAll } from \"../util/web.ts\";\nimport { setPageTheme } from \"../util/theme.ts\";\n\n/**\n * Sets up the logic for updating theme post-load.\n *\n * Note that this does _not_ handle setting the theme initially on page load.\n * That's done in a separate file since it needs to happen in the head, whereas\n * this code runs at the end of the body.\n */\nexport function setupThemeController() {\n querySelectorAll(\".theme-option\").forEach(($option) => {\n $option.addEventListener(\"click\", (e) => {\n e.preventDefault();\n setPageTheme($option.dataset.theme);\n });\n });\n}\n", "import { setupDocsNav } from \"./docs.ts\";\nimport { setupInstallerPicker } from \"./installer.ts\";\nimport { setupSmoothScrolling } from \"./scroll.ts\";\nimport { setupSearch, setupSearchModal } from \"./search.ts\";\nimport { setupThemeController } from \"./theme.ts\";\n\n/**\n * Run all page setup operations, initializing all interactive widgets.\n *\n * There are currently three widgets:\n *\n * - Theme Controller in the navigation bar.\n * - Installer Picker on the homepage.\n * - Search button in the navigation bar.\n */\nfunction setup() {\n setupThemeController();\n setupInstallerPicker();\n setupSearchModal();\n setupSearch();\n setupSmoothScrolling();\n setupDocsNav();\n}\n\n/**\n * Do setup, logging errors to the console.\n */\n(function () {\n try {\n setup();\n } catch (e) {\n console.error(e);\n }\n})();\n"], + "mappings": "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", + "names": ["updateIcon", "$node", "oldName", "newName", "newIconUrl", "getIconUrl", "setIconUrl", "iconUrl", "XLINK_NS", "IconError", "url", "querySelector", "selector", "$elem", "QueryError", "querySelectorAll", "$elems", "copyToClipboard", "text", "reason", "ClipboardError", "source", "msg", "setupDocsNav", "$toggles", "querySelectorAll", "$toggle", "$toggleIcon", "e", "$parent", "$subsection", "sectionIsHidden", "updateIcon", "setupInstallerPicker", "$buttons", "$cmd", "$copy", "$copyIcon", "querySelectorAll", "querySelector", "$button", "e", "installerForPlatform", "copyToClipboard", "updateIcon", "platform", "UnknownPlatformError", "host", "resolve_host", "unix_installer", "windows_installer", "protocol", "setupSmoothScrolling", "querySelectorAll", "anchor", "e", "targetHeader", "headerPosition", "querySelector", "scrollAmount", "offsetPosition", "debounce", "waitFor", "func", "timeout", "args", "removeUndefinedValues", "x", "entries", "_k", "v", "elem", "tag", "attrs", "extras", "children", "element", "c", "k", "nodes", "e", "setupSearchModal", "$button", "querySelector", "$modal", "$modalClose", "$modalShroud", "$modalBox", "$searchInput", "e", "toggleModal", "modalIsOpen", "SEARCH_INDEX", "MAX_ITEMS", "setupSearch", "$searchResults", "$searchResultsItems", "index", "currentTerm", "initIndex", "response", "debounce", "term", "results", "i", "entry", "buildListEntry", "data", "terms", "elem", "makeTeaser", "body", "stemmedTerms", "w", "termFound", "weighted", "sentences", "words", "value", "j", "word", "k", "final", "span", "windowWeights", "windowSize", "curSum", "maxSumIndex", "maxFound", "teaser", "startIndex", "setPageTheme", "theme", "ThemeError", "preferredTheme", "setButtons", "querySelectorAll", "$option", "setupThemeController", "querySelectorAll", "$option", "e", "setPageTheme", "setup", "setupThemeController", "setupInstallerPicker", "setupSearchModal", "setupSearch", "setupSmoothScrolling", "setupDocsNav"] }