static: add module versions with an inline mod file to run package examples

For all non-standard library packages, their examples in the docs are ran using the version as the docs by adding an inline mod file that specifies the module version of the package.

For golang/go#50769

Change-Id: I539260147aedade112a2e812c5ea4d19235774c2
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/444455
Reviewed-by: Jamal Carvalho <jamal@golang.org>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Run-TryBot: Dylan Le <dungtuanle@google.com>
diff --git a/static/frontend/unit/main/main.js b/static/frontend/unit/main/main.js
index 4affcb6..525c597 100644
--- a/static/frontend/unit/main/main.js
+++ b/static/frontend/unit/main/main.js
@@ -1,4 +1,9 @@
-var d={PLAY_HREF:".js-exampleHref",PLAY_CONTAINER:".js-exampleContainer",EXAMPLE_INPUT:".Documentation-exampleCode",EXAMPLE_OUTPUT:".Documentation-exampleOutput",EXAMPLE_ERROR:".Documentation-exampleError",PLAY_BUTTON:".Documentation-examplePlayButton",SHARE_BUTTON:".Documentation-exampleShareButton",FORMAT_BUTTON:".Documentation-exampleFormatButton",RUN_BUTTON:".Documentation-exampleRunButton"},g=class{constructor(e){this.exampleEl=e;var t,i,s,r;this.exampleEl=e,this.anchorEl=e.querySelector("a"),this.errorEl=e.querySelector(d.EXAMPLE_ERROR),this.playButtonEl=e.querySelector(d.PLAY_BUTTON),this.shareButtonEl=e.querySelector(d.SHARE_BUTTON),this.formatButtonEl=e.querySelector(d.FORMAT_BUTTON),this.runButtonEl=e.querySelector(d.RUN_BUTTON),this.inputEl=this.makeTextArea(e.querySelector(d.EXAMPLE_INPUT)),this.outputEl=e.querySelector(d.EXAMPLE_OUTPUT),(t=this.playButtonEl)==null||t.addEventListener("click",()=>this.handleShareButtonClick()),(i=this.shareButtonEl)==null||i.addEventListener("click",()=>this.handleShareButtonClick()),(s=this.formatButtonEl)==null||s.addEventListener("click",()=>this.handleFormatButtonClick()),(r=this.runButtonEl)==null||r.addEventListener("click",()=>this.handleRunButtonClick()),!!this.inputEl&&(this.resize(),this.inputEl.addEventListener("keyup",()=>this.resize()),this.inputEl.addEventListener("keydown",n=>this.onKeydown(n)))}makeTextArea(e){var i,s;let t=document.createElement("textarea");return t.classList.add("Documentation-exampleCode","code"),t.spellcheck=!1,t.value=(i=e==null?void 0:e.textContent)!=null?i:"",(s=e==null?void 0:e.parentElement)==null||s.replaceChild(t,e),t}getAnchorHash(){var e;return(e=this.anchorEl)==null?void 0:e.hash}expand(){this.exampleEl.open=!0}resize(){var e;if((e=this.inputEl)==null?void 0:e.value){let t=(this.inputEl.value.match(/\n/g)||[]).length;this.inputEl.style.height=`${(20+t*20+12+2)/16}rem`}}onKeydown(e){e.key==="Tab"&&(document.execCommand("insertText",!1,"	"),e.preventDefault())}setInputText(e){this.inputEl&&(this.inputEl.value=e)}setOutputText(e){this.outputEl&&(this.outputEl.textContent=e)}setOutputHTML(e){this.outputEl&&(this.outputEl.innerHTML=e)}setErrorText(e){this.errorEl&&(this.errorEl.textContent=e),this.setOutputText("An error has occurred\u2026")}handleShareButtonClick(){var t;let e="https://play.golang.org/p/";this.setOutputText("Waiting for remote server\u2026"),fetch("/play/share",{method:"POST",body:(t=this.inputEl)==null?void 0:t.value}).then(i=>i.text()).then(i=>{let s=e+i;this.setOutputHTML(`<a href="${s}">${s}</a>`),window.open(s)}).catch(i=>{this.setErrorText(i)})}handleFormatButtonClick(){var t,i;this.setOutputText("Waiting for remote server\u2026");let e=new FormData;e.append("body",(i=(t=this.inputEl)==null?void 0:t.value)!=null?i:""),fetch("/play/fmt",{method:"POST",body:e}).then(s=>s.json()).then(({Body:s,Error:r})=>{this.setOutputText(r||"Done."),s&&(this.setInputText(s),this.resize())}).catch(s=>{this.setErrorText(s)})}handleRunButtonClick(){var e;this.setOutputText("Waiting for remote server\u2026"),fetch("/play/compile",{method:"POST",body:JSON.stringify({body:(e=this.inputEl)==null?void 0:e.value,version:2})}).then(t=>t.json()).then(async({Events:t,Errors:i})=>{this.setOutputText(i||"");for(let s of t||[])this.setOutputText(s.Message),await new Promise(r=>setTimeout(r,s.Delay/1e6))}).catch(t=>{this.setErrorText(t)})}};function y(){let l=location.hash.match(/^#(example-.*)$/);if(l){let i=document.getElementById(l[1]);i&&(i.open=!0)}let e=[...document.querySelectorAll(d.PLAY_HREF)],t=i=>e.find(s=>s.hash===i.getAnchorHash());for(let i of document.querySelectorAll(d.PLAY_CONTAINER)){let s=new g(i),r=t(s);r?r.addEventListener("click",()=>{s.expand()}):console.warn("example href not found")}}var p=class{constructor(e){this.el=e;this.el.addEventListener("change",t=>{let i=t.target,s=i.value;i.value.startsWith("/")||(s="/"+s),window.location.href=s})}};function L(l){let e=document.createElement("label");e.classList.add("go-Label"),e.setAttribute("aria-label","Menu");let t=document.createElement("select");t.classList.add("go-Select","js-selectNav"),e.appendChild(t);let i=document.createElement("optgroup");i.label="Outline",t.appendChild(i);let s={},r;for(let n of l.treeitems){if(Number(n.depth)>4)continue;n.groupTreeitem?(r=s[n.groupTreeitem.label],r||(r=s[n.groupTreeitem.label]=document.createElement("optgroup"),r.label=n.groupTreeitem.label,t.appendChild(r))):r=i;let a=document.createElement("option");a.label=n.label,a.textContent=n.label,a.value=n.el.href.replace(window.location.origin,"").replace("/",""),r.appendChild(a)}return l.addObserver(n=>{var c;let a=n.el.hash,h=(c=t.querySelector(`[value$="${a}"]`))==null?void 0:c.value;h&&(t.value=h)},50),e}var f=class{constructor(e){this.el=e;this.handleResize=()=>{this.el.style.setProperty("--js-tree-height","100vh"),this.el.style.setProperty("--js-tree-height",this.el.clientHeight+"px")};this.treeitems=[],this.firstChars=[],this.firstTreeitem=null,this.lastTreeitem=null,this.observerCallbacks=[],this.init()}init(){this.handleResize(),window.addEventListener("resize",this.handleResize),this.findTreeItems(),this.updateVisibleTreeitems(),this.observeTargets(),this.firstTreeitem&&(this.firstTreeitem.el.tabIndex=0)}observeTargets(){this.addObserver(i=>{this.expandTreeitem(i),this.setSelected(i)});let e=new Map,t=new IntersectionObserver(i=>{for(let s of i)e.set(s.target.id,s.isIntersecting||s.intersectionRatio===1);for(let[s,r]of e)if(r){let n=this.treeitems.find(a=>{var h;return(h=a.el)==null?void 0:h.href.endsWith(`#${s}`)});if(n)for(let a of this.observerCallbacks)a(n);break}},{threshold:1,rootMargin:"-60px 0px 0px 0px"});for(let i of this.treeitems.map(s=>s.el.getAttribute("href")))if(i){let s=i.replace(window.location.origin,"").replace("/","").replace("#",""),r=document.getElementById(s);r&&t.observe(r)}}addObserver(e,t=200){this.observerCallbacks.push(M(e,t))}setFocusToNextItem(e){let t=null;for(let i=e.index+1;i<this.treeitems.length;i++){let s=this.treeitems[i];if(s.isVisible){t=s;break}}t&&this.setFocusToItem(t)}setFocusToPreviousItem(e){let t=null;for(let i=e.index-1;i>-1;i--){let s=this.treeitems[i];if(s.isVisible){t=s;break}}t&&this.setFocusToItem(t)}setFocusToParentItem(e){e.groupTreeitem&&this.setFocusToItem(e.groupTreeitem)}setFocusToFirstItem(){this.firstTreeitem&&this.setFocusToItem(this.firstTreeitem)}setFocusToLastItem(){this.lastTreeitem&&this.setFocusToItem(this.lastTreeitem)}setSelected(e){var t;for(let i of this.el.querySelectorAll('[aria-expanded="true"]'))i!==e.el&&(((t=i.nextElementSibling)==null?void 0:t.contains(e.el))||i.setAttribute("aria-expanded","false"));for(let i of this.el.querySelectorAll("[aria-selected]"))i!==e.el&&i.setAttribute("aria-selected","false");e.el.setAttribute("aria-selected","true"),this.updateVisibleTreeitems(),this.setFocusToItem(e,!1)}expandTreeitem(e){let t=e;for(;t;)t.isExpandable&&t.el.setAttribute("aria-expanded","true"),t=t.groupTreeitem;this.updateVisibleTreeitems()}expandAllSiblingItems(e){for(let t of this.treeitems)t.groupTreeitem===e.groupTreeitem&&t.isExpandable&&this.expandTreeitem(t)}collapseTreeitem(e){let t=null;e.isExpanded()?t=e:t=e.groupTreeitem,t&&(t.el.setAttribute("aria-expanded","false"),this.updateVisibleTreeitems(),this.setFocusToItem(t))}setFocusByFirstCharacter(e,t){let i,s;t=t.toLowerCase(),i=e.index+1,i===this.treeitems.length&&(i=0),s=this.getIndexFirstChars(i,t),s===-1&&(s=this.getIndexFirstChars(0,t)),s>-1&&this.setFocusToItem(this.treeitems[s])}findTreeItems(){let e=(t,i)=>{let s=i,r=t.firstElementChild;for(;r;)(r.tagName==="A"||r.tagName==="SPAN")&&(s=new A(r,this,i),this.treeitems.push(s),this.firstChars.push(s.label.substring(0,1).toLowerCase())),r.firstElementChild&&e(r,s),r=r.nextElementSibling};e(this.el,null),this.treeitems.map((t,i)=>t.index=i)}updateVisibleTreeitems(){this.firstTreeitem=this.treeitems[0];for(let e of this.treeitems){let t=e.groupTreeitem;for(e.isVisible=!0;t&&t.el!==this.el;)t.isExpanded()||(e.isVisible=!1),t=t.groupTreeitem;e.isVisible&&(this.lastTreeitem=e)}}setFocusToItem(e,t=!0){e.el.tabIndex=0,t&&e.el.focus();for(let i of this.treeitems)i!==e&&(i.el.tabIndex=-1)}getIndexFirstChars(e,t){for(let i=e;i<this.firstChars.length;i++)if(this.treeitems[i].isVisible&&t===this.firstChars[i])return i;return-1}},A=class{constructor(e,t,i){var n,a,h,c,v;e.tabIndex=-1,this.el=e,this.groupTreeitem=i,this.label=(a=(n=e.textContent)==null?void 0:n.trim())!=null?a:"",this.tree=t,this.depth=((i==null?void 0:i.depth)||0)+1,this.index=0;let s=e.parentElement;(s==null?void 0:s.tagName.toLowerCase())==="li"&&(s==null||s.setAttribute("role","none")),e.setAttribute("aria-level",this.depth+""),e.getAttribute("aria-label")&&(this.label=(c=(h=e==null?void 0:e.getAttribute("aria-label"))==null?void 0:h.trim())!=null?c:""),this.isExpandable=!1,this.isVisible=!1,this.isInGroup=!!i;let r=e.nextElementSibling;for(;r;){if(r.tagName.toLowerCase()=="ul"){let x=`${(v=i==null?void 0:i.label)!=null?v:""} nav group ${this.label}`.replace(/[\W_]+/g,"_");e.setAttribute("aria-owns",x),e.setAttribute("aria-expanded","false"),r.setAttribute("role","group"),r.setAttribute("id",x),this.isExpandable=!0;break}r=r.nextElementSibling}this.init()}init(){this.el.tabIndex=-1,this.el.getAttribute("role")||this.el.setAttribute("role","treeitem"),this.el.addEventListener("keydown",this.handleKeydown.bind(this)),this.el.addEventListener("click",this.handleClick.bind(this)),this.el.addEventListener("focus",this.handleFocus.bind(this)),this.el.addEventListener("blur",this.handleBlur.bind(this))}isExpanded(){return this.isExpandable?this.el.getAttribute("aria-expanded")==="true":!1}isSelected(){return this.el.getAttribute("aria-selected")==="true"}handleClick(e){e.target!==this.el&&e.target!==this.el.firstElementChild||(this.isExpandable&&(this.isExpanded()&&this.isSelected()?this.tree.collapseTreeitem(this):this.tree.expandTreeitem(this),e.stopPropagation()),this.tree.setSelected(this))}handleFocus(){var t;let e=this.el;this.isExpandable&&(e=(t=e.firstElementChild)!=null?t:e),e.classList.add("focus")}handleBlur(){var t;let e=this.el;this.isExpandable&&(e=(t=e.firstElementChild)!=null?t:e),e.classList.remove("focus")}handleKeydown(e){if(e.altKey||e.ctrlKey||e.metaKey)return;let t=!1;switch(e.key){case" ":case"Enter":this.isExpandable?(this.isExpanded()&&this.isSelected()?this.tree.collapseTreeitem(this):this.tree.expandTreeitem(this),t=!0):e.stopPropagation(),this.tree.setSelected(this);break;case"ArrowUp":this.tree.setFocusToPreviousItem(this),t=!0;break;case"ArrowDown":this.tree.setFocusToNextItem(this),t=!0;break;case"ArrowRight":this.isExpandable&&(this.isExpanded()?this.tree.setFocusToNextItem(this):this.tree.expandTreeitem(this)),t=!0;break;case"ArrowLeft":this.isExpandable&&this.isExpanded()?(this.tree.collapseTreeitem(this),t=!0):this.isInGroup&&(this.tree.setFocusToParentItem(this),t=!0);break;case"Home":this.tree.setFocusToFirstItem(),t=!0;break;case"End":this.tree.setFocusToLastItem(),t=!0;break;default:e.key.length===1&&e.key.match(/\S/)&&(e.key=="*"?this.tree.expandAllSiblingItems(this):this.tree.setFocusByFirstCharacter(this,e.key),t=!0);break}t&&(e.stopPropagation(),e.preventDefault())}};function M(l,e){let t;return(...i)=>{let s=()=>{t=null,l(...i)};t&&clearTimeout(t),t=setTimeout(s,e)}}var T=class{constructor(e,t){this.table=e;this.toggleAll=t;this.expandAllItems=()=>{this.toggles.map(e=>e.setAttribute("aria-expanded","true")),this.update()};this.collapseAllItems=()=>{this.toggles.map(e=>e.setAttribute("aria-expanded","false")),this.update()};this.update=()=>{this.updateVisibleItems(),setTimeout(()=>this.updateGlobalToggle())};this.rows=Array.from(e.querySelectorAll("[data-aria-controls]")),this.toggles=Array.from(this.table.querySelectorAll("[aria-expanded]")),this.setAttributes(),this.attachEventListeners(),this.update()}setAttributes(){for(let e of["data-aria-controls","data-aria-labelledby","data-id"])this.table.querySelectorAll(`[${e}]`).forEach(t=>{var i;t.setAttribute(e.replace("data-",""),(i=t.getAttribute(e))!=null?i:""),t.removeAttribute(e)})}attachEventListeners(){var e;this.rows.forEach(t=>{t.addEventListener("click",i=>{this.handleToggleClick(i)})}),(e=this.toggleAll)==null||e.addEventListener("click",()=>{this.expandAllItems()}),document.addEventListener("keydown",t=>{(t.ctrlKey||t.metaKey)&&t.key==="f"&&this.expandAllItems()})}handleToggleClick(e){let t=e.currentTarget;(t==null?void 0:t.hasAttribute("aria-expanded"))||(t=this.table.querySelector(`button[aria-controls="${t==null?void 0:t.getAttribute("aria-controls")}"]`));let i=(t==null?void 0:t.getAttribute("aria-expanded"))==="true";t==null||t.setAttribute("aria-expanded",i?"false":"true"),e.stopPropagation(),this.update()}updateVisibleItems(){this.rows.map(e=>{var s;let t=(e==null?void 0:e.getAttribute("aria-expanded"))==="true",i=(s=e==null?void 0:e.getAttribute("aria-controls"))==null?void 0:s.trimEnd().split(" ");i==null||i.map(r=>{let n=document.getElementById(`${r}`);t?(n==null||n.classList.add("visible"),n==null||n.classList.remove("hidden")):(n==null||n.classList.add("hidden"),n==null||n.classList.remove("visible"))})})}updateGlobalToggle(){if(!this.toggleAll)return;this.rows.some(t=>t.hasAttribute("aria-expanded"))&&(this.toggleAll.style.display="block"),this.toggles.some(t=>t.getAttribute("aria-expanded")==="false")?(this.toggleAll.innerText="Expand all",this.toggleAll.onclick=this.expandAllItems):(this.toggleAll.innerText="Collapse all",this.toggleAll.onclick=this.collapseAllItems)}};y();var I=document.querySelector(".js-expandableTable");if(I){let l=new T(I,document.querySelector(".js-expandAllDirectories"));window.location.search.includes("expand-directories")&&l.expandAllItems()}var C=document.querySelector(".js-tree");if(C){let l=new f(C),e=L(l),t=document.querySelector(".js-mainNavMobile");t&&t.firstElementChild&&(t==null||t.replaceChild(e,t.firstElementChild)),e.firstElementChild&&new p(e.firstElementChild)}var o=document.querySelector(".js-readme"),E=document.querySelector(".js-readmeContent"),S=document.querySelector(".js-readmeOutline"),m=document.querySelectorAll(".js-readmeExpand"),k=document.querySelector(".js-readmeCollapse"),b=document.querySelector(".DocNavMobile-select");o&&E&&S&&m.length&&k&&(o.clientHeight>320&&(o==null||o.classList.remove("UnitReadme--expanded"),o==null||o.classList.add("UnitReadme--toggle")),window.location.hash.includes("readme")&&u(),b==null||b.addEventListener("change",l=>{l.target.value.startsWith("readme-")&&u()}),m.forEach(l=>l.addEventListener("click",e=>{e.preventDefault(),u(),o.scrollIntoView()})),k.addEventListener("click",l=>{l.preventDefault(),o.classList.remove("UnitReadme--expanded"),m[1]&&m[1].scrollIntoView({block:"center"})}),E.addEventListener("keyup",()=>{u()}),E.addEventListener("click",()=>{u()}),S.addEventListener("click",()=>{u()}),document.addEventListener("keydown",l=>{(l.ctrlKey||l.metaKey)&&l.key==="f"&&u()}));function u(){history.replaceState(null,"",`${location.pathname}#section-readme`),o==null||o.classList.add("UnitReadme--expanded")}function w(){var t;if(!location.hash)return;let l=document.getElementById(location.hash.slice(1)),e=(t=l==null?void 0:l.parentElement)==null?void 0:t.parentElement;(e==null?void 0:e.nodeName)==="DETAILS"&&(e.open=!0)}w();window.addEventListener("hashchange",()=>w());document.querySelectorAll(".js-buildContextSelect").forEach(l=>{l.addEventListener("change",e=>{window.location.search=`?GOOS=${e.target.value}`})});
+var h={PLAY_HREF:".js-exampleHref",PLAY_CONTAINER:".js-exampleContainer",EXAMPLE_INPUT:".Documentation-exampleCode",EXAMPLE_OUTPUT:".Documentation-exampleOutput",EXAMPLE_ERROR:".Documentation-exampleError",PLAY_BUTTON:".Documentation-examplePlayButton",SHARE_BUTTON:".Documentation-exampleShareButton",FORMAT_BUTTON:".Documentation-exampleFormatButton",RUN_BUTTON:".Documentation-exampleRunButton"},g=class{constructor(e){this.exampleEl=e;var t,i,s,r;this.exampleEl=e,this.anchorEl=e.querySelector("a"),this.errorEl=e.querySelector(h.EXAMPLE_ERROR),this.playButtonEl=e.querySelector(h.PLAY_BUTTON),this.shareButtonEl=e.querySelector(h.SHARE_BUTTON),this.formatButtonEl=e.querySelector(h.FORMAT_BUTTON),this.runButtonEl=e.querySelector(h.RUN_BUTTON),this.inputEl=this.makeTextArea(e.querySelector(h.EXAMPLE_INPUT)),this.outputEl=e.querySelector(h.EXAMPLE_OUTPUT),(t=this.playButtonEl)==null||t.addEventListener("click",()=>this.handleShareButtonClick()),(i=this.shareButtonEl)==null||i.addEventListener("click",()=>this.handleShareButtonClick()),(s=this.formatButtonEl)==null||s.addEventListener("click",()=>this.handleFormatButtonClick()),(r=this.runButtonEl)==null||r.addEventListener("click",()=>this.handleRunButtonClick()),!!this.inputEl&&(this.resize(),this.inputEl.addEventListener("keyup",()=>this.resize()),this.inputEl.addEventListener("keydown",l=>this.onKeydown(l)))}makeTextArea(e){var i,s;let t=document.createElement("textarea");return t.classList.add("Documentation-exampleCode","code"),t.spellcheck=!1,t.value=(i=e==null?void 0:e.textContent)!=null?i:"",(s=e==null?void 0:e.parentElement)==null||s.replaceChild(t,e),t}getAnchorHash(){var e;return(e=this.anchorEl)==null?void 0:e.hash}expand(){this.exampleEl.open=!0}resize(){var e;if((e=this.inputEl)==null?void 0:e.value){let t=(this.inputEl.value.match(/\n/g)||[]).length;this.inputEl.style.height=`${(20+t*20+12+2)/16}rem`}}onKeydown(e){e.key==="Tab"&&(document.execCommand("insertText",!1,"	"),e.preventDefault())}setInputText(e){this.inputEl&&(this.inputEl.value=e)}setOutputText(e){this.outputEl&&(this.outputEl.textContent=e)}setOutputHTML(e){this.outputEl&&(this.outputEl.innerHTML=e)}setErrorText(e){this.errorEl&&(this.errorEl.textContent=e),this.setOutputText("An error has occurred\u2026")}handleShareButtonClick(){var t;let e="https://play.golang.org/p/";this.setOutputText("Waiting for remote server\u2026"),fetch("/play/share",{method:"POST",body:(t=this.inputEl)==null?void 0:t.value}).then(i=>i.text()).then(i=>{let s=e+i;this.setOutputHTML(`<a href="${s}">${s}</a>`),window.open(s)}).catch(i=>{this.setErrorText(i)})}handleFormatButtonClick(){var t,i;this.setOutputText("Waiting for remote server\u2026");let e=new FormData;e.append("body",(i=(t=this.inputEl)==null?void 0:t.value)!=null?i:""),fetch("/play/fmt",{method:"POST",body:e}).then(s=>s.json()).then(({Body:s,Error:r})=>{this.setOutputText(r||"Done."),s&&(this.setInputText(s),this.resize())}).catch(s=>{this.setErrorText(s)})}handleRunButtonClick(){var i,s,r,l;this.setOutputText("Waiting for remote server\u2026");let e=(s=(i=this.inputEl)==null?void 0:i.value)!=null?s:"",t=(l=(r=document.querySelector(".js-playgroundVars"))==null?void 0:r.dataset)!=null?l:{};console.log(t.unitpath),t.pagetype!=="std"&&(e=e.concat(`
+-- go.mod --
+module play.ground
+
+require ${t.unitpath} ${t.version}
+`)),fetch("/play/compile",{method:"POST",body:JSON.stringify({body:e,version:2})}).then(a=>a.json()).then(async({Events:a,Errors:d})=>{this.setOutputText(d||"");for(let u of a||[])this.setOutputText(u.Message),await new Promise(m=>setTimeout(m,u.Delay/1e6))}).catch(a=>{this.setErrorText(a)})}};function y(){let n=location.hash.match(/^#(example-.*)$/);if(n){let i=document.getElementById(n[1]);i&&(i.open=!0)}let e=[...document.querySelectorAll(h.PLAY_HREF)],t=i=>e.find(s=>s.hash===i.getAnchorHash());for(let i of document.querySelectorAll(h.PLAY_CONTAINER)){let s=new g(i),r=t(s);r?r.addEventListener("click",()=>{s.expand()}):console.warn("example href not found")}}var f=class{constructor(e){this.el=e;this.el.addEventListener("change",t=>{let i=t.target,s=i.value;i.value.startsWith("/")||(s="/"+s),window.location.href=s})}};function L(n){let e=document.createElement("label");e.classList.add("go-Label"),e.setAttribute("aria-label","Menu");let t=document.createElement("select");t.classList.add("go-Select","js-selectNav"),e.appendChild(t);let i=document.createElement("optgroup");i.label="Outline",t.appendChild(i);let s={},r;for(let l of n.treeitems){if(Number(l.depth)>4)continue;l.groupTreeitem?(r=s[l.groupTreeitem.label],r||(r=s[l.groupTreeitem.label]=document.createElement("optgroup"),r.label=l.groupTreeitem.label,t.appendChild(r))):r=i;let a=document.createElement("option");a.label=l.label,a.textContent=l.label,a.value=l.el.href.replace(window.location.origin,"").replace("/",""),r.appendChild(a)}return n.addObserver(l=>{var u;let a=l.el.hash,d=(u=t.querySelector(`[value$="${a}"]`))==null?void 0:u.value;d&&(t.value=d)},50),e}var T=class{constructor(e){this.el=e;this.handleResize=()=>{this.el.style.setProperty("--js-tree-height","100vh"),this.el.style.setProperty("--js-tree-height",this.el.clientHeight+"px")};this.treeitems=[],this.firstChars=[],this.firstTreeitem=null,this.lastTreeitem=null,this.observerCallbacks=[],this.init()}init(){this.handleResize(),window.addEventListener("resize",this.handleResize),this.findTreeItems(),this.updateVisibleTreeitems(),this.observeTargets(),this.firstTreeitem&&(this.firstTreeitem.el.tabIndex=0)}observeTargets(){this.addObserver(i=>{this.expandTreeitem(i),this.setSelected(i)});let e=new Map,t=new IntersectionObserver(i=>{for(let s of i)e.set(s.target.id,s.isIntersecting||s.intersectionRatio===1);for(let[s,r]of e)if(r){let l=this.treeitems.find(a=>{var d;return(d=a.el)==null?void 0:d.href.endsWith(`#${s}`)});if(l)for(let a of this.observerCallbacks)a(l);break}},{threshold:1,rootMargin:"-60px 0px 0px 0px"});for(let i of this.treeitems.map(s=>s.el.getAttribute("href")))if(i){let s=i.replace(window.location.origin,"").replace("/","").replace("#",""),r=document.getElementById(s);r&&t.observe(r)}}addObserver(e,t=200){this.observerCallbacks.push(M(e,t))}setFocusToNextItem(e){let t=null;for(let i=e.index+1;i<this.treeitems.length;i++){let s=this.treeitems[i];if(s.isVisible){t=s;break}}t&&this.setFocusToItem(t)}setFocusToPreviousItem(e){let t=null;for(let i=e.index-1;i>-1;i--){let s=this.treeitems[i];if(s.isVisible){t=s;break}}t&&this.setFocusToItem(t)}setFocusToParentItem(e){e.groupTreeitem&&this.setFocusToItem(e.groupTreeitem)}setFocusToFirstItem(){this.firstTreeitem&&this.setFocusToItem(this.firstTreeitem)}setFocusToLastItem(){this.lastTreeitem&&this.setFocusToItem(this.lastTreeitem)}setSelected(e){var t;for(let i of this.el.querySelectorAll('[aria-expanded="true"]'))i!==e.el&&(((t=i.nextElementSibling)==null?void 0:t.contains(e.el))||i.setAttribute("aria-expanded","false"));for(let i of this.el.querySelectorAll("[aria-selected]"))i!==e.el&&i.setAttribute("aria-selected","false");e.el.setAttribute("aria-selected","true"),this.updateVisibleTreeitems(),this.setFocusToItem(e,!1)}expandTreeitem(e){let t=e;for(;t;)t.isExpandable&&t.el.setAttribute("aria-expanded","true"),t=t.groupTreeitem;this.updateVisibleTreeitems()}expandAllSiblingItems(e){for(let t of this.treeitems)t.groupTreeitem===e.groupTreeitem&&t.isExpandable&&this.expandTreeitem(t)}collapseTreeitem(e){let t=null;e.isExpanded()?t=e:t=e.groupTreeitem,t&&(t.el.setAttribute("aria-expanded","false"),this.updateVisibleTreeitems(),this.setFocusToItem(t))}setFocusByFirstCharacter(e,t){let i,s;t=t.toLowerCase(),i=e.index+1,i===this.treeitems.length&&(i=0),s=this.getIndexFirstChars(i,t),s===-1&&(s=this.getIndexFirstChars(0,t)),s>-1&&this.setFocusToItem(this.treeitems[s])}findTreeItems(){let e=(t,i)=>{let s=i,r=t.firstElementChild;for(;r;)(r.tagName==="A"||r.tagName==="SPAN")&&(s=new A(r,this,i),this.treeitems.push(s),this.firstChars.push(s.label.substring(0,1).toLowerCase())),r.firstElementChild&&e(r,s),r=r.nextElementSibling};e(this.el,null),this.treeitems.map((t,i)=>t.index=i)}updateVisibleTreeitems(){this.firstTreeitem=this.treeitems[0];for(let e of this.treeitems){let t=e.groupTreeitem;for(e.isVisible=!0;t&&t.el!==this.el;)t.isExpanded()||(e.isVisible=!1),t=t.groupTreeitem;e.isVisible&&(this.lastTreeitem=e)}}setFocusToItem(e,t=!0){e.el.tabIndex=0,t&&e.el.focus();for(let i of this.treeitems)i!==e&&(i.el.tabIndex=-1)}getIndexFirstChars(e,t){for(let i=e;i<this.firstChars.length;i++)if(this.treeitems[i].isVisible&&t===this.firstChars[i])return i;return-1}},A=class{constructor(e,t,i){var l,a,d,u,m;e.tabIndex=-1,this.el=e,this.groupTreeitem=i,this.label=(a=(l=e.textContent)==null?void 0:l.trim())!=null?a:"",this.tree=t,this.depth=((i==null?void 0:i.depth)||0)+1,this.index=0;let s=e.parentElement;(s==null?void 0:s.tagName.toLowerCase())==="li"&&(s==null||s.setAttribute("role","none")),e.setAttribute("aria-level",this.depth+""),e.getAttribute("aria-label")&&(this.label=(u=(d=e==null?void 0:e.getAttribute("aria-label"))==null?void 0:d.trim())!=null?u:""),this.isExpandable=!1,this.isVisible=!1,this.isInGroup=!!i;let r=e.nextElementSibling;for(;r;){if(r.tagName.toLowerCase()=="ul"){let x=`${(m=i==null?void 0:i.label)!=null?m:""} nav group ${this.label}`.replace(/[\W_]+/g,"_");e.setAttribute("aria-owns",x),e.setAttribute("aria-expanded","false"),r.setAttribute("role","group"),r.setAttribute("id",x),this.isExpandable=!0;break}r=r.nextElementSibling}this.init()}init(){this.el.tabIndex=-1,this.el.getAttribute("role")||this.el.setAttribute("role","treeitem"),this.el.addEventListener("keydown",this.handleKeydown.bind(this)),this.el.addEventListener("click",this.handleClick.bind(this)),this.el.addEventListener("focus",this.handleFocus.bind(this)),this.el.addEventListener("blur",this.handleBlur.bind(this))}isExpanded(){return this.isExpandable?this.el.getAttribute("aria-expanded")==="true":!1}isSelected(){return this.el.getAttribute("aria-selected")==="true"}handleClick(e){e.target!==this.el&&e.target!==this.el.firstElementChild||(this.isExpandable&&(this.isExpanded()&&this.isSelected()?this.tree.collapseTreeitem(this):this.tree.expandTreeitem(this),e.stopPropagation()),this.tree.setSelected(this))}handleFocus(){var t;let e=this.el;this.isExpandable&&(e=(t=e.firstElementChild)!=null?t:e),e.classList.add("focus")}handleBlur(){var t;let e=this.el;this.isExpandable&&(e=(t=e.firstElementChild)!=null?t:e),e.classList.remove("focus")}handleKeydown(e){if(e.altKey||e.ctrlKey||e.metaKey)return;let t=!1;switch(e.key){case" ":case"Enter":this.isExpandable?(this.isExpanded()&&this.isSelected()?this.tree.collapseTreeitem(this):this.tree.expandTreeitem(this),t=!0):e.stopPropagation(),this.tree.setSelected(this);break;case"ArrowUp":this.tree.setFocusToPreviousItem(this),t=!0;break;case"ArrowDown":this.tree.setFocusToNextItem(this),t=!0;break;case"ArrowRight":this.isExpandable&&(this.isExpanded()?this.tree.setFocusToNextItem(this):this.tree.expandTreeitem(this)),t=!0;break;case"ArrowLeft":this.isExpandable&&this.isExpanded()?(this.tree.collapseTreeitem(this),t=!0):this.isInGroup&&(this.tree.setFocusToParentItem(this),t=!0);break;case"Home":this.tree.setFocusToFirstItem(),t=!0;break;case"End":this.tree.setFocusToLastItem(),t=!0;break;default:e.key.length===1&&e.key.match(/\S/)&&(e.key=="*"?this.tree.expandAllSiblingItems(this):this.tree.setFocusByFirstCharacter(this,e.key),t=!0);break}t&&(e.stopPropagation(),e.preventDefault())}};function M(n,e){let t;return(...i)=>{let s=()=>{t=null,n(...i)};t&&clearTimeout(t),t=setTimeout(s,e)}}var E=class{constructor(e,t){this.table=e;this.toggleAll=t;this.expandAllItems=()=>{this.toggles.map(e=>e.setAttribute("aria-expanded","true")),this.update()};this.collapseAllItems=()=>{this.toggles.map(e=>e.setAttribute("aria-expanded","false")),this.update()};this.update=()=>{this.updateVisibleItems(),setTimeout(()=>this.updateGlobalToggle())};this.rows=Array.from(e.querySelectorAll("[data-aria-controls]")),this.toggles=Array.from(this.table.querySelectorAll("[aria-expanded]")),this.setAttributes(),this.attachEventListeners(),this.update()}setAttributes(){for(let e of["data-aria-controls","data-aria-labelledby","data-id"])this.table.querySelectorAll(`[${e}]`).forEach(t=>{var i;t.setAttribute(e.replace("data-",""),(i=t.getAttribute(e))!=null?i:""),t.removeAttribute(e)})}attachEventListeners(){var e;this.rows.forEach(t=>{t.addEventListener("click",i=>{this.handleToggleClick(i)})}),(e=this.toggleAll)==null||e.addEventListener("click",()=>{this.expandAllItems()}),document.addEventListener("keydown",t=>{(t.ctrlKey||t.metaKey)&&t.key==="f"&&this.expandAllItems()})}handleToggleClick(e){let t=e.currentTarget;(t==null?void 0:t.hasAttribute("aria-expanded"))||(t=this.table.querySelector(`button[aria-controls="${t==null?void 0:t.getAttribute("aria-controls")}"]`));let i=(t==null?void 0:t.getAttribute("aria-expanded"))==="true";t==null||t.setAttribute("aria-expanded",i?"false":"true"),e.stopPropagation(),this.update()}updateVisibleItems(){this.rows.map(e=>{var s;let t=(e==null?void 0:e.getAttribute("aria-expanded"))==="true",i=(s=e==null?void 0:e.getAttribute("aria-controls"))==null?void 0:s.trimEnd().split(" ");i==null||i.map(r=>{let l=document.getElementById(`${r}`);t?(l==null||l.classList.add("visible"),l==null||l.classList.remove("hidden")):(l==null||l.classList.add("hidden"),l==null||l.classList.remove("visible"))})})}updateGlobalToggle(){if(!this.toggleAll)return;this.rows.some(t=>t.hasAttribute("aria-expanded"))&&(this.toggleAll.style.display="block"),this.toggles.some(t=>t.getAttribute("aria-expanded")==="false")?(this.toggleAll.innerText="Expand all",this.toggleAll.onclick=this.expandAllItems):(this.toggleAll.innerText="Collapse all",this.toggleAll.onclick=this.collapseAllItems)}};y();var I=document.querySelector(".js-expandableTable");if(I){let n=new E(I,document.querySelector(".js-expandAllDirectories"));window.location.search.includes("expand-directories")&&n.expandAllItems()}var C=document.querySelector(".js-tree");if(C){let n=new T(C),e=L(n),t=document.querySelector(".js-mainNavMobile");t&&t.firstElementChild&&(t==null||t.replaceChild(e,t.firstElementChild)),e.firstElementChild&&new f(e.firstElementChild)}var o=document.querySelector(".js-readme"),b=document.querySelector(".js-readmeContent"),S=document.querySelector(".js-readmeOutline"),p=document.querySelectorAll(".js-readmeExpand"),k=document.querySelector(".js-readmeCollapse"),v=document.querySelector(".DocNavMobile-select");o&&b&&S&&p.length&&k&&(o.clientHeight>320&&(o==null||o.classList.remove("UnitReadme--expanded"),o==null||o.classList.add("UnitReadme--toggle")),window.location.hash.includes("readme")&&c(),v==null||v.addEventListener("change",n=>{n.target.value.startsWith("readme-")&&c()}),p.forEach(n=>n.addEventListener("click",e=>{e.preventDefault(),c(),o.scrollIntoView()})),k.addEventListener("click",n=>{n.preventDefault(),o.classList.remove("UnitReadme--expanded"),p[1]&&p[1].scrollIntoView({block:"center"})}),b.addEventListener("keyup",()=>{c()}),b.addEventListener("click",()=>{c()}),S.addEventListener("click",()=>{c()}),document.addEventListener("keydown",n=>{(n.ctrlKey||n.metaKey)&&n.key==="f"&&c()}));function c(){history.replaceState(null,"",`${location.pathname}#section-readme`),o==null||o.classList.add("UnitReadme--expanded")}function w(){var t;if(!location.hash)return;let n=document.getElementById(location.hash.slice(1)),e=(t=n==null?void 0:n.parentElement)==null?void 0:t.parentElement;(e==null?void 0:e.nodeName)==="DETAILS"&&(e.open=!0)}w();window.addEventListener("hashchange",()=>w());document.querySelectorAll(".js-buildContextSelect").forEach(n=>{n.addEventListener("change",e=>{window.location.search=`?GOOS=${e.target.value}`})});
 /*!
  * @license
  * Copyright 2020 The Go Authors. All rights reserved.
diff --git a/static/frontend/unit/main/main.js.map b/static/frontend/unit/main/main.js.map
index 4ddd214..540f8ab 100644
--- a/static/frontend/unit/main/main.js.map
+++ b/static/frontend/unit/main/main.js.map
@@ -1,7 +1,7 @@
 {
   "version": 3,
   "sources": ["../../../shared/playground/playground.ts", "../../../shared/outline/select.ts", "../../../shared/outline/tree.ts", "../../../shared/table/table.ts", "main.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\n// This file implements the playground implementation of the documentation\n// page. The playground involves a \"play\" button that allows you to open up\n// a new link to play.golang.org using the example code.\n\n// The CSS is in static/frontend/unit/main/_doc.css\n\n/**\n * CSS classes used by PlaygroundExampleController\n */\nconst PlayExampleClassName = {\n  PLAY_HREF: '.js-exampleHref',\n  PLAY_CONTAINER: '.js-exampleContainer',\n  EXAMPLE_INPUT: '.Documentation-exampleCode',\n  EXAMPLE_OUTPUT: '.Documentation-exampleOutput',\n  EXAMPLE_ERROR: '.Documentation-exampleError',\n  PLAY_BUTTON: '.Documentation-examplePlayButton',\n  SHARE_BUTTON: '.Documentation-exampleShareButton',\n  FORMAT_BUTTON: '.Documentation-exampleFormatButton',\n  RUN_BUTTON: '.Documentation-exampleRunButton',\n};\n\n/**\n * This controller enables playground examples to expand their dropdown or\n * generate shareable Go Playground URLs.\n */\nexport class PlaygroundExampleController {\n  /**\n   * The anchor tag used to identify the container with an example href.\n   * There is only one in an example container div.\n   */\n  private readonly anchorEl: HTMLAnchorElement | null;\n\n  /**\n   * The error element\n   */\n  private readonly errorEl: Element | null;\n\n  /**\n   * Buttons that redirect to an example's playground, this element\n   * only exists in executable examples.\n   */\n  private readonly playButtonEl: Element | null;\n  private readonly shareButtonEl: Element | null;\n\n  /**\n   * Button that formats the code in an example's playground.\n   */\n  private readonly formatButtonEl: Element | null;\n\n  /**\n   * Button that runs the code in an example's playground, this element\n   * only exists in executable examples.\n   */\n  private readonly runButtonEl: Element | null;\n\n  /**\n   * The executable code of an example.\n   */\n  private readonly inputEl: HTMLTextAreaElement | null;\n\n  /**\n   * The output of the given example code. This only exists if the\n   * author of the package provides an output for this example.\n   */\n  private readonly outputEl: Element | null;\n\n  /**\n   * @param exampleEl The div that contains playground content for the given example.\n   */\n  constructor(private readonly exampleEl: HTMLDetailsElement) {\n    this.exampleEl = exampleEl;\n    this.anchorEl = exampleEl.querySelector('a');\n    this.errorEl = exampleEl.querySelector(PlayExampleClassName.EXAMPLE_ERROR);\n    this.playButtonEl = exampleEl.querySelector(PlayExampleClassName.PLAY_BUTTON);\n    this.shareButtonEl = exampleEl.querySelector(PlayExampleClassName.SHARE_BUTTON);\n    this.formatButtonEl = exampleEl.querySelector(PlayExampleClassName.FORMAT_BUTTON);\n    this.runButtonEl = exampleEl.querySelector(PlayExampleClassName.RUN_BUTTON);\n    this.inputEl = this.makeTextArea(exampleEl.querySelector(PlayExampleClassName.EXAMPLE_INPUT));\n    this.outputEl = exampleEl.querySelector(PlayExampleClassName.EXAMPLE_OUTPUT);\n\n    // This is legacy listener to be replaced the listener for shareButtonEl.\n    this.playButtonEl?.addEventListener('click', () => this.handleShareButtonClick());\n    this.shareButtonEl?.addEventListener('click', () => this.handleShareButtonClick());\n    this.formatButtonEl?.addEventListener('click', () => this.handleFormatButtonClick());\n    this.runButtonEl?.addEventListener('click', () => this.handleRunButtonClick());\n\n    if (!this.inputEl) return;\n\n    this.resize();\n    this.inputEl.addEventListener('keyup', () => this.resize());\n    this.inputEl.addEventListener('keydown', e => this.onKeydown(e));\n  }\n\n  /**\n   * Replace the pre element with a textarea. The examples are initially rendered\n   * as pre elements so they're fully visible when JS is disabled.\n   */\n  makeTextArea(el: Element | null): HTMLTextAreaElement {\n    const t = document.createElement('textarea');\n    t.classList.add('Documentation-exampleCode', 'code');\n    t.spellcheck = false;\n    t.value = el?.textContent ?? '';\n    el?.parentElement?.replaceChild(t, el);\n    return t;\n  }\n\n  /**\n   * Retrieve the hash value of the anchor element.\n   */\n  getAnchorHash(): string | undefined {\n    return this.anchorEl?.hash;\n  }\n\n  /**\n   * Expands the current playground example.\n   */\n  expand(): void {\n    this.exampleEl.open = true;\n  }\n\n  /**\n   * Resizes the input element to accommodate the amount of text present.\n   */\n  private resize(): void {\n    if (this.inputEl?.value) {\n      const numLineBreaks = (this.inputEl.value.match(/\\n/g) || []).length;\n      // min-height + lines x line-height + padding + border\n      this.inputEl.style.height = `${(20 + numLineBreaks * 20 + 12 + 2) / 16}rem`;\n    }\n  }\n\n  /**\n   * Handler to override keyboard behavior in the playground's\n   * textarea element.\n   *\n   * Tab key inserts tabs into the example playground instead of\n   * switching to the next interactive element.\n   * @param e input element keyboard event.\n   */\n  private onKeydown(e: KeyboardEvent) {\n    if (e.key === 'Tab') {\n      document.execCommand('insertText', false, '\\t');\n      e.preventDefault();\n    }\n  }\n\n  /**\n   * Changes the text of the example's input box.\n   */\n  private setInputText(output: string) {\n    if (this.inputEl) {\n      this.inputEl.value = output;\n    }\n  }\n\n  /**\n   * Changes the text of the example's output box.\n   */\n  private setOutputText(output: string) {\n    if (this.outputEl) {\n      this.outputEl.textContent = output;\n    }\n  }\n\n  private setOutputHTML(output: string) {\n    if (this.outputEl) {\n      this.outputEl.innerHTML = output;\n    }\n  }\n\n  /**\n   * Sets the error message text and overwrites\n   * output box to indicate a failed response.\n   */\n  private setErrorText(err: string) {\n    if (this.errorEl) {\n      this.errorEl.textContent = err;\n    }\n    this.setOutputText('An error has occurred\u2026');\n  }\n\n  /**\n   * Opens a new window to play.golang.org using the\n   * example snippet's code in the playground.\n   */\n  private handleShareButtonClick() {\n    const PLAYGROUND_BASE_URL = 'https://play.golang.org/p/';\n\n    this.setOutputText('Waiting for remote server\u2026');\n\n    fetch('/play/share', {\n      method: 'POST',\n      body: this.inputEl?.value,\n    })\n      .then(res => res.text())\n      .then(shareId => {\n        const href = PLAYGROUND_BASE_URL + shareId;\n        this.setOutputHTML(`<a href=\"${href}\">${href}</a>`);\n        window.open(href);\n      })\n      .catch(err => {\n        this.setErrorText(err);\n      });\n  }\n\n  /**\n   * Runs gofmt on the example snippet in the playground.\n   */\n  private handleFormatButtonClick() {\n    this.setOutputText('Waiting for remote server\u2026');\n    const body = new FormData();\n    body.append('body', this.inputEl?.value ?? '');\n\n    fetch('/play/fmt', {\n      method: 'POST',\n      body: body,\n    })\n      .then(res => res.json())\n      .then(({ Body, Error }) => {\n        this.setOutputText(Error || 'Done.');\n        if (Body) {\n          this.setInputText(Body);\n          this.resize();\n        }\n      })\n      .catch(err => {\n        this.setErrorText(err);\n      });\n  }\n\n  /**\n   * Runs the code snippet in the example playground.\n   */\n  private handleRunButtonClick() {\n    this.setOutputText('Waiting for remote server\u2026');\n\n    fetch('/play/compile', {\n      method: 'POST',\n      body: JSON.stringify({ body: this.inputEl?.value, version: 2 }),\n    })\n      .then(res => res.json())\n      .then(async ({ Events, Errors }) => {\n        this.setOutputText(Errors || '');\n        for (const e of Events || []) {\n          this.setOutputText(e.Message);\n          await new Promise(resolve => setTimeout(resolve, e.Delay / 1000000));\n        }\n      })\n      .catch(err => {\n        this.setErrorText(err);\n      });\n  }\n}\n\nexport function initPlaygrounds(): void {\n  const exampleHashRegex = location.hash.match(/^#(example-.*)$/);\n  if (exampleHashRegex) {\n    const exampleHashEl = document.getElementById(exampleHashRegex[1]) as HTMLDetailsElement;\n    if (exampleHashEl) {\n      exampleHashEl.open = true;\n    }\n  }\n\n  // We use a spread operator to convert a nodelist into an array of elements.\n  const exampleHrefs = [\n    ...document.querySelectorAll<HTMLAnchorElement>(PlayExampleClassName.PLAY_HREF),\n  ];\n\n  /**\n   * Sometimes exampleHrefs and playContainers are in different order, so we\n   * find an exampleHref from a common hash.\n   * @param playContainer - playground container\n   */\n  const findExampleHash = (playContainer: PlaygroundExampleController) =>\n    exampleHrefs.find(ex => {\n      return ex.hash === playContainer.getAnchorHash();\n    });\n\n  for (const el of document.querySelectorAll(PlayExampleClassName.PLAY_CONTAINER)) {\n    // There should be the same amount of hrefs referencing examples as example containers.\n    const playContainer = new PlaygroundExampleController(el as HTMLDetailsElement);\n    const exampleHref = findExampleHash(playContainer);\n    if (exampleHref) {\n      exampleHref.addEventListener('click', () => {\n        playContainer.expand();\n      });\n    } else {\n      console.warn('example href not found');\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\n/**\n * TreeNavController is the navigation tree component of the documentation page.\n * It adds accessiblity attributes to a tree, observes the heading elements\n * focus the topmost link for headings visible on the page, and implements the\n * WAI-ARIA Treeview Design Pattern with full\n * [keyboard support](https://www.w3.org/TR/wai-aria-practices/examples/treeview/treeview-2/treeview-2a.html#kbd_label).\n */\nexport class TreeNavController {\n  treeitems: TreeItem[];\n\n  /**\n   * firstChars is the first character of each treeitem in the same order\n   * as this.treeitems. We use this array to set focus by character when\n   * navigating the tree with a keyboard.\n   */\n  private firstChars: string[];\n  private firstTreeitem: TreeItem | null;\n  private lastTreeitem: TreeItem | null;\n  private observerCallbacks: ((t: TreeItem) => void)[];\n\n  constructor(private el: HTMLElement) {\n    this.treeitems = [];\n    this.firstChars = [];\n    this.firstTreeitem = null;\n    this.lastTreeitem = null;\n    this.observerCallbacks = [];\n    this.init();\n  }\n\n  private init(): void {\n    this.handleResize();\n    window.addEventListener('resize', this.handleResize);\n    this.findTreeItems();\n    this.updateVisibleTreeitems();\n    this.observeTargets();\n    if (this.firstTreeitem) {\n      this.firstTreeitem.el.tabIndex = 0;\n    }\n  }\n\n  private handleResize = (): void => {\n    this.el.style.setProperty('--js-tree-height', '100vh');\n    this.el.style.setProperty('--js-tree-height', this.el.clientHeight + 'px');\n  };\n\n  private observeTargets() {\n    this.addObserver(treeitem => {\n      this.expandTreeitem(treeitem);\n      this.setSelected(treeitem);\n      // TODO: Fix scroll issue in https://golang.org/issue/47450.\n      // treeitem.el.scrollIntoView({ block: 'nearest' });\n    });\n\n    const targets = new Map<string, boolean>();\n    const observer = new IntersectionObserver(\n      entries => {\n        for (const entry of entries) {\n          targets.set(entry.target.id, entry.isIntersecting || entry.intersectionRatio === 1);\n        }\n        for (const [id, isIntersecting] of targets) {\n          if (isIntersecting) {\n            const active = this.treeitems.find(t =>\n              (t.el as HTMLAnchorElement)?.href.endsWith(`#${id}`)\n            );\n            if (active) {\n              for (const fn of this.observerCallbacks) {\n                fn(active);\n              }\n            }\n            break;\n          }\n        }\n      },\n      {\n        threshold: 1.0,\n        rootMargin: '-60px 0px 0px 0px',\n      }\n    );\n\n    for (const href of this.treeitems.map(t => t.el.getAttribute('href'))) {\n      if (href) {\n        const id = href.replace(window.location.origin, '').replace('/', '').replace('#', '');\n        const target = document.getElementById(id);\n        if (target) {\n          observer.observe(target);\n        }\n      }\n    }\n  }\n\n  addObserver(fn: (t: TreeItem) => void, delay = 200): void {\n    this.observerCallbacks.push(debounce(fn, delay));\n  }\n\n  setFocusToNextItem(currentItem: TreeItem): void {\n    let nextItem = null;\n    for (let i = currentItem.index + 1; i < this.treeitems.length; i++) {\n      const ti = this.treeitems[i];\n      if (ti.isVisible) {\n        nextItem = ti;\n        break;\n      }\n    }\n    if (nextItem) {\n      this.setFocusToItem(nextItem);\n    }\n  }\n\n  setFocusToPreviousItem(currentItem: TreeItem): void {\n    let prevItem = null;\n    for (let i = currentItem.index - 1; i > -1; i--) {\n      const ti = this.treeitems[i];\n      if (ti.isVisible) {\n        prevItem = ti;\n        break;\n      }\n    }\n    if (prevItem) {\n      this.setFocusToItem(prevItem);\n    }\n  }\n\n  setFocusToParentItem(currentItem: TreeItem): void {\n    if (currentItem.groupTreeitem) {\n      this.setFocusToItem(currentItem.groupTreeitem);\n    }\n  }\n\n  setFocusToFirstItem(): void {\n    this.firstTreeitem && this.setFocusToItem(this.firstTreeitem);\n  }\n\n  setFocusToLastItem(): void {\n    this.lastTreeitem && this.setFocusToItem(this.lastTreeitem);\n  }\n\n  setSelected(currentItem: TreeItem): void {\n    for (const l1 of this.el.querySelectorAll('[aria-expanded=\"true\"]')) {\n      if (l1 === currentItem.el) continue;\n      if (!l1.nextElementSibling?.contains(currentItem.el)) {\n        l1.setAttribute('aria-expanded', 'false');\n      }\n    }\n    for (const l1 of this.el.querySelectorAll('[aria-selected]')) {\n      if (l1 !== currentItem.el) {\n        l1.setAttribute('aria-selected', 'false');\n      }\n    }\n    currentItem.el.setAttribute('aria-selected', 'true');\n    this.updateVisibleTreeitems();\n    this.setFocusToItem(currentItem, false);\n  }\n\n  expandTreeitem(treeitem: TreeItem): void {\n    let currentItem: TreeItem | null = treeitem;\n    while (currentItem) {\n      if (currentItem.isExpandable) {\n        currentItem.el.setAttribute('aria-expanded', 'true');\n      }\n      currentItem = currentItem.groupTreeitem;\n    }\n    this.updateVisibleTreeitems();\n  }\n\n  expandAllSiblingItems(currentItem: TreeItem): void {\n    for (const ti of this.treeitems) {\n      if (ti.groupTreeitem === currentItem.groupTreeitem && ti.isExpandable) {\n        this.expandTreeitem(ti);\n      }\n    }\n  }\n\n  collapseTreeitem(currentItem: TreeItem): void {\n    let groupTreeitem = null;\n\n    if (currentItem.isExpanded()) {\n      groupTreeitem = currentItem;\n    } else {\n      groupTreeitem = currentItem.groupTreeitem;\n    }\n\n    if (groupTreeitem) {\n      groupTreeitem.el.setAttribute('aria-expanded', 'false');\n      this.updateVisibleTreeitems();\n      this.setFocusToItem(groupTreeitem);\n    }\n  }\n\n  setFocusByFirstCharacter(currentItem: TreeItem, char: string): void {\n    let start: number, index: number;\n    char = char.toLowerCase();\n\n    // Get start index for search based on position of currentItem\n    start = currentItem.index + 1;\n    if (start === this.treeitems.length) {\n      start = 0;\n    }\n\n    // Check remaining slots in the menu\n    index = this.getIndexFirstChars(start, char);\n\n    // If not found in remaining slots, check from beginning\n    if (index === -1) {\n      index = this.getIndexFirstChars(0, char);\n    }\n\n    // If match was found...\n    if (index > -1) {\n      this.setFocusToItem(this.treeitems[index]);\n    }\n  }\n\n  private findTreeItems() {\n    const findItems = (el: HTMLElement, group: TreeItem | null) => {\n      let ti = group;\n      let curr = el.firstElementChild as HTMLElement;\n      while (curr) {\n        if (curr.tagName === 'A' || curr.tagName === 'SPAN') {\n          ti = new TreeItem(curr, this, group);\n          this.treeitems.push(ti);\n          this.firstChars.push(ti.label.substring(0, 1).toLowerCase());\n        }\n        if (curr.firstElementChild) {\n          findItems(curr, ti);\n        }\n        curr = curr.nextElementSibling as HTMLElement;\n      }\n    };\n    findItems(this.el as HTMLElement, null);\n    this.treeitems.map((ti, idx) => (ti.index = idx));\n  }\n\n  private updateVisibleTreeitems(): void {\n    this.firstTreeitem = this.treeitems[0];\n\n    for (const ti of this.treeitems) {\n      let parent = ti.groupTreeitem;\n      ti.isVisible = true;\n      while (parent && parent.el !== this.el) {\n        if (!parent.isExpanded()) {\n          ti.isVisible = false;\n        }\n        parent = parent.groupTreeitem;\n      }\n      if (ti.isVisible) {\n        this.lastTreeitem = ti;\n      }\n    }\n  }\n\n  private setFocusToItem(treeitem: TreeItem, focusEl = true) {\n    treeitem.el.tabIndex = 0;\n    if (focusEl) {\n      treeitem.el.focus();\n    }\n    for (const ti of this.treeitems) {\n      if (ti !== treeitem) {\n        ti.el.tabIndex = -1;\n      }\n    }\n  }\n\n  private getIndexFirstChars(startIndex: number, char: string): number {\n    for (let i = startIndex; i < this.firstChars.length; i++) {\n      if (this.treeitems[i].isVisible && char === this.firstChars[i]) {\n        return i;\n      }\n    }\n    return -1;\n  }\n}\n\nclass TreeItem {\n  el: HTMLElement;\n  groupTreeitem: TreeItem | null;\n  label: string;\n  isExpandable: boolean;\n  isVisible: boolean;\n  depth: number;\n  index: number;\n\n  private tree: TreeNavController;\n  private isInGroup: boolean;\n\n  constructor(el: HTMLElement, treeObj: TreeNavController, group: TreeItem | null) {\n    el.tabIndex = -1;\n    this.el = el;\n    this.groupTreeitem = group;\n    this.label = el.textContent?.trim() ?? '';\n    this.tree = treeObj;\n    this.depth = (group?.depth || 0) + 1;\n    this.index = 0;\n\n    const parent = el.parentElement;\n    if (parent?.tagName.toLowerCase() === 'li') {\n      parent?.setAttribute('role', 'none');\n    }\n    el.setAttribute('aria-level', this.depth + '');\n    if (el.getAttribute('aria-label')) {\n      this.label = el?.getAttribute('aria-label')?.trim() ?? '';\n    }\n\n    this.isExpandable = false;\n    this.isVisible = false;\n    this.isInGroup = !!group;\n\n    let curr = el.nextElementSibling;\n    while (curr) {\n      if (curr.tagName.toLowerCase() == 'ul') {\n        const groupId = `${group?.label ?? ''} nav group ${this.label}`.replace(/[\\W_]+/g, '_');\n        el.setAttribute('aria-owns', groupId);\n        el.setAttribute('aria-expanded', 'false');\n        curr.setAttribute('role', 'group');\n        curr.setAttribute('id', groupId);\n        this.isExpandable = true;\n        break;\n      }\n\n      curr = curr.nextElementSibling;\n    }\n    this.init();\n  }\n\n  private init() {\n    this.el.tabIndex = -1;\n    if (!this.el.getAttribute('role')) {\n      this.el.setAttribute('role', 'treeitem');\n    }\n    this.el.addEventListener('keydown', this.handleKeydown.bind(this));\n    this.el.addEventListener('click', this.handleClick.bind(this));\n    this.el.addEventListener('focus', this.handleFocus.bind(this));\n    this.el.addEventListener('blur', this.handleBlur.bind(this));\n  }\n\n  isExpanded() {\n    if (this.isExpandable) {\n      return this.el.getAttribute('aria-expanded') === 'true';\n    }\n\n    return false;\n  }\n\n  isSelected() {\n    return this.el.getAttribute('aria-selected') === 'true';\n  }\n\n  private handleClick(event: MouseEvent) {\n    // only process click events that directly happened on this treeitem\n    if (event.target !== this.el && event.target !== this.el.firstElementChild) {\n      return;\n    }\n    if (this.isExpandable) {\n      if (this.isExpanded() && this.isSelected()) {\n        this.tree.collapseTreeitem(this);\n      } else {\n        this.tree.expandTreeitem(this);\n      }\n      event.stopPropagation();\n    }\n    this.tree.setSelected(this);\n  }\n\n  private handleFocus() {\n    let el = this.el;\n    if (this.isExpandable) {\n      el = (el.firstElementChild as HTMLElement) ?? el;\n    }\n    el.classList.add('focus');\n  }\n\n  private handleBlur() {\n    let el = this.el;\n    if (this.isExpandable) {\n      el = (el.firstElementChild as HTMLElement) ?? el;\n    }\n    el.classList.remove('focus');\n  }\n\n  private handleKeydown(event: KeyboardEvent) {\n    if (event.altKey || event.ctrlKey || event.metaKey) {\n      return;\n    }\n\n    let captured = false;\n    switch (event.key) {\n      case ' ':\n      case 'Enter':\n        if (this.isExpandable) {\n          if (this.isExpanded() && this.isSelected()) {\n            this.tree.collapseTreeitem(this);\n          } else {\n            this.tree.expandTreeitem(this);\n          }\n          captured = true;\n        } else {\n          event.stopPropagation();\n        }\n        this.tree.setSelected(this);\n        break;\n\n      case 'ArrowUp':\n        this.tree.setFocusToPreviousItem(this);\n        captured = true;\n        break;\n\n      case 'ArrowDown':\n        this.tree.setFocusToNextItem(this);\n        captured = true;\n        break;\n\n      case 'ArrowRight':\n        if (this.isExpandable) {\n          if (this.isExpanded()) {\n            this.tree.setFocusToNextItem(this);\n          } else {\n            this.tree.expandTreeitem(this);\n          }\n        }\n        captured = true;\n        break;\n\n      case 'ArrowLeft':\n        if (this.isExpandable && this.isExpanded()) {\n          this.tree.collapseTreeitem(this);\n          captured = true;\n        } else {\n          if (this.isInGroup) {\n            this.tree.setFocusToParentItem(this);\n            captured = true;\n          }\n        }\n        break;\n\n      case 'Home':\n        this.tree.setFocusToFirstItem();\n        captured = true;\n        break;\n\n      case 'End':\n        this.tree.setFocusToLastItem();\n        captured = true;\n        break;\n\n      default:\n        if (event.key.length === 1 && event.key.match(/\\S/)) {\n          if (event.key == '*') {\n            this.tree.expandAllSiblingItems(this);\n          } else {\n            this.tree.setFocusByFirstCharacter(this, event.key);\n          }\n          captured = true;\n        }\n        break;\n    }\n\n    if (captured) {\n      event.stopPropagation();\n      event.preventDefault();\n    }\n  }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction debounce<T extends (...args: any[]) => any>(func: T, wait: number) {\n  let timeout: ReturnType<typeof setTimeout> | null;\n  return (...args: Parameters<T>) => {\n    const later = () => {\n      timeout = null;\n      func(...args);\n    };\n    if (timeout) {\n      clearTimeout(timeout);\n    }\n    timeout = setTimeout(later, wait);\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\n/**\n * Controller for a table element with expandable rows. Adds event listeners to\n * a toggle within a table row that controls visiblity of additional related\n * rows in the table.\n *\n * @example\n * ```typescript\n * import {ExpandableRowsTableController} from '/static/js/table';\n *\n * const el = document .querySelector<HTMLTableElement>('.js-myTableElement')\n * new ExpandableRowsTableController(el));\n * ```\n */\nexport class ExpandableRowsTableController {\n  private rows: HTMLTableRowElement[];\n  private toggles: HTMLButtonElement[];\n\n  /**\n   * Create a table controller.\n   * @param table - The table element to which the controller binds.\n   */\n  constructor(private table: HTMLTableElement, private toggleAll?: HTMLButtonElement | null) {\n    this.rows = Array.from(table.querySelectorAll<HTMLTableRowElement>('[data-aria-controls]'));\n    this.toggles = Array.from(this.table.querySelectorAll('[aria-expanded]'));\n    this.setAttributes();\n    this.attachEventListeners();\n    this.update();\n  }\n\n  /**\n   * setAttributes sets data-aria-* and data-id attributes to regular\n   * html attributes as a workaround for limitations from safehtml.\n   */\n  private setAttributes() {\n    for (const a of ['data-aria-controls', 'data-aria-labelledby', 'data-id']) {\n      this.table.querySelectorAll(`[${a}]`).forEach(t => {\n        t.setAttribute(a.replace('data-', ''), t.getAttribute(a) ?? '');\n        t.removeAttribute(a);\n      });\n    }\n  }\n\n  private attachEventListeners() {\n    this.rows.forEach(t => {\n      t.addEventListener('click', e => {\n        this.handleToggleClick(e);\n      });\n    });\n    this.toggleAll?.addEventListener('click', () => {\n      this.expandAllItems();\n    });\n\n    document.addEventListener('keydown', e => {\n      if ((e.ctrlKey || e.metaKey) && e.key === 'f') {\n        this.expandAllItems();\n      }\n    });\n  }\n\n  private handleToggleClick(e: MouseEvent) {\n    let target = e.currentTarget as HTMLTableRowElement | null;\n    if (!target?.hasAttribute('aria-expanded')) {\n      target = this.table.querySelector(\n        `button[aria-controls=\"${target?.getAttribute('aria-controls')}\"]`\n      );\n    }\n    const isExpanded = target?.getAttribute('aria-expanded') === 'true';\n    target?.setAttribute('aria-expanded', isExpanded ? 'false' : 'true');\n    e.stopPropagation();\n    this.update();\n  }\n\n  expandAllItems = (): void => {\n    this.toggles.map(t => t.setAttribute('aria-expanded', 'true'));\n    this.update();\n  };\n\n  private collapseAllItems = () => {\n    this.toggles.map(t => t.setAttribute('aria-expanded', 'false'));\n    this.update();\n  };\n\n  private update = () => {\n    this.updateVisibleItems();\n    setTimeout(() => this.updateGlobalToggle());\n  };\n\n  private updateVisibleItems() {\n    this.rows.map(t => {\n      const isExpanded = t?.getAttribute('aria-expanded') === 'true';\n      const rowIds = t?.getAttribute('aria-controls')?.trimEnd().split(' ');\n      rowIds?.map(id => {\n        const target = document.getElementById(`${id}`);\n        if (isExpanded) {\n          target?.classList.add('visible');\n          target?.classList.remove('hidden');\n        } else {\n          target?.classList.add('hidden');\n          target?.classList.remove('visible');\n        }\n      });\n    });\n  }\n\n  private updateGlobalToggle() {\n    if (!this.toggleAll) return;\n    if (this.rows.some(t => t.hasAttribute('aria-expanded'))) {\n      this.toggleAll.style.display = 'block';\n    }\n    const someCollapsed = this.toggles.some(el => el.getAttribute('aria-expanded') === 'false');\n    if (someCollapsed) {\n      this.toggleAll.innerText = 'Expand all';\n      this.toggleAll.onclick = this.expandAllItems;\n    } else {\n      this.toggleAll.innerText = 'Collapse all';\n      this.toggleAll.onclick = this.collapseAllItems;\n    }\n  }\n}\n", "import { initPlaygrounds } from 'static/shared/playground/playground';\nimport { SelectNavController, makeSelectNav } from 'static/shared/outline/select';\nimport { TreeNavController } from 'static/shared/outline/tree';\nimport { ExpandableRowsTableController } from 'static/shared/table/table';\n\ninitPlaygrounds();\n\nconst directories = document.querySelector<HTMLTableElement>('.js-expandableTable');\nif (directories) {\n  const table = new ExpandableRowsTableController(\n    directories,\n    document.querySelector<HTMLButtonElement>('.js-expandAllDirectories')\n  );\n  // Expand directories on page load with expand-directories query param.\n  if (window.location.search.includes('expand-directories')) {\n    table.expandAllItems();\n  }\n}\n\nconst treeEl = document.querySelector<HTMLElement>('.js-tree');\nif (treeEl) {\n  const treeCtrl = new TreeNavController(treeEl);\n  const select = makeSelectNav(treeCtrl);\n  const mobileNav = document.querySelector('.js-mainNavMobile');\n  if (mobileNav && mobileNav.firstElementChild) {\n    mobileNav?.replaceChild(select, mobileNav.firstElementChild);\n  }\n  if (select.firstElementChild) {\n    new SelectNavController(select.firstElementChild);\n  }\n}\n\n/**\n * Event handlers for expanding and collapsing the readme section.\n */\nconst readme = document.querySelector('.js-readme');\nconst readmeContent = document.querySelector('.js-readmeContent');\nconst readmeOutline = document.querySelector('.js-readmeOutline');\nconst readmeExpand = document.querySelectorAll('.js-readmeExpand');\nconst readmeCollapse = document.querySelector('.js-readmeCollapse');\nconst mobileNavSelect = document.querySelector<HTMLSelectElement>('.DocNavMobile-select');\nif (readme && readmeContent && readmeOutline && readmeExpand.length && readmeCollapse) {\n  if (readme.clientHeight > 320) {\n    readme?.classList.remove('UnitReadme--expanded');\n    readme?.classList.add('UnitReadme--toggle');\n  }\n  if (window.location.hash.includes('readme')) {\n    expandReadme();\n  }\n  mobileNavSelect?.addEventListener('change', e => {\n    if ((e.target as HTMLSelectElement).value.startsWith('readme-')) {\n      expandReadme();\n    }\n  });\n  readmeExpand.forEach(el =>\n    el.addEventListener('click', e => {\n      e.preventDefault();\n      expandReadme();\n      readme.scrollIntoView();\n    })\n  );\n  readmeCollapse.addEventListener('click', e => {\n    e.preventDefault();\n    readme.classList.remove('UnitReadme--expanded');\n    if (readmeExpand[1]) {\n      readmeExpand[1].scrollIntoView({ block: 'center' });\n    }\n  });\n  readmeContent.addEventListener('keyup', () => {\n    expandReadme();\n  });\n  readmeContent.addEventListener('click', () => {\n    expandReadme();\n  });\n  readmeOutline.addEventListener('click', () => {\n    expandReadme();\n  });\n  document.addEventListener('keydown', e => {\n    if ((e.ctrlKey || e.metaKey) && e.key === 'f') {\n      expandReadme();\n    }\n  });\n}\n\n/**\n * expandReadme expands the readme and adds the section-readme hash to the\n * URL so it stays expanded when navigating back from an external link.\n */\nfunction expandReadme() {\n  history.replaceState(null, '', `${location.pathname}#section-readme`);\n  readme?.classList.add('UnitReadme--expanded');\n}\n\n/**\n * Expand details items that are focused. This will expand\n * deprecated symbols when they are navigated to from the index\n * or a direct link.\n */\nfunction openDeprecatedSymbol() {\n  if (!location.hash) return;\n  const heading = document.getElementById(location.hash.slice(1));\n  const grandParent = heading?.parentElement?.parentElement as HTMLDetailsElement | null;\n  if (grandParent?.nodeName === 'DETAILS') {\n    grandParent.open = true;\n  }\n}\nopenDeprecatedSymbol();\nwindow.addEventListener('hashchange', () => openDeprecatedSymbol());\n\n/**\n * Listen for changes in the build context dropdown.\n */\ndocument.querySelectorAll('.js-buildContextSelect').forEach(el => {\n  el.addEventListener('change', e => {\n    window.location.search = `?GOOS=${(e.target as HTMLSelectElement).value}`;\n  });\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\n// This file implements the playground implementation of the documentation\n// page. The playground involves a \"play\" button that allows you to open up\n// a new link to play.golang.org using the example code.\n\n// The CSS is in static/frontend/unit/main/_doc.css\n\n/**\n * CSS classes used by PlaygroundExampleController\n */\nconst PlayExampleClassName = {\n  PLAY_HREF: '.js-exampleHref',\n  PLAY_CONTAINER: '.js-exampleContainer',\n  EXAMPLE_INPUT: '.Documentation-exampleCode',\n  EXAMPLE_OUTPUT: '.Documentation-exampleOutput',\n  EXAMPLE_ERROR: '.Documentation-exampleError',\n  PLAY_BUTTON: '.Documentation-examplePlayButton',\n  SHARE_BUTTON: '.Documentation-exampleShareButton',\n  FORMAT_BUTTON: '.Documentation-exampleFormatButton',\n  RUN_BUTTON: '.Documentation-exampleRunButton',\n};\n\n/**\n * This controller enables playground examples to expand their dropdown or\n * generate shareable Go Playground URLs.\n */\nexport class PlaygroundExampleController {\n  /**\n   * The anchor tag used to identify the container with an example href.\n   * There is only one in an example container div.\n   */\n  private readonly anchorEl: HTMLAnchorElement | null;\n\n  /**\n   * The error element\n   */\n  private readonly errorEl: Element | null;\n\n  /**\n   * Buttons that redirect to an example's playground, this element\n   * only exists in executable examples.\n   */\n  private readonly playButtonEl: Element | null;\n  private readonly shareButtonEl: Element | null;\n\n  /**\n   * Button that formats the code in an example's playground.\n   */\n  private readonly formatButtonEl: Element | null;\n\n  /**\n   * Button that runs the code in an example's playground, this element\n   * only exists in executable examples.\n   */\n  private readonly runButtonEl: Element | null;\n\n  /**\n   * The executable code of an example.\n   */\n  private readonly inputEl: HTMLTextAreaElement | null;\n\n  /**\n   * The output of the given example code. This only exists if the\n   * author of the package provides an output for this example.\n   */\n  private readonly outputEl: Element | null;\n\n  /**\n   * @param exampleEl The div that contains playground content for the given example.\n   */\n  constructor(private readonly exampleEl: HTMLDetailsElement) {\n    this.exampleEl = exampleEl;\n    this.anchorEl = exampleEl.querySelector('a');\n    this.errorEl = exampleEl.querySelector(PlayExampleClassName.EXAMPLE_ERROR);\n    this.playButtonEl = exampleEl.querySelector(PlayExampleClassName.PLAY_BUTTON);\n    this.shareButtonEl = exampleEl.querySelector(PlayExampleClassName.SHARE_BUTTON);\n    this.formatButtonEl = exampleEl.querySelector(PlayExampleClassName.FORMAT_BUTTON);\n    this.runButtonEl = exampleEl.querySelector(PlayExampleClassName.RUN_BUTTON);\n    this.inputEl = this.makeTextArea(exampleEl.querySelector(PlayExampleClassName.EXAMPLE_INPUT));\n    this.outputEl = exampleEl.querySelector(PlayExampleClassName.EXAMPLE_OUTPUT);\n\n    // This is legacy listener to be replaced the listener for shareButtonEl.\n    this.playButtonEl?.addEventListener('click', () => this.handleShareButtonClick());\n    this.shareButtonEl?.addEventListener('click', () => this.handleShareButtonClick());\n    this.formatButtonEl?.addEventListener('click', () => this.handleFormatButtonClick());\n    this.runButtonEl?.addEventListener('click', () => this.handleRunButtonClick());\n\n    if (!this.inputEl) return;\n\n    this.resize();\n    this.inputEl.addEventListener('keyup', () => this.resize());\n    this.inputEl.addEventListener('keydown', e => this.onKeydown(e));\n  }\n\n  /**\n   * Replace the pre element with a textarea. The examples are initially rendered\n   * as pre elements so they're fully visible when JS is disabled.\n   */\n  makeTextArea(el: Element | null): HTMLTextAreaElement {\n    const t = document.createElement('textarea');\n    t.classList.add('Documentation-exampleCode', 'code');\n    t.spellcheck = false;\n    t.value = el?.textContent ?? '';\n    el?.parentElement?.replaceChild(t, el);\n    return t;\n  }\n\n  /**\n   * Retrieve the hash value of the anchor element.\n   */\n  getAnchorHash(): string | undefined {\n    return this.anchorEl?.hash;\n  }\n\n  /**\n   * Expands the current playground example.\n   */\n  expand(): void {\n    this.exampleEl.open = true;\n  }\n\n  /**\n   * Resizes the input element to accommodate the amount of text present.\n   */\n  private resize(): void {\n    if (this.inputEl?.value) {\n      const numLineBreaks = (this.inputEl.value.match(/\\n/g) || []).length;\n      // min-height + lines x line-height + padding + border\n      this.inputEl.style.height = `${(20 + numLineBreaks * 20 + 12 + 2) / 16}rem`;\n    }\n  }\n\n  /**\n   * Handler to override keyboard behavior in the playground's\n   * textarea element.\n   *\n   * Tab key inserts tabs into the example playground instead of\n   * switching to the next interactive element.\n   * @param e input element keyboard event.\n   */\n  private onKeydown(e: KeyboardEvent) {\n    if (e.key === 'Tab') {\n      document.execCommand('insertText', false, '\\t');\n      e.preventDefault();\n    }\n  }\n\n  /**\n   * Changes the text of the example's input box.\n   */\n  private setInputText(output: string) {\n    if (this.inputEl) {\n      this.inputEl.value = output;\n    }\n  }\n\n  /**\n   * Changes the text of the example's output box.\n   */\n  private setOutputText(output: string) {\n    if (this.outputEl) {\n      this.outputEl.textContent = output;\n    }\n  }\n\n  private setOutputHTML(output: string) {\n    if (this.outputEl) {\n      this.outputEl.innerHTML = output;\n    }\n  }\n\n  /**\n   * Sets the error message text and overwrites\n   * output box to indicate a failed response.\n   */\n  private setErrorText(err: string) {\n    if (this.errorEl) {\n      this.errorEl.textContent = err;\n    }\n    this.setOutputText('An error has occurred\u2026');\n  }\n\n  /**\n   * Opens a new window to play.golang.org using the\n   * example snippet's code in the playground.\n   */\n  private handleShareButtonClick() {\n    const PLAYGROUND_BASE_URL = 'https://play.golang.org/p/';\n\n    this.setOutputText('Waiting for remote server\u2026');\n\n    fetch('/play/share', {\n      method: 'POST',\n      body: this.inputEl?.value,\n    })\n      .then(res => res.text())\n      .then(shareId => {\n        const href = PLAYGROUND_BASE_URL + shareId;\n        this.setOutputHTML(`<a href=\"${href}\">${href}</a>`);\n        window.open(href);\n      })\n      .catch(err => {\n        this.setErrorText(err);\n      });\n  }\n\n  /**\n   * Runs gofmt on the example snippet in the playground.\n   */\n  private handleFormatButtonClick() {\n    this.setOutputText('Waiting for remote server\u2026');\n    const body = new FormData();\n    body.append('body', this.inputEl?.value ?? '');\n\n    fetch('/play/fmt', {\n      method: 'POST',\n      body: body,\n    })\n      .then(res => res.json())\n      .then(({ Body, Error }) => {\n        this.setOutputText(Error || 'Done.');\n        if (Body) {\n          this.setInputText(Body);\n          this.resize();\n        }\n      })\n      .catch(err => {\n        this.setErrorText(err);\n      });\n  }\n\n  /**\n   * Runs the code snippet in the example playground.\n   */\n  private handleRunButtonClick() {\n    this.setOutputText('Waiting for remote server\u2026');\n\n    let codeWithModFile = this.inputEl?.value ?? '';\n    const moduleVars = document.querySelector<HTMLDivElement>('.js-playgroundVars')?.dataset ?? {};\n    console.log(moduleVars.unitpath);\n    if (moduleVars.pagetype !== 'std') {\n      codeWithModFile = codeWithModFile.concat(`\n-- go.mod --\nmodule play.ground\n\nrequire ${moduleVars.unitpath} ${moduleVars.version}\n`);\n    }\n    fetch('/play/compile', {\n      method: 'POST',\n      body: JSON.stringify({ body: codeWithModFile, version: 2 }),\n    })\n      .then(res => res.json())\n      .then(async ({ Events, Errors }) => {\n        this.setOutputText(Errors || '');\n        for (const e of Events || []) {\n          this.setOutputText(e.Message);\n          await new Promise(resolve => setTimeout(resolve, e.Delay / 1000000));\n        }\n      })\n      .catch(err => {\n        this.setErrorText(err);\n      });\n  }\n}\n\nexport function initPlaygrounds(): void {\n  const exampleHashRegex = location.hash.match(/^#(example-.*)$/);\n  if (exampleHashRegex) {\n    const exampleHashEl = document.getElementById(exampleHashRegex[1]) as HTMLDetailsElement;\n    if (exampleHashEl) {\n      exampleHashEl.open = true;\n    }\n  }\n\n  // We use a spread operator to convert a nodelist into an array of elements.\n  const exampleHrefs = [\n    ...document.querySelectorAll<HTMLAnchorElement>(PlayExampleClassName.PLAY_HREF),\n  ];\n\n  /**\n   * Sometimes exampleHrefs and playContainers are in different order, so we\n   * find an exampleHref from a common hash.\n   * @param playContainer - playground container\n   */\n  const findExampleHash = (playContainer: PlaygroundExampleController) =>\n    exampleHrefs.find(ex => {\n      return ex.hash === playContainer.getAnchorHash();\n    });\n\n  for (const el of document.querySelectorAll(PlayExampleClassName.PLAY_CONTAINER)) {\n    // There should be the same amount of hrefs referencing examples as example containers.\n    const playContainer = new PlaygroundExampleController(el as HTMLDetailsElement);\n    const exampleHref = findExampleHash(playContainer);\n    if (exampleHref) {\n      exampleHref.addEventListener('click', () => {\n        playContainer.expand();\n      });\n    } else {\n      console.warn('example href not found');\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\n/**\n * TreeNavController is the navigation tree component of the documentation page.\n * It adds accessiblity attributes to a tree, observes the heading elements\n * focus the topmost link for headings visible on the page, and implements the\n * WAI-ARIA Treeview Design Pattern with full\n * [keyboard support](https://www.w3.org/TR/wai-aria-practices/examples/treeview/treeview-2/treeview-2a.html#kbd_label).\n */\nexport class TreeNavController {\n  treeitems: TreeItem[];\n\n  /**\n   * firstChars is the first character of each treeitem in the same order\n   * as this.treeitems. We use this array to set focus by character when\n   * navigating the tree with a keyboard.\n   */\n  private firstChars: string[];\n  private firstTreeitem: TreeItem | null;\n  private lastTreeitem: TreeItem | null;\n  private observerCallbacks: ((t: TreeItem) => void)[];\n\n  constructor(private el: HTMLElement) {\n    this.treeitems = [];\n    this.firstChars = [];\n    this.firstTreeitem = null;\n    this.lastTreeitem = null;\n    this.observerCallbacks = [];\n    this.init();\n  }\n\n  private init(): void {\n    this.handleResize();\n    window.addEventListener('resize', this.handleResize);\n    this.findTreeItems();\n    this.updateVisibleTreeitems();\n    this.observeTargets();\n    if (this.firstTreeitem) {\n      this.firstTreeitem.el.tabIndex = 0;\n    }\n  }\n\n  private handleResize = (): void => {\n    this.el.style.setProperty('--js-tree-height', '100vh');\n    this.el.style.setProperty('--js-tree-height', this.el.clientHeight + 'px');\n  };\n\n  private observeTargets() {\n    this.addObserver(treeitem => {\n      this.expandTreeitem(treeitem);\n      this.setSelected(treeitem);\n      // TODO: Fix scroll issue in https://golang.org/issue/47450.\n      // treeitem.el.scrollIntoView({ block: 'nearest' });\n    });\n\n    const targets = new Map<string, boolean>();\n    const observer = new IntersectionObserver(\n      entries => {\n        for (const entry of entries) {\n          targets.set(entry.target.id, entry.isIntersecting || entry.intersectionRatio === 1);\n        }\n        for (const [id, isIntersecting] of targets) {\n          if (isIntersecting) {\n            const active = this.treeitems.find(t =>\n              (t.el as HTMLAnchorElement)?.href.endsWith(`#${id}`)\n            );\n            if (active) {\n              for (const fn of this.observerCallbacks) {\n                fn(active);\n              }\n            }\n            break;\n          }\n        }\n      },\n      {\n        threshold: 1.0,\n        rootMargin: '-60px 0px 0px 0px',\n      }\n    );\n\n    for (const href of this.treeitems.map(t => t.el.getAttribute('href'))) {\n      if (href) {\n        const id = href.replace(window.location.origin, '').replace('/', '').replace('#', '');\n        const target = document.getElementById(id);\n        if (target) {\n          observer.observe(target);\n        }\n      }\n    }\n  }\n\n  addObserver(fn: (t: TreeItem) => void, delay = 200): void {\n    this.observerCallbacks.push(debounce(fn, delay));\n  }\n\n  setFocusToNextItem(currentItem: TreeItem): void {\n    let nextItem = null;\n    for (let i = currentItem.index + 1; i < this.treeitems.length; i++) {\n      const ti = this.treeitems[i];\n      if (ti.isVisible) {\n        nextItem = ti;\n        break;\n      }\n    }\n    if (nextItem) {\n      this.setFocusToItem(nextItem);\n    }\n  }\n\n  setFocusToPreviousItem(currentItem: TreeItem): void {\n    let prevItem = null;\n    for (let i = currentItem.index - 1; i > -1; i--) {\n      const ti = this.treeitems[i];\n      if (ti.isVisible) {\n        prevItem = ti;\n        break;\n      }\n    }\n    if (prevItem) {\n      this.setFocusToItem(prevItem);\n    }\n  }\n\n  setFocusToParentItem(currentItem: TreeItem): void {\n    if (currentItem.groupTreeitem) {\n      this.setFocusToItem(currentItem.groupTreeitem);\n    }\n  }\n\n  setFocusToFirstItem(): void {\n    this.firstTreeitem && this.setFocusToItem(this.firstTreeitem);\n  }\n\n  setFocusToLastItem(): void {\n    this.lastTreeitem && this.setFocusToItem(this.lastTreeitem);\n  }\n\n  setSelected(currentItem: TreeItem): void {\n    for (const l1 of this.el.querySelectorAll('[aria-expanded=\"true\"]')) {\n      if (l1 === currentItem.el) continue;\n      if (!l1.nextElementSibling?.contains(currentItem.el)) {\n        l1.setAttribute('aria-expanded', 'false');\n      }\n    }\n    for (const l1 of this.el.querySelectorAll('[aria-selected]')) {\n      if (l1 !== currentItem.el) {\n        l1.setAttribute('aria-selected', 'false');\n      }\n    }\n    currentItem.el.setAttribute('aria-selected', 'true');\n    this.updateVisibleTreeitems();\n    this.setFocusToItem(currentItem, false);\n  }\n\n  expandTreeitem(treeitem: TreeItem): void {\n    let currentItem: TreeItem | null = treeitem;\n    while (currentItem) {\n      if (currentItem.isExpandable) {\n        currentItem.el.setAttribute('aria-expanded', 'true');\n      }\n      currentItem = currentItem.groupTreeitem;\n    }\n    this.updateVisibleTreeitems();\n  }\n\n  expandAllSiblingItems(currentItem: TreeItem): void {\n    for (const ti of this.treeitems) {\n      if (ti.groupTreeitem === currentItem.groupTreeitem && ti.isExpandable) {\n        this.expandTreeitem(ti);\n      }\n    }\n  }\n\n  collapseTreeitem(currentItem: TreeItem): void {\n    let groupTreeitem = null;\n\n    if (currentItem.isExpanded()) {\n      groupTreeitem = currentItem;\n    } else {\n      groupTreeitem = currentItem.groupTreeitem;\n    }\n\n    if (groupTreeitem) {\n      groupTreeitem.el.setAttribute('aria-expanded', 'false');\n      this.updateVisibleTreeitems();\n      this.setFocusToItem(groupTreeitem);\n    }\n  }\n\n  setFocusByFirstCharacter(currentItem: TreeItem, char: string): void {\n    let start: number, index: number;\n    char = char.toLowerCase();\n\n    // Get start index for search based on position of currentItem\n    start = currentItem.index + 1;\n    if (start === this.treeitems.length) {\n      start = 0;\n    }\n\n    // Check remaining slots in the menu\n    index = this.getIndexFirstChars(start, char);\n\n    // If not found in remaining slots, check from beginning\n    if (index === -1) {\n      index = this.getIndexFirstChars(0, char);\n    }\n\n    // If match was found...\n    if (index > -1) {\n      this.setFocusToItem(this.treeitems[index]);\n    }\n  }\n\n  private findTreeItems() {\n    const findItems = (el: HTMLElement, group: TreeItem | null) => {\n      let ti = group;\n      let curr = el.firstElementChild as HTMLElement;\n      while (curr) {\n        if (curr.tagName === 'A' || curr.tagName === 'SPAN') {\n          ti = new TreeItem(curr, this, group);\n          this.treeitems.push(ti);\n          this.firstChars.push(ti.label.substring(0, 1).toLowerCase());\n        }\n        if (curr.firstElementChild) {\n          findItems(curr, ti);\n        }\n        curr = curr.nextElementSibling as HTMLElement;\n      }\n    };\n    findItems(this.el as HTMLElement, null);\n    this.treeitems.map((ti, idx) => (ti.index = idx));\n  }\n\n  private updateVisibleTreeitems(): void {\n    this.firstTreeitem = this.treeitems[0];\n\n    for (const ti of this.treeitems) {\n      let parent = ti.groupTreeitem;\n      ti.isVisible = true;\n      while (parent && parent.el !== this.el) {\n        if (!parent.isExpanded()) {\n          ti.isVisible = false;\n        }\n        parent = parent.groupTreeitem;\n      }\n      if (ti.isVisible) {\n        this.lastTreeitem = ti;\n      }\n    }\n  }\n\n  private setFocusToItem(treeitem: TreeItem, focusEl = true) {\n    treeitem.el.tabIndex = 0;\n    if (focusEl) {\n      treeitem.el.focus();\n    }\n    for (const ti of this.treeitems) {\n      if (ti !== treeitem) {\n        ti.el.tabIndex = -1;\n      }\n    }\n  }\n\n  private getIndexFirstChars(startIndex: number, char: string): number {\n    for (let i = startIndex; i < this.firstChars.length; i++) {\n      if (this.treeitems[i].isVisible && char === this.firstChars[i]) {\n        return i;\n      }\n    }\n    return -1;\n  }\n}\n\nclass TreeItem {\n  el: HTMLElement;\n  groupTreeitem: TreeItem | null;\n  label: string;\n  isExpandable: boolean;\n  isVisible: boolean;\n  depth: number;\n  index: number;\n\n  private tree: TreeNavController;\n  private isInGroup: boolean;\n\n  constructor(el: HTMLElement, treeObj: TreeNavController, group: TreeItem | null) {\n    el.tabIndex = -1;\n    this.el = el;\n    this.groupTreeitem = group;\n    this.label = el.textContent?.trim() ?? '';\n    this.tree = treeObj;\n    this.depth = (group?.depth || 0) + 1;\n    this.index = 0;\n\n    const parent = el.parentElement;\n    if (parent?.tagName.toLowerCase() === 'li') {\n      parent?.setAttribute('role', 'none');\n    }\n    el.setAttribute('aria-level', this.depth + '');\n    if (el.getAttribute('aria-label')) {\n      this.label = el?.getAttribute('aria-label')?.trim() ?? '';\n    }\n\n    this.isExpandable = false;\n    this.isVisible = false;\n    this.isInGroup = !!group;\n\n    let curr = el.nextElementSibling;\n    while (curr) {\n      if (curr.tagName.toLowerCase() == 'ul') {\n        const groupId = `${group?.label ?? ''} nav group ${this.label}`.replace(/[\\W_]+/g, '_');\n        el.setAttribute('aria-owns', groupId);\n        el.setAttribute('aria-expanded', 'false');\n        curr.setAttribute('role', 'group');\n        curr.setAttribute('id', groupId);\n        this.isExpandable = true;\n        break;\n      }\n\n      curr = curr.nextElementSibling;\n    }\n    this.init();\n  }\n\n  private init() {\n    this.el.tabIndex = -1;\n    if (!this.el.getAttribute('role')) {\n      this.el.setAttribute('role', 'treeitem');\n    }\n    this.el.addEventListener('keydown', this.handleKeydown.bind(this));\n    this.el.addEventListener('click', this.handleClick.bind(this));\n    this.el.addEventListener('focus', this.handleFocus.bind(this));\n    this.el.addEventListener('blur', this.handleBlur.bind(this));\n  }\n\n  isExpanded() {\n    if (this.isExpandable) {\n      return this.el.getAttribute('aria-expanded') === 'true';\n    }\n\n    return false;\n  }\n\n  isSelected() {\n    return this.el.getAttribute('aria-selected') === 'true';\n  }\n\n  private handleClick(event: MouseEvent) {\n    // only process click events that directly happened on this treeitem\n    if (event.target !== this.el && event.target !== this.el.firstElementChild) {\n      return;\n    }\n    if (this.isExpandable) {\n      if (this.isExpanded() && this.isSelected()) {\n        this.tree.collapseTreeitem(this);\n      } else {\n        this.tree.expandTreeitem(this);\n      }\n      event.stopPropagation();\n    }\n    this.tree.setSelected(this);\n  }\n\n  private handleFocus() {\n    let el = this.el;\n    if (this.isExpandable) {\n      el = (el.firstElementChild as HTMLElement) ?? el;\n    }\n    el.classList.add('focus');\n  }\n\n  private handleBlur() {\n    let el = this.el;\n    if (this.isExpandable) {\n      el = (el.firstElementChild as HTMLElement) ?? el;\n    }\n    el.classList.remove('focus');\n  }\n\n  private handleKeydown(event: KeyboardEvent) {\n    if (event.altKey || event.ctrlKey || event.metaKey) {\n      return;\n    }\n\n    let captured = false;\n    switch (event.key) {\n      case ' ':\n      case 'Enter':\n        if (this.isExpandable) {\n          if (this.isExpanded() && this.isSelected()) {\n            this.tree.collapseTreeitem(this);\n          } else {\n            this.tree.expandTreeitem(this);\n          }\n          captured = true;\n        } else {\n          event.stopPropagation();\n        }\n        this.tree.setSelected(this);\n        break;\n\n      case 'ArrowUp':\n        this.tree.setFocusToPreviousItem(this);\n        captured = true;\n        break;\n\n      case 'ArrowDown':\n        this.tree.setFocusToNextItem(this);\n        captured = true;\n        break;\n\n      case 'ArrowRight':\n        if (this.isExpandable) {\n          if (this.isExpanded()) {\n            this.tree.setFocusToNextItem(this);\n          } else {\n            this.tree.expandTreeitem(this);\n          }\n        }\n        captured = true;\n        break;\n\n      case 'ArrowLeft':\n        if (this.isExpandable && this.isExpanded()) {\n          this.tree.collapseTreeitem(this);\n          captured = true;\n        } else {\n          if (this.isInGroup) {\n            this.tree.setFocusToParentItem(this);\n            captured = true;\n          }\n        }\n        break;\n\n      case 'Home':\n        this.tree.setFocusToFirstItem();\n        captured = true;\n        break;\n\n      case 'End':\n        this.tree.setFocusToLastItem();\n        captured = true;\n        break;\n\n      default:\n        if (event.key.length === 1 && event.key.match(/\\S/)) {\n          if (event.key == '*') {\n            this.tree.expandAllSiblingItems(this);\n          } else {\n            this.tree.setFocusByFirstCharacter(this, event.key);\n          }\n          captured = true;\n        }\n        break;\n    }\n\n    if (captured) {\n      event.stopPropagation();\n      event.preventDefault();\n    }\n  }\n}\n\n// eslint-disable-next-line @typescript-eslint/no-explicit-any\nfunction debounce<T extends (...args: any[]) => any>(func: T, wait: number) {\n  let timeout: ReturnType<typeof setTimeout> | null;\n  return (...args: Parameters<T>) => {\n    const later = () => {\n      timeout = null;\n      func(...args);\n    };\n    if (timeout) {\n      clearTimeout(timeout);\n    }\n    timeout = setTimeout(later, wait);\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\n/**\n * Controller for a table element with expandable rows. Adds event listeners to\n * a toggle within a table row that controls visiblity of additional related\n * rows in the table.\n *\n * @example\n * ```typescript\n * import {ExpandableRowsTableController} from '/static/js/table';\n *\n * const el = document .querySelector<HTMLTableElement>('.js-myTableElement')\n * new ExpandableRowsTableController(el));\n * ```\n */\nexport class ExpandableRowsTableController {\n  private rows: HTMLTableRowElement[];\n  private toggles: HTMLButtonElement[];\n\n  /**\n   * Create a table controller.\n   * @param table - The table element to which the controller binds.\n   */\n  constructor(private table: HTMLTableElement, private toggleAll?: HTMLButtonElement | null) {\n    this.rows = Array.from(table.querySelectorAll<HTMLTableRowElement>('[data-aria-controls]'));\n    this.toggles = Array.from(this.table.querySelectorAll('[aria-expanded]'));\n    this.setAttributes();\n    this.attachEventListeners();\n    this.update();\n  }\n\n  /**\n   * setAttributes sets data-aria-* and data-id attributes to regular\n   * html attributes as a workaround for limitations from safehtml.\n   */\n  private setAttributes() {\n    for (const a of ['data-aria-controls', 'data-aria-labelledby', 'data-id']) {\n      this.table.querySelectorAll(`[${a}]`).forEach(t => {\n        t.setAttribute(a.replace('data-', ''), t.getAttribute(a) ?? '');\n        t.removeAttribute(a);\n      });\n    }\n  }\n\n  private attachEventListeners() {\n    this.rows.forEach(t => {\n      t.addEventListener('click', e => {\n        this.handleToggleClick(e);\n      });\n    });\n    this.toggleAll?.addEventListener('click', () => {\n      this.expandAllItems();\n    });\n\n    document.addEventListener('keydown', e => {\n      if ((e.ctrlKey || e.metaKey) && e.key === 'f') {\n        this.expandAllItems();\n      }\n    });\n  }\n\n  private handleToggleClick(e: MouseEvent) {\n    let target = e.currentTarget as HTMLTableRowElement | null;\n    if (!target?.hasAttribute('aria-expanded')) {\n      target = this.table.querySelector(\n        `button[aria-controls=\"${target?.getAttribute('aria-controls')}\"]`\n      );\n    }\n    const isExpanded = target?.getAttribute('aria-expanded') === 'true';\n    target?.setAttribute('aria-expanded', isExpanded ? 'false' : 'true');\n    e.stopPropagation();\n    this.update();\n  }\n\n  expandAllItems = (): void => {\n    this.toggles.map(t => t.setAttribute('aria-expanded', 'true'));\n    this.update();\n  };\n\n  private collapseAllItems = () => {\n    this.toggles.map(t => t.setAttribute('aria-expanded', 'false'));\n    this.update();\n  };\n\n  private update = () => {\n    this.updateVisibleItems();\n    setTimeout(() => this.updateGlobalToggle());\n  };\n\n  private updateVisibleItems() {\n    this.rows.map(t => {\n      const isExpanded = t?.getAttribute('aria-expanded') === 'true';\n      const rowIds = t?.getAttribute('aria-controls')?.trimEnd().split(' ');\n      rowIds?.map(id => {\n        const target = document.getElementById(`${id}`);\n        if (isExpanded) {\n          target?.classList.add('visible');\n          target?.classList.remove('hidden');\n        } else {\n          target?.classList.add('hidden');\n          target?.classList.remove('visible');\n        }\n      });\n    });\n  }\n\n  private updateGlobalToggle() {\n    if (!this.toggleAll) return;\n    if (this.rows.some(t => t.hasAttribute('aria-expanded'))) {\n      this.toggleAll.style.display = 'block';\n    }\n    const someCollapsed = this.toggles.some(el => el.getAttribute('aria-expanded') === 'false');\n    if (someCollapsed) {\n      this.toggleAll.innerText = 'Expand all';\n      this.toggleAll.onclick = this.expandAllItems;\n    } else {\n      this.toggleAll.innerText = 'Collapse all';\n      this.toggleAll.onclick = this.collapseAllItems;\n    }\n  }\n}\n", "import { initPlaygrounds } from 'static/shared/playground/playground';\nimport { SelectNavController, makeSelectNav } from 'static/shared/outline/select';\nimport { TreeNavController } from 'static/shared/outline/tree';\nimport { ExpandableRowsTableController } from 'static/shared/table/table';\n\ninitPlaygrounds();\n\nconst directories = document.querySelector<HTMLTableElement>('.js-expandableTable');\nif (directories) {\n  const table = new ExpandableRowsTableController(\n    directories,\n    document.querySelector<HTMLButtonElement>('.js-expandAllDirectories')\n  );\n  // Expand directories on page load with expand-directories query param.\n  if (window.location.search.includes('expand-directories')) {\n    table.expandAllItems();\n  }\n}\n\nconst treeEl = document.querySelector<HTMLElement>('.js-tree');\nif (treeEl) {\n  const treeCtrl = new TreeNavController(treeEl);\n  const select = makeSelectNav(treeCtrl);\n  const mobileNav = document.querySelector('.js-mainNavMobile');\n  if (mobileNav && mobileNav.firstElementChild) {\n    mobileNav?.replaceChild(select, mobileNav.firstElementChild);\n  }\n  if (select.firstElementChild) {\n    new SelectNavController(select.firstElementChild);\n  }\n}\n\n/**\n * Event handlers for expanding and collapsing the readme section.\n */\nconst readme = document.querySelector('.js-readme');\nconst readmeContent = document.querySelector('.js-readmeContent');\nconst readmeOutline = document.querySelector('.js-readmeOutline');\nconst readmeExpand = document.querySelectorAll('.js-readmeExpand');\nconst readmeCollapse = document.querySelector('.js-readmeCollapse');\nconst mobileNavSelect = document.querySelector<HTMLSelectElement>('.DocNavMobile-select');\nif (readme && readmeContent && readmeOutline && readmeExpand.length && readmeCollapse) {\n  if (readme.clientHeight > 320) {\n    readme?.classList.remove('UnitReadme--expanded');\n    readme?.classList.add('UnitReadme--toggle');\n  }\n  if (window.location.hash.includes('readme')) {\n    expandReadme();\n  }\n  mobileNavSelect?.addEventListener('change', e => {\n    if ((e.target as HTMLSelectElement).value.startsWith('readme-')) {\n      expandReadme();\n    }\n  });\n  readmeExpand.forEach(el =>\n    el.addEventListener('click', e => {\n      e.preventDefault();\n      expandReadme();\n      readme.scrollIntoView();\n    })\n  );\n  readmeCollapse.addEventListener('click', e => {\n    e.preventDefault();\n    readme.classList.remove('UnitReadme--expanded');\n    if (readmeExpand[1]) {\n      readmeExpand[1].scrollIntoView({ block: 'center' });\n    }\n  });\n  readmeContent.addEventListener('keyup', () => {\n    expandReadme();\n  });\n  readmeContent.addEventListener('click', () => {\n    expandReadme();\n  });\n  readmeOutline.addEventListener('click', () => {\n    expandReadme();\n  });\n  document.addEventListener('keydown', e => {\n    if ((e.ctrlKey || e.metaKey) && e.key === 'f') {\n      expandReadme();\n    }\n  });\n}\n\n/**\n * expandReadme expands the readme and adds the section-readme hash to the\n * URL so it stays expanded when navigating back from an external link.\n */\nfunction expandReadme() {\n  history.replaceState(null, '', `${location.pathname}#section-readme`);\n  readme?.classList.add('UnitReadme--expanded');\n}\n\n/**\n * Expand details items that are focused. This will expand\n * deprecated symbols when they are navigated to from the index\n * or a direct link.\n */\nfunction openDeprecatedSymbol() {\n  if (!location.hash) return;\n  const heading = document.getElementById(location.hash.slice(1));\n  const grandParent = heading?.parentElement?.parentElement as HTMLDetailsElement | null;\n  if (grandParent?.nodeName === 'DETAILS') {\n    grandParent.open = true;\n  }\n}\nopenDeprecatedSymbol();\nwindow.addEventListener('hashchange', () => openDeprecatedSymbol());\n\n/**\n * Listen for changes in the build context dropdown.\n */\ndocument.querySelectorAll('.js-buildContextSelect').forEach(el => {\n  el.addEventListener('change', e => {\n    window.location.search = `?GOOS=${(e.target as HTMLSelectElement).value}`;\n  });\n});\n"],
+  "mappings": "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",
   "names": []
 }
diff --git a/static/frontend/unit/main/main.tmpl b/static/frontend/unit/main/main.tmpl
index 6493905..dbf87a2 100644
--- a/static/frontend/unit/main/main.tmpl
+++ b/static/frontend/unit/main/main.tmpl
@@ -78,6 +78,7 @@
 
 {{define "main-scripts"}}
   <div class="js-canonicalURLPath" data-canonical-url-path="{{.CanonicalURLPath}}" hidden></div>
+  <div class="js-playgroundVars" data-modulepath="{{.Unit.ModulePath}}" data-version="{{.Unit.Version}}" hidden></div>
   <script>
     loadScript('/static/frontend/unit/main/main.js')
   </script>
diff --git a/static/shared/playground/playground.test.ts b/static/shared/playground/playground.test.ts
index 02a468b..60ca821 100644
--- a/static/shared/playground/playground.test.ts
+++ b/static/shared/playground/playground.test.ts
@@ -39,30 +39,39 @@
 
 describe('PlaygroundExampleController', () => {
   let example: HTMLDetailsElement;
+  const snippetWithModeFile = codeSnippet.concat(`
+-- go.mod --
+module play.ground
+
+require example v1
+`);
+  const htmlEl = `
+  <details tabindex="-1" id="example-Sprintln" class="Documentation-exampleDetails js-exampleContainer">
+  <summary class="Documentation-exampleDetailsHeader">Example <a href="#example-Sprintln">¶</a></summary>
+  <div class="Documentation-exampleDetailsBody">
+  <p>Code:</p>
+
+  <pre class="Documentation-exampleCode">${escapeHTML(codeSnippet)}</pre>
+
+  <pre>
+    <span class="Documentation-exampleOutputLabel">Output:</span>
+    <span class="Documentation-exampleOutput">Kim is 22 years old.</span>
+  </pre>
+  </div>
+  <div class="Documentation-exampleButtonsContainer">
+    <p class="Documentation-exampleError" role="alert" aria-atomic="true"></p>
+    <button class="Documentation-exampleShareButton" aria-label="Share Code">Share</button>
+    <button class="Documentation-exampleFormatButton" aria-label="Format Code">Format</button>
+    <button class="Documentation-exampleRunButton" aria-label="Run Code">Run</button>
+  </div></details>
+`;
   window.fetch = jest.fn();
   window.open = jest.fn();
 
   beforeEach(() => {
-    document.body.innerHTML = `
-      <details tabindex="-1" id="example-Sprintln" class="Documentation-exampleDetails js-exampleContainer">
-      <summary class="Documentation-exampleDetailsHeader">Example <a href="#example-Sprintln">¶</a></summary>
-      <div class="Documentation-exampleDetailsBody">
-      <p>Code:</p>
-
-      <pre class="Documentation-exampleCode">${escapeHTML(codeSnippet)}</pre>
-
-      <pre>
-        <span class="Documentation-exampleOutputLabel">Output:</span>
-        <span class="Documentation-exampleOutput">Kim is 22 years old.</span>
-      </pre>
-      </div>
-      <div class="Documentation-exampleButtonsContainer">
-        <p class="Documentation-exampleError" role="alert" aria-atomic="true"></p>
-        <button class="Documentation-exampleShareButton" aria-label="Share Code">Share</button>
-        <button class="Documentation-exampleFormatButton" aria-label="Format Code">Format</button>
-        <button class="Documentation-exampleRunButton" aria-label="Run Code">Run</button>
-      </div></details>
-    `;
+    document.body.innerHTML = htmlEl.concat(`
+    <div class="js-playgroundVars" data-modulepath="example" data-version="v1" hidden></div>
+`);
     example = el('.js-exampleContainer') as HTMLDetailsElement;
     new PlaygroundExampleController(example);
   });
@@ -153,7 +162,7 @@
     await flushPromises();
 
     expect(window.fetch).toHaveBeenCalledWith('/play/compile', {
-      body: JSON.stringify({ body: codeSnippet, version: 2 }),
+      body: JSON.stringify({ body: snippetWithModeFile, version: 2 }),
       method: 'POST',
     });
     expect(el('.Documentation-exampleOutput').textContent).toContain('// mocked response');
@@ -171,7 +180,7 @@
     await flushPromises();
 
     expect(window.fetch).toHaveBeenCalledWith('/play/compile', {
-      body: JSON.stringify({ body: codeSnippet, version: 2 }),
+      body: JSON.stringify({ body: snippetWithModeFile, version: 2 }),
       method: 'POST',
     });
     expect(el('.Documentation-exampleOutput').textContent).toContain('// mocked error');
@@ -189,6 +198,30 @@
     await flushPromises();
 
     expect(window.fetch).toHaveBeenCalledWith('/play/compile', {
+      body: JSON.stringify({ body: snippetWithModeFile, version: 2 }),
+      method: 'POST',
+    });
+    expect(el('.Documentation-exampleOutput').innerHTML).toBe('&lt;input required&gt;');
+  });
+
+  it('snippet without mod file for standard package', async () => {
+    document.body.innerHTML = htmlEl.concat(`
+    <div class="js-playgroundVars" data-modulepath="std" data-version="v1" hidden></div>
+`);
+    example = el('.js-exampleContainer') as HTMLDetailsElement;
+    new PlaygroundExampleController(example);
+
+    mocked(window.fetch).mockResolvedValue({
+      json: () =>
+        Promise.resolve({
+          Events: [{ Message: '\u003cinput required\u003e', Kind: 'stdout', Delay: 0 }],
+          Errors: null,
+        }),
+    } as Response);
+    el('[aria-label="Run Code"]').click();
+    await flushPromises();
+
+    expect(window.fetch).toHaveBeenCalledWith('/play/compile', {
       body: JSON.stringify({ body: codeSnippet, version: 2 }),
       method: 'POST',
     });
diff --git a/static/shared/playground/playground.ts b/static/shared/playground/playground.ts
index a24a27f..ad3156d 100644
--- a/static/shared/playground/playground.ts
+++ b/static/shared/playground/playground.ts
@@ -241,9 +241,19 @@
   private handleRunButtonClick() {
     this.setOutputText('Waiting for remote server…');
 
+    let codeWithModFile = this.inputEl?.value ?? '';
+    const moduleVars = document.querySelector<HTMLDivElement>('.js-playgroundVars')?.dataset ?? {};
+    if (moduleVars.modulepath !== 'std') {
+      codeWithModFile = codeWithModFile.concat(`
+-- go.mod --
+module play.ground
+
+require ${moduleVars.modulepath} ${moduleVars.version}
+`);
+    }
     fetch('/play/compile', {
       method: 'POST',
-      body: JSON.stringify({ body: this.inputEl?.value, version: 2 }),
+      body: JSON.stringify({ body: codeWithModFile, version: 2 }),
     })
       .then(res => res.json())
       .then(async ({ Events, Errors }) => {