static/frontend: fix dark theme toggle for self hosted instances

Defaulting to a blank domain allows for the dark theme toggle
to work on a pkgsite instance hosted at any domain.

Change-Id: Iefb1fea8ef050e520233eef0490d4630b1d95925
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/398416
Trust: Jamal Carvalho <jamal@golang.org>
Run-TryBot: Jamal Carvalho <jamal@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
diff --git a/static/frontend/frontend.js b/static/frontend/frontend.js
index bec592d..d1aeba1 100644
--- a/static/frontend/frontend.js
+++ b/static/frontend/frontend.js
@@ -9,7 +9,7 @@
           <img class="go-Icon" height="24" width="24" src="/static/shared/icon/arrow_right_gm_grey_24dp.svg" alt="">
         </button>
       </li>
-    `,(n=t.querySelector(".go-Carousel-prevSlide"))==null||n.addEventListener("click",()=>this.setActive(this.activeIndex-1)),(o=t.querySelector(".go-Carousel-nextSlide"))==null||o.addEventListener("click",()=>this.setActive(this.activeIndex+1)),this.el.append(t)}initDots(){let t=document.createElement("ul");t.classList.add("go-Carousel-dots");for(let n=0;n<this.slides.length;n++){let o=document.createElement("li"),i=document.createElement("button");i.classList.add("go-Carousel-dot"),n===this.activeIndex&&i.classList.add("go-Carousel-dot--active"),i.innerHTML=`<span class="go-Carousel-obscured">Slide ${n+1}</span>`,i.addEventListener("click",()=>this.setActive(n)),o.append(i),t.append(o),this.dots.push(i)}this.el.append(t)}initLiveRegion(){this.liveRegion.setAttribute("aria-live","polite"),this.liveRegion.setAttribute("aria-atomic","true"),this.liveRegion.setAttribute("class","go-Carousel-obscured"),this.liveRegion.textContent=`Slide ${this.activeIndex+1} of ${this.slides.length}`,this.el.appendChild(this.liveRegion)}};var S=class{constructor(t){this.el=t;var n,o,i,l,h;this.data=(n=t.dataset.toCopy)!=null?n:t.innerText,!this.data&&((o=t.parentElement)==null?void 0:o.classList.contains("go-InputGroup"))&&(this.data=(h=this.data||((l=(i=t.parentElement)==null?void 0:i.querySelector("input"))==null?void 0:l.value))!=null?h:""),t.addEventListener("click",w=>this.handleCopyClick(w))}handleCopyClick(t){t.preventDefault();let n=1e3;if(!navigator.clipboard){this.showTooltipText("Unable to copy",n);return}navigator.clipboard.writeText(this.data).then(()=>{this.showTooltipText("Copied!",n)}).catch(()=>{this.showTooltipText("Unable to copy",n)})}showTooltipText(t,n){this.el.setAttribute("data-tooltip",t),setTimeout(()=>this.el.setAttribute("data-tooltip",""),n)}};var M=class{constructor(t){this.el=t;document.addEventListener("click",n=>{this.el.contains(n.target)||this.el.removeAttribute("open")})}};var H=class{constructor(t){this.el=t;this.el.addEventListener("change",n=>{let o=n.target,i=o.value;o.value.startsWith("/")||(i="/"+i),window.location.href=i})}};var k=class{constructor(t){this.el=t;window.dialogPolyfill&&window.dialogPolyfill.registerDialog(t),this.init()}init(){let t=document.querySelector(`[aria-controls="${this.el.id}"]`);t&&t.addEventListener("click",()=>{var n;this.el.showModal?this.el.showModal():this.el.setAttribute("opened","true"),(n=this.el.querySelector("input"))==null||n.focus()});for(let n of this.el.querySelectorAll("[data-modal-close]"))n.addEventListener("click",()=>{this.el.close?this.el.close():this.el.removeAttribute("opened")})}};function L(e,t,n,o){var i;(i=window.dataLayer)!=null||(window.dataLayer=[]),typeof e=="string"?window.dataLayer.push({event:e,event_category:t,event_action:n,event_label:o}):window.dataLayer.push(e)}function _(e){var t;(t=window.dataLayer)!=null||(window.dataLayer=[]),window.dataLayer.push(e)}var O=class{constructor(){this.handlers={},document.addEventListener("keydown",t=>this.handleKeyPress(t))}on(t,n,o,i){var l,h;return(h=(l=this.handlers)[t])!=null||(l[t]=new Set),this.handlers[t].add({description:n,callback:o,...i}),this}handleKeyPress(t){var n;for(let o of(n=this.handlers[t.key.toLowerCase()])!=null?n:new Set){if(o.target&&o.target!==t.target)return;let i=t.target;if(!o.target&&((i==null?void 0:i.tagName)==="INPUT"||(i==null?void 0:i.tagName)==="SELECT"||(i==null?void 0:i.tagName)==="TEXTAREA")||(i==null?void 0:i.isContentEditable)||o.withMeta&&!(t.ctrlKey||t.metaKey)||!o.withMeta&&(t.ctrlKey||t.metaKey))return;L("keypress","hotkeys",`${t.key} pressed`,o.description),o.callback(t)}}},g=new O;function J(){var q;let e=document.querySelector(".JumpDialog"),t=e==null?void 0:e.querySelector(".JumpDialog-body"),n=e==null?void 0:e.querySelector(".JumpDialog-list"),o=e==null?void 0:e.querySelector(".JumpDialog-input"),i=document.querySelector(".js-documentation"),l;function h(){let s=[];if(!!i){for(let r of i.querySelectorAll("[data-kind]"))s.push(w(r));for(let r of s)r.link.addEventListener("click",function(){e==null||e.close()});return s.sort(function(r,c){return r.lower.localeCompare(c.lower)}),s}}function w(s){var v;let r=document.createElement("a"),c=s.getAttribute("id");r.setAttribute("href","#"+c),r.setAttribute("tabindex","-1"),r.setAttribute("data-gtmc","jump to link");let u=s.getAttribute("data-kind");return{link:r,name:c!=null?c:"",kind:u!=null?u:"",lower:(v=c==null?void 0:c.toLowerCase())!=null?v:""}}let A,m=-1;function T(s){for(A=s,l||(l=h()),E(-1);n==null?void 0:n.firstChild;)n.firstChild.remove();if(s){let r=s.toLowerCase(),c=[],u=[],v=[],b=(d,p,f)=>d.name.substring(0,p)+"<b>"+d.name.substring(p,f)+"</b>"+d.name.substring(f);for(let d of l!=null?l:[]){let p=d.name.toLowerCase();if(p===r)d.link.innerHTML=b(d,0,d.name.length),c.push(d);else if(p.startsWith(r))d.link.innerHTML=b(d,0,s.length),u.push(d);else{let f=p.indexOf(r);f>-1&&(d.link.innerHTML=b(d,f,f+s.length),v.push(d))}}for(let d of c.concat(u).concat(v))n==null||n.appendChild(d.link)}else{if(!l||l.length===0){let r=document.createElement("i");r.innerHTML="There are no symbols on this page.",n==null||n.appendChild(r)}for(let r of l!=null?l:[])r.link.innerHTML=r.name+" <i>"+r.kind+"</i>",n==null||n.appendChild(r.link)}t&&(t.scrollTop=0),(l==null?void 0:l.length)&&n&&n.children.length>0&&E(0)}function E(s){let r=n==null?void 0:n.children;if(!(!r||!t)){if(m>=0&&r[m].classList.remove("JumpDialog-active"),s>=r.length&&(s=r.length-1),s>=0){r[s].classList.add("JumpDialog-active");let c=r[s].offsetTop-r[0].offsetTop,u=c+r[s].clientHeight;c<t.scrollTop?t.scrollTop=c:u>t.scrollTop+t.clientHeight&&(t.scrollTop=u-t.clientHeight)}m=s}}function C(s){if(m<0)return;let r=m+s;r<0&&(r=0),E(r)}o==null||o.addEventListener("keyup",function(){o.value.toUpperCase()!=A.toUpperCase()&&T(o.value)}),o==null||o.addEventListener("keydown",function(s){let r=38,c=40,u=13;switch(s.which){case r:C(-1),s.preventDefault();break;case c:C(1),s.preventDefault();break;case u:m>=0&&n&&(n.children[m].click(),s.preventDefault());break}});let a=document.querySelector(".ShortcutsDialog");g.on("f","open jump to modal",s=>{var r;(e==null?void 0:e.open)||(a==null?void 0:a.open)||(s.preventDefault(),o&&(o.value=""),(r=e==null?void 0:e.showModal)==null||r.call(e),o==null||o.focus(),T(""))}).on("?","open shortcuts modal",()=>{var s;(e==null?void 0:e.open)||(a==null?void 0:a.open)||(s=a==null?void 0:a.showModal)==null||s.call(a)});let x=document.querySelector(".js-jumpToInput");x&&x.addEventListener("click",()=>{var s;o&&(o.value=""),T(""),!((e==null?void 0:e.open)||(a==null?void 0:a.open))&&((s=e==null?void 0:e.showModal)==null||s.call(e),o==null||o.focus())}),(q=document.querySelector(".js-openShortcuts"))==null||q.addEventListener("click",()=>{var s;(s=a==null?void 0:a.showModal)==null||s.call(a)})}for(let e of document.querySelectorAll(".js-clipboard"))new S(e);for(let e of document.querySelectorAll(".js-modal"))new k(e);for(let e of document.querySelectorAll(".js-tooltip"))new M(e);for(let e of document.querySelectorAll(".js-selectNav"))new H(e);for(let e of document.querySelectorAll(".js-carousel"))new y(e);I();R();window.addEventListener("load",()=>{J()});g.on("/","focus search",e=>{let t=Array.from(document.querySelectorAll(".js-searchFocus")).pop();t&&!window.navigator.userAgent.includes("Firefox")&&(e.preventDefault(),t.focus())});g.on("y","set canonical url",()=>{var t;let e=(t=document.querySelector(".js-canonicalURLPath"))==null?void 0:t.dataset.canonicalUrlPath;if(e&&e!==""){let n=window.location.hash;n&&(e+=n),window.history.replaceState(null,"",e)}});(function(){L({"gtm.start":new Date().getTime(),event:"gtm.js"})})();function N(){let e=new URLSearchParams(window.location.search),t=e.get("utm_source");if(t!=="gopls"&&t!=="godoc"&&t!=="pkggodev")return;let n=new URL(window.location.href);e.delete("utm_source"),n.search=e.toString(),window.history.replaceState(null,"",n.toString())}var U;((U=document.querySelector(".js-gtmID"))==null?void 0:U.dataset.gtmid)&&window.dataLayer?_(function(){N()}):N();for(let e of document.querySelectorAll(".js-toggleTheme"))e.addEventListener("click",()=>{P()});function P(){let e="dark",t=document.documentElement.getAttribute("data-theme");t==="dark"?e="light":t==="light"&&(e="auto");let n="domain=.go.dev;";location.hostname==="localhost"&&(n=""),document.documentElement.setAttribute("data-theme",e),document.cookie=`prefers-color-scheme=${e};${n}path=/;max-age=31536000;`}
+    `,(n=t.querySelector(".go-Carousel-prevSlide"))==null||n.addEventListener("click",()=>this.setActive(this.activeIndex-1)),(o=t.querySelector(".go-Carousel-nextSlide"))==null||o.addEventListener("click",()=>this.setActive(this.activeIndex+1)),this.el.append(t)}initDots(){let t=document.createElement("ul");t.classList.add("go-Carousel-dots");for(let n=0;n<this.slides.length;n++){let o=document.createElement("li"),i=document.createElement("button");i.classList.add("go-Carousel-dot"),n===this.activeIndex&&i.classList.add("go-Carousel-dot--active"),i.innerHTML=`<span class="go-Carousel-obscured">Slide ${n+1}</span>`,i.addEventListener("click",()=>this.setActive(n)),o.append(i),t.append(o),this.dots.push(i)}this.el.append(t)}initLiveRegion(){this.liveRegion.setAttribute("aria-live","polite"),this.liveRegion.setAttribute("aria-atomic","true"),this.liveRegion.setAttribute("class","go-Carousel-obscured"),this.liveRegion.textContent=`Slide ${this.activeIndex+1} of ${this.slides.length}`,this.el.appendChild(this.liveRegion)}};var S=class{constructor(t){this.el=t;var n,o,i,l,h;this.data=(n=t.dataset.toCopy)!=null?n:t.innerText,!this.data&&((o=t.parentElement)==null?void 0:o.classList.contains("go-InputGroup"))&&(this.data=(h=this.data||((l=(i=t.parentElement)==null?void 0:i.querySelector("input"))==null?void 0:l.value))!=null?h:""),t.addEventListener("click",w=>this.handleCopyClick(w))}handleCopyClick(t){t.preventDefault();let n=1e3;if(!navigator.clipboard){this.showTooltipText("Unable to copy",n);return}navigator.clipboard.writeText(this.data).then(()=>{this.showTooltipText("Copied!",n)}).catch(()=>{this.showTooltipText("Unable to copy",n)})}showTooltipText(t,n){this.el.setAttribute("data-tooltip",t),setTimeout(()=>this.el.setAttribute("data-tooltip",""),n)}};var M=class{constructor(t){this.el=t;document.addEventListener("click",n=>{this.el.contains(n.target)||this.el.removeAttribute("open")})}};var H=class{constructor(t){this.el=t;this.el.addEventListener("change",n=>{let o=n.target,i=o.value;o.value.startsWith("/")||(i="/"+i),window.location.href=i})}};var k=class{constructor(t){this.el=t;window.dialogPolyfill&&window.dialogPolyfill.registerDialog(t),this.init()}init(){let t=document.querySelector(`[aria-controls="${this.el.id}"]`);t&&t.addEventListener("click",()=>{var n;this.el.showModal?this.el.showModal():this.el.setAttribute("opened","true"),(n=this.el.querySelector("input"))==null||n.focus()});for(let n of this.el.querySelectorAll("[data-modal-close]"))n.addEventListener("click",()=>{this.el.close?this.el.close():this.el.removeAttribute("opened")})}};function L(e,t,n,o){var i;(i=window.dataLayer)!=null||(window.dataLayer=[]),typeof e=="string"?window.dataLayer.push({event:e,event_category:t,event_action:n,event_label:o}):window.dataLayer.push(e)}function _(e){var t;(t=window.dataLayer)!=null||(window.dataLayer=[]),window.dataLayer.push(e)}var O=class{constructor(){this.handlers={},document.addEventListener("keydown",t=>this.handleKeyPress(t))}on(t,n,o,i){var l,h;return(h=(l=this.handlers)[t])!=null||(l[t]=new Set),this.handlers[t].add({description:n,callback:o,...i}),this}handleKeyPress(t){var n;for(let o of(n=this.handlers[t.key.toLowerCase()])!=null?n:new Set){if(o.target&&o.target!==t.target)return;let i=t.target;if(!o.target&&((i==null?void 0:i.tagName)==="INPUT"||(i==null?void 0:i.tagName)==="SELECT"||(i==null?void 0:i.tagName)==="TEXTAREA")||(i==null?void 0:i.isContentEditable)||o.withMeta&&!(t.ctrlKey||t.metaKey)||!o.withMeta&&(t.ctrlKey||t.metaKey))return;L("keypress","hotkeys",`${t.key} pressed`,o.description),o.callback(t)}}},g=new O;function J(){var q;let e=document.querySelector(".JumpDialog"),t=e==null?void 0:e.querySelector(".JumpDialog-body"),n=e==null?void 0:e.querySelector(".JumpDialog-list"),o=e==null?void 0:e.querySelector(".JumpDialog-input"),i=document.querySelector(".js-documentation"),l;function h(){let s=[];if(!!i){for(let r of i.querySelectorAll("[data-kind]"))s.push(w(r));for(let r of s)r.link.addEventListener("click",function(){e==null||e.close()});return s.sort(function(r,c){return r.lower.localeCompare(c.lower)}),s}}function w(s){var v;let r=document.createElement("a"),c=s.getAttribute("id");r.setAttribute("href","#"+c),r.setAttribute("tabindex","-1"),r.setAttribute("data-gtmc","jump to link");let u=s.getAttribute("data-kind");return{link:r,name:c!=null?c:"",kind:u!=null?u:"",lower:(v=c==null?void 0:c.toLowerCase())!=null?v:""}}let A,m=-1;function T(s){for(A=s,l||(l=h()),E(-1);n==null?void 0:n.firstChild;)n.firstChild.remove();if(s){let r=s.toLowerCase(),c=[],u=[],v=[],b=(d,p,f)=>d.name.substring(0,p)+"<b>"+d.name.substring(p,f)+"</b>"+d.name.substring(f);for(let d of l!=null?l:[]){let p=d.name.toLowerCase();if(p===r)d.link.innerHTML=b(d,0,d.name.length),c.push(d);else if(p.startsWith(r))d.link.innerHTML=b(d,0,s.length),u.push(d);else{let f=p.indexOf(r);f>-1&&(d.link.innerHTML=b(d,f,f+s.length),v.push(d))}}for(let d of c.concat(u).concat(v))n==null||n.appendChild(d.link)}else{if(!l||l.length===0){let r=document.createElement("i");r.innerHTML="There are no symbols on this page.",n==null||n.appendChild(r)}for(let r of l!=null?l:[])r.link.innerHTML=r.name+" <i>"+r.kind+"</i>",n==null||n.appendChild(r.link)}t&&(t.scrollTop=0),(l==null?void 0:l.length)&&n&&n.children.length>0&&E(0)}function E(s){let r=n==null?void 0:n.children;if(!(!r||!t)){if(m>=0&&r[m].classList.remove("JumpDialog-active"),s>=r.length&&(s=r.length-1),s>=0){r[s].classList.add("JumpDialog-active");let c=r[s].offsetTop-r[0].offsetTop,u=c+r[s].clientHeight;c<t.scrollTop?t.scrollTop=c:u>t.scrollTop+t.clientHeight&&(t.scrollTop=u-t.clientHeight)}m=s}}function C(s){if(m<0)return;let r=m+s;r<0&&(r=0),E(r)}o==null||o.addEventListener("keyup",function(){o.value.toUpperCase()!=A.toUpperCase()&&T(o.value)}),o==null||o.addEventListener("keydown",function(s){let r=38,c=40,u=13;switch(s.which){case r:C(-1),s.preventDefault();break;case c:C(1),s.preventDefault();break;case u:m>=0&&n&&(n.children[m].click(),s.preventDefault());break}});let a=document.querySelector(".ShortcutsDialog");g.on("f","open jump to modal",s=>{var r;(e==null?void 0:e.open)||(a==null?void 0:a.open)||(s.preventDefault(),o&&(o.value=""),(r=e==null?void 0:e.showModal)==null||r.call(e),o==null||o.focus(),T(""))}).on("?","open shortcuts modal",()=>{var s;(e==null?void 0:e.open)||(a==null?void 0:a.open)||(s=a==null?void 0:a.showModal)==null||s.call(a)});let x=document.querySelector(".js-jumpToInput");x&&x.addEventListener("click",()=>{var s;o&&(o.value=""),T(""),!((e==null?void 0:e.open)||(a==null?void 0:a.open))&&((s=e==null?void 0:e.showModal)==null||s.call(e),o==null||o.focus())}),(q=document.querySelector(".js-openShortcuts"))==null||q.addEventListener("click",()=>{var s;(s=a==null?void 0:a.showModal)==null||s.call(a)})}for(let e of document.querySelectorAll(".js-clipboard"))new S(e);for(let e of document.querySelectorAll(".js-modal"))new k(e);for(let e of document.querySelectorAll(".js-tooltip"))new M(e);for(let e of document.querySelectorAll(".js-selectNav"))new H(e);for(let e of document.querySelectorAll(".js-carousel"))new y(e);I();R();window.addEventListener("load",()=>{J()});g.on("/","focus search",e=>{let t=Array.from(document.querySelectorAll(".js-searchFocus")).pop();t&&!window.navigator.userAgent.includes("Firefox")&&(e.preventDefault(),t.focus())});g.on("y","set canonical url",()=>{var t;let e=(t=document.querySelector(".js-canonicalURLPath"))==null?void 0:t.dataset.canonicalUrlPath;if(e&&e!==""){let n=window.location.hash;n&&(e+=n),window.history.replaceState(null,"",e)}});(function(){L({"gtm.start":new Date().getTime(),event:"gtm.js"})})();function N(){let e=new URLSearchParams(window.location.search),t=e.get("utm_source");if(t!=="gopls"&&t!=="godoc"&&t!=="pkggodev")return;let n=new URL(window.location.href);e.delete("utm_source"),n.search=e.toString(),window.history.replaceState(null,"",n.toString())}var U;((U=document.querySelector(".js-gtmID"))==null?void 0:U.dataset.gtmid)&&window.dataLayer?_(function(){N()}):N();for(let e of document.querySelectorAll(".js-toggleTheme"))e.addEventListener("click",()=>{P()});function P(){let e="dark",t=document.documentElement.getAttribute("data-theme");t==="dark"?e="light":t==="light"&&(e="auto");let n="";location.hostname.endsWith("go.dev")&&(n="domain=.go.dev;"),document.documentElement.setAttribute("data-theme",e),document.cookie=`prefers-color-scheme=${e};${n}path=/;max-age=31536000;`}
 /*!
  * @license
  * Copyright 2019-2020 The Go Authors. All rights reserved.
diff --git a/static/frontend/frontend.js.map b/static/frontend/frontend.js.map
index c161754..c911be5 100644
--- a/static/frontend/frontend.js.map
+++ b/static/frontend/frontend.js.map
@@ -1,7 +1,7 @@
 {
   "version": 3,
   "sources": ["../shared/header/header.ts", "../shared/carousel/carousel.ts", "../shared/clipboard/clipboard.ts", "../shared/tooltip/tooltip.ts", "../shared/outline/select.ts", "../shared/modal/modal.ts", "../shared/analytics/analytics.ts", "../shared/keyboard/keyboard.ts", "../shared/jump/jump.ts", "frontend.ts"],
-  "sourcesContent": ["/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nexport function registerHeaderListeners(): void {\n  const header = document.querySelector('.js-header');\n  const menuButtons = document.querySelectorAll('.js-headerMenuButton');\n  menuButtons.forEach(button => {\n    button.addEventListener('click', e => {\n      e.preventDefault();\n      header?.classList.toggle('is-active');\n      button.setAttribute('aria-expanded', String(header?.classList.contains('is-active')));\n    });\n  });\n\n  const scrim = document.querySelector('.js-scrim');\n  scrim?.addEventListener('click', e => {\n    e.preventDefault();\n    header?.classList.remove('is-active');\n    menuButtons.forEach(button => {\n      button.setAttribute('aria-expanded', String(header?.classList.contains('is-active')));\n    });\n  });\n}\n\nexport function registerSearchFormListeners(): void {\n  const searchForm = document.querySelector('.js-searchForm');\n  const expandSearch = document.querySelector('.js-expandSearch');\n  const input = searchForm?.querySelector('input');\n  const headerLogo = document.querySelector('.js-headerLogo');\n  const menuButton = document.querySelector('.js-headerMenuButton');\n  expandSearch?.addEventListener('click', () => {\n    searchForm?.classList.add('go-SearchForm--expanded');\n    headerLogo?.classList.add('go-Header-logo--hidden');\n    menuButton?.classList.add('go-Header-navOpen--hidden');\n    input?.focus();\n  });\n  document?.addEventListener('click', e => {\n    if (!searchForm?.contains(e.target as Node)) {\n      searchForm?.classList.remove('go-SearchForm--expanded');\n      headerLogo?.classList.remove('go-Header-logo--hidden');\n      menuButton?.classList.remove('go-Header-navOpen--hidden');\n    }\n  });\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * Carousel Controller adds event listeners, accessibility enhancements, and\n * control elements to a carousel component.\n */\nexport class CarouselController {\n  /**\n   * slides is a collection of slides in the carousel.\n   */\n  private slides: HTMLLIElement[];\n  /**\n   * dots is a collection of dot navigation controls, added to the carousel\n   * by this controller.\n   */\n  private dots: HTMLElement[];\n  /**\n   * liveRegion is a visually hidden element that notifies assitive devices\n   * of visual changes to the carousel. They are added to the carousel by\n   * this controller.\n   */\n  private liveRegion: HTMLElement;\n  /**\n   * activeIndex is the 0-index of the currently active slide.\n   */\n  private activeIndex: number;\n\n  constructor(private el: HTMLElement) {\n    this.slides = Array.from(el.querySelectorAll('.go-Carousel-slide'));\n    this.dots = [];\n    this.liveRegion = document.createElement('div');\n    this.activeIndex = Number(el.getAttribute('data-slide-index') ?? 0);\n\n    this.initSlides();\n    this.initArrows();\n    this.initDots();\n    this.initLiveRegion();\n  }\n\n  private initSlides() {\n    for (const [i, v] of this.slides.entries()) {\n      if (i === this.activeIndex) continue;\n      v.setAttribute('aria-hidden', 'true');\n    }\n  }\n\n  private initArrows() {\n    const arrows = document.createElement('ul');\n    arrows.classList.add('go-Carousel-arrows');\n    arrows.innerHTML = `\n      <li>\n        <button class=\"go-Carousel-prevSlide\" aria-label=\"Go to previous slide\">\n          <img class=\"go-Icon\" height=\"24\" width=\"24\" src=\"/static/shared/icon/arrow_left_gm_grey_24dp.svg\" alt=\"\">\n        </button>\n      </li>\n      <li>\n        <button class=\"go-Carousel-nextSlide\" aria-label=\"Go to next slide\">\n          <img class=\"go-Icon\" height=\"24\" width=\"24\" src=\"/static/shared/icon/arrow_right_gm_grey_24dp.svg\" alt=\"\">\n        </button>\n      </li>\n    `;\n    arrows\n      .querySelector('.go-Carousel-prevSlide')\n      ?.addEventListener('click', () => this.setActive(this.activeIndex - 1));\n    arrows\n      .querySelector('.go-Carousel-nextSlide')\n      ?.addEventListener('click', () => this.setActive(this.activeIndex + 1));\n    this.el.append(arrows);\n  }\n\n  private initDots() {\n    const dots = document.createElement('ul');\n    dots.classList.add('go-Carousel-dots');\n    for (let i = 0; i < this.slides.length; i++) {\n      const li = document.createElement('li');\n      const button = document.createElement('button');\n      button.classList.add('go-Carousel-dot');\n      if (i === this.activeIndex) {\n        button.classList.add('go-Carousel-dot--active');\n      }\n      button.innerHTML = `<span class=\"go-Carousel-obscured\">Slide ${i + 1}</span>`;\n      button.addEventListener('click', () => this.setActive(i));\n      li.append(button);\n      dots.append(li);\n      this.dots.push(button);\n    }\n    this.el.append(dots);\n  }\n\n  private initLiveRegion() {\n    this.liveRegion.setAttribute('aria-live', 'polite');\n    this.liveRegion.setAttribute('aria-atomic', 'true');\n    this.liveRegion.setAttribute('class', 'go-Carousel-obscured');\n    this.liveRegion.textContent = `Slide ${this.activeIndex + 1} of ${this.slides.length}`;\n    this.el.appendChild(this.liveRegion);\n  }\n\n  private setActive = (index: number) => {\n    this.activeIndex = (index + this.slides.length) % this.slides.length;\n    this.el.setAttribute('data-slide-index', String(this.activeIndex));\n    for (const d of this.dots) {\n      d.classList.remove('go-Carousel-dot--active');\n    }\n    this.dots[this.activeIndex].classList.add('go-Carousel-dot--active');\n    for (const s of this.slides) {\n      s.setAttribute('aria-hidden', 'true');\n    }\n    this.slides[this.activeIndex].removeAttribute('aria-hidden');\n    this.liveRegion.textContent = 'Slide ' + (this.activeIndex + 1) + ' of ' + this.slides.length;\n  };\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This class decorates an element to copy arbitrary data attached via a data-\n * attribute to the clipboard.\n */\nexport class ClipboardController {\n  /**\n   * The data to be copied to the clipboard.\n   */\n  private data: string;\n\n  /**\n   * @param el The element that will trigger copying text to the clipboard. The text is\n   * expected to be within its data-to-copy attribute.\n   */\n  constructor(private el: HTMLButtonElement) {\n    this.data = el.dataset['toCopy'] ?? el.innerText;\n    // if data-to-copy is empty and the button is part of an input group\n    // capture the value of the input.\n    if (!this.data && el.parentElement?.classList.contains('go-InputGroup')) {\n      this.data = (this.data || el.parentElement?.querySelector('input')?.value) ?? '';\n    }\n    el.addEventListener('click', e => this.handleCopyClick(e));\n  }\n\n  /**\n   * Handles when the primary element is clicked.\n   */\n  handleCopyClick(e: MouseEvent): void {\n    e.preventDefault();\n    const TOOLTIP_SHOW_DURATION_MS = 1000;\n\n    // This API is not available on iOS.\n    if (!navigator.clipboard) {\n      this.showTooltipText('Unable to copy', TOOLTIP_SHOW_DURATION_MS);\n      return;\n    }\n    navigator.clipboard\n      .writeText(this.data)\n      .then(() => {\n        this.showTooltipText('Copied!', TOOLTIP_SHOW_DURATION_MS);\n      })\n      .catch(() => {\n        this.showTooltipText('Unable to copy', TOOLTIP_SHOW_DURATION_MS);\n      });\n  }\n\n  /**\n   * Shows the given text in a tooltip for a specified amount of time, in milliseconds.\n   */\n  showTooltipText(text: string, durationMs: number): void {\n    this.el.setAttribute('data-tooltip', text);\n    setTimeout(() => this.el.setAttribute('data-tooltip', ''), durationMs);\n  }\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * ToolTipController handles closing tooltips on external clicks.\n */\nexport class ToolTipController {\n  constructor(private el: HTMLDetailsElement) {\n    document.addEventListener('click', e => {\n      const insideTooltip = this.el.contains(e.target as Element);\n      if (!insideTooltip) {\n        this.el.removeAttribute('open');\n      }\n    });\n  }\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { TreeNavController } from './tree.js';\n\nexport class SelectNavController {\n  constructor(private el: Element) {\n    this.el.addEventListener('change', e => {\n      const target = e.target as HTMLSelectElement;\n      let href = target.value;\n      if (!target.value.startsWith('/')) {\n        href = '/' + href;\n      }\n      window.location.href = href;\n    });\n  }\n}\n\nexport function makeSelectNav(tree: TreeNavController): HTMLLabelElement {\n  const label = document.createElement('label');\n  label.classList.add('go-Label');\n  label.setAttribute('aria-label', 'Menu');\n  const select = document.createElement('select');\n  select.classList.add('go-Select', 'js-selectNav');\n  label.appendChild(select);\n  const outline = document.createElement('optgroup');\n  outline.label = 'Outline';\n  select.appendChild(outline);\n  const groupMap: Record<string, HTMLOptGroupElement> = {};\n  let group: HTMLOptGroupElement;\n  for (const t of tree.treeitems) {\n    if (Number(t.depth) > 4) continue;\n    if (t.groupTreeitem) {\n      group = groupMap[t.groupTreeitem.label];\n      if (!group) {\n        group = groupMap[t.groupTreeitem.label] = document.createElement('optgroup');\n        group.label = t.groupTreeitem.label;\n        select.appendChild(group);\n      }\n    } else {\n      group = outline;\n    }\n    const o = document.createElement('option');\n    o.label = t.label;\n    o.textContent = t.label;\n    o.value = (t.el as HTMLAnchorElement).href.replace(window.location.origin, '').replace('/', '');\n    group.appendChild(o);\n  }\n  tree.addObserver(t => {\n    const hash = (t.el as HTMLAnchorElement).hash;\n    const value = select.querySelector<HTMLOptionElement>(`[value$=\"${hash}\"]`)?.value;\n    if (value) {\n      select.value = value;\n    }\n  }, 50);\n  return label;\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\ninterface Window {\n  dialogPolyfill?: {\n    registerDialog: (el: HTMLDialogElement) => void;\n  };\n}\n\ndeclare const window: Window;\n\n/**\n * ModalController registers a dialog element with the polyfill if\n * necessary for the current browser, add adds event listeners to\n * close and open modals.\n */\nexport class ModalController {\n  constructor(private el: HTMLDialogElement) {\n    if (window.dialogPolyfill) {\n      window.dialogPolyfill.registerDialog(el);\n    }\n    this.init();\n  }\n\n  init() {\n    const button = document.querySelector<HTMLButtonElement>(`[aria-controls=\"${this.el.id}\"]`);\n    if (button) {\n      button.addEventListener('click', () => {\n        if (this.el.showModal) {\n          this.el.showModal();\n        } else {\n          this.el.setAttribute('opened', 'true');\n        }\n        this.el.querySelector('input')?.focus();\n      });\n    }\n    for (const btn of this.el.querySelectorAll<HTMLButtonElement>('[data-modal-close]')) {\n      btn.addEventListener('click', () => {\n        if (this.el.close) {\n          this.el.close();\n        } else {\n          this.el.removeAttribute('opened');\n        }\n      });\n    }\n  }\n}\n", "interface TagManagerEvent {\n  /**\n   * event is the name of the event, used to filter events in\n   * Google Analytics.\n   */\n  event: string;\n\n  /**\n   * event_category is a name that you supply as a way to group objects\n   * that to analyze. Typically, you will use the same category name\n   * multiple times over related UI elements (buttons, links, etc).\n   */\n  event_category?: string;\n\n  /**\n   * event_action is used to name the type of event or interaction you\n   * want to measure for a particular web object. For example, with a\n   * single \"form\" category, you can analyze a number of specific events\n   * with this parameter, such as: form entered, form submitted.\n   */\n  event_action?: string;\n\n  /**\n   * event_label provide additional information for events that you want\n   * to analyze, such as the text label of a link.\n   */\n  event_label?: string;\n\n  /**\n   * gtm.start is used to initialize Google Tag Manager.\n   */\n  'gtm.start'?: number;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ndeclare global {\n  interface Window {\n    dataLayer?: (TagManagerEvent | VoidFunction)[];\n    ga?: unknown;\n  }\n}\n\n/**\n * track sends events to Google Tag Manager.\n */\nexport function track(\n  event: string | TagManagerEvent,\n  category?: string,\n  action?: string,\n  label?: string\n): void {\n  window.dataLayer ??= [];\n  if (typeof event === 'string') {\n    window.dataLayer.push({\n      event,\n      event_category: category,\n      event_action: action,\n      event_label: label,\n    });\n  } else {\n    window.dataLayer.push(event);\n  }\n}\n\n/**\n * func adds functions to run sequentionally after\n * Google Tag Manager is ready.\n */\nexport function func(fn: () => void): void {\n  window.dataLayer ??= [];\n  window.dataLayer.push(fn);\n}\n", "/*!\n * @license\n * Copyright 2019-2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { track } from '../analytics/analytics';\n\n/**\n * Options are keyhandler callback options.\n */\ninterface Options {\n  /**\n   * target is the element the key event should filter on. The\n   * default target is the document.\n   */\n  target?: Element;\n\n  /**\n   * withMeta specifies if the event callback should fire when\n   * the key is pressed with a meta key (ctrl, alt, etc). By\n   * default meta keypresses are ignored.\n   */\n  withMeta?: boolean;\n}\n\n/**\n * KeyHandler is the config for a keyboard event callback.\n */\ninterface KeyHandler extends Options {\n  description: string;\n  callback: (e: KeyboardEvent) => void;\n}\n\n/**\n * KeyboardController controls event callbacks for sitewide\n * keyboard events. Multiple callbacks can be registered for\n * a single key and by default the controller ignores events\n * for text input targets.\n */\nclass KeyboardController {\n  handlers: Record<string, Set<KeyHandler>>;\n\n  constructor() {\n    this.handlers = {};\n    document.addEventListener('keydown', e => this.handleKeyPress(e));\n  }\n\n  /**\n   * on registers keyboard event callbacks.\n   * @param key the key to register.\n   * @param description name of the event.\n   * @param callback event callback.\n   * @param options set target and withMeta options to override the default behaviors.\n   */\n  on(key: string, description: string, callback: (e: KeyboardEvent) => void, options?: Options) {\n    this.handlers[key] ??= new Set();\n    this.handlers[key].add({ description, callback, ...options });\n    return this;\n  }\n\n  private handleKeyPress(e: KeyboardEvent) {\n    for (const handler of this.handlers[e.key.toLowerCase()] ?? new Set()) {\n      if (handler.target && handler.target !== e.target) {\n        return;\n      }\n      const t = e.target as HTMLElement | null;\n      if (\n        !handler.target &&\n        (t?.tagName === 'INPUT' || t?.tagName === 'SELECT' || t?.tagName === 'TEXTAREA')\n      ) {\n        return;\n      }\n      if (t?.isContentEditable) {\n        return;\n      }\n      if (\n        (handler.withMeta && !(e.ctrlKey || e.metaKey)) ||\n        (!handler.withMeta && (e.ctrlKey || e.metaKey))\n      ) {\n        return;\n      }\n      track('keypress', 'hotkeys', `${e.key} pressed`, handler.description);\n      handler.callback(e);\n    }\n  }\n}\n\nexport const keyboard = new KeyboardController();\n", "/*!\n * @license\n * Copyright 2019-2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n// This file implements the behavior of the \"jump to symbol\" dialog for Go\n// package documentation, as well as the simple dialog that displays keyboard\n// shortcuts.\n\n// The DOM for the dialogs is at the bottom of static/frontend/unit/main/_modals.tmpl.\n// The CSS is in static/frontend/unit/main/_modals.css.\n\n// The dialog is activated by pressing the 'f' key. It presents a list\n// (#JumpDialog-list) of all Go symbols displayed in the documentation.\n// Entering text in the dialog's text box (#JumpDialog-filter) restricts the\n// list to symbols containing the text. Clicking on an symbol jumps to\n// its documentation.\n\n// This code is based on\n// https://go.googlesource.com/gddo/+/refs/heads/master/gddo-server/assets/site.js.\n// It was modified to remove the dependence on jquery and bootstrap.\n\nimport { keyboard } from '../keyboard/keyboard';\n\nexport function initModals(): void {\n  const jumpDialog = document.querySelector<HTMLDialogElement>('.JumpDialog');\n  const jumpBody = jumpDialog?.querySelector<HTMLDivElement>('.JumpDialog-body');\n  const jumpList = jumpDialog?.querySelector<HTMLDivElement>('.JumpDialog-list');\n  const jumpFilter = jumpDialog?.querySelector<HTMLInputElement>('.JumpDialog-input');\n  const doc = document.querySelector<HTMLDivElement>('.js-documentation');\n\n  interface JumpListItem {\n    link: HTMLAnchorElement;\n    name: string;\n    kind: string;\n    lower: string;\n  }\n\n  let jumpListItems: JumpListItem[] | undefined; // All the symbols in the doc; computed only once.\n\n  // collectJumpListItems returns a list of items, one for each symbol in the\n  // documentation on the current page.\n  //\n  // It uses the data-kind attribute generated in the documentation HTML to find\n  // the symbols and their id attributes.\n  //\n  // If there are no data-kind attributes, then we have older doc; fall back to\n  // a less precise method.\n  function collectJumpListItems() {\n    const items = [];\n    if (!doc) return;\n    for (const el of doc.querySelectorAll('[data-kind]')) {\n      items.push(newJumpListItem(el));\n    }\n\n    // Clicking on any of the links closes the dialog.\n    for (const item of items) {\n      item.link.addEventListener('click', function () {\n        jumpDialog?.close();\n      });\n    }\n    // Sort case-insensitively by symbol name.\n    items.sort(function (a, b) {\n      return a.lower.localeCompare(b.lower);\n    });\n    return items;\n  }\n\n  // newJumpListItem creates a new item for the DOM element el.\n  // An item is an object with:\n  // - name: the element's id (which is the symbol name)\n  // - kind: the element's kind (function, variable, etc.),\n  // - link: a link ('a' tag) to the element\n  // - lower: the name in lower case, just for sorting\n  function newJumpListItem(el: Element): JumpListItem {\n    const a = document.createElement('a');\n    const name = el.getAttribute('id');\n    a.setAttribute('href', '#' + name);\n    a.setAttribute('tabindex', '-1');\n    a.setAttribute('data-gtmc', 'jump to link');\n    const kind = el.getAttribute('data-kind');\n    return {\n      link: a,\n      name: name ?? '',\n      kind: kind ?? '',\n      lower: name?.toLowerCase() ?? '', // for sorting\n    };\n  }\n\n  let lastFilterValue: string; // The last contents of the filter text box.\n  let activeJumpItem = -1; // The index of the currently active item in the list.\n\n  // updateJumpList sets the elements of the dialog list to\n  // everything whose name contains filter.\n  function updateJumpList(filter: string) {\n    lastFilterValue = filter;\n    if (!jumpListItems) {\n      jumpListItems = collectJumpListItems();\n    }\n    setActiveJumpItem(-1);\n\n    // Remove all children from list.\n    while (jumpList?.firstChild) {\n      jumpList.firstChild.remove();\n    }\n\n    if (filter) {\n      // A filter is set. We treat the filter as a substring that can appear in\n      // an item name (case insensitive), and find the following matches - in\n      // order of priority:\n      //\n      // 1. Exact matches (the filter matches the item's name exactly)\n      // 2. Prefix matches (the item's name starts with filter)\n      // 3. Infix matches (the filter is a substring of the item's name)\n      const filterLowerCase = filter.toLowerCase();\n\n      const exactMatches = [];\n      const prefixMatches = [];\n      const infixMatches = [];\n\n      // makeLinkHtml creates the link name HTML for a list item. item is the DOM\n      // item. item.name.substr(boldStart, boldEnd) will be bolded.\n      const makeLinkHtml = (item: JumpListItem, boldStart: number, boldEnd: number) => {\n        return (\n          item.name.substring(0, boldStart) +\n          '<b>' +\n          item.name.substring(boldStart, boldEnd) +\n          '</b>' +\n          item.name.substring(boldEnd)\n        );\n      };\n\n      for (const item of jumpListItems ?? []) {\n        const nameLowerCase = item.name.toLowerCase();\n\n        if (nameLowerCase === filterLowerCase) {\n          item.link.innerHTML = makeLinkHtml(item, 0, item.name.length);\n          exactMatches.push(item);\n        } else if (nameLowerCase.startsWith(filterLowerCase)) {\n          item.link.innerHTML = makeLinkHtml(item, 0, filter.length);\n          prefixMatches.push(item);\n        } else {\n          const index = nameLowerCase.indexOf(filterLowerCase);\n          if (index > -1) {\n            item.link.innerHTML = makeLinkHtml(item, index, index + filter.length);\n            infixMatches.push(item);\n          }\n        }\n      }\n\n      for (const item of exactMatches.concat(prefixMatches).concat(infixMatches)) {\n        jumpList?.appendChild(item.link);\n      }\n    } else {\n      if (!jumpListItems || jumpListItems.length === 0) {\n        const msg = document.createElement('i');\n        msg.innerHTML = 'There are no symbols on this page.';\n        jumpList?.appendChild(msg);\n      }\n      // No filter set; display all items in their existing order.\n      for (const item of jumpListItems ?? []) {\n        item.link.innerHTML = item.name + ' <i>' + item.kind + '</i>';\n        jumpList?.appendChild(item.link);\n      }\n    }\n\n    if (jumpBody) {\n      jumpBody.scrollTop = 0;\n    }\n    if (jumpListItems?.length && jumpList && jumpList.children.length > 0) {\n      setActiveJumpItem(0);\n    }\n  }\n\n  // Set the active jump item to n.\n  function setActiveJumpItem(n: number) {\n    const cs = jumpList?.children as HTMLCollectionOf<HTMLElement> | null | undefined;\n    if (!cs || !jumpBody) {\n      return;\n    }\n    if (activeJumpItem >= 0) {\n      cs[activeJumpItem].classList.remove('JumpDialog-active');\n    }\n    if (n >= cs.length) {\n      n = cs.length - 1;\n    }\n    if (n >= 0) {\n      cs[n].classList.add('JumpDialog-active');\n\n      // Scroll so the active item is visible.\n      // For some reason cs[n].scrollIntoView() doesn't behave as I'd expect:\n      // it moves the entire dialog box in the viewport.\n\n      // Get the top and bottom of the active item relative to jumpBody.\n      const activeTop = cs[n].offsetTop - cs[0].offsetTop;\n      const activeBottom = activeTop + cs[n].clientHeight;\n      if (activeTop < jumpBody.scrollTop) {\n        // Off the top; scroll up.\n        jumpBody.scrollTop = activeTop;\n      } else if (activeBottom > jumpBody.scrollTop + jumpBody.clientHeight) {\n        // Off the bottom; scroll down.\n        jumpBody.scrollTop = activeBottom - jumpBody.clientHeight;\n      }\n    }\n    activeJumpItem = n;\n  }\n\n  // Increment the activeJumpItem by delta.\n  function incActiveJumpItem(delta: number) {\n    if (activeJumpItem < 0) {\n      return;\n    }\n    let n = activeJumpItem + delta;\n    if (n < 0) {\n      n = 0;\n    }\n    setActiveJumpItem(n);\n  }\n\n  // Pressing a key in the filter updates the list (if the filter actually changed).\n  jumpFilter?.addEventListener('keyup', function () {\n    if (jumpFilter.value.toUpperCase() != lastFilterValue.toUpperCase()) {\n      updateJumpList(jumpFilter.value);\n    }\n  });\n\n  // Pressing enter in the filter selects the first element in the list.\n  jumpFilter?.addEventListener('keydown', function (event) {\n    const upArrow = 38;\n    const downArrow = 40;\n    const enterKey = 13;\n    switch (event.which) {\n      case upArrow:\n        incActiveJumpItem(-1);\n        event.preventDefault();\n        break;\n      case downArrow:\n        incActiveJumpItem(1);\n        event.preventDefault();\n        break;\n      case enterKey:\n        if (activeJumpItem >= 0) {\n          if (jumpList) {\n            (jumpList.children[activeJumpItem] as HTMLElement).click();\n            event.preventDefault();\n          }\n        }\n        break;\n    }\n  });\n\n  const shortcutsDialog = document.querySelector<HTMLDialogElement>('.ShortcutsDialog');\n\n  // - Pressing 'f' or 'F' opens the jump-to-symbol dialog.\n  // - Pressing '?' opens up the shortcut dialog.\n  // Ignore a keypress if a dialog is already open, or if it is pressed on a\n  // component that wants to consume it.\n  keyboard\n    .on('f', 'open jump to modal', e => {\n      if (jumpDialog?.open || shortcutsDialog?.open) {\n        return;\n      }\n      e.preventDefault();\n      if (jumpFilter) {\n        jumpFilter.value = '';\n      }\n      jumpDialog?.showModal?.();\n      jumpFilter?.focus();\n      updateJumpList('');\n    })\n    .on('?', 'open shortcuts modal', () => {\n      if (jumpDialog?.open || shortcutsDialog?.open) {\n        return;\n      }\n      shortcutsDialog?.showModal?.();\n    });\n\n  const jumpOutlineInput = document.querySelector('.js-jumpToInput');\n  if (jumpOutlineInput) {\n    jumpOutlineInput.addEventListener('click', () => {\n      if (jumpFilter) {\n        jumpFilter.value = '';\n      }\n      updateJumpList('');\n      if (jumpDialog?.open || shortcutsDialog?.open) {\n        return;\n      }\n      jumpDialog?.showModal?.();\n      jumpFilter?.focus();\n    });\n  }\n\n  document.querySelector('.js-openShortcuts')?.addEventListener('click', () => {\n    shortcutsDialog?.showModal?.();\n  });\n}\n", "/**\n * @license\n * Copyright 2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { registerHeaderListeners, registerSearchFormListeners } from 'static/shared/header/header';\nimport { CarouselController } from 'static/shared/carousel/carousel';\nimport { ClipboardController } from 'static/shared/clipboard/clipboard';\nimport { ToolTipController } from 'static/shared/tooltip/tooltip';\nimport { SelectNavController } from 'static/shared/outline/select';\nimport { ModalController } from 'static/shared/modal/modal';\nimport { initModals } from 'static/shared/jump/jump';\n\nimport { keyboard } from 'static/shared/keyboard/keyboard';\nimport * as analytics from 'static/shared/analytics/analytics';\n\nfor (const el of document.querySelectorAll<HTMLButtonElement>('.js-clipboard')) {\n  new ClipboardController(el);\n}\n\nfor (const el of document.querySelectorAll<HTMLDialogElement>('.js-modal')) {\n  new ModalController(el);\n}\n\nfor (const t of document.querySelectorAll<HTMLDetailsElement>('.js-tooltip')) {\n  new ToolTipController(t);\n}\n\nfor (const el of document.querySelectorAll<HTMLSelectElement>('.js-selectNav')) {\n  new SelectNavController(el);\n}\n\nfor (const el of document.querySelectorAll<HTMLSelectElement>('.js-carousel')) {\n  new CarouselController(el);\n}\n\nregisterHeaderListeners();\nregisterSearchFormListeners();\nwindow.addEventListener('load', () => {\n  initModals();\n});\n\n// Pressing '/' focuses the search box\nkeyboard.on('/', 'focus search', e => {\n  const searchInput = Array.from(\n    document.querySelectorAll<HTMLInputElement>('.js-searchFocus')\n  ).pop();\n  // Favoring the Firefox quick find feature over search input\n  // focus. See: https://github.com/golang/go/issues/41093.\n  if (searchInput && !window.navigator.userAgent.includes('Firefox')) {\n    e.preventDefault();\n    searchInput.focus();\n  }\n});\n\n// Pressing 'y' changes the browser URL to the canonical URL\n// without triggering a reload.\nkeyboard.on('y', 'set canonical url', () => {\n  let canonicalURLPath = document.querySelector<HTMLDivElement>('.js-canonicalURLPath')?.dataset[\n    'canonicalUrlPath'\n  ];\n  if (canonicalURLPath && canonicalURLPath !== '') {\n    const fragment = window.location.hash;\n    if (fragment) {\n      canonicalURLPath += fragment;\n    }\n    window.history.replaceState(null, '', canonicalURLPath);\n  }\n});\n\n/**\n * setupGoogleTagManager intializes Google Tag Manager.\n */\n(function setupGoogleTagManager() {\n  analytics.track({\n    'gtm.start': new Date().getTime(),\n    event: 'gtm.js',\n  });\n})();\n\n/**\n * removeUTMSource removes the utm_source GET parameter if present.\n * This is done using JavaScript, so that the utm_source is still\n * captured by Google Analytics.\n */\nfunction removeUTMSource() {\n  const urlParams = new URLSearchParams(window.location.search);\n  const utmSource = urlParams.get('utm_source');\n  if (utmSource !== 'gopls' && utmSource !== 'godoc' && utmSource !== 'pkggodev') {\n    return;\n  }\n\n  /** Strip the utm_source query parameter and replace the URL. **/\n  const newURL = new URL(window.location.href);\n  urlParams.delete('utm_source');\n  newURL.search = urlParams.toString();\n  window.history.replaceState(null, '', newURL.toString());\n}\n\nif (document.querySelector<HTMLElement>('.js-gtmID')?.dataset.gtmid && window.dataLayer) {\n  analytics.func(function () {\n    removeUTMSource();\n  });\n} else {\n  removeUTMSource();\n}\n\nfor (const el of document.querySelectorAll('.js-toggleTheme')) {\n  el.addEventListener('click', () => {\n    toggleTheme();\n  });\n}\n\n/**\n * toggleTheme switches the preferred color scheme between auto, light, and dark.\n */\nfunction toggleTheme() {\n  let nextTheme = 'dark';\n  const theme = document.documentElement.getAttribute('data-theme');\n  if (theme === 'dark') {\n    nextTheme = 'light';\n  } else if (theme === 'light') {\n    nextTheme = 'auto';\n  }\n  let domain = 'domain=.go.dev;';\n  if (location.hostname === 'localhost') {\n    domain = '';\n  }\n  document.documentElement.setAttribute('data-theme', nextTheme);\n  document.cookie = `prefers-color-scheme=${nextTheme};${domain}path=/;max-age=31536000;`;\n}\n"],
-  "mappings": "AAAA,AAOO,YAAyC,CAC9C,GAAM,GAAS,SAAS,cAAc,cAChC,EAAc,SAAS,iBAAiB,wBAC9C,EAAY,QAAQ,GAAU,CAC5B,EAAO,iBAAiB,QAAS,GAAK,CACpC,EAAE,iBACF,WAAQ,UAAU,OAAO,aACzB,EAAO,aAAa,gBAAiB,OAAO,iBAAQ,UAAU,SAAS,mBAI3E,GAAM,GAAQ,SAAS,cAAc,aACrC,WAAO,iBAAiB,QAAS,GAAK,CACpC,EAAE,iBACF,WAAQ,UAAU,OAAO,aACzB,EAAY,QAAQ,GAAU,CAC5B,EAAO,aAAa,gBAAiB,OAAO,iBAAQ,UAAU,SAAS,mBAKtE,YAA6C,CAClD,GAAM,GAAa,SAAS,cAAc,kBACpC,EAAe,SAAS,cAAc,oBACtC,EAAQ,iBAAY,cAAc,SAClC,EAAa,SAAS,cAAc,kBACpC,EAAa,SAAS,cAAc,wBAC1C,WAAc,iBAAiB,QAAS,IAAM,CAC5C,WAAY,UAAU,IAAI,2BAC1B,WAAY,UAAU,IAAI,0BAC1B,WAAY,UAAU,IAAI,6BAC1B,WAAO,UAET,yBAAU,iBAAiB,QAAS,GAAK,CACvC,AAAK,kBAAY,SAAS,EAAE,UAC1B,YAAY,UAAU,OAAO,2BAC7B,WAAY,UAAU,OAAO,0BAC7B,WAAY,UAAU,OAAO,gCC5CnC,AAWO,WAAyB,CAqB9B,YAAoB,EAAiB,CAAjB,UAsEZ,eAAY,AAAC,GAAkB,CACrC,KAAK,YAAe,GAAQ,KAAK,OAAO,QAAU,KAAK,OAAO,OAC9D,KAAK,GAAG,aAAa,mBAAoB,OAAO,KAAK,cACrD,OAAW,KAAK,MAAK,KACnB,EAAE,UAAU,OAAO,2BAErB,KAAK,KAAK,KAAK,aAAa,UAAU,IAAI,2BAC1C,OAAW,KAAK,MAAK,OACnB,EAAE,aAAa,cAAe,QAEhC,KAAK,OAAO,KAAK,aAAa,gBAAgB,eAC9C,KAAK,WAAW,YAAc,SAAY,MAAK,YAAc,GAAK,OAAS,KAAK,OAAO,QAjH3F,MAiCI,KAAK,OAAS,MAAM,KAAK,EAAG,iBAAiB,uBAC7C,KAAK,KAAO,GACZ,KAAK,WAAa,SAAS,cAAc,OACzC,KAAK,YAAc,OAAO,KAAG,aAAa,sBAAhB,OAAuC,GAEjE,KAAK,aACL,KAAK,aACL,KAAK,WACL,KAAK,iBAGC,YAAa,CACnB,OAAW,CAAC,EAAG,IAAM,MAAK,OAAO,UAC/B,AAAI,IAAM,KAAK,aACf,EAAE,aAAa,cAAe,QAI1B,YAAa,CAnDvB,QAoDI,GAAM,GAAS,SAAS,cAAc,MACtC,EAAO,UAAU,IAAI,sBACrB,EAAO,UAAY;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,MAYnB,KACG,cAAc,4BADjB,QAEI,iBAAiB,QAAS,IAAM,KAAK,UAAU,KAAK,YAAc,IACtE,KACG,cAAc,4BADjB,QAEI,iBAAiB,QAAS,IAAM,KAAK,UAAU,KAAK,YAAc,IACtE,KAAK,GAAG,OAAO,GAGT,UAAW,CACjB,GAAM,GAAO,SAAS,cAAc,MACpC,EAAK,UAAU,IAAI,oBACnB,OAAS,GAAI,EAAG,EAAI,KAAK,OAAO,OAAQ,IAAK,CAC3C,GAAM,GAAK,SAAS,cAAc,MAC5B,EAAS,SAAS,cAAc,UACtC,EAAO,UAAU,IAAI,mBACjB,IAAM,KAAK,aACb,EAAO,UAAU,IAAI,2BAEvB,EAAO,UAAY,4CAA4C,EAAI,WACnE,EAAO,iBAAiB,QAAS,IAAM,KAAK,UAAU,IACtD,EAAG,OAAO,GACV,EAAK,OAAO,GACZ,KAAK,KAAK,KAAK,GAEjB,KAAK,GAAG,OAAO,GAGT,gBAAiB,CACvB,KAAK,WAAW,aAAa,YAAa,UAC1C,KAAK,WAAW,aAAa,cAAe,QAC5C,KAAK,WAAW,aAAa,QAAS,wBACtC,KAAK,WAAW,YAAc,SAAS,KAAK,YAAc,QAAQ,KAAK,OAAO,SAC9E,KAAK,GAAG,YAAY,KAAK,cCnG7B,AAWO,WAA0B,CAU/B,YAAoB,EAAuB,CAAvB,UArBtB,cAsBI,KAAK,KAAO,KAAG,QAAQ,SAAX,OAAwB,EAAG,UAGnC,CAAC,KAAK,MAAQ,MAAG,gBAAH,cAAkB,UAAU,SAAS,mBACrD,MAAK,KAAQ,QAAK,MAAQ,SAAG,gBAAH,cAAkB,cAAc,WAAhC,cAA0C,SAAvD,OAAiE,IAEhF,EAAG,iBAAiB,QAAS,GAAK,KAAK,gBAAgB,IAMzD,gBAAgB,EAAqB,CACnC,EAAE,iBACF,GAAM,GAA2B,IAGjC,GAAI,CAAC,UAAU,UAAW,CACxB,KAAK,gBAAgB,iBAAkB,GACvC,OAEF,UAAU,UACP,UAAU,KAAK,MACf,KAAK,IAAM,CACV,KAAK,gBAAgB,UAAW,KAEjC,MAAM,IAAM,CACX,KAAK,gBAAgB,iBAAkB,KAO7C,gBAAgB,EAAc,EAA0B,CACtD,KAAK,GAAG,aAAa,eAAgB,GACrC,WAAW,IAAM,KAAK,GAAG,aAAa,eAAgB,IAAK,KC1D/D,AAUO,WAAwB,CAC7B,YAAoB,EAAwB,CAAxB,UAClB,SAAS,iBAAiB,QAAS,GAAK,CAEtC,AAAK,AADiB,KAAK,GAAG,SAAS,EAAE,SAEvC,KAAK,GAAG,gBAAgB,YCfhC,AASO,WAA0B,CAC/B,YAAoB,EAAa,CAAb,UAClB,KAAK,GAAG,iBAAiB,SAAU,GAAK,CACtC,GAAM,GAAS,EAAE,OACb,EAAO,EAAO,MAClB,AAAK,EAAO,MAAM,WAAW,MAC3B,GAAO,IAAM,GAEf,OAAO,SAAS,KAAO,MCjB7B,AAoBO,WAAsB,CAC3B,YAAoB,EAAuB,CAAvB,UAClB,AAAI,OAAO,gBACT,OAAO,eAAe,eAAe,GAEvC,KAAK,OAGP,MAAO,CACL,GAAM,GAAS,SAAS,cAAiC,mBAAmB,KAAK,GAAG,QACpF,AAAI,GACF,EAAO,iBAAiB,QAAS,IAAM,CA/B7C,MAgCQ,AAAI,KAAK,GAAG,UACV,KAAK,GAAG,YAER,KAAK,GAAG,aAAa,SAAU,QAEjC,QAAK,GAAG,cAAc,WAAtB,QAAgC,UAGpC,OAAW,KAAO,MAAK,GAAG,iBAAoC,sBAC5D,EAAI,iBAAiB,QAAS,IAAM,CAClC,AAAI,KAAK,GAAG,MACV,KAAK,GAAG,QAER,KAAK,GAAG,gBAAgB,cCA3B,WACL,EACA,EACA,EACA,EACM,CAlDR,MAmDE,UAAO,YAAP,cAAO,UAAc,IACrB,AAAI,MAAO,IAAU,SACnB,OAAO,UAAU,KAAK,CACpB,QACA,eAAgB,EAChB,aAAc,EACd,YAAa,IAGf,OAAO,UAAU,KAAK,GAQnB,WAAc,EAAsB,CApE3C,MAqEE,UAAO,YAAP,cAAO,UAAc,IACrB,OAAO,UAAU,KAAK,GCtExB,AAyCA,WAAyB,CAGvB,aAAc,CACZ,KAAK,SAAW,GAChB,SAAS,iBAAiB,UAAW,GAAK,KAAK,eAAe,IAUhE,GAAG,EAAa,EAAqB,EAAsC,EAAmB,CAxDhG,QAyDI,iBAAK,UAAL,iBAAuB,GAAI,MAC3B,KAAK,SAAS,GAAK,IAAI,CAAE,cAAa,cAAa,IAC5C,KAGD,eAAe,EAAkB,CA9D3C,MA+DI,OAAW,KAAW,QAAK,SAAS,EAAE,IAAI,iBAApB,OAAsC,GAAI,KAAO,CACrE,GAAI,EAAQ,QAAU,EAAQ,SAAW,EAAE,OACzC,OAEF,GAAM,GAAI,EAAE,OAUZ,GARE,CAAC,EAAQ,QACR,mBAAG,WAAY,SAAW,kBAAG,WAAY,UAAY,kBAAG,WAAY,aAInE,kBAAG,oBAIJ,EAAQ,UAAY,CAAE,GAAE,SAAW,EAAE,UACrC,CAAC,EAAQ,UAAa,GAAE,SAAW,EAAE,SAEtC,OAEF,EAAM,WAAY,UAAW,GAAG,EAAE,cAAe,EAAQ,aACzD,EAAQ,SAAS,MAKV,EAAW,GAAI,GCzF5B,AA0BO,YAA4B,CA1BnC,MA2BE,GAAM,GAAa,SAAS,cAAiC,eACvD,EAAW,iBAAY,cAA8B,oBACrD,EAAW,iBAAY,cAA8B,oBACrD,EAAa,iBAAY,cAAgC,qBACzD,EAAM,SAAS,cAA8B,qBAS/C,EAUJ,YAAgC,CAC9B,GAAM,GAAQ,GACd,GAAI,EAAC,EACL,QAAW,KAAM,GAAI,iBAAiB,eACpC,EAAM,KAAK,EAAgB,IAI7B,OAAW,KAAQ,GACjB,EAAK,KAAK,iBAAiB,QAAS,UAAY,CAC9C,WAAY,UAIhB,SAAM,KAAK,SAAU,EAAG,EAAG,CACzB,MAAO,GAAE,MAAM,cAAc,EAAE,SAE1B,GAST,WAAyB,EAA2B,CA5EtD,MA6EI,GAAM,GAAI,SAAS,cAAc,KAC3B,EAAO,EAAG,aAAa,MAC7B,EAAE,aAAa,OAAQ,IAAM,GAC7B,EAAE,aAAa,WAAY,MAC3B,EAAE,aAAa,YAAa,gBAC5B,GAAM,GAAO,EAAG,aAAa,aAC7B,MAAO,CACL,KAAM,EACN,KAAM,UAAQ,GACd,KAAM,UAAQ,GACd,MAAO,oBAAM,gBAAN,OAAuB,IAIlC,GAAI,GACA,EAAiB,GAIrB,WAAwB,EAAgB,CAQtC,IAPA,EAAkB,EACb,GACH,GAAgB,KAElB,EAAkB,IAGX,iBAAU,YACf,EAAS,WAAW,SAGtB,GAAI,EAAQ,CAQV,GAAM,GAAkB,EAAO,cAEzB,EAAe,GACf,EAAgB,GAChB,EAAe,GAIf,EAAe,CAAC,EAAoB,EAAmB,IAEzD,EAAK,KAAK,UAAU,EAAG,GACvB,MACA,EAAK,KAAK,UAAU,EAAW,GAC/B,OACA,EAAK,KAAK,UAAU,GAIxB,OAAW,KAAQ,WAAiB,GAAI,CACtC,GAAM,GAAgB,EAAK,KAAK,cAEhC,GAAI,IAAkB,EACpB,EAAK,KAAK,UAAY,EAAa,EAAM,EAAG,EAAK,KAAK,QACtD,EAAa,KAAK,WACT,EAAc,WAAW,GAClC,EAAK,KAAK,UAAY,EAAa,EAAM,EAAG,EAAO,QACnD,EAAc,KAAK,OACd,CACL,GAAM,GAAQ,EAAc,QAAQ,GACpC,AAAI,EAAQ,IACV,GAAK,KAAK,UAAY,EAAa,EAAM,EAAO,EAAQ,EAAO,QAC/D,EAAa,KAAK,KAKxB,OAAW,KAAQ,GAAa,OAAO,GAAe,OAAO,GAC3D,WAAU,YAAY,EAAK,UAExB,CACL,GAAI,CAAC,GAAiB,EAAc,SAAW,EAAG,CAChD,GAAM,GAAM,SAAS,cAAc,KACnC,EAAI,UAAY,qCAChB,WAAU,YAAY,GAGxB,OAAW,KAAQ,WAAiB,GAClC,EAAK,KAAK,UAAY,EAAK,KAAO,OAAS,EAAK,KAAO,OACvD,WAAU,YAAY,EAAK,MAI/B,AAAI,GACF,GAAS,UAAY,GAEnB,kBAAe,SAAU,GAAY,EAAS,SAAS,OAAS,GAClE,EAAkB,GAKtB,WAA2B,EAAW,CACpC,GAAM,GAAK,iBAAU,SACrB,GAAI,GAAC,GAAM,CAAC,GASZ,IANI,GAAkB,GACpB,EAAG,GAAgB,UAAU,OAAO,qBAElC,GAAK,EAAG,QACV,GAAI,EAAG,OAAS,GAEd,GAAK,EAAG,CACV,EAAG,GAAG,UAAU,IAAI,qBAOpB,GAAM,GAAY,EAAG,GAAG,UAAY,EAAG,GAAG,UACpC,EAAe,EAAY,EAAG,GAAG,aACvC,AAAI,EAAY,EAAS,UAEvB,EAAS,UAAY,EACZ,EAAe,EAAS,UAAY,EAAS,cAEtD,GAAS,UAAY,EAAe,EAAS,cAGjD,EAAiB,GAInB,WAA2B,EAAe,CACxC,GAAI,EAAiB,EACnB,OAEF,GAAI,GAAI,EAAiB,EACzB,AAAI,EAAI,GACN,GAAI,GAEN,EAAkB,GAIpB,WAAY,iBAAiB,QAAS,UAAY,CAChD,AAAI,EAAW,MAAM,eAAiB,EAAgB,eACpD,EAAe,EAAW,SAK9B,WAAY,iBAAiB,UAAW,SAAU,EAAO,CACvD,GAAM,GAAU,GACV,EAAY,GACZ,EAAW,GACjB,OAAQ,EAAM,WACP,GACH,EAAkB,IAClB,EAAM,iBACN,UACG,GACH,EAAkB,GAClB,EAAM,iBACN,UACG,GACH,AAAI,GAAkB,GAChB,GACD,GAAS,SAAS,GAAgC,QACnD,EAAM,kBAGV,SAIN,GAAM,GAAkB,SAAS,cAAiC,oBAMlE,EACG,GAAG,IAAK,qBAAsB,GAAK,CApQxC,MAqQM,AAAI,kBAAY,OAAQ,kBAAiB,OAGzC,GAAE,iBACE,GACF,GAAW,MAAQ,IAErB,oBAAY,YAAZ,gBACA,WAAY,QACZ,EAAe,OAEhB,GAAG,IAAK,uBAAwB,IAAM,CAhR3C,MAiRM,AAAI,kBAAY,OAAQ,kBAAiB,OAGzC,oBAAiB,YAAjB,kBAGJ,GAAM,GAAmB,SAAS,cAAc,mBAChD,AAAI,GACF,EAAiB,iBAAiB,QAAS,IAAM,CAzRrD,MA8RM,AAJI,GACF,GAAW,MAAQ,IAErB,EAAe,IACX,oBAAY,OAAQ,kBAAiB,QAGzC,qBAAY,YAAZ,gBACA,WAAY,WAIhB,YAAS,cAAc,uBAAvB,QAA6C,iBAAiB,QAAS,IAAM,CAtS/E,MAuSI,oBAAiB,YAAjB,kBCvSJ,AAkBA,OAAW,KAAM,UAAS,iBAAoC,iBAC5D,GAAI,GAAoB,GAG1B,OAAW,KAAM,UAAS,iBAAoC,aAC5D,GAAI,GAAgB,GAGtB,OAAW,KAAK,UAAS,iBAAqC,eAC5D,GAAI,GAAkB,GAGxB,OAAW,KAAM,UAAS,iBAAoC,iBAC5D,GAAI,GAAoB,GAG1B,OAAW,KAAM,UAAS,iBAAoC,gBAC5D,GAAI,GAAmB,GAGzB,IACA,IACA,OAAO,iBAAiB,OAAQ,IAAM,CACpC,MAIF,EAAS,GAAG,IAAK,eAAgB,GAAK,CACpC,GAAM,GAAc,MAAM,KACxB,SAAS,iBAAmC,oBAC5C,MAGF,AAAI,GAAe,CAAC,OAAO,UAAU,UAAU,SAAS,YACtD,GAAE,iBACF,EAAY,WAMhB,EAAS,GAAG,IAAK,oBAAqB,IAAM,CA3D5C,MA4DE,GAAI,GAAmB,YAAS,cAA8B,0BAAvC,cAAgE,QACrF,iBAEF,GAAI,GAAoB,IAAqB,GAAI,CAC/C,GAAM,GAAW,OAAO,SAAS,KACjC,AAAI,GACF,IAAoB,GAEtB,OAAO,QAAQ,aAAa,KAAM,GAAI,MAO1C,AAAC,WAAiC,CAChC,AAAU,EAAM,CACd,YAAa,GAAI,QAAO,UACxB,MAAO,eASX,YAA2B,CACzB,GAAM,GAAY,GAAI,iBAAgB,OAAO,SAAS,QAChD,EAAY,EAAU,IAAI,cAChC,GAAI,IAAc,SAAW,IAAc,SAAW,IAAc,WAClE,OAIF,GAAM,GAAS,GAAI,KAAI,OAAO,SAAS,MACvC,EAAU,OAAO,cACjB,EAAO,OAAS,EAAU,WAC1B,OAAO,QAAQ,aAAa,KAAM,GAAI,EAAO,YAlG/C,MAqGA,AAAI,aAAS,cAA2B,eAApC,cAAkD,QAAQ,QAAS,OAAO,UAC5E,AAAU,EAAK,UAAY,CACzB,MAGF,IAGF,OAAW,KAAM,UAAS,iBAAiB,mBACzC,EAAG,iBAAiB,QAAS,IAAM,CACjC,MAOJ,YAAuB,CACrB,GAAI,GAAY,OACV,EAAQ,SAAS,gBAAgB,aAAa,cACpD,AAAI,IAAU,OACZ,EAAY,QACH,IAAU,SACnB,GAAY,QAEd,GAAI,GAAS,kBACb,AAAI,SAAS,WAAa,aACxB,GAAS,IAEX,SAAS,gBAAgB,aAAa,aAAc,GACpD,SAAS,OAAS,wBAAwB,KAAa",
+  "sourcesContent": ["/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nexport function registerHeaderListeners(): void {\n  const header = document.querySelector('.js-header');\n  const menuButtons = document.querySelectorAll('.js-headerMenuButton');\n  menuButtons.forEach(button => {\n    button.addEventListener('click', e => {\n      e.preventDefault();\n      header?.classList.toggle('is-active');\n      button.setAttribute('aria-expanded', String(header?.classList.contains('is-active')));\n    });\n  });\n\n  const scrim = document.querySelector('.js-scrim');\n  scrim?.addEventListener('click', e => {\n    e.preventDefault();\n    header?.classList.remove('is-active');\n    menuButtons.forEach(button => {\n      button.setAttribute('aria-expanded', String(header?.classList.contains('is-active')));\n    });\n  });\n}\n\nexport function registerSearchFormListeners(): void {\n  const searchForm = document.querySelector('.js-searchForm');\n  const expandSearch = document.querySelector('.js-expandSearch');\n  const input = searchForm?.querySelector('input');\n  const headerLogo = document.querySelector('.js-headerLogo');\n  const menuButton = document.querySelector('.js-headerMenuButton');\n  expandSearch?.addEventListener('click', () => {\n    searchForm?.classList.add('go-SearchForm--expanded');\n    headerLogo?.classList.add('go-Header-logo--hidden');\n    menuButton?.classList.add('go-Header-navOpen--hidden');\n    input?.focus();\n  });\n  document?.addEventListener('click', e => {\n    if (!searchForm?.contains(e.target as Node)) {\n      searchForm?.classList.remove('go-SearchForm--expanded');\n      headerLogo?.classList.remove('go-Header-logo--hidden');\n      menuButton?.classList.remove('go-Header-navOpen--hidden');\n    }\n  });\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * Carousel Controller adds event listeners, accessibility enhancements, and\n * control elements to a carousel component.\n */\nexport class CarouselController {\n  /**\n   * slides is a collection of slides in the carousel.\n   */\n  private slides: HTMLLIElement[];\n  /**\n   * dots is a collection of dot navigation controls, added to the carousel\n   * by this controller.\n   */\n  private dots: HTMLElement[];\n  /**\n   * liveRegion is a visually hidden element that notifies assitive devices\n   * of visual changes to the carousel. They are added to the carousel by\n   * this controller.\n   */\n  private liveRegion: HTMLElement;\n  /**\n   * activeIndex is the 0-index of the currently active slide.\n   */\n  private activeIndex: number;\n\n  constructor(private el: HTMLElement) {\n    this.slides = Array.from(el.querySelectorAll('.go-Carousel-slide'));\n    this.dots = [];\n    this.liveRegion = document.createElement('div');\n    this.activeIndex = Number(el.getAttribute('data-slide-index') ?? 0);\n\n    this.initSlides();\n    this.initArrows();\n    this.initDots();\n    this.initLiveRegion();\n  }\n\n  private initSlides() {\n    for (const [i, v] of this.slides.entries()) {\n      if (i === this.activeIndex) continue;\n      v.setAttribute('aria-hidden', 'true');\n    }\n  }\n\n  private initArrows() {\n    const arrows = document.createElement('ul');\n    arrows.classList.add('go-Carousel-arrows');\n    arrows.innerHTML = `\n      <li>\n        <button class=\"go-Carousel-prevSlide\" aria-label=\"Go to previous slide\">\n          <img class=\"go-Icon\" height=\"24\" width=\"24\" src=\"/static/shared/icon/arrow_left_gm_grey_24dp.svg\" alt=\"\">\n        </button>\n      </li>\n      <li>\n        <button class=\"go-Carousel-nextSlide\" aria-label=\"Go to next slide\">\n          <img class=\"go-Icon\" height=\"24\" width=\"24\" src=\"/static/shared/icon/arrow_right_gm_grey_24dp.svg\" alt=\"\">\n        </button>\n      </li>\n    `;\n    arrows\n      .querySelector('.go-Carousel-prevSlide')\n      ?.addEventListener('click', () => this.setActive(this.activeIndex - 1));\n    arrows\n      .querySelector('.go-Carousel-nextSlide')\n      ?.addEventListener('click', () => this.setActive(this.activeIndex + 1));\n    this.el.append(arrows);\n  }\n\n  private initDots() {\n    const dots = document.createElement('ul');\n    dots.classList.add('go-Carousel-dots');\n    for (let i = 0; i < this.slides.length; i++) {\n      const li = document.createElement('li');\n      const button = document.createElement('button');\n      button.classList.add('go-Carousel-dot');\n      if (i === this.activeIndex) {\n        button.classList.add('go-Carousel-dot--active');\n      }\n      button.innerHTML = `<span class=\"go-Carousel-obscured\">Slide ${i + 1}</span>`;\n      button.addEventListener('click', () => this.setActive(i));\n      li.append(button);\n      dots.append(li);\n      this.dots.push(button);\n    }\n    this.el.append(dots);\n  }\n\n  private initLiveRegion() {\n    this.liveRegion.setAttribute('aria-live', 'polite');\n    this.liveRegion.setAttribute('aria-atomic', 'true');\n    this.liveRegion.setAttribute('class', 'go-Carousel-obscured');\n    this.liveRegion.textContent = `Slide ${this.activeIndex + 1} of ${this.slides.length}`;\n    this.el.appendChild(this.liveRegion);\n  }\n\n  private setActive = (index: number) => {\n    this.activeIndex = (index + this.slides.length) % this.slides.length;\n    this.el.setAttribute('data-slide-index', String(this.activeIndex));\n    for (const d of this.dots) {\n      d.classList.remove('go-Carousel-dot--active');\n    }\n    this.dots[this.activeIndex].classList.add('go-Carousel-dot--active');\n    for (const s of this.slides) {\n      s.setAttribute('aria-hidden', 'true');\n    }\n    this.slides[this.activeIndex].removeAttribute('aria-hidden');\n    this.liveRegion.textContent = 'Slide ' + (this.activeIndex + 1) + ' of ' + this.slides.length;\n  };\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * This class decorates an element to copy arbitrary data attached via a data-\n * attribute to the clipboard.\n */\nexport class ClipboardController {\n  /**\n   * The data to be copied to the clipboard.\n   */\n  private data: string;\n\n  /**\n   * @param el The element that will trigger copying text to the clipboard. The text is\n   * expected to be within its data-to-copy attribute.\n   */\n  constructor(private el: HTMLButtonElement) {\n    this.data = el.dataset['toCopy'] ?? el.innerText;\n    // if data-to-copy is empty and the button is part of an input group\n    // capture the value of the input.\n    if (!this.data && el.parentElement?.classList.contains('go-InputGroup')) {\n      this.data = (this.data || el.parentElement?.querySelector('input')?.value) ?? '';\n    }\n    el.addEventListener('click', e => this.handleCopyClick(e));\n  }\n\n  /**\n   * Handles when the primary element is clicked.\n   */\n  handleCopyClick(e: MouseEvent): void {\n    e.preventDefault();\n    const TOOLTIP_SHOW_DURATION_MS = 1000;\n\n    // This API is not available on iOS.\n    if (!navigator.clipboard) {\n      this.showTooltipText('Unable to copy', TOOLTIP_SHOW_DURATION_MS);\n      return;\n    }\n    navigator.clipboard\n      .writeText(this.data)\n      .then(() => {\n        this.showTooltipText('Copied!', TOOLTIP_SHOW_DURATION_MS);\n      })\n      .catch(() => {\n        this.showTooltipText('Unable to copy', TOOLTIP_SHOW_DURATION_MS);\n      });\n  }\n\n  /**\n   * Shows the given text in a tooltip for a specified amount of time, in milliseconds.\n   */\n  showTooltipText(text: string, durationMs: number): void {\n    this.el.setAttribute('data-tooltip', text);\n    setTimeout(() => this.el.setAttribute('data-tooltip', ''), durationMs);\n  }\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n/**\n * ToolTipController handles closing tooltips on external clicks.\n */\nexport class ToolTipController {\n  constructor(private el: HTMLDetailsElement) {\n    document.addEventListener('click', e => {\n      const insideTooltip = this.el.contains(e.target as Element);\n      if (!insideTooltip) {\n        this.el.removeAttribute('open');\n      }\n    });\n  }\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { TreeNavController } from './tree.js';\n\nexport class SelectNavController {\n  constructor(private el: Element) {\n    this.el.addEventListener('change', e => {\n      const target = e.target as HTMLSelectElement;\n      let href = target.value;\n      if (!target.value.startsWith('/')) {\n        href = '/' + href;\n      }\n      window.location.href = href;\n    });\n  }\n}\n\nexport function makeSelectNav(tree: TreeNavController): HTMLLabelElement {\n  const label = document.createElement('label');\n  label.classList.add('go-Label');\n  label.setAttribute('aria-label', 'Menu');\n  const select = document.createElement('select');\n  select.classList.add('go-Select', 'js-selectNav');\n  label.appendChild(select);\n  const outline = document.createElement('optgroup');\n  outline.label = 'Outline';\n  select.appendChild(outline);\n  const groupMap: Record<string, HTMLOptGroupElement> = {};\n  let group: HTMLOptGroupElement;\n  for (const t of tree.treeitems) {\n    if (Number(t.depth) > 4) continue;\n    if (t.groupTreeitem) {\n      group = groupMap[t.groupTreeitem.label];\n      if (!group) {\n        group = groupMap[t.groupTreeitem.label] = document.createElement('optgroup');\n        group.label = t.groupTreeitem.label;\n        select.appendChild(group);\n      }\n    } else {\n      group = outline;\n    }\n    const o = document.createElement('option');\n    o.label = t.label;\n    o.textContent = t.label;\n    o.value = (t.el as HTMLAnchorElement).href.replace(window.location.origin, '').replace('/', '');\n    group.appendChild(o);\n  }\n  tree.addObserver(t => {\n    const hash = (t.el as HTMLAnchorElement).hash;\n    const value = select.querySelector<HTMLOptionElement>(`[value$=\"${hash}\"]`)?.value;\n    if (value) {\n      select.value = value;\n    }\n  }, 50);\n  return label;\n}\n", "/**\n * @license\n * Copyright 2021 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\ninterface Window {\n  dialogPolyfill?: {\n    registerDialog: (el: HTMLDialogElement) => void;\n  };\n}\n\ndeclare const window: Window;\n\n/**\n * ModalController registers a dialog element with the polyfill if\n * necessary for the current browser, add adds event listeners to\n * close and open modals.\n */\nexport class ModalController {\n  constructor(private el: HTMLDialogElement) {\n    if (window.dialogPolyfill) {\n      window.dialogPolyfill.registerDialog(el);\n    }\n    this.init();\n  }\n\n  init() {\n    const button = document.querySelector<HTMLButtonElement>(`[aria-controls=\"${this.el.id}\"]`);\n    if (button) {\n      button.addEventListener('click', () => {\n        if (this.el.showModal) {\n          this.el.showModal();\n        } else {\n          this.el.setAttribute('opened', 'true');\n        }\n        this.el.querySelector('input')?.focus();\n      });\n    }\n    for (const btn of this.el.querySelectorAll<HTMLButtonElement>('[data-modal-close]')) {\n      btn.addEventListener('click', () => {\n        if (this.el.close) {\n          this.el.close();\n        } else {\n          this.el.removeAttribute('opened');\n        }\n      });\n    }\n  }\n}\n", "interface TagManagerEvent {\n  /**\n   * event is the name of the event, used to filter events in\n   * Google Analytics.\n   */\n  event: string;\n\n  /**\n   * event_category is a name that you supply as a way to group objects\n   * that to analyze. Typically, you will use the same category name\n   * multiple times over related UI elements (buttons, links, etc).\n   */\n  event_category?: string;\n\n  /**\n   * event_action is used to name the type of event or interaction you\n   * want to measure for a particular web object. For example, with a\n   * single \"form\" category, you can analyze a number of specific events\n   * with this parameter, such as: form entered, form submitted.\n   */\n  event_action?: string;\n\n  /**\n   * event_label provide additional information for events that you want\n   * to analyze, such as the text label of a link.\n   */\n  event_label?: string;\n\n  /**\n   * gtm.start is used to initialize Google Tag Manager.\n   */\n  'gtm.start'?: number;\n}\n\n// eslint-disable-next-line @typescript-eslint/no-unused-vars\ndeclare global {\n  interface Window {\n    dataLayer?: (TagManagerEvent | VoidFunction)[];\n    ga?: unknown;\n  }\n}\n\n/**\n * track sends events to Google Tag Manager.\n */\nexport function track(\n  event: string | TagManagerEvent,\n  category?: string,\n  action?: string,\n  label?: string\n): void {\n  window.dataLayer ??= [];\n  if (typeof event === 'string') {\n    window.dataLayer.push({\n      event,\n      event_category: category,\n      event_action: action,\n      event_label: label,\n    });\n  } else {\n    window.dataLayer.push(event);\n  }\n}\n\n/**\n * func adds functions to run sequentionally after\n * Google Tag Manager is ready.\n */\nexport function func(fn: () => void): void {\n  window.dataLayer ??= [];\n  window.dataLayer.push(fn);\n}\n", "/*!\n * @license\n * Copyright 2019-2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { track } from '../analytics/analytics';\n\n/**\n * Options are keyhandler callback options.\n */\ninterface Options {\n  /**\n   * target is the element the key event should filter on. The\n   * default target is the document.\n   */\n  target?: Element;\n\n  /**\n   * withMeta specifies if the event callback should fire when\n   * the key is pressed with a meta key (ctrl, alt, etc). By\n   * default meta keypresses are ignored.\n   */\n  withMeta?: boolean;\n}\n\n/**\n * KeyHandler is the config for a keyboard event callback.\n */\ninterface KeyHandler extends Options {\n  description: string;\n  callback: (e: KeyboardEvent) => void;\n}\n\n/**\n * KeyboardController controls event callbacks for sitewide\n * keyboard events. Multiple callbacks can be registered for\n * a single key and by default the controller ignores events\n * for text input targets.\n */\nclass KeyboardController {\n  handlers: Record<string, Set<KeyHandler>>;\n\n  constructor() {\n    this.handlers = {};\n    document.addEventListener('keydown', e => this.handleKeyPress(e));\n  }\n\n  /**\n   * on registers keyboard event callbacks.\n   * @param key the key to register.\n   * @param description name of the event.\n   * @param callback event callback.\n   * @param options set target and withMeta options to override the default behaviors.\n   */\n  on(key: string, description: string, callback: (e: KeyboardEvent) => void, options?: Options) {\n    this.handlers[key] ??= new Set();\n    this.handlers[key].add({ description, callback, ...options });\n    return this;\n  }\n\n  private handleKeyPress(e: KeyboardEvent) {\n    for (const handler of this.handlers[e.key.toLowerCase()] ?? new Set()) {\n      if (handler.target && handler.target !== e.target) {\n        return;\n      }\n      const t = e.target as HTMLElement | null;\n      if (\n        !handler.target &&\n        (t?.tagName === 'INPUT' || t?.tagName === 'SELECT' || t?.tagName === 'TEXTAREA')\n      ) {\n        return;\n      }\n      if (t?.isContentEditable) {\n        return;\n      }\n      if (\n        (handler.withMeta && !(e.ctrlKey || e.metaKey)) ||\n        (!handler.withMeta && (e.ctrlKey || e.metaKey))\n      ) {\n        return;\n      }\n      track('keypress', 'hotkeys', `${e.key} pressed`, handler.description);\n      handler.callback(e);\n    }\n  }\n}\n\nexport const keyboard = new KeyboardController();\n", "/*!\n * @license\n * Copyright 2019-2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\n// This file implements the behavior of the \"jump to symbol\" dialog for Go\n// package documentation, as well as the simple dialog that displays keyboard\n// shortcuts.\n\n// The DOM for the dialogs is at the bottom of static/frontend/unit/main/_modals.tmpl.\n// The CSS is in static/frontend/unit/main/_modals.css.\n\n// The dialog is activated by pressing the 'f' key. It presents a list\n// (#JumpDialog-list) of all Go symbols displayed in the documentation.\n// Entering text in the dialog's text box (#JumpDialog-filter) restricts the\n// list to symbols containing the text. Clicking on an symbol jumps to\n// its documentation.\n\n// This code is based on\n// https://go.googlesource.com/gddo/+/refs/heads/master/gddo-server/assets/site.js.\n// It was modified to remove the dependence on jquery and bootstrap.\n\nimport { keyboard } from '../keyboard/keyboard';\n\nexport function initModals(): void {\n  const jumpDialog = document.querySelector<HTMLDialogElement>('.JumpDialog');\n  const jumpBody = jumpDialog?.querySelector<HTMLDivElement>('.JumpDialog-body');\n  const jumpList = jumpDialog?.querySelector<HTMLDivElement>('.JumpDialog-list');\n  const jumpFilter = jumpDialog?.querySelector<HTMLInputElement>('.JumpDialog-input');\n  const doc = document.querySelector<HTMLDivElement>('.js-documentation');\n\n  interface JumpListItem {\n    link: HTMLAnchorElement;\n    name: string;\n    kind: string;\n    lower: string;\n  }\n\n  let jumpListItems: JumpListItem[] | undefined; // All the symbols in the doc; computed only once.\n\n  // collectJumpListItems returns a list of items, one for each symbol in the\n  // documentation on the current page.\n  //\n  // It uses the data-kind attribute generated in the documentation HTML to find\n  // the symbols and their id attributes.\n  //\n  // If there are no data-kind attributes, then we have older doc; fall back to\n  // a less precise method.\n  function collectJumpListItems() {\n    const items = [];\n    if (!doc) return;\n    for (const el of doc.querySelectorAll('[data-kind]')) {\n      items.push(newJumpListItem(el));\n    }\n\n    // Clicking on any of the links closes the dialog.\n    for (const item of items) {\n      item.link.addEventListener('click', function () {\n        jumpDialog?.close();\n      });\n    }\n    // Sort case-insensitively by symbol name.\n    items.sort(function (a, b) {\n      return a.lower.localeCompare(b.lower);\n    });\n    return items;\n  }\n\n  // newJumpListItem creates a new item for the DOM element el.\n  // An item is an object with:\n  // - name: the element's id (which is the symbol name)\n  // - kind: the element's kind (function, variable, etc.),\n  // - link: a link ('a' tag) to the element\n  // - lower: the name in lower case, just for sorting\n  function newJumpListItem(el: Element): JumpListItem {\n    const a = document.createElement('a');\n    const name = el.getAttribute('id');\n    a.setAttribute('href', '#' + name);\n    a.setAttribute('tabindex', '-1');\n    a.setAttribute('data-gtmc', 'jump to link');\n    const kind = el.getAttribute('data-kind');\n    return {\n      link: a,\n      name: name ?? '',\n      kind: kind ?? '',\n      lower: name?.toLowerCase() ?? '', // for sorting\n    };\n  }\n\n  let lastFilterValue: string; // The last contents of the filter text box.\n  let activeJumpItem = -1; // The index of the currently active item in the list.\n\n  // updateJumpList sets the elements of the dialog list to\n  // everything whose name contains filter.\n  function updateJumpList(filter: string) {\n    lastFilterValue = filter;\n    if (!jumpListItems) {\n      jumpListItems = collectJumpListItems();\n    }\n    setActiveJumpItem(-1);\n\n    // Remove all children from list.\n    while (jumpList?.firstChild) {\n      jumpList.firstChild.remove();\n    }\n\n    if (filter) {\n      // A filter is set. We treat the filter as a substring that can appear in\n      // an item name (case insensitive), and find the following matches - in\n      // order of priority:\n      //\n      // 1. Exact matches (the filter matches the item's name exactly)\n      // 2. Prefix matches (the item's name starts with filter)\n      // 3. Infix matches (the filter is a substring of the item's name)\n      const filterLowerCase = filter.toLowerCase();\n\n      const exactMatches = [];\n      const prefixMatches = [];\n      const infixMatches = [];\n\n      // makeLinkHtml creates the link name HTML for a list item. item is the DOM\n      // item. item.name.substr(boldStart, boldEnd) will be bolded.\n      const makeLinkHtml = (item: JumpListItem, boldStart: number, boldEnd: number) => {\n        return (\n          item.name.substring(0, boldStart) +\n          '<b>' +\n          item.name.substring(boldStart, boldEnd) +\n          '</b>' +\n          item.name.substring(boldEnd)\n        );\n      };\n\n      for (const item of jumpListItems ?? []) {\n        const nameLowerCase = item.name.toLowerCase();\n\n        if (nameLowerCase === filterLowerCase) {\n          item.link.innerHTML = makeLinkHtml(item, 0, item.name.length);\n          exactMatches.push(item);\n        } else if (nameLowerCase.startsWith(filterLowerCase)) {\n          item.link.innerHTML = makeLinkHtml(item, 0, filter.length);\n          prefixMatches.push(item);\n        } else {\n          const index = nameLowerCase.indexOf(filterLowerCase);\n          if (index > -1) {\n            item.link.innerHTML = makeLinkHtml(item, index, index + filter.length);\n            infixMatches.push(item);\n          }\n        }\n      }\n\n      for (const item of exactMatches.concat(prefixMatches).concat(infixMatches)) {\n        jumpList?.appendChild(item.link);\n      }\n    } else {\n      if (!jumpListItems || jumpListItems.length === 0) {\n        const msg = document.createElement('i');\n        msg.innerHTML = 'There are no symbols on this page.';\n        jumpList?.appendChild(msg);\n      }\n      // No filter set; display all items in their existing order.\n      for (const item of jumpListItems ?? []) {\n        item.link.innerHTML = item.name + ' <i>' + item.kind + '</i>';\n        jumpList?.appendChild(item.link);\n      }\n    }\n\n    if (jumpBody) {\n      jumpBody.scrollTop = 0;\n    }\n    if (jumpListItems?.length && jumpList && jumpList.children.length > 0) {\n      setActiveJumpItem(0);\n    }\n  }\n\n  // Set the active jump item to n.\n  function setActiveJumpItem(n: number) {\n    const cs = jumpList?.children as HTMLCollectionOf<HTMLElement> | null | undefined;\n    if (!cs || !jumpBody) {\n      return;\n    }\n    if (activeJumpItem >= 0) {\n      cs[activeJumpItem].classList.remove('JumpDialog-active');\n    }\n    if (n >= cs.length) {\n      n = cs.length - 1;\n    }\n    if (n >= 0) {\n      cs[n].classList.add('JumpDialog-active');\n\n      // Scroll so the active item is visible.\n      // For some reason cs[n].scrollIntoView() doesn't behave as I'd expect:\n      // it moves the entire dialog box in the viewport.\n\n      // Get the top and bottom of the active item relative to jumpBody.\n      const activeTop = cs[n].offsetTop - cs[0].offsetTop;\n      const activeBottom = activeTop + cs[n].clientHeight;\n      if (activeTop < jumpBody.scrollTop) {\n        // Off the top; scroll up.\n        jumpBody.scrollTop = activeTop;\n      } else if (activeBottom > jumpBody.scrollTop + jumpBody.clientHeight) {\n        // Off the bottom; scroll down.\n        jumpBody.scrollTop = activeBottom - jumpBody.clientHeight;\n      }\n    }\n    activeJumpItem = n;\n  }\n\n  // Increment the activeJumpItem by delta.\n  function incActiveJumpItem(delta: number) {\n    if (activeJumpItem < 0) {\n      return;\n    }\n    let n = activeJumpItem + delta;\n    if (n < 0) {\n      n = 0;\n    }\n    setActiveJumpItem(n);\n  }\n\n  // Pressing a key in the filter updates the list (if the filter actually changed).\n  jumpFilter?.addEventListener('keyup', function () {\n    if (jumpFilter.value.toUpperCase() != lastFilterValue.toUpperCase()) {\n      updateJumpList(jumpFilter.value);\n    }\n  });\n\n  // Pressing enter in the filter selects the first element in the list.\n  jumpFilter?.addEventListener('keydown', function (event) {\n    const upArrow = 38;\n    const downArrow = 40;\n    const enterKey = 13;\n    switch (event.which) {\n      case upArrow:\n        incActiveJumpItem(-1);\n        event.preventDefault();\n        break;\n      case downArrow:\n        incActiveJumpItem(1);\n        event.preventDefault();\n        break;\n      case enterKey:\n        if (activeJumpItem >= 0) {\n          if (jumpList) {\n            (jumpList.children[activeJumpItem] as HTMLElement).click();\n            event.preventDefault();\n          }\n        }\n        break;\n    }\n  });\n\n  const shortcutsDialog = document.querySelector<HTMLDialogElement>('.ShortcutsDialog');\n\n  // - Pressing 'f' or 'F' opens the jump-to-symbol dialog.\n  // - Pressing '?' opens up the shortcut dialog.\n  // Ignore a keypress if a dialog is already open, or if it is pressed on a\n  // component that wants to consume it.\n  keyboard\n    .on('f', 'open jump to modal', e => {\n      if (jumpDialog?.open || shortcutsDialog?.open) {\n        return;\n      }\n      e.preventDefault();\n      if (jumpFilter) {\n        jumpFilter.value = '';\n      }\n      jumpDialog?.showModal?.();\n      jumpFilter?.focus();\n      updateJumpList('');\n    })\n    .on('?', 'open shortcuts modal', () => {\n      if (jumpDialog?.open || shortcutsDialog?.open) {\n        return;\n      }\n      shortcutsDialog?.showModal?.();\n    });\n\n  const jumpOutlineInput = document.querySelector('.js-jumpToInput');\n  if (jumpOutlineInput) {\n    jumpOutlineInput.addEventListener('click', () => {\n      if (jumpFilter) {\n        jumpFilter.value = '';\n      }\n      updateJumpList('');\n      if (jumpDialog?.open || shortcutsDialog?.open) {\n        return;\n      }\n      jumpDialog?.showModal?.();\n      jumpFilter?.focus();\n    });\n  }\n\n  document.querySelector('.js-openShortcuts')?.addEventListener('click', () => {\n    shortcutsDialog?.showModal?.();\n  });\n}\n", "/**\n * @license\n * Copyright 2020 The Go Authors. All rights reserved.\n * Use of this source code is governed by a BSD-style\n * license that can be found in the LICENSE file.\n */\n\nimport { registerHeaderListeners, registerSearchFormListeners } from 'static/shared/header/header';\nimport { CarouselController } from 'static/shared/carousel/carousel';\nimport { ClipboardController } from 'static/shared/clipboard/clipboard';\nimport { ToolTipController } from 'static/shared/tooltip/tooltip';\nimport { SelectNavController } from 'static/shared/outline/select';\nimport { ModalController } from 'static/shared/modal/modal';\nimport { initModals } from 'static/shared/jump/jump';\n\nimport { keyboard } from 'static/shared/keyboard/keyboard';\nimport * as analytics from 'static/shared/analytics/analytics';\n\nfor (const el of document.querySelectorAll<HTMLButtonElement>('.js-clipboard')) {\n  new ClipboardController(el);\n}\n\nfor (const el of document.querySelectorAll<HTMLDialogElement>('.js-modal')) {\n  new ModalController(el);\n}\n\nfor (const t of document.querySelectorAll<HTMLDetailsElement>('.js-tooltip')) {\n  new ToolTipController(t);\n}\n\nfor (const el of document.querySelectorAll<HTMLSelectElement>('.js-selectNav')) {\n  new SelectNavController(el);\n}\n\nfor (const el of document.querySelectorAll<HTMLSelectElement>('.js-carousel')) {\n  new CarouselController(el);\n}\n\nregisterHeaderListeners();\nregisterSearchFormListeners();\nwindow.addEventListener('load', () => {\n  initModals();\n});\n\n// Pressing '/' focuses the search box\nkeyboard.on('/', 'focus search', e => {\n  const searchInput = Array.from(\n    document.querySelectorAll<HTMLInputElement>('.js-searchFocus')\n  ).pop();\n  // Favoring the Firefox quick find feature over search input\n  // focus. See: https://github.com/golang/go/issues/41093.\n  if (searchInput && !window.navigator.userAgent.includes('Firefox')) {\n    e.preventDefault();\n    searchInput.focus();\n  }\n});\n\n// Pressing 'y' changes the browser URL to the canonical URL\n// without triggering a reload.\nkeyboard.on('y', 'set canonical url', () => {\n  let canonicalURLPath = document.querySelector<HTMLDivElement>('.js-canonicalURLPath')?.dataset[\n    'canonicalUrlPath'\n  ];\n  if (canonicalURLPath && canonicalURLPath !== '') {\n    const fragment = window.location.hash;\n    if (fragment) {\n      canonicalURLPath += fragment;\n    }\n    window.history.replaceState(null, '', canonicalURLPath);\n  }\n});\n\n/**\n * setupGoogleTagManager intializes Google Tag Manager.\n */\n(function setupGoogleTagManager() {\n  analytics.track({\n    'gtm.start': new Date().getTime(),\n    event: 'gtm.js',\n  });\n})();\n\n/**\n * removeUTMSource removes the utm_source GET parameter if present.\n * This is done using JavaScript, so that the utm_source is still\n * captured by Google Analytics.\n */\nfunction removeUTMSource() {\n  const urlParams = new URLSearchParams(window.location.search);\n  const utmSource = urlParams.get('utm_source');\n  if (utmSource !== 'gopls' && utmSource !== 'godoc' && utmSource !== 'pkggodev') {\n    return;\n  }\n\n  /** Strip the utm_source query parameter and replace the URL. **/\n  const newURL = new URL(window.location.href);\n  urlParams.delete('utm_source');\n  newURL.search = urlParams.toString();\n  window.history.replaceState(null, '', newURL.toString());\n}\n\nif (document.querySelector<HTMLElement>('.js-gtmID')?.dataset.gtmid && window.dataLayer) {\n  analytics.func(function () {\n    removeUTMSource();\n  });\n} else {\n  removeUTMSource();\n}\n\nfor (const el of document.querySelectorAll('.js-toggleTheme')) {\n  el.addEventListener('click', () => {\n    toggleTheme();\n  });\n}\n\n/**\n * toggleTheme switches the preferred color scheme between auto, light, and dark.\n */\nfunction toggleTheme() {\n  let nextTheme = 'dark';\n  const theme = document.documentElement.getAttribute('data-theme');\n  if (theme === 'dark') {\n    nextTheme = 'light';\n  } else if (theme === 'light') {\n    nextTheme = 'auto';\n  }\n  let domain = '';\n  if (location.hostname.endsWith('go.dev')) {\n    domain = 'domain=.go.dev;';\n  }\n  document.documentElement.setAttribute('data-theme', nextTheme);\n  document.cookie = `prefers-color-scheme=${nextTheme};${domain}path=/;max-age=31536000;`;\n}\n"],
+  "mappings": "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",
   "names": []
 }
diff --git a/static/frontend/frontend.ts b/static/frontend/frontend.ts
index dad49f1..34365ae 100644
--- a/static/frontend/frontend.ts
+++ b/static/frontend/frontend.ts
@@ -124,9 +124,9 @@
   } else if (theme === 'light') {
     nextTheme = 'auto';
   }
-  let domain = 'domain=.go.dev;';
-  if (location.hostname === 'localhost') {
-    domain = '';
+  let domain = '';
+  if (location.hostname.endsWith('go.dev')) {
+    domain = 'domain=.go.dev;';
   }
   document.documentElement.setAttribute('data-theme', nextTheme);
   document.cookie = `prefers-color-scheme=${nextTheme};${domain}path=/;max-age=31536000;`;