static/frontend: share color scheme preference across go.dev domains

With dark mode added to go.dev in CL 391536 we can update the cookie
to apply the cookie to both pkg.go.dev and go.dev.

For golang/go#34601.

Change-Id: I49b50241f9e57ede369260aeb52512aebef88239
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/391517
Trust: Jamal Carvalho <jamal@golang.org>
Run-TryBot: Jamal Carvalho <jamal@golang.org>
Reviewed-by: Jonathan Amsterdam <jba@google.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
diff --git a/static/frontend/frontend.js b/static/frontend/frontend.js
index 05997fc..bec592d 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"),document.documentElement.setAttribute("data-theme",e),document.cookie=`prefers-color-scheme=${e};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="domain=.go.dev;";location.hostname==="localhost"&&(n=""),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 2524c7f..c161754 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  document.documentElement.setAttribute('data-theme', nextTheme);\n  document.cookie = `prefers-color-scheme=${nextTheme};path=/;max-age=31536000;`;\n}\n"],
-  "mappings": "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",
+  "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": "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",
   "names": []
 }
diff --git a/static/frontend/frontend.ts b/static/frontend/frontend.ts
index b516674..dad49f1 100644
--- a/static/frontend/frontend.ts
+++ b/static/frontend/frontend.ts
@@ -124,6 +124,10 @@
   } else if (theme === 'light') {
     nextTheme = 'auto';
   }
+  let domain = 'domain=.go.dev;';
+  if (location.hostname === 'localhost') {
+    domain = '';
+  }
   document.documentElement.setAttribute('data-theme', nextTheme);
-  document.cookie = `prefers-color-scheme=${nextTheme};path=/;max-age=31536000;`;
+  document.cookie = `prefers-color-scheme=${nextTheme};${domain}path=/;max-age=31536000;`;
 }