static: add module versions with an inline mod file when sharing package examples
For all non-standard library packages, when their examples in the docs are shared, their code will be appended with an inline mod file that specifies the module version of the package.
Change-Id: Id242c3cd3515d7f5c2713d37be8b88e49d3fa8d0
Reviewed-on: https://go-review.googlesource.com/c/pkgsite/+/450475
Run-TryBot: Dylan Le <dungtuanle@google.com>
TryBot-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Jamal Carvalho <jamal@golang.org>
diff --git a/static/frontend/unit/main/main.js b/static/frontend/unit/main/main.js
index 0f1e6d6..f3af0ce 100644
--- a/static/frontend/unit/main/main.js
+++ b/static/frontend/unit/main/main.js
@@ -1,9 +1,9 @@
-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:{};t.modulepath!=="std"&&(e=e.concat(`
+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",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")}getCodeWithModFile(){var i,s,r,l;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:{};return t.modulepath!=="std"&&(e=e.concat(`
-- go.mod --
module play.ground
require ${t.modulepath} ${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}`})});
+`)),e}handleShareButtonClick(){let e="https://play.golang.org/p/";this.setOutputText("Waiting for remote server\u2026"),fetch("/play/share",{method:"POST",body:this.getCodeWithModFile()}).then(t=>t.text()).then(t=>{let i=e+t;this.setOutputHTML(`<a href="${i}">${i}</a>`),window.open(i)}).catch(t=>{this.setErrorText(t)})}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(){this.setOutputText("Waiting for remote server\u2026"),fetch("/play/compile",{method:"POST",body:JSON.stringify({body:this.getCodeWithModFile(),version:2})}).then(e=>e.json()).then(async({Events:e,Errors:t})=>{this.setOutputText(t||"");for(let i of e||[])this.setOutputText(i.Message),await new Promise(s=>setTimeout(s,i.Delay/1e6))}).catch(e=>{this.setErrorText(e)})}};function y(){let n=location.hash.match(/^#(example-.*)$/);if(n){let i=document.getElementById(n[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(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 c;let a=l.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 l=this.treeitems.find(a=>{var h;return(h=a.el)==null?void 0:h.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,h,c,v;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=(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(n,e){let t;return(...i)=>{let s=()=>{t=null,n(...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 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 C=document.querySelector(".js-expandableTable");if(C){let n=new T(C,document.querySelector(".js-expandAllDirectories"));window.location.search.includes("expand-directories")&&n.expandAllItems()}var I=document.querySelector(".js-tree");if(I){let n=new f(I),e=L(n),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",n=>{n.target.value.startsWith("readme-")&&u()}),m.forEach(n=>n.addEventListener("click",e=>{e.preventDefault(),u(),o.scrollIntoView()})),k.addEventListener("click",n=>{n.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",n=>{(n.ctrlKey||n.metaKey)&&n.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 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 f1b8149..e2f9671 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 let codeWithModFile = this.inputEl?.value ?? '';\n const moduleVars = document.querySelector<HTMLDivElement>('.js-playgroundVars')?.dataset ?? {};\n if (moduleVars.modulepath !== 'std') {\n codeWithModFile = codeWithModFile.concat(`\n-- go.mod --\nmodule play.ground\n\nrequire ${moduleVars.modulepath} ${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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",
+ "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 private getCodeWithModFile(): string {\n let codeWithModFile = this.inputEl?.value ?? '';\n const moduleVars = document.querySelector<HTMLDivElement>('.js-playgroundVars')?.dataset ?? {};\n if (moduleVars.modulepath !== 'std') {\n codeWithModFile = codeWithModFile.concat(`\n-- go.mod --\nmodule play.ground\n\nrequire ${moduleVars.modulepath} ${moduleVars.version}\n`);\n }\n\n return codeWithModFile;\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.getCodeWithModFile(),\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.getCodeWithModFile(), 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/shared/playground/playground.test.ts b/static/shared/playground/playground.test.ts
index 60ca821..8a657ef 100644
--- a/static/shared/playground/playground.test.ts
+++ b/static/shared/playground/playground.test.ts
@@ -103,7 +103,7 @@
await flushPromises();
expect(window.fetch).toHaveBeenCalledWith('/play/share', {
- body: codeSnippet,
+ body: snippetWithModeFile,
method: 'POST',
});
expect(window.open).toHaveBeenCalledWith('https://play.golang.org/p/abcdefg');
diff --git a/static/shared/playground/playground.ts b/static/shared/playground/playground.ts
index ad3156d..5efe7b8 100644
--- a/static/shared/playground/playground.ts
+++ b/static/shared/playground/playground.ts
@@ -186,6 +186,21 @@
this.setOutputText('An error has occurred…');
}
+ private getCodeWithModFile(): string {
+ 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}
+`);
+ }
+
+ return codeWithModFile;
+ }
+
/**
* Opens a new window to play.golang.org using the
* example snippet's code in the playground.
@@ -197,7 +212,7 @@
fetch('/play/share', {
method: 'POST',
- body: this.inputEl?.value,
+ body: this.getCodeWithModFile(),
})
.then(res => res.text())
.then(shareId => {
@@ -241,19 +256,9 @@
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: codeWithModFile, version: 2 }),
+ body: JSON.stringify({ body: this.getCodeWithModFile(), version: 2 }),
})
.then(res => res.json())
.then(async ({ Events, Errors }) => {