diff --git a/material/assets/javascripts/bundle.4fa4ebaf.min.js b/material/assets/javascripts/bundle.4fa4ebaf.min.js deleted file mode 100644 index 18c3730da..000000000 --- a/material/assets/javascripts/bundle.4fa4ebaf.min.js +++ /dev/null @@ -1,2 +0,0 @@ -!function(e,t){for(var n in t)e[n]=t[n]}(window,function(e){function t(t){for(var a,o,i=t[0],s=t[1],p=t[2],u=0,l=[];u"focus"===e),Object(m.a)(e===(document.activeElement instanceof HTMLElement?document.activeElement:void 0)))}var v=n(55),w=n(56),$=n(57),x=n(59),y=n(43);const _=new a.a,E=Object(r.a)(()=>Object(v.a)(new ResizeObserver(e=>{for(const t of e)_.next(t)}))).pipe(Object(i.a)(e=>w.a.pipe(Object(m.a)(e)).pipe(Object($.a)(()=>e.disconnect()))),Object(s.a)(1));function k(e){return{width:e.offsetWidth,height:e.offsetHeight}}function A(e){return E.pipe(Object(x.a)(t=>t.observe(e)),Object(i.a)(t=>_.pipe(Object(y.a)(({target:t})=>t===e),Object($.a)(()=>t.unobserve(e)),Object(o.a)(({contentRect:e})=>({width:e.width,height:e.height})))),Object(m.a)(k(e)))}var S=n(42);var T=n(60);function R(){return new URL(location.href)}function M(){return location.hash.substring(1)}function C(e){const t=matchMedia(e);return Object(u.a)(t,"change").pipe(Object(o.a)(e=>e.matches),Object(m.a)(t.matches))}function L(e,t){return e.pipe(Object(i.a)(e=>e?t():w.a))}var P=n(6);function U(e,t={credentials:"same-origin"}){return Object(P.a)(fetch(e,t)).pipe(Object(y.a)(e=>200===e.status))}function z(e,t){return U(e,t).pipe(Object(i.a)(e=>e.json()),Object(s.a)(1))}const H={drawer:d("[data-md-toggle=drawer]"),search:d("[data-md-toggle=search]")};var N=n(46),I=n(61);function Y(){return{x:Math.max(0,pageXOffset),y:Math.max(0,pageYOffset)}}function D({x:e,y:t}){window.scrollTo(e||0,t||0)}function F(){return{width:innerWidth,height:innerHeight}}function q(e,{viewport$:t,header$:n}){const a=t.pipe(Object(I.a)("size")),c=Object(N.a)([a,n]).pipe(Object(o.a)(()=>({x:e.offsetLeft,y:e.offsetTop})));return Object(N.a)([n,t,c]).pipe(Object(o.a)(([{height:e},{offset:t,size:n},{x:a,y:c}])=>({offset:{x:t.x-a,y:t.y-c+e},size:n})))}var J=n(62),W=n(63);const Q=d("#__config"),B=JSON.parse(Q.textContent);function K(){return B}function V(e){return B.features.includes(e)}function X(e,t){return void 0!==t?B.translations[e].replace("#",t.toString()):B.translations[e]}B.base=new URL(B.base,R()).toString().replace(/\/$/,"");var G,Z=n(26),ee=n.n(Z),te=n(64);function ne(e,t){e.setAttribute("data-md-state",t)}function ae(e){e.removeAttribute("data-md-state")}function ce(e,t){e.classList.toggle("md-nav__link--active",t)}function re(e){e.classList.remove("md-nav__link--active")}function oe(e,t){e.appendChild(t)}function ie(e){e.removeAttribute("data-md-state")}function se(e,t){if("string"==typeof t||"number"==typeof t)e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(const n of t)se(e,n)}function pe(e,t,...n){const a=document.createElement(e);if(t)for(const e of Object.keys(t))"boolean"!=typeof t[e]?a.setAttribute(e,t[e]):t[e]&&a.setAttribute(e,"");for(const e of n)se(a,e);return a}function be(e){if(e>999){return((e+1e-6)/1e3).toFixed(+((e-950)%1e3>99))+"k"}return e.toString()}function ue(e,t){const n=t&G.PARENT,a=t&G.TEASER,c=Object.keys(e.terms).filter(t=>!e.terms[t]).map(e=>[pe("del",null,e)," "]).flat().slice(0,-1);return pe("a",{href:e.location,class:"md-search-result__link",tabIndex:-1},pe("article",{class:["md-search-result__article",...n?["md-search-result__article--document"]:[]].join(" "),"data-md-score":e.score.toFixed(2)},n>0&&pe("div",{class:"md-search-result__icon md-icon"}),pe("h1",{class:"md-search-result__title"},e.title),a>0&&e.text.length>0&&pe("p",{class:"md-search-result__teaser"},function(e,t){let n=t;if(e.length>n){for(;" "!==e[n]&&--n>0;);return e.substring(0,n)+"..."}return e}(e.text,320)),a>0&&c.length>0&&pe("p",{class:"md-search-result__terms"},X("search.result.term.missing"),": ",c)))}function le(e,t=1/0){const n=[...e],a=n.findIndex(e=>!e.location.includes("#")),[c]=n.splice(a,1);let r=n.findIndex(e=>e.scoreue(e,G.TEASER)),...i.length?[pe("details",{class:"md-search-result__more"},pe("summary",{tabIndex:-1},i.length>0&&1===i.length?X("search.result.more.one"):X("search.result.more.other",i.length)),i.map(e=>ue(e,G.TEASER)))]:[]];return pe("li",{class:"md-search-result__item"},s)}!function(e){e[e.TEASER=1]="TEASER",e[e.PARENT=2]="PARENT"}(G||(G={}));let fe=0;function de(e,t){const n=new a.a;if(n.pipe(Object(te.a)(C("(hover)"))).subscribe(([{scroll:t},n])=>{t&&n?function(e,t=0){e.setAttribute("tabindex",t.toString())}(e):function(e){e.removeAttribute("tabindex")}(e)}),ee.a.isSupported()){const t=e.closest("pre");t.id="__code_"+fe++,t.insertBefore((c=t.id,pe("button",{class:"md-clipboard md-icon",title:X("clipboard.copy"),"data-clipboard-target":`#${c} > code`})),e)}var c;return function(e,{viewport$:t}){return t.pipe(Object(I.a)("size"),Object(o.a)(()=>{const t=k(e);return{scroll:function(e){return{width:e.scrollWidth,height:e.scrollHeight}}(e).width>t.width}}),Object(I.a)("scroll"))}(e,t).pipe(Object(x.a)(n),Object($.a)(()=>n.complete()),Object(o.a)(t=>Object.assign({ref:e},t)))}function Oe(e,t){const n=new a.a;return n.subscribe(()=>{e.setAttribute("open",""),e.scrollIntoView()}),function(e,{target$:t,print$:n}){return t.pipe(Object(o.a)(e=>e.closest("details:not([open])")),Object(y.a)(t=>e===t),Object(p.a)(n),Object(l.a)(e))}(e,t).pipe(Object(x.a)(n),Object($.a)(()=>n.complete()),Object(l.a)({ref:e}))}const je=j("table");function he(e){return h(e,je),h(je,pe("div",{class:"md-typeset__scrollwrap"},pe("div",{class:"md-typeset__table"},e))),Object(v.a)({ref:e})}var me=n(77),ge=n(78),ve=n(66);function we(e,t){const n=new a.a;return n.pipe(Object(ve.a)(me.a)).subscribe(({message:t,open:n})=>{!function(e,t){e.firstElementChild.innerHTML=t}(e,t),n?function(e,t){e.setAttribute("data-md-state",t)}(e,"open"):function(e){e.removeAttribute("data-md-state")}(e)}),function(e,{alert$:t}){return t.pipe(Object(i.a)(e=>Object(c.a)(Object(v.a)(!0),Object(v.a)(!1).pipe(Object(ge.a)(2e3))).pipe(Object(o.a)(t=>({message:e,open:t})))))}(0,t).pipe(Object(x.a)(n),Object($.a)(()=>n.complete()),Object(o.a)(t=>Object.assign({ref:e},t)))}var $e=n(67),xe=n(44),ye=n(68);function _e({viewport$:e}){if(!V("header.autohide"))return Object(v.a)(!1);const t=e.pipe(Object(o.a)(({offset:{y:e}})=>e),Object($e.a)(2,1),Object(o.a)(([e,t])=>[eMath.abs(t-e.y)>100),Object(o.a)(([,[e]])=>e),Object(xe.a)()),a=function(e){const t=H[e];return Object(u.a)(t,"change").pipe(Object(o.a)(()=>t.checked),Object(m.a)(t.checked))}("search");return Object(N.a)([e,a]).pipe(Object(o.a)(([{offset:e},t])=>e.y>400&&!t),Object(xe.a)(),Object(i.a)(e=>e?n:w.a),Object(m.a)(!1))}function Ee(e,t){const n=new a.a;n.pipe(Object(ve.a)(me.a)).subscribe(({active:t})=>{t?function(e,t){e.setAttribute("data-md-state",t)}(e,"active"):function(e){e.removeAttribute("data-md-state")}(e)});const c=f("article h1");return void 0===c?w.a:function(e,{viewport$:t,header$:n}){return q(e,{header$:n,viewport$:t}).pipe(Object(o.a)(({offset:{y:t}})=>{const{height:n}=k(e);return{active:t>=n}}),Object(I.a)("active"))}(c,t).pipe(Object(x.a)(n),Object($.a)(()=>n.complete()),Object(o.a)(t=>Object.assign({ref:e},t)))}var ke=n(71),Ae=n(39),Se=n(4);var Te=n(21),Re=n(69),Me=n(70),Ce=n(72),Le=n(73),Pe=n(79);var Ue;n(45);function ze(e){return e.split(/"([^"]+)"/g).map((e,t)=>1&t?e.replace(/^\b|^(?![^\x00-\x7F]|$)|\s+/g," +"):e).join("").replace(/"|(?:^|\s+)[*+\-:^~]+(?=\s+|$)/g,"").trim()}function He(e){return e.type===Ue.READY}function Ne(e){return e.type===Ue.QUERY}function Ie(e){return e.type===Ue.RESULT}function Ye({config:e,docs:t,index:n}){1===e.lang.length&&"en"===e.lang[0]&&(e.lang=[X("search.config.lang")]),"[\\s\\-]+"===e.separator&&(e.separator=X("search.config.separator"));return{config:e,docs:t,index:n,pipeline:X("search.config.pipeline").split(/\s*,\s*/).filter(Boolean)}}function De(e,t){const n=K(),c=new Worker(e),r=new a.a,i=function(e,{tx$:t}){const n=Object(u.a)(e,"message").pipe(Object(o.a)(({data:e})=>e));return t.pipe(Object(J.a)(()=>n,{leading:!0,trailing:!0}),Object(x.a)(t=>e.postMessage(t)),Object(W.a)(n),Object(S.a)())}(c,{tx$:r}).pipe(Object(o.a)(e=>{if(Ie(e))for(const t of e.data)for(const e of t)e.location=`${n.base}/${e.location}`;return e}),Object(S.a)());return Object(P.a)(t).pipe(Object(o.a)(e=>({type:Ue.SETUP,data:Ye(e)}))).subscribe(r.next.bind(r)),{tx$:r,rx$:i}}!function(e){e[e.SETUP=0]="SETUP",e[e.READY=1]="READY",e[e.QUERY=2]="QUERY",e[e.RESULT=3]="RESULT"}(Ue||(Ue={}));var Fe=n(74),qe=n(75);function Je(e,{tx$:t}){const n=new a.a;return n.pipe(Object(I.a)("value"),Object(o.a)(({value:e})=>({type:Ue.QUERY,data:e}))).subscribe(t.next.bind(t)),n.pipe(Object(I.a)("focus")).subscribe(({focus:t})=>{var n,a;t?(a=t,H[n="search"].checked!==a&&H[n].click(),function(e,t){e.placeholder=t}(e,"")):function(e){e.placeholder=X("search.placeholder")}(e)}),Object(u.a)(e.form,"reset").pipe(Object(Fe.a)(n.pipe(Object(qe.a)(1)))).subscribe(()=>function(e,t=!0){t?e.focus():e.blur()}(e)),function(e){const t=(null===__search||void 0===__search?void 0:__search.transform)||ze,n=g(e),a=Object(c.a)(Object(u.a)(e,"keyup"),Object(u.a)(e,"focus").pipe(Object(ge.a)(1))).pipe(Object(o.a)(()=>t(e.value)),Object(m.a)(t(e.value)),Object(xe.a)());return Object(N.a)([a,n]).pipe(Object(o.a)(([e,t])=>({value:e,focus:t})))}(e).pipe(Object(x.a)(n),Object($.a)(()=>n.complete()),Object(o.a)(t=>Object.assign({ref:e},t)))}function We(e,{rx$:t},{query$:n}){const c=new a.a,r=d(":scope > :first-child",e);c.pipe(Object(te.a)(n)).subscribe(([{data:e},{value:t}])=>{t?function(e,t){switch(t){case 0:e.textContent=X("search.result.none");break;case 1:e.textContent=X("search.result.one");break;default:e.textContent=X("search.result.other",t)}}(r,e.length):function(e){e.textContent=X("search.result.placeholder")}(r)});const i=d(":scope > :last-child",e);c.subscribe(({data:e})=>{!function(e){e.innerHTML=""}(i);const t=[...e.map(([e])=>e.score),0];for(let n=0;n({data:e})),Object(m.a)({data:[]})).pipe(Object(x.a)(c),Object($.a)(()=>c.complete()),Object(o.a)(t=>Object.assign({ref:e},t)))}function Qe(e){const t=K(),n=De(t.search,(a=t.base+"/search/search_index.json",(null===__search||void 0===__search?void 0:__search.index)||z(a)));var a;const{tx$:r,rx$:o}=n;r.pipe(Object(y.a)(Ne),Object(ke.a)(o.pipe(Object(y.a)(He))),Object(Ae.a)(1)).subscribe(r.next.bind(r));const i=Je(d("[data-md-component=search-query]",e),n);return Object(c.a)(i,We(d("[data-md-component=search-result]",e),n,{query$:i}))}var Be=n(25);function Ke(e,t){var{header$:n}=t,c=Object(Be.c)(t,["header$"]);const r=new a.a;return r.pipe(Object(ve.a)(me.a),Object(te.a)(n)).subscribe({next([{height:t},{height:n}]){!function(e,t){const n=e.firstElementChild;n.style.height=t-2*n.offsetTop+"px"}(e,t),function(e,t){e.style.top=t+"px"}(e,n)},complete(){!function(e){e.style.top=""}(e),function(e){e.firstElementChild.style.height=""}(e)}}),function(e,{viewport$:t,main$:n}){const a=e.parentElement.offsetTop-e.parentElement.parentElement.offsetTop;return Object(N.a)([n,t]).pipe(Object(o.a)(([{offset:e,height:t},{offset:{y:n}}])=>({height:t=t+Math.min(a,Math.max(0,n-e))-a,locked:n>=e+a})),Object(xe.a)((e,t)=>e.height===t.height&&e.locked===t.locked))}(e,c).pipe(Object(x.a)(r),Object($.a)(()=>r.complete()),Object(o.a)(t=>Object.assign({ref:e},t)))}var Ve=n(76);function Xe(e){const[t]=e.match(/(git(?:hub|lab))/i)||[];switch(t.toLowerCase()){case"github":const[,t,n]=e.match(/^.+github\.com\/([^/]+)\/?([^/]+)?/i);return function(e,t){return z(void 0!==t?`https://api.github.com/repos/${e}/${t}`:"https://api.github.com/users/"+e).pipe(Object(o.a)(e=>{if(void 0!==t){const{stargazers_count:t,forks_count:n}=e;return[be(t)+" Stars",be(n)+" Forks"]}{const{public_repos:t}=e;return[be(t)+" Repositories"]}}),Object(Ve.a)([]))}(t,n);case"gitlab":const[,a,c]=e.match(/^.+?([^/]*gitlab[^/]+)\/(.+?)\/?$/i);return function(e,t){return z(`https://${e}/api/v4/projects/${encodeURIComponent(t)}`).pipe(Object(o.a)(({star_count:e,forks_count:t})=>[be(e)+" Stars",be(t)+" Forks"]),Object(Ve.a)([]))}(a,c);default:return w.a}}let Ge;function Ze(e){const t=new a.a;return t.subscribe(({facts:t})=>{!function(e,t){e.lastElementChild.appendChild(t)}(e,function(e){return pe("ul",{class:"md-source__facts"},e.map(e=>pe("li",{class:"md-source__fact"},e)))}(t)),function(e,t){e.lastElementChild.setAttribute("data-md-state",t)}(e,"done")}),function(e){const t=function(e){let t=0;for(let n=0,a=e.length;n{const n=sessionStorage.getItem(t);if(n)return Object(v.a)(JSON.parse(n));{const n=Xe(e.href);return n.subscribe(e=>{try{sessionStorage.setItem(t,JSON.stringify(e))}catch(e){}}),n}}).pipe(Object(Me.a)(()=>w.a),Object(y.a)(e=>e.length>0),Object(o.a)(e=>({facts:e})),Object(s.a)(1)))}(e).pipe(Object(x.a)(t),Object($.a)(()=>t.complete()),Object(o.a)(t=>Object.assign({ref:e},t)))}function et(e,t){const n=new a.a;return n.pipe(Object(ve.a)(me.a)).subscribe({next({hidden:t}){t?function(e,t){e.setAttribute("data-md-state",t)}(e,"hidden"):ie(e)},complete(){ie(e)}}),function(e,{viewport$:t,header$:n}){return q(e,{header$:n,viewport$:t}).pipe(Object(o.a)(({offset:{y:e}})=>({hidden:e>=10})),Object(I.a)("hidden"))}(e,t).pipe(Object(x.a)(n),Object($.a)(()=>n.complete()),Object(o.a)(t=>Object.assign({ref:e},t)))}var tt=n(80);function nt(e,t){const n=new a.a;n.pipe(Object(ve.a)(me.a)).subscribe(({prev:e,next:t})=>{for(const[e]of t)re(e),ae(e);for(const[t,[n]]of e.entries())ce(n,t===e.length-1),ne(n,"blur")});return function(e,{viewport$:t,header$:n}){const a=new Map;for(const t of e){const e=f(`[id="${decodeURIComponent(t.hash.substring(1))}"]`);void 0!==e&&a.set(t,e)}const c=n.pipe(Object(o.a)(e=>24+e.height));return A(document.body).pipe(Object(I.a)("height"),Object(o.a)(()=>{let e=[];return[...a].reduce((t,[n,c])=>{for(;e.length;){if(!(a.get(e[e.length-1]).tagName>=c.tagName))break;e.pop()}let r=c.offsetTop;for(;!r&&c.parentElement;)r=(c=c.parentElement).offsetTop;return t.set([...e=[...e,n]].reverse(),r)},new Map)}),Object(i.a)(e=>Object(N.a)([c,t]).pipe(Object(tt.a)(([e,t],[n,{offset:{y:a}}])=>{for(;t.length;){const[,c]=t[0];if(!(c-n=a))break;t=[e.pop(),...t]}return[e,t]},[[],[...e]]),Object(xe.a)((e,t)=>e[0]===t[0]&&e[1]===t[1])))).pipe(Object(o.a)(([e,t])=>({prev:e.map(([e])=>e),next:t.map(([e])=>e)})),Object(m.a)({prev:[],next:[]}),Object($e.a)(2,1),Object(o.a)(([e,t])=>e.prev.lengthn.complete()),Object(o.a)(t=>Object.assign({ref:e},t)))}var at=n(14);document.documentElement.classList.remove("no-js"),document.documentElement.classList.add("js");const ct=function(){const e=new b.a;return Object(u.a)(document,"DOMContentLoaded").pipe(Object(l.a)(document)).subscribe(e),e}(),rt=new T.a(R()),ot=Object(u.a)(window,"hashchange").pipe(Object(o.a)(M),Object(m.a)(M()),Object(y.a)(e=>e.length>0),Object(S.a)()).pipe(Object(i.a)(e=>Object(v.a)(f(`[id="${e}"]`)))),it=Object(N.a)([Object(c.a)(Object(u.a)(window,"scroll",{passive:!0}),Object(u.a)(window,"resize",{passive:!0})).pipe(Object(o.a)(Y),Object(m.a)(Y())),Object(u.a)(window,"resize",{passive:!0}).pipe(Object(o.a)(F),Object(m.a)(F()))]).pipe(Object(o.a)(([e,t])=>({offset:e,size:t})),Object(s.a)(1)),st=C("(min-width: 960px)"),pt=C("(min-width: 1220px)"),bt=Object(c.a)(C("print").pipe(Object(y.a)(Boolean)),Object(u.a)(window,"beforeprint")).pipe(Object(l.a)(void 0)),ut=new a.a;!function({alert$:e}){ee.a.isSupported()&&new Se.a(e=>{new ee.a("[data-clipboard-target], [data-clipboard-text]").on("success",t=>e.next(t))}).subscribe(()=>e.next(X("clipboard.copied")))}({alert$:ut}),V("navigation.instant")&&function({document$:e,location$:t,viewport$:n}){const a=K();if("file:"===location.protocol)return;"scrollRestoration"in history&&(history.scrollRestoration="manual",Object(u.a)(window,"beforeunload").subscribe(()=>{history.scrollRestoration="auto"}));const r=f("link[rel='shortcut icon']");void 0!==r&&(r.href=r.href);const p=function(e,t){const n=new DOMParser;return U(e,t).pipe(Object(i.a)(e=>e.text()),Object(o.a)(e=>n.parseFromString(e,"text/xml")),Object(s.a)(1))}(a.base+"/sitemap.xml").pipe(Object(o.a)(e=>function(e){if(e.length<2)return e;const[t,n]=e.sort((e,t)=>e.length-t.length);let a=0;if(t===n)a=t.length;else for(;t.charCodeAt(a)==t.charCodeAt(a);)a++;const c=K();return e.map(e=>e.replace(t.slice(0,a),c.base+"/"))}(O("loc",e).map(e=>e.textContent))),Object(i.a)(e=>Object(u.a)(document.body,"click").pipe(Object(y.a)(e=>!e.metaKey&&!e.ctrlKey),Object(i.a)(t=>{if(t.target instanceof HTMLElement){const n=t.target.closest("a");if(n&&!n.target&&e.includes(n.href))return t.preventDefault(),Object(v.a)({url:new URL(n.href)})}return w.a}))),Object(S.a)()),b=Object(u.a)(window,"popstate").pipe(Object(y.a)(e=>null!==e.state),Object(o.a)(e=>({url:new URL(location.href),offset:e.state})),Object(S.a)());Object(c.a)(p,b).pipe(Object(xe.a)((e,t)=>e.url.href===t.url.href),Object(o.a)(({url:e})=>e)).subscribe(t);const l=t.pipe(Object(I.a)("pathname"),Object(Re.a)(1),Object(i.a)(e=>U(e.href).pipe(Object(Me.a)(()=>(function(e){location.href=e.href}(e),w.a)))),Object(S.a)());p.pipe(Object(ke.a)(l)).subscribe(({url:e})=>{history.pushState({},"",e.toString())});const m=new DOMParser;l.pipe(Object(i.a)(e=>e.text()),Object(o.a)(e=>m.parseFromString(e,"text/html"))).subscribe(e),Object(c.a)(p,b).pipe(Object(ke.a)(e)).subscribe(({url:e,offset:t})=>{e.hash&&!t?function(e){const t=j("a");t.href=e,t.addEventListener("click",e=>e.stopPropagation()),t.click()}(e.hash):D(t||{y:0})}),e.pipe(Object(Re.a)(1)).subscribe(e=>{for(const t of["title","link[rel='canonical']","meta[name='author']","meta[name='description']","[data-md-component=announce]","[data-md-component=header-title]","[data-md-component=container]","[data-md-component=skip]"]){const n=f(t),a=f(t,e);void 0!==n&&void 0!==a&&h(n,a)}}),e.pipe(Object(Re.a)(1),Object(o.a)(()=>d("[data-md-component=container]")),Object(i.a)(e=>Object(v.a)(...O("script",e))),Object(Ce.a)(e=>{const t=j("script");return e.src?(t.src=e.src,h(e,t),new Se.a(e=>{t.onload=()=>e.complete()})):(t.textContent=e.textContent,h(e,t),Te.a)})).subscribe(),n.pipe(Object(Le.a)(p),Object(Pe.a)(250),Object(I.a)("offset")).subscribe(({offset:e})=>{history.replaceState(e,"")}),Object(c.a)(p,b).pipe(Object($e.a)(2,1),Object(y.a)(([e,t])=>e.url.pathname===t.url.pathname),Object(o.a)(([,e])=>e)).subscribe(({offset:e})=>{D(e||{y:0})})}({document$:ct,location$:rt,viewport$:it}),function({document$:e}){e.subscribe(()=>{for(const e of O("[data-md-state=indeterminate]"))e.setAttribute("data-md-state",""),e.indeterminate=!0,e.checked=!1})}({document$:ct}),function({document$:e}){/(iPad|iPhone|iPod)/.test(navigator.userAgent)&&e.pipe(Object(i.a)(()=>Object(v.a)(...O("[data-md-scrollfix]"))),Object(x.a)(e=>e.removeAttribute("data-md-scrollfix")),Object(at.a)(e=>Object(u.a)(e,"touchstart").pipe(Object(l.a)(e)))).subscribe(e=>{const t=e.scrollTop;0===t?e.scrollTop=1:t+e.offsetHeight===e.scrollHeight&&(e.scrollTop=t-1)})}({document$:ct});const lt=(ft=d("[data-md-component=header]"),dt={viewport$:it},Object(r.a)(()=>{const e=getComputedStyle(ft);return Object(v.a)("sticky"===e.position||"-webkit-sticky"===e.position)}).pipe(Object(ye.a)(A(ft),_e(dt)),Object(o.a)(([e,{height:t},n])=>({height:e?t:0,sticky:e,hidden:n})),Object(xe.a)((e,t)=>e.sticky===t.sticky&&e.height===t.height&&e.hidden===t.hidden),Object(s.a)(1)));var ft,dt;const Ot=ct.pipe(Object(o.a)(()=>d("[data-md-component=main]")),Object(i.a)(e=>function(e,{viewport$:t,header$:n}){const a=n.pipe(Object(o.a)(({height:e})=>e),Object(xe.a)()),c=a.pipe(Object(i.a)(()=>A(e).pipe(Object(o.a)(({height:t})=>({top:e.offsetTop,bottom:e.offsetTop+t})),Object(I.a)("bottom"))));return Object(N.a)([a,c,t]).pipe(Object(o.a)(([e,{top:t,bottom:n},{offset:{y:a},size:{height:c}}])=>({offset:t-e,height:c=Math.max(0,c-Math.max(0,t-a,e)-Math.max(0,c+a-n)),active:t-e<=a})),Object(xe.a)((e,t)=>e.offset===t.offset&&e.height===t.height&&e.active===t.active))}(e,{viewport$:it,header$:lt})),Object(s.a)(1)),jt=Object(c.a)(...O("[data-md-component=dialog]").map(e=>we(e,{alert$:ut})),...O("[data-md-component=header]").map(e=>function(e,{header$:t,main$:n}){const c=new a.a;return c.pipe(Object(I.a)("active"),Object(ye.a)(t),Object(ve.a)(me.a)).subscribe(([{active:t},{hidden:n}])=>{t?function(e,t){e.setAttribute("data-md-state",t)}(e,n?"hidden":"shadow"):function(e){e.removeAttribute("data-md-state")}(e)}),n.subscribe(e=>c.next(e)),t.pipe(Object(o.a)(t=>Object.assign({ref:e},t)))}(e,{viewport$:it,header$:lt,main$:Ot})),...O("[data-md-component=search]").map(e=>Qe(e)),...O("[data-md-component=source]").map(e=>Ze(e)),...O("[data-md-component=tabs]").map(e=>et(e,{viewport$:it,header$:lt}))),ht=Object(r.a)(()=>Object(c.a)(...O("[data-md-component=content]").map(e=>function(e,{target$:t,viewport$:n,print$:a}){return Object(c.a)(...O("pre > code",e).map(e=>de(e,{viewport$:n})),...O("table:not([class])",e).map(e=>he(e)),...O("details",e).map(e=>Oe(e,{target$:t,print$:a})))}(e,{target$:ot,viewport$:it,print$:bt})),...O("[data-md-component=header-title]").map(e=>Ee(e,{viewport$:it,header$:lt})),...O("[data-md-component=sidebar]").map(e=>"navigation"===e.getAttribute("data-md-type")?L(pt,()=>Ke(e,{viewport$:it,header$:lt,main$:Ot})):L(st,()=>Ke(e,{viewport$:it,header$:lt,main$:Ot}))),...O("[data-md-component=toc]").map(e=>nt(e,{viewport$:it,header$:lt})))),mt=ct.pipe(Object(i.a)(()=>ht),Object(p.a)(jt));mt.subscribe()}})); -//# sourceMappingURL=bundle.4fa4ebaf.min.js.map \ No newline at end of file diff --git a/material/assets/javascripts/bundle.4fa4ebaf.min.js.map b/material/assets/javascripts/bundle.4fa4ebaf.min.js.map deleted file mode 100644 index c979b0900..000000000 --- a/material/assets/javascripts/bundle.4fa4ebaf.min.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/assets/javascripts/browser/element/_/index.ts","webpack:///./src/assets/javascripts/browser/element/focus/index.ts","webpack:///./src/assets/javascripts/browser/element/size/index.ts","webpack:///./src/assets/javascripts/browser/location/_/index.ts","webpack:///./src/assets/javascripts/browser/location/hash/index.ts","webpack:///./src/assets/javascripts/browser/media/index.ts","webpack:///./src/assets/javascripts/browser/request/index.ts","webpack:///./src/assets/javascripts/browser/toggle/index.ts","webpack:///./src/assets/javascripts/browser/viewport/offset/index.ts","webpack:///./src/assets/javascripts/browser/viewport/size/index.ts","webpack:///./src/assets/javascripts/browser/viewport/_/index.ts","webpack:///./src/assets/javascripts/_/index.ts","webpack:///./src/assets/javascripts/templates/search/index.tsx","webpack:///./src/assets/javascripts/actions/anchor/index.ts","webpack:///./src/assets/javascripts/actions/search/result/index.ts","webpack:///./src/assets/javascripts/actions/tabs/index.ts","webpack:///./src/assets/javascripts/utilities/jsx/index.ts","webpack:///./src/assets/javascripts/utilities/string/index.ts","webpack:///./src/assets/javascripts/components/content/code/index.ts","webpack:///./src/assets/javascripts/actions/_/index.ts","webpack:///./src/assets/javascripts/templates/clipboard/index.tsx","webpack:///./src/assets/javascripts/components/content/details/index.ts","webpack:///./src/assets/javascripts/components/content/table/index.ts","webpack:///./src/assets/javascripts/templates/table/index.tsx","webpack:///./src/assets/javascripts/components/dialog/index.ts","webpack:///./src/assets/javascripts/actions/dialog/index.ts","webpack:///./src/assets/javascripts/components/header/_/index.ts","webpack:///./src/assets/javascripts/components/header/title/index.ts","webpack:///./src/assets/javascripts/actions/header/title/index.ts","webpack:///./src/assets/javascripts/integrations/search/worker/message/index.ts","webpack:///./src/assets/javascripts/integrations/search/query/transform/index.ts","webpack:///./src/assets/javascripts/integrations/search/worker/_/index.ts","webpack:///./src/assets/javascripts/browser/worker/index.ts","webpack:///./src/assets/javascripts/components/search/query/index.ts","webpack:///./src/assets/javascripts/actions/search/query/index.ts","webpack:///./src/assets/javascripts/components/search/result/index.ts","webpack:///./src/assets/javascripts/components/search/_/index.ts","webpack:///./src/assets/javascripts/components/sidebar/index.ts","webpack:///./src/assets/javascripts/actions/sidebar/index.ts","webpack:///./src/assets/javascripts/components/source/facts/_/index.ts","webpack:///./src/assets/javascripts/components/source/facts/github/index.ts","webpack:///./src/assets/javascripts/components/source/facts/gitlab/index.ts","webpack:///./src/assets/javascripts/components/source/_/index.ts","webpack:///./src/assets/javascripts/actions/source/index.ts","webpack:///./src/assets/javascripts/templates/source/index.tsx","webpack:///./src/assets/javascripts/components/tabs/index.ts","webpack:///./src/assets/javascripts/components/toc/index.ts","webpack:///./src/assets/javascripts/index.ts","webpack:///./src/assets/javascripts/browser/document/index.ts","webpack:///./src/assets/javascripts/integrations/clipboard/index.ts","webpack:///./src/assets/javascripts/integrations/instant/index.ts","webpack:///./src/assets/javascripts/patches/indeterminate/index.ts","webpack:///./src/assets/javascripts/patches/scrollfix/index.ts","webpack:///./src/assets/javascripts/components/main/index.ts","webpack:///./src/assets/javascripts/actions/header/_/index.ts","webpack:///./src/assets/javascripts/components/content/_/index.ts"],"names":["webpackJsonpCallback","data","moduleId","chunkId","chunkIds","moreModules","executeModules","i","resolves","length","Object","prototype","hasOwnProperty","call","installedChunks","push","modules","parentJsonpFunction","shift","deferredModules","apply","checkDeferredModules","result","deferredModule","fulfilled","j","depId","splice","__webpack_require__","s","installedModules","0","exports","module","l","m","c","d","name","getter","o","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","p","jsonpArray","window","oldJsonpFunction","slice","getElement","selector","node","document","querySelector","undefined","getElementOrThrow","el","ReferenceError","getElements","Array","from","querySelectorAll","createElement","tagName","replaceElement","source","target","replaceWith","watchElementFocus","merge","fromEvent","pipe","map","type","startWith","activeElement","HTMLElement","entry$","Subject","observer$","defer","of","ResizeObserver","entries","entry","next","switchMap","resize","finalize","disconnect","shareReplay","getElementSize","width","offsetWidth","height","offsetHeight","watchElementSize","tap","observer","observe","filter","unobserve","contentRect","getLocation","URL","location","href","getLocationHash","hash","substring","watchMedia","query","media","matchMedia","ev","matches","at","toggle$","factory","active","request","url","options","credentials","fetch","res","status","requestJSON","json","toggles","drawer","search","getViewportOffset","x","Math","max","pageXOffset","y","pageYOffset","setViewportOffset","scrollTo","getViewportSize","innerWidth","innerHeight","watchViewportAt","viewport$","header$","size$","distinctUntilKeyChanged","offset$","combineLatest","offsetLeft","offsetTop","offset","size","JSON","parse","textContent","configuration","feature","flag","features","includes","translation","translations","replace","toString","base","Flag","setAnchorState","state","setAttribute","resetAnchorState","removeAttribute","setAnchorActive","classList","toggle","resetAnchorActive","remove","addToSearchResultList","child","appendChild","resetTabsState","innerHTML","Node","isArray","h","tag","attributes","children","attr","keys","round","toFixed","renderSearchDocument","parent","PARENT","teaser","TEASER","missing","terms","flat","class","tabIndex","join","score","title","text","truncate","renderSearchResult","threshold","Infinity","docs","findIndex","doc","article","index","best","more","section","mountCodeBlock","internal$","withLatestFrom","subscribe","scroll","hover","setFocusable","resetFocusable","isSupported","closest","id","insertBefore","visible","scrollWidth","scrollHeight","getElementContentSize","watchCodeBlock","complete","ref","mountDetails","scrollIntoView","target$","print$","details","mergeWith","mapTo","watchDetails","sentinel","mountDataTable","mountDialog","observeOn","animationFrame","message","open","firstElementChild","setDialogMessage","setDialogState","resetDialogState","_el","alert$","delay","watchDialog","isHidden","direction$","bufferCount","a","b","hidden$","abs","direction","distinctUntilChanged","search$","checked","watchToggle","mountHeaderTitle","setHeaderTitleState","resetHeaderTitleState","headline","watchHeaderTitle","SearchMessageType","defaultTransform","split","trim","isSearchReadyMessage","READY","isSearchQueryMessage","QUERY","isSearchResultMessage","RESULT","setupSearchIndex","config","lang","separator","pipeline","Boolean","setupSearchWorker","worker","Worker","tx$","rx$","throttle","leading","trailing","postMessage","switchMapTo","share","watchWorker","SETUP","mountSearchQuery","focus","click","placeholder","setSearchQueryPlaceholder","resetSearchQueryPlaceholder","form","takeUntil","takeLast","blur","setElementFocus","fn","__search","transform","focus$","value$","watchSearchQuery","mountSearchResult","query$","meta","setSearchResultMeta","resetSearchResultMeta","list","resetSearchResultList","thresholds","mountSearch","sample","take","mountSidebar","scrollwrap","style","setSidebarHeight","top","setSidebarOffset","resetSidebarOffset","resetSidebarHeight","main$","adjust","parentElement","min","locked","watchSidebar","fetchSourceFacts","match","toLowerCase","user","repo","stargazers_count","forks_count","public_repos","defaultIfEmpty","fetchSourceFactsFromGitHub","slug","project","encodeURIComponent","star_count","fetchSourceFactsFromGitLab","fetch$","mountSource","facts","lastElementChild","setSourceFacts","fact","renderSourceFacts","setSourceState","digest","len","charCodeAt","sessionStorage","getItem","setItem","stringify","err","catchError","watchSource","mountTabs","hidden","setTabsState","watchTabs","mountTableOfContents","prev","anchor","anchors","table","Map","decodeURIComponent","set","adjust$","header","body","path","reduce","pop","reverse","scan","watchTableOfContents","documentElement","add","document$","ReplaySubject","watchDocument","BehaviorSubject","passive","tablet$","screen$","Observable","subscriber","on","setupClipboardJS","location$","protocol","history","scrollRestoration","favicon","push$","dom","DOMParser","parseFromString","requestXML","sitemap","urls","root","sort","preprocess","metaKey","ctrlKey","preventDefault","pop$","response$","skip","setLocation","pushState","addEventListener","stopPropagation","setLocationHash","replacement","concatMap","script","src","onload","skipUntil","debounceTime","replaceState","pathname","setupInstantLoading","indeterminate","patchIndeterminate","test","navigator","userAgent","mergeMap","scrollTop","patchScrollfix","styles","getComputedStyle","position","combineLatestWith","sticky","border$","bottom","watchMain","control$","setHeaderState","resetHeaderState","main","mountHeader","content$","mountContent","getAttribute","component$"],"mappings":"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","file":"assets/javascripts/bundle.4fa4ebaf.min.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t0: 0\n \t};\n\n \tvar deferredModules = [];\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \tvar jsonpArray = window[\"webpackJsonp\"] = window[\"webpackJsonp\"] || [];\n \tvar oldJsonpFunction = jsonpArray.push.bind(jsonpArray);\n \tjsonpArray.push = webpackJsonpCallback;\n \tjsonpArray = jsonpArray.slice();\n \tfor(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);\n \tvar parentJsonpFunction = oldJsonpFunction;\n\n\n \t// add entry module to deferred list\n \tdeferredModules.push([50,1]);\n \t// run deferred modules when ready\n \treturn checkDeferredModules();\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve an element matching the query selector\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @returns Element or nothing\n */\nexport function getElement(\n selector: T, node?: ParentNode\n): HTMLElementTagNameMap[T]\n\nexport function getElement(\n selector: string, node?: ParentNode\n): T | undefined\n\nexport function getElement(\n selector: string, node: ParentNode = document\n): T | undefined {\n return node.querySelector(selector) || undefined\n}\n\n/**\n * Retrieve an element matching a query selector or throw a reference error\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @returns Element\n */\nexport function getElementOrThrow(\n selector: T, node?: ParentNode\n): HTMLElementTagNameMap[T]\n\nexport function getElementOrThrow(\n selector: string, node?: ParentNode\n): T\n\nexport function getElementOrThrow(\n selector: string, node: ParentNode = document\n): T {\n const el = getElement(selector, node)\n if (typeof el === \"undefined\")\n throw new ReferenceError(\n `Missing element: expected \"${selector}\" to be present`\n )\n return el\n}\n\n/**\n * Retrieve the currently active element\n *\n * @returns Element or nothing\n */\nexport function getActiveElement(): HTMLElement | undefined {\n return document.activeElement instanceof HTMLElement\n ? document.activeElement\n : undefined\n}\n\n/**\n * Retrieve all elements matching the query selector\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @returns Elements\n */\nexport function getElements(\n selector: T, node?: ParentNode\n): HTMLElementTagNameMap[T][]\n\nexport function getElements(\n selector: string, node?: ParentNode\n): T[]\n\nexport function getElements(\n selector: string, node: ParentNode = document\n): T[] {\n return Array.from(node.querySelectorAll(selector))\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Create an element\n *\n * @template T - Tag name type\n *\n * @param tagName - Tag name\n *\n * @returns Element\n */\nexport function createElement(\n tagName: T\n): HTMLElementTagNameMap[T] {\n return document.createElement(tagName)\n}\n\n/**\n * Replace an element with another element\n *\n * @param source - Source element\n * @param target - Target element\n */\nexport function replaceElement(\n source: HTMLElement, target: Node\n): void {\n source.replaceWith(target)\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, merge } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\nimport { getActiveElement } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set element focus\n *\n * @param el - Element\n * @param value - Whether the element should be focused\n */\nexport function setElementFocus(\n el: HTMLElement, value = true\n): void {\n if (value)\n el.focus()\n else\n el.blur()\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element focus\n *\n * @param el - Element\n *\n * @returns Element focus observable\n */\nexport function watchElementFocus(\n el: HTMLElement\n): Observable {\n return merge(\n fromEvent(el, \"focus\"),\n fromEvent(el, \"blur\")\n )\n .pipe(\n map(({ type }) => type === \"focus\"),\n startWith(el === getActiveElement())\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n NEVER,\n Observable,\n Subject,\n defer,\n of\n} from \"rxjs\"\nimport {\n filter,\n finalize,\n map,\n shareReplay,\n startWith,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Element offset\n */\nexport interface ElementSize {\n width: number /* Element width */\n height: number /* Element height */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Resize observer entry subject\n */\nconst entry$ = new Subject()\n\n/**\n * Resize observer observable\n *\n * This observable will create a `ResizeObserver` on the first subscription\n * and will automatically terminate it when there are no more subscribers.\n * It's quite important to centralize observation in a single `ResizeObserver`,\n * as the performance difference can be quite dramatic, as the link shows.\n *\n * @see https://bit.ly/3iIYfEm - Google Groups on performance\n */\nconst observer$ = defer(() => of(\n new ResizeObserver(entries => {\n for (const entry of entries)\n entry$.next(entry)\n })\n))\n .pipe(\n switchMap(resize => NEVER.pipe(startWith(resize))\n .pipe(\n finalize(() => resize.disconnect())\n )\n ),\n shareReplay(1)\n )\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve element size\n *\n * @param el - Element\n *\n * @returns Element size\n */\nexport function getElementSize(el: HTMLElement): ElementSize {\n return {\n width: el.offsetWidth,\n height: el.offsetHeight\n }\n}\n\n/**\n * Retrieve element content size, i.e. including overflowing content\n *\n * @param el - Element\n *\n * @returns Element size\n */\nexport function getElementContentSize(el: HTMLElement): ElementSize {\n return {\n width: el.scrollWidth,\n height: el.scrollHeight\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element size\n *\n * This function returns an observable that will subscribe to a single internal\n * instance of `ResizeObserver` upon subscription, and emit resize events until\n * termination. Note that this function should not be called with the same\n * element twice, as the first unsubscription will terminate observation.\n *\n * @param el - Element\n *\n * @returns Element size observable\n */\nexport function watchElementSize(\n el: HTMLElement\n): Observable {\n return observer$\n .pipe(\n tap(observer => observer.observe(el)),\n switchMap(observer => entry$\n .pipe(\n filter(({ target }) => target === el),\n finalize(() => observer.unobserve(el)),\n map(({ contentRect }) => ({\n width: contentRect.width,\n height: contentRect.height\n }))\n )\n ),\n startWith(getElementSize(el))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { BehaviorSubject, Subject } from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve location\n *\n * This function will return a `URL` object (and not `Location`) in order to\n * normalize typings across the application. Furthermore, locations need to be\n * tracked without setting them and `Location` is a singleton which represents\n * the current location.\n *\n * @returns URL\n */\nexport function getLocation(): URL {\n return new URL(location.href)\n}\n\n/**\n * Set location\n *\n * @param url - URL to change to\n */\nexport function setLocation(url: URL): void {\n location.href = url.href\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch location\n *\n * @returns Location subject\n */\nexport function watchLocation(): Subject {\n return new BehaviorSubject(getLocation())\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, of } from \"rxjs\"\nimport { filter, map, share, startWith, switchMap } from \"rxjs/operators\"\n\nimport { createElement, getElement } from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve location hash\n *\n * @returns Location hash\n */\nexport function getLocationHash(): string {\n return location.hash.substring(1)\n}\n\n/**\n * Set location hash\n *\n * Setting a new fragment identifier via `location.hash` will have no effect\n * if the value doesn't change. When a new fragment identifier is set, we want\n * the browser to target the respective element at all times, which is why we\n * use this dirty little trick.\n *\n * @param hash - Location hash\n */\nexport function setLocationHash(hash: string): void {\n const el = createElement(\"a\")\n el.href = hash\n el.addEventListener(\"click\", ev => ev.stopPropagation())\n el.click()\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch location hash\n *\n * @returns Location hash observable\n */\nexport function watchLocationHash(): Observable {\n return fromEvent(window, \"hashchange\")\n .pipe(\n map(getLocationHash),\n startWith(getLocationHash()),\n filter(hash => hash.length > 0),\n share()\n )\n}\n\n/**\n * Watch location target\n *\n * @returns Location target observable\n */\nexport function watchLocationTarget(): Observable {\n return watchLocationHash()\n .pipe(\n switchMap(id => of(getElement(`[id=\"${id}\"]`)!))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { NEVER, Observable, fromEvent, merge } from \"rxjs\"\nimport {\n filter,\n map,\n mapTo,\n startWith,\n switchMap\n} from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch media query\n *\n * @param query - Media query\n *\n * @returns Media observable\n */\nexport function watchMedia(query: string): Observable {\n const media = matchMedia(query)\n return fromEvent(media, \"change\")\n .pipe(\n map(ev => ev.matches),\n startWith(media.matches)\n )\n}\n\n/**\n * Watch print mode, cross-browser\n *\n * @returns Print observable\n */\nexport function watchPrint(): Observable {\n return merge(\n watchMedia(\"print\").pipe(filter(Boolean)), /* Webkit */\n fromEvent(window, \"beforeprint\") /* IE, FF */\n )\n .pipe(\n mapTo(undefined)\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Toggle an observable with another one\n *\n * @template T - Data type\n *\n * @param toggle$ - Toggle observable\n * @param factory - Observable factory\n *\n * @returns Toggled observable\n */\nexport function at(\n toggle$: Observable, factory: () => Observable\n): Observable {\n return toggle$\n .pipe(\n switchMap(active => active ? factory() : NEVER)\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, from } from \"rxjs\"\nimport {\n filter,\n map,\n shareReplay,\n switchMap\n} from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch the given URL\n *\n * @param url - Request URL\n * @param options - Request options\n *\n * @returns Response observable\n */\nexport function request(\n url: string, options: RequestInit = { credentials: \"same-origin\" }\n): Observable {\n return from(fetch(url, options))\n .pipe(\n filter(res => res.status === 200),\n )\n}\n\n/**\n * Fetch JSON from the given URL\n *\n * @template T - Data type\n *\n * @param url - Request URL\n * @param options - Request options\n *\n * @returns Data observable\n */\nexport function requestJSON(\n url: string, options?: RequestInit\n): Observable {\n return request(url, options)\n .pipe(\n switchMap(res => res.json()),\n shareReplay(1)\n )\n}\n\n/**\n * Fetch XML from the given URL\n *\n * @param url - Request URL\n * @param options - Request options\n *\n * @returns Data observable\n */\nexport function requestXML(\n url: string, options?: RequestInit\n): Observable {\n const dom = new DOMParser()\n return request(url, options)\n .pipe(\n switchMap(res => res.text()),\n map(res => dom.parseFromString(res, \"text/xml\")),\n shareReplay(1)\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\nimport { getElementOrThrow } from \"../element\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Toggle\n */\nexport type Toggle =\n | \"drawer\" /* Toggle for drawer */\n | \"search\" /* Toggle for search */\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Toggle map\n */\nconst toggles: Record = {\n drawer: getElementOrThrow(\"[data-md-toggle=drawer]\"),\n search: getElementOrThrow(\"[data-md-toggle=search]\")\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve the value of a toggle\n *\n * @param name - Toggle\n *\n * @returns Toggle value\n */\nexport function getToggle(name: Toggle): boolean {\n return toggles[name].checked\n}\n\n/**\n * Set toggle\n *\n * Simulating a click event seems to be the most cross-browser compatible way\n * of changing the value while also emitting a `change` event. Before, Material\n * used `CustomEvent` to programmatically change the value of a toggle, but this\n * is a much simpler and cleaner solution which doesn't require a polyfill.\n *\n * @param name - Toggle\n * @param value - Toggle value\n */\nexport function setToggle(name: Toggle, value: boolean): void {\n if (toggles[name].checked !== value)\n toggles[name].click()\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch toggle\n *\n * @param name - Toggle\n *\n * @returns Toggle value observable\n */\nexport function watchToggle(name: Toggle): Observable {\n const el = toggles[name]\n return fromEvent(el, \"change\")\n .pipe(\n map(() => el.checked),\n startWith(el.checked)\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, merge } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Viewport offset\n */\nexport interface ViewportOffset {\n x: number /* Horizontal offset */\n y: number /* Vertical offset */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve viewport offset\n *\n * On iOS Safari, viewport offset can be negative due to overflow scrolling.\n * As this may induce strange behaviors downstream, we'll just limit it to 0.\n *\n * @returns Viewport offset\n */\nexport function getViewportOffset(): ViewportOffset {\n return {\n x: Math.max(0, pageXOffset),\n y: Math.max(0, pageYOffset)\n }\n}\n\n/**\n * Set viewport offset\n *\n * @param offset - Viewport offset\n */\nexport function setViewportOffset(\n { x, y }: Partial\n): void {\n window.scrollTo(x || 0, y || 0)\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport offset\n *\n * @returns Viewport offset observable\n */\nexport function watchViewportOffset(): Observable {\n return merge(\n fromEvent(window, \"scroll\", { passive: true }),\n fromEvent(window, \"resize\", { passive: true })\n )\n .pipe(\n map(getViewportOffset),\n startWith(getViewportOffset())\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Viewport size\n */\nexport interface ViewportSize {\n width: number /* Viewport width */\n height: number /* Viewport height */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve viewport size\n *\n * @returns Viewport size\n */\nexport function getViewportSize(): ViewportSize {\n return {\n width: innerWidth,\n height: innerHeight\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport size\n *\n * @returns Viewport size observable\n */\nexport function watchViewportSize(): Observable {\n return fromEvent(window, \"resize\", { passive: true })\n .pipe(\n map(getViewportSize),\n startWith(getViewportSize())\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, combineLatest } from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n map,\n shareReplay\n} from \"rxjs/operators\"\n\nimport { Header } from \"~/components\"\n\nimport {\n ViewportOffset,\n watchViewportOffset\n} from \"../offset\"\nimport {\n ViewportSize,\n watchViewportSize\n} from \"../size\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Viewport\n */\nexport interface Viewport {\n offset: ViewportOffset /* Viewport offset */\n size: ViewportSize /* Viewport size */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch at options\n */\ninterface WatchAtOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
/* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport\n *\n * @returns Viewport observable\n */\nexport function watchViewport(): Observable {\n return combineLatest([\n watchViewportOffset(),\n watchViewportSize()\n ])\n .pipe(\n map(([offset, size]) => ({ offset, size })),\n shareReplay(1)\n )\n}\n\n/**\n * Watch viewport relative to element\n *\n * @param el - Element\n * @param options - Options\n *\n * @returns Viewport observable\n */\nexport function watchViewportAt(\n el: HTMLElement, { viewport$, header$ }: WatchAtOptions\n): Observable {\n const size$ = viewport$\n .pipe(\n distinctUntilKeyChanged(\"size\")\n )\n\n /* Compute element offset */\n const offset$ = combineLatest([size$, header$])\n .pipe(\n map((): ViewportOffset => ({\n x: el.offsetLeft,\n y: el.offsetTop\n }))\n )\n\n /* Compute relative viewport, return hot observable */\n return combineLatest([header$, viewport$, offset$])\n .pipe(\n map(([{ height }, { offset, size }, { x, y }]) => ({\n offset: {\n x: offset.x - x,\n y: offset.y - y + height\n },\n size\n }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { getElementOrThrow, getLocation } from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Feature flag\n */\nexport type Flag =\n | \"header.autohide\" /* Hide header */\n | \"navigation.tabs\" /* Tabs navigation */\n | \"navigation.instant\" /* Instant loading */\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Translation\n */\nexport type Translation =\n | \"clipboard.copy\" /* Copy to clipboard */\n | \"clipboard.copied\" /* Copied to clipboard */\n | \"search.config.lang\" /* Search language */\n | \"search.config.pipeline\" /* Search pipeline */\n | \"search.config.separator\" /* Search separator */\n | \"search.placeholder\" /* Search */\n | \"search.result.placeholder\" /* Type to start searching */\n | \"search.result.none\" /* No matching documents */\n | \"search.result.one\" /* 1 matching document */\n | \"search.result.other\" /* # matching documents */\n | \"search.result.more.one\" /* 1 more on this page */\n | \"search.result.more.other\" /* # more on this page */\n | \"search.result.term.missing\" /* Missing */\n\n/**\n * Translations\n */\nexport type Translations = Record\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Configuration\n */\nexport interface Config {\n base: string /* Base URL */\n features: Flag[] /* Feature flags */\n translations: Translations /* Translations */\n search: string /* Search worker URL */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve global configuration and make base URL absolute\n */\nconst script = getElementOrThrow(\"#__config\")\nconst config: Config = JSON.parse(script.textContent!)\nconfig.base = new URL(config.base, getLocation())\n .toString()\n .replace(/\\/$/, \"\")\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve global configuration\n *\n * @returns Global configuration\n */\nexport function configuration(): Config {\n return config\n}\n\n/**\n * Check whether a feature flag is enabled\n *\n * @param flag - Feature flag\n *\n * @returns Test result\n */\nexport function feature(flag: Flag): boolean {\n return config.features.includes(flag)\n}\n\n/**\n * Retrieve the translation for the given key\n *\n * @param key - Key to be translated\n * @param value - Value to be replaced\n *\n * @returns Translation\n */\nexport function translation(\n key: Translation, value?: string | number\n): string {\n return typeof value !== \"undefined\"\n ? config.translations[key].replace(\"#\", value.toString())\n : config.translations[key]\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { translation } from \"~/_\"\nimport {\n SearchDocument,\n SearchMetadata,\n SearchResult\n} from \"~/integrations/search\"\nimport { h, truncate } from \"~/utilities\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Render flag\n */\nconst enum Flag {\n TEASER = 1, /* Render teaser */\n PARENT = 2 /* Render as parent */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper function\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a search document\n *\n * @param section - Search document\n * @param flag - Render flags\n *\n * @returns Element\n */\nfunction renderSearchDocument(\n document: SearchDocument & SearchMetadata, flag: Flag\n) {\n const parent = flag & Flag.PARENT\n const teaser = flag & Flag.TEASER\n\n /* Render missing query terms */\n const missing = Object.keys(document.terms)\n .filter(key => !document.terms[key])\n .map(key => [{key}, \" \"])\n .flat()\n .slice(0, -1)\n\n /* Render article or section, depending on flags */\n const url = document.location\n return (\n \n \n {parent > 0 &&
}\n

{document.title}

\n {teaser > 0 && document.text.length > 0 &&\n

\n {truncate(document.text, 320)}\n

\n }\n {teaser > 0 && missing.length > 0 &&\n

\n {translation(\"search.result.term.missing\")}: {...missing}\n

\n }\n \n
\n )\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a search result\n *\n * @param result - Search result\n * @param threshold - Score threshold\n *\n * @returns Element\n */\nexport function renderSearchResult(\n result: SearchResult, threshold: number = Infinity\n) {\n const docs = [...result]\n\n /* Find and extract parent article */\n const parent = docs.findIndex(doc => !doc.location.includes(\"#\"))\n const [article] = docs.splice(parent, 1)\n\n /* Determine last index above threshold */\n let index = docs.findIndex(doc => doc.score < threshold)\n if (index === -1)\n index = docs.length\n\n /* Partition sections */\n const best = docs.slice(0, index)\n const more = docs.slice(index)\n\n /* Render children */\n const children = [\n renderSearchDocument(article, Flag.PARENT | +(!parent && index === 0)),\n ...best.map(section => renderSearchDocument(section, Flag.TEASER)),\n ...more.length ? [\n
\n \n {more.length > 0 && more.length === 1\n ? translation(\"search.result.more.one\")\n : translation(\"search.result.more.other\", more.length)\n }\n \n {...more.map(section => renderSearchDocument(section, Flag.TEASER))}\n
\n ] : []\n ]\n\n /* Render search result */\n return (\n
  • \n {children}\n
  • \n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set anchor state\n *\n * @param el - Anchor element\n * @param state - Anchor state\n */\nexport function setAnchorState(\n el: HTMLElement, state: \"blur\"\n): void {\n el.setAttribute(\"data-md-state\", state)\n}\n\n/**\n * Reset anchor state\n *\n * @param el - Anchor element\n */\nexport function resetAnchorState(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Set anchor active\n *\n * @param el - Anchor element\n * @param value - Whether the anchor is active\n */\nexport function setAnchorActive(\n el: HTMLElement, value: boolean\n): void {\n el.classList.toggle(\"md-nav__link--active\", value)\n}\n\n/**\n * Reset anchor active\n *\n * @param el - Anchor element\n */\nexport function resetAnchorActive(\n el: HTMLElement\n): void {\n el.classList.remove(\"md-nav__link--active\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { translation } from \"~/_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set number of search results\n *\n * @param el - Search result metadata element\n * @param value - Number of results\n */\nexport function setSearchResultMeta(\n el: HTMLElement, value: number\n): void {\n switch (value) {\n\n /* No results */\n case 0:\n el.textContent = translation(\"search.result.none\")\n break\n\n /* One result */\n case 1:\n el.textContent = translation(\"search.result.one\")\n break\n\n /* Multiple result */\n default:\n el.textContent = translation(\"search.result.other\", value)\n }\n}\n\n/**\n * Reset number of search results\n *\n * @param el - Search result metadata element\n */\nexport function resetSearchResultMeta(\n el: HTMLElement\n): void {\n el.textContent = translation(\"search.result.placeholder\")\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Add an element to the search result list\n *\n * @param el - Search result list element\n * @param child - Search result element\n */\nexport function addToSearchResultList(\n el: HTMLElement, child: Element\n): void {\n el.appendChild(child)\n}\n\n/**\n * Reset search result list\n *\n * @param el - Search result list element\n */\nexport function resetSearchResultList(\n el: HTMLElement\n): void {\n el.innerHTML = \"\"\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set tabs state\n *\n * @param el - Tabs element\n * @param state - Tabs state\n */\nexport function setTabsState(\n el: HTMLElement, state: \"hidden\"\n): void {\n el.setAttribute(\"data-md-state\", state)\n}\n\n/**\n * Reset tabs state\n *\n * @param el - Tabs element\n */\nexport function resetTabsState(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { JSX as JSXInternal } from \"preact\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * HTML attributes\n */\ntype Attributes =\n & JSXInternal.HTMLAttributes\n & JSXInternal.SVGAttributes\n & Record\n\n/**\n * Child element\n */\ntype Child =\n | HTMLElement\n | Text\n | string\n | number\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Append a child node to an element\n *\n * @param el - Element\n * @param child - Child node(s)\n */\nfunction appendChild(el: HTMLElement, child: Child | Child[]): void {\n\n /* Handle primitive types (including raw HTML) */\n if (typeof child === \"string\" || typeof child === \"number\") {\n el.innerHTML += child.toString()\n\n /* Handle nodes */\n } else if (child instanceof Node) {\n el.appendChild(child)\n\n /* Handle nested children */\n } else if (Array.isArray(child)) {\n for (const node of child)\n appendChild(el, node)\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * JSX factory\n *\n * @param tag - HTML tag\n * @param attributes - HTML attributes\n * @param children - Child elements\n *\n * @returns Element\n */\nexport function h(\n tag: string, attributes: Attributes | null, ...children: Child[]\n): HTMLElement {\n const el = document.createElement(tag)\n\n /* Set attributes, if any */\n if (attributes)\n for (const attr of Object.keys(attributes))\n if (typeof attributes[attr] !== \"boolean\")\n el.setAttribute(attr, attributes[attr])\n else if (attributes[attr])\n el.setAttribute(attr, \"\")\n\n /* Append child nodes */\n for (const child of children)\n appendChild(el, child)\n\n /* Return element */\n return el\n}\n\n/* ----------------------------------------------------------------------------\n * Namespace\n * ------------------------------------------------------------------------- */\n\nexport declare namespace h {\n namespace JSX {\n type Element = HTMLElement\n type IntrinsicElements = JSXInternal.IntrinsicElements\n }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Truncate a string after the given number of characters\n *\n * This is not a very reasonable approach, since the summaries kind of suck.\n * It would be better to create something more intelligent, highlighting the\n * search occurrences and making a better summary out of it, but this note was\n * written three years ago, so who knows if we'll ever fix it.\n *\n * @param value - Value to be truncated\n * @param n - Number of characters\n *\n * @returns Truncated value\n */\nexport function truncate(value: string, n: number): string {\n let i = n\n if (value.length > i) {\n while (value[i] !== \" \" && --i > 0) { /* keep eating */ }\n return `${value.substring(0, i)}...`\n }\n return value\n}\n\n/**\n * Round a number for display with repository facts\n *\n * This is a reverse-engineered version of GitHub's weird rounding algorithm\n * for stars, forks and all other numbers. While all numbers below `1,000` are\n * returned as-is, bigger numbers are converted to fixed numbers:\n *\n * - `1,049` => `1k`\n * - `1,050` => `1.1k`\n * - `1,949` => `1.9k`\n * - `1,950` => `2k`\n *\n * @param value - Original value\n *\n * @returns Rounded value\n */\nexport function round(value: number): string {\n if (value > 999) {\n const digits = +((value - 950) % 1000 > 99)\n return `${((value + 0.000001) / 1000).toFixed(digits)}k`\n } else {\n return value.toString()\n }\n}\n\n/**\n * Simple hash function\n *\n * @see https://bit.ly/2wsVjJ4 - Original source\n *\n * @param value - Value to be hashed\n *\n * @returns Hash as 32bit integer\n */\nexport function hash(value: string): number {\n let h = 0\n for (let i = 0, len = value.length; i < len; i++) {\n h = ((h << 5) - h) + value.charCodeAt(i)\n h |= 0 // Convert to 32bit integer\n }\n return h\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport ClipboardJS from \"clipboard\"\nimport { Observable, Subject } from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n finalize,\n map,\n tap,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport { resetFocusable, setFocusable } from \"~/actions\"\nimport {\n Viewport,\n getElementContentSize,\n getElementSize,\n watchMedia\n} from \"~/browser\"\nimport { renderClipboardButton } from \"~/templates\"\n\nimport { Component } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Code block\n */\nexport interface CodeBlock {\n scroll: boolean /* Code block overflows */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Global index for Clipboard.js integration\n */\nlet index = 0\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch code block\n *\n * @param el - Code block element\n * @param options - Options\n *\n * @returns Code block observable\n */\nexport function watchCodeBlock(\n el: HTMLElement, { viewport$ }: WatchOptions\n): Observable {\n return viewport$\n .pipe(\n distinctUntilKeyChanged(\"size\"),\n map(() => {\n const visible = getElementSize(el)\n const content = getElementContentSize(el)\n return {\n scroll: content.width > visible.width\n }\n }),\n distinctUntilKeyChanged(\"scroll\")\n )\n}\n\n/**\n * Mount code block\n *\n * This function ensures that overflowing code blocks are focusable by keyboard,\n * so they can be scrolled without a mouse to improve on accessibility.\n *\n * @param el - Code block element\n * @param options - Options\n *\n * @returns Code block component observable\n */\nexport function mountCodeBlock(\n el: HTMLElement, options: MountOptions\n): Observable> {\n const internal$ = new Subject()\n internal$\n .pipe(\n withLatestFrom(watchMedia(\"(hover)\"))\n )\n .subscribe(([{ scroll }, hover]) => {\n if (scroll && hover)\n setFocusable(el)\n else\n resetFocusable(el)\n })\n\n /* Inject button for Clipboard.js integration */\n if (ClipboardJS.isSupported()) {\n const parent = el.closest(\"pre\")!\n parent.id = `__code_${index++}`\n parent.insertBefore(\n renderClipboardButton(parent.id),\n el\n )\n }\n\n /* Create and return component */\n return watchCodeBlock(el, options)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set focusable property\n *\n * @param el - Element\n * @param value - Tabindex value\n */\nexport function setFocusable(\n el: HTMLElement, value = 0\n): void {\n el.setAttribute(\"tabindex\", value.toString())\n}\n\n/**\n * Reset focusable property\n *\n * @param el - Element\n */\nexport function resetFocusable(\n el: HTMLElement\n): void {\n el.removeAttribute(\"tabindex\")\n}\n\n/**\n * Set scroll lock\n *\n * @param el - Scrollable element\n * @param value - Vertical offset\n */\nexport function setScrollLock(\n el: HTMLElement, value: number\n): void {\n el.setAttribute(\"data-md-state\", \"lock\")\n el.style.top = `-${value}px`\n}\n\n/**\n * Reset scroll lock\n *\n * @param el - Scrollable element\n */\nexport function resetScrollLock(\n el: HTMLElement\n): void {\n const value = -1 * parseInt(el.style.top, 10)\n el.removeAttribute(\"data-md-state\")\n el.style.top = \"\"\n if (value)\n window.scrollTo(0, value)\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { translation } from \"~/_\"\nimport { h } from \"~/utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a 'copy-to-clipboard' button\n *\n * @param id - Unique identifier\n *\n * @returns Element\n */\nexport function renderClipboardButton(id: string) {\n return (\n code`}\n >\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, Subject } from \"rxjs\"\nimport {\n filter,\n finalize,\n map,\n mapTo,\n mergeWith,\n tap\n} from \"rxjs/operators\"\n\nimport { Component } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Details\n */\nexport interface Details {}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n target$: Observable /* Location target observable */\n print$: Observable /* Print observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n target$: Observable /* Location target observable */\n print$: Observable /* Print observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch details\n *\n * @param el - Details element\n * @param options - Options\n *\n * @returns Details observable\n */\nexport function watchDetails(\n el: HTMLDetailsElement, { target$, print$ }: WatchOptions\n): Observable
    {\n return target$\n .pipe(\n map(target => target.closest(\"details:not([open])\")!),\n filter(details => el === details),\n mergeWith(print$),\n mapTo(el)\n )\n}\n\n/**\n * Mount details\n *\n * This function ensures that `details` tags are opened prior to printing, so\n * the whole content of the page is included and on anchor jumps.\n *\n * @param el - Details element\n * @param options - Options\n *\n * @returns Details component observable\n */\nexport function mountDetails(\n el: HTMLDetailsElement, options: MountOptions\n): Observable> {\n const internal$ = new Subject
    ()\n internal$.subscribe(() => {\n el.setAttribute(\"open\", \"\")\n el.scrollIntoView()\n })\n\n /* Create and return component */\n return watchDetails(el, options)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n mapTo({ ref: el })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, of } from \"rxjs\"\n\nimport { createElement, replaceElement } from \"~/browser\"\nimport { renderTable } from \"~/templates\"\n\nimport { Component } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Data table\n */\nexport interface DataTable {}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Sentinel for replacement\n */\nconst sentinel = createElement(\"table\")\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount data table\n *\n * @param el - Data table element\n *\n * @returns Data table component observable\n */\nexport function mountDataTable(\n el: HTMLElement\n): Observable> {\n replaceElement(el, sentinel)\n replaceElement(sentinel, renderTable(el))\n\n /* Create and return component */\n return of({ ref: el })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { h } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a table inside a wrapper to improve scrolling on mobile\n *\n * @param table - Table element\n *\n * @returns Element\n */\nexport function renderTable(table: HTMLElement) {\n return (\n
    \n
    \n {table}\n
    \n
    \n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n animationFrameScheduler,\n merge,\n of\n} from \"rxjs\"\nimport {\n delay,\n finalize,\n map,\n observeOn,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\nimport {\n resetDialogState,\n setDialogMessage,\n setDialogState\n} from \"~/actions\"\n\nimport { Component } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Dialog\n */\nexport interface Dialog {\n message: string /* Dialog message */\n open: boolean /* Dialog is visible */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n alert$: Subject /* Alert subject */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n alert$: Subject /* Alert subject */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch dialog\n *\n * @param _el - Dialog element\n * @param options - Options\n *\n * @returns Dialog observable\n */\nexport function watchDialog(\n _el: HTMLElement, { alert$ }: WatchOptions\n): Observable {\n return alert$\n .pipe(\n switchMap(message => merge(\n of(true),\n of(false).pipe(delay(2000))\n )\n .pipe(\n map(open => ({ message, open }))\n )\n )\n )\n}\n\n/**\n * Mount dialog\n *\n * @param el - Dialog element\n * @param options - Options\n *\n * @returns Dialog component observable\n */\nexport function mountDialog(\n el: HTMLElement, options: MountOptions\n): Observable> {\n const internal$ = new Subject()\n internal$\n .pipe(\n observeOn(animationFrameScheduler)\n )\n .subscribe(({ message, open }) => {\n setDialogMessage(el, message)\n if (open)\n setDialogState(el, \"open\")\n else\n resetDialogState(el)\n })\n\n /* Create and return component */\n return watchDialog(el, options)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set dialog message\n *\n * @param el - Dialog element\n * @param value - Dialog message\n */\nexport function setDialogMessage(\n el: HTMLElement, value: string\n): void {\n el.firstElementChild!.innerHTML = value\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Set dialog state\n *\n * @param el - Dialog element\n * @param state - Dialog state\n */\nexport function setDialogState(\n el: HTMLElement, state: \"open\"\n): void {\n el.setAttribute(\"data-md-state\", state)\n}\n\n/**\n * Reset dialog state\n *\n * @param el - Dialog element\n */\nexport function resetDialogState(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n NEVER,\n Observable,\n Subject,\n animationFrameScheduler,\n combineLatest,\n defer,\n of\n} from \"rxjs\"\nimport {\n bufferCount,\n combineLatestWith,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n filter,\n map,\n observeOn,\n shareReplay,\n startWith,\n switchMap\n} from \"rxjs/operators\"\n\nimport { feature } from \"~/_\"\nimport { resetHeaderState, setHeaderState } from \"~/actions\"\nimport {\n Viewport,\n watchElementSize,\n watchToggle\n} from \"~/browser\"\n\nimport { Component } from \"../../_\"\nimport { Main } from \"../../main\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Header\n */\nexport interface Header {\n height: number /* Header visible height */\n sticky: boolean /* Header stickyness */\n hidden: boolean /* User scrolled past threshold */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n main$: Observable
    /* Main area observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Compute whether the header is hidden\n *\n * If the user scrolls past a certain threshold, the header can be hidden when\n * scrolling down, and shown when scrolling up.\n *\n * @param options - Options\n *\n * @returns Toggle observable\n */\nfunction isHidden({ viewport$ }: WatchOptions): Observable {\n if (!feature(\"header.autohide\"))\n return of(false)\n\n /* Compute direction and turning point */\n const direction$ = viewport$\n .pipe(\n map(({ offset: { y } }) => y),\n bufferCount(2, 1),\n map(([a, b]) => [a < b, b] as const),\n distinctUntilKeyChanged(0)\n )\n\n /* Compute whether header should be hidden */\n const hidden$ = combineLatest([viewport$, direction$])\n .pipe(\n filter(([{ offset }, [, y]]) => Math.abs(y - offset.y) > 100),\n map(([, [direction]]) => direction),\n distinctUntilChanged(),\n )\n\n /* Compute threshold for autohiding */\n const search$ = watchToggle(\"search\")\n return combineLatest([viewport$, search$])\n .pipe(\n map(([{ offset }, search]) => offset.y > 400 && !search),\n distinctUntilChanged(),\n switchMap(active => active ? hidden$ : NEVER),\n startWith(false)\n )\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch header\n *\n * @param el - Header element\n * @param options - Options\n *\n * @returns Header observable\n */\nexport function watchHeader(\n el: HTMLElement, options: WatchOptions\n): Observable
    {\n return defer(() => {\n const styles = getComputedStyle(el)\n return of(\n styles.position === \"sticky\" ||\n styles.position === \"-webkit-sticky\"\n )\n })\n .pipe(\n combineLatestWith(watchElementSize(el), isHidden(options)),\n map(([sticky, { height }, hidden]) => ({\n height: sticky ? height : 0,\n sticky,\n hidden\n })),\n distinctUntilChanged((a, b) => (\n a.sticky === b.sticky &&\n a.height === b.height &&\n a.hidden === b.hidden\n )),\n shareReplay(1)\n )\n}\n\n/**\n * Mount header\n *\n * The header must be connected to the main area observable outside of the\n * operator function, as the header will persist in-between document switches\n * while the main area is replaced. However, the header observable must be\n * passed to this function, so we connect both via a long-living subject.\n *\n * @param el - Header element\n * @param options - Options\n *\n * @returns Header component observable\n */\nexport function mountHeader(\n el: HTMLElement, { header$, main$ }: MountOptions\n): Observable> {\n const internal$ = new Subject
    ()\n internal$\n .pipe(\n distinctUntilKeyChanged(\"active\"),\n combineLatestWith(header$),\n observeOn(animationFrameScheduler)\n )\n .subscribe(([{ active }, { hidden }]) => {\n if (active)\n setHeaderState(el, hidden ? \"hidden\" : \"shadow\")\n else\n resetHeaderState(el)\n })\n\n /* Connect to long-living subject and return component */\n main$.subscribe(main => internal$.next(main))\n return header$\n .pipe(\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { NEVER, Observable, Subject, animationFrameScheduler } from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n finalize,\n map,\n observeOn,\n tap\n} from \"rxjs/operators\"\n\nimport {\n resetHeaderTitleState,\n setHeaderTitleState\n} from \"~/actions\"\nimport {\n Viewport,\n getElement,\n getElementSize,\n watchViewportAt\n} from \"~/browser\"\n\nimport { Component } from \"../../_\"\nimport { Header } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Header\n */\nexport interface HeaderTitle {\n active: boolean /* User scrolled past first headline */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch header title\n *\n * @param el - Heading element\n * @param options - Options\n *\n * @returns Header title observable\n */\nexport function watchHeaderTitle(\n el: HTMLHeadingElement, { viewport$, header$ }: WatchOptions\n): Observable {\n return watchViewportAt(el, { header$, viewport$ })\n .pipe(\n map(({ offset: { y } }) => {\n const { height } = getElementSize(el)\n return {\n active: y >= height\n }\n }),\n distinctUntilKeyChanged(\"active\")\n )\n}\n\n/**\n * Mount header title\n *\n * @param el - Header title element\n * @param options - Options\n *\n * @returns Header title component observable\n */\nexport function mountHeaderTitle(\n el: HTMLElement, options: MountOptions\n): Observable> {\n const internal$ = new Subject()\n internal$\n .pipe(\n observeOn(animationFrameScheduler),\n )\n .subscribe(({ active }) => {\n if (active)\n setHeaderTitleState(el, \"active\")\n else\n resetHeaderTitleState(el)\n })\n\n /* Obtain headline, if any */\n const headline = getElement(\"article h1\")\n if (typeof headline === \"undefined\")\n return NEVER\n\n /* Create and return component */\n return watchHeaderTitle(headline, options)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set header title state\n *\n * @param el - Header title element\n * @param state - Header title state\n */\nexport function setHeaderTitleState(\n el: HTMLElement, state: \"active\"\n): void {\n el.setAttribute(\"data-md-state\", state)\n}\n\n/**\n * Reset header title state\n *\n * @param el - Header title element\n */\nexport function resetHeaderTitleState(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SearchIndex, SearchResult } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search message type\n */\nexport const enum SearchMessageType {\n SETUP, /* Search index setup */\n READY, /* Search index ready */\n QUERY, /* Search query */\n RESULT /* Search results */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * A message containing the data necessary to setup the search index\n */\nexport interface SearchSetupMessage {\n type: SearchMessageType.SETUP /* Message type */\n data: SearchIndex /* Message data */\n}\n\n/**\n * A message indicating the search index is ready\n */\nexport interface SearchReadyMessage {\n type: SearchMessageType.READY /* Message type */\n}\n\n/**\n * A message containing a search query\n */\nexport interface SearchQueryMessage {\n type: SearchMessageType.QUERY /* Message type */\n data: string /* Message data */\n}\n\n/**\n * A message containing results for a search query\n */\nexport interface SearchResultMessage {\n type: SearchMessageType.RESULT /* Message type */\n data: SearchResult[] /* Message data */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * A message exchanged with the search worker\n */\nexport type SearchMessage =\n | SearchSetupMessage\n | SearchReadyMessage\n | SearchQueryMessage\n | SearchResultMessage\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Type guard for search setup messages\n *\n * @param message - Search worker message\n *\n * @returns Test result\n */\nexport function isSearchSetupMessage(\n message: SearchMessage\n): message is SearchSetupMessage {\n return message.type === SearchMessageType.SETUP\n}\n\n/**\n * Type guard for search ready messages\n *\n * @param message - Search worker message\n *\n * @returns Test result\n */\nexport function isSearchReadyMessage(\n message: SearchMessage\n): message is SearchReadyMessage {\n return message.type === SearchMessageType.READY\n}\n\n/**\n * Type guard for search query messages\n *\n * @param message - Search worker message\n *\n * @returns Test result\n */\nexport function isSearchQueryMessage(\n message: SearchMessage\n): message is SearchQueryMessage {\n return message.type === SearchMessageType.QUERY\n}\n\n/**\n * Type guard for search result messages\n *\n * @param message - Search worker message\n *\n * @returns Test result\n */\nexport function isSearchResultMessage(\n message: SearchMessage\n): message is SearchResultMessage {\n return message.type === SearchMessageType.RESULT\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search transformation function\n *\n * @param value - Query value\n *\n * @returns Transformed query value\n */\nexport type SearchTransformFn = (value: string) => string\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Default transformation function\n *\n * 1. Search for terms in quotation marks and prepend a `+` modifier to denote\n * that the resulting document must contain all terms, converting the query\n * to an `AND` query (as opposed to the default `OR` behavior). While users\n * may expect terms enclosed in quotation marks to map to span queries, i.e.\n * for which order is important, `lunr` doesn't support them, so the best\n * we can do is to convert the terms to an `AND` query.\n *\n * 2. Replace control characters which are not located at the beginning of the\n * query or preceded by white space, or are not followed by a non-whitespace\n * character or are at the end of the query string. Furthermore, filter\n * unmatched quotation marks.\n *\n * 3. Trim excess whitespace from left and right.\n *\n * @param query - Query value\n *\n * @returns Transformed query value\n */\nexport function defaultTransform(query: string): string {\n return query\n .split(/\"([^\"]+)\"/g) /* => 1 */\n .map((terms, index) => index & 1\n ? terms.replace(/^\\b|^(?![^\\x00-\\x7F]|$)|\\s+/g, \" +\")\n : terms\n )\n .join(\"\")\n .replace(/\"|(?:^|\\s+)[*+\\-:^~]+(?=\\s+|$)/g, \"\") /* => 2 */\n .trim() /* => 3 */\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { ObservableInput, Subject, from } from \"rxjs\"\nimport { map, share } from \"rxjs/operators\"\n\nimport { configuration, translation } from \"~/_\"\nimport { WorkerHandler, watchWorker } from \"~/browser\"\n\nimport { SearchIndex, SearchIndexPipeline } from \"../../_\"\nimport {\n SearchMessage,\n SearchMessageType,\n SearchSetupMessage,\n isSearchResultMessage\n} from \"../message\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search worker\n */\nexport type SearchWorker = WorkerHandler\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up search index\n *\n * @param data - Search index\n *\n * @returns Search index\n */\nfunction setupSearchIndex(\n { config, docs, index }: SearchIndex\n): SearchIndex {\n\n /* Override default language with value from translation */\n if (config.lang.length === 1 && config.lang[0] === \"en\")\n config.lang = [\n translation(\"search.config.lang\")\n ]\n\n /* Override default separator with value from translation */\n if (config.separator === \"[\\\\s\\\\-]+\")\n config.separator = translation(\"search.config.separator\")\n\n /* Set pipeline from translation */\n const pipeline = translation(\"search.config.pipeline\")\n .split(/\\s*,\\s*/)\n .filter(Boolean) as SearchIndexPipeline\n\n /* Return search index after defaulting */\n return { config, docs, index, pipeline }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up search worker\n *\n * This function will create a web worker to set up and query the search index\n * which is done using `lunr`. The index must be passed as an observable to\n * enable hacks like _localsearch_ via search index embedding as JSON.\n *\n * @param url - Worker URL\n * @param index - Search index observable input\n *\n * @returns Search worker\n */\nexport function setupSearchWorker(\n url: string, index: ObservableInput\n): SearchWorker {\n const config = configuration()\n const worker = new Worker(url)\n\n /* Create communication channels and resolve relative links */\n const tx$ = new Subject()\n const rx$ = watchWorker(worker, { tx$ })\n .pipe(\n map(message => {\n if (isSearchResultMessage(message)) {\n for (const result of message.data)\n for (const document of result)\n document.location = `${config.base}/${document.location}`\n }\n return message\n }),\n share()\n )\n\n /* Set up search index */\n from(index)\n .pipe(\n map(data => ({\n type: SearchMessageType.SETUP,\n data: setupSearchIndex(data)\n }))\n )\n .subscribe(tx$.next.bind(tx$))\n\n /* Return search worker */\n return { tx$, rx$ }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, Subject, fromEvent } from \"rxjs\"\nimport {\n map,\n share,\n switchMapTo,\n tap,\n throttle\n} from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Worker message\n */\nexport interface WorkerMessage {\n type: unknown /* Message type */\n data?: unknown /* Message data */\n}\n\n/**\n * Worker handler\n *\n * @template T - Message type\n */\nexport interface WorkerHandler<\n T extends WorkerMessage\n> {\n tx$: Subject /* Message transmission subject */\n rx$: Observable /* Message receive observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n *\n * @template T - Worker message type\n */\ninterface WatchOptions {\n tx$: Observable /* Message transmission observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch a web worker\n *\n * This function returns an observable that will send all values emitted by the\n * message observable to the web worker. Web worker communication is expected\n * to be bidirectional (request-response) and synchronous. Messages that are\n * emitted during a pending request are throttled, the last one is emitted.\n *\n * @param worker - Web worker\n * @param options - Options\n *\n * @returns Worker message observable\n */\nexport function watchWorker(\n worker: Worker, { tx$ }: WatchOptions\n): Observable {\n\n /* Intercept messages from worker-like objects */\n const rx$ = fromEvent(worker, \"message\")\n .pipe(\n map(({ data }) => data)\n )\n\n /* Send and receive messages, return hot observable */\n return tx$\n .pipe(\n throttle(() => rx$, { leading: true, trailing: true }),\n tap(message => worker.postMessage(message)),\n switchMapTo(rx$),\n share()\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n combineLatest,\n fromEvent,\n merge\n} from \"rxjs\"\nimport {\n delay,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n finalize,\n map,\n startWith,\n takeLast,\n takeUntil,\n tap\n} from \"rxjs/operators\"\n\nimport {\n resetSearchQueryPlaceholder,\n setSearchQueryPlaceholder\n} from \"~/actions\"\nimport {\n setElementFocus,\n setToggle,\n watchElementFocus\n} from \"~/browser\"\nimport {\n SearchMessageType,\n SearchQueryMessage,\n SearchWorker,\n defaultTransform\n} from \"~/integrations\"\n\nimport { Component } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search query\n */\nexport interface SearchQuery {\n value: string /* Query value */\n focus: boolean /* Query focus */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch search query\n *\n * Note that the focus event which triggers re-reading the current query value\n * is delayed by `1ms` so the input's empty state is allowed to propagate.\n *\n * @param el - Search query element\n *\n * @returns Search query observable\n */\nexport function watchSearchQuery(\n el: HTMLInputElement\n): Observable {\n const fn = __search?.transform || defaultTransform\n\n /* Intercept focus and input events */\n const focus$ = watchElementFocus(el)\n const value$ = merge(\n fromEvent(el, \"keyup\"),\n fromEvent(el, \"focus\").pipe(delay(1))\n )\n .pipe(\n map(() => fn(el.value)),\n startWith(fn(el.value)),\n distinctUntilChanged()\n )\n\n /* Combine into single observable */\n return combineLatest([value$, focus$])\n .pipe(\n map(([value, focus]) => ({ value, focus }))\n )\n}\n\n/**\n * Mount search query\n *\n * @param el - Search query element\n * @param worker - Search worker\n *\n * @returns Search query component observable\n */\nexport function mountSearchQuery(\n el: HTMLInputElement, { tx$ }: SearchWorker\n): Observable> {\n const internal$ = new Subject()\n\n /* Handle value changes */\n internal$\n .pipe(\n distinctUntilKeyChanged(\"value\"),\n map(({ value }): SearchQueryMessage => ({\n type: SearchMessageType.QUERY,\n data: value\n }))\n )\n .subscribe(tx$.next.bind(tx$))\n\n /* Handle focus changes */\n internal$\n .pipe(\n distinctUntilKeyChanged(\"focus\")\n )\n .subscribe(({ focus }) => {\n if (focus) {\n setToggle(\"search\", focus)\n setSearchQueryPlaceholder(el, \"\")\n } else {\n resetSearchQueryPlaceholder(el)\n }\n })\n\n /* Handle reset */\n fromEvent(el.form!, \"reset\")\n .pipe(\n takeUntil(internal$.pipe(takeLast(1)))\n )\n .subscribe(() => setElementFocus(el))\n\n /* Create and return component */\n return watchSearchQuery(el)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { translation } from \"~/_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set search query placeholder\n *\n * @param el - Search query element\n * @param value - Placeholder\n */\nexport function setSearchQueryPlaceholder(\n el: HTMLInputElement, value: string\n): void {\n el.placeholder = value\n}\n\n/**\n * Reset search query placeholder\n *\n * @param el - Search query element\n */\nexport function resetSearchQueryPlaceholder(\n el: HTMLInputElement\n): void {\n el.placeholder = translation(\"search.placeholder\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, Subject } from \"rxjs\"\nimport {\n filter,\n finalize,\n map,\n startWith,\n tap,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport {\n addToSearchResultList,\n resetSearchResultList,\n resetSearchResultMeta,\n setSearchResultMeta\n} from \"~/actions\"\nimport { getElementOrThrow } from \"~/browser\"\nimport {\n SearchResult as SearchResultData,\n SearchWorker,\n isSearchResultMessage\n} from \"~/integrations\"\nimport { renderSearchResult } from \"~/templates\"\n\nimport { Component } from \"../../_\"\nimport { SearchQuery } from \"../query\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search result\n */\nexport interface SearchResult {\n data: SearchResultData[] /* Search result data */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n query$: Observable /* Search query observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search result list\n *\n * @param el - Search result list element\n * @param worker - Search worker\n * @param options - Options\n *\n * @returns Search result list component observable\n */\nexport function mountSearchResult(\n el: HTMLElement, { rx$ }: SearchWorker, { query$ }: MountOptions\n): Observable> {\n const internal$ = new Subject()\n\n /* Update search result metadata */\n const meta = getElementOrThrow(\":scope > :first-child\", el)\n internal$\n .pipe(\n withLatestFrom(query$)\n )\n .subscribe(([{ data }, { value }]) => {\n if (value)\n setSearchResultMeta(meta, data.length)\n else\n resetSearchResultMeta(meta)\n })\n\n /* Update search result list */\n const list = getElementOrThrow(\":scope > :last-child\", el)\n internal$\n .subscribe(({ data }) => {\n resetSearchResultList(list)\n\n /* Compute thresholds and search results */\n const thresholds = [...data.map(([best]) => best.score), 0]\n for (let index = 0; index < data.length; index++)\n addToSearchResultList(list, renderSearchResult(\n data[index++], thresholds[index]\n ))\n })\n\n /* Filter search result list */\n const result$ = rx$\n .pipe(\n filter(isSearchResultMessage),\n map(({ data }) => ({ data })),\n startWith({ data: [] })\n )\n\n /* Create and return component */\n return result$\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, merge } from \"rxjs\"\nimport { filter, sample, take } from \"rxjs/operators\"\n\nimport { configuration } from \"~/_\"\nimport {\n getElementOrThrow,\n requestJSON\n} from \"~/browser\"\nimport {\n SearchIndex,\n isSearchQueryMessage,\n isSearchReadyMessage,\n setupSearchWorker\n} from \"~/integrations\"\n\nimport { Component } from \"../../_\"\nimport { SearchQuery, mountSearchQuery } from \"../query\"\nimport { SearchResult, mountSearchResult } from \"../result\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search\n */\nexport type Search =\n | SearchQuery\n | SearchResult\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch search index\n *\n * @param url - Search index URL\n *\n * @returns Promise resolving with search index\n */\nfunction fetchSearchIndex(url: string) {\n return __search?.index || requestJSON(url)\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search\n *\n * @param el - Search element\n *\n * @returns Search component observable\n */\nexport function mountSearch(\n el: HTMLElement\n): Observable> {\n const config = configuration()\n const worker = setupSearchWorker(config.search, fetchSearchIndex(\n `${config.base}/search/search_index.json`\n ))\n\n /* Re-emit query when search is ready */\n const { tx$, rx$ } = worker\n tx$\n .pipe(\n filter(isSearchQueryMessage),\n sample(rx$.pipe(filter(isSearchReadyMessage))),\n take(1)\n )\n .subscribe(tx$.next.bind(tx$))\n\n /* Mount search query component */\n const query$ = mountSearchQuery(\n getElementOrThrow(\"[data-md-component=search-query]\", el),\n worker\n )\n\n /* Mount search result and return component */\n return merge(\n query$,\n mountSearchResult(\n getElementOrThrow(\"[data-md-component=search-result]\", el),\n worker, { query$ }\n )\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n animationFrameScheduler,\n combineLatest\n} from \"rxjs\"\nimport {\n distinctUntilChanged,\n finalize,\n map,\n observeOn,\n tap,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport {\n resetSidebarHeight,\n resetSidebarOffset,\n setSidebarHeight,\n setSidebarOffset\n} from \"~/actions\"\nimport { Viewport } from \"~/browser\"\n\nimport { Component } from \"../_\"\nimport { Header } from \"../header\"\nimport { Main } from \"../main\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Sidebar\n */\nexport interface Sidebar {\n height: number /* Sidebar height */\n locked: boolean /* User scrolled past header */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n main$: Observable
    /* Main area observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n main$: Observable
    /* Main area observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch sidebar\n *\n * This function returns an observable that computes the visual parameters of\n * the sidebar which depends on the vertical viewport offset, as well as the\n * height of the main area. When the page is scrolled beyond the header, the\n * sidebar is locked and fills the remaining space.\n *\n * @param el - Sidebar element\n * @param options - Options\n *\n * @returns Sidebar observable\n */\nexport function watchSidebar(\n el: HTMLElement, { viewport$, main$ }: WatchOptions\n): Observable {\n const adjust =\n el.parentElement!.offsetTop -\n el.parentElement!.parentElement!.offsetTop\n\n /* Compute the sidebar's available height and if it should be locked */\n return combineLatest([main$, viewport$])\n .pipe(\n map(([{ offset, height }, { offset: { y } }]) => {\n height = height\n + Math.min(adjust, Math.max(0, y - offset))\n - adjust\n return {\n height,\n locked: y >= offset + adjust\n }\n }),\n distinctUntilChanged((a, b) => (\n a.height === b.height &&\n a.locked === b.locked\n ))\n )\n}\n\n/**\n * Mount sidebar\n *\n * @param el - Sidebar element\n * @param options - Options\n *\n * @returns Sidebar component observable\n */\nexport function mountSidebar(\n el: HTMLElement, { header$, ...options }: MountOptions\n): Observable> {\n const internal$ = new Subject()\n internal$\n .pipe(\n observeOn(animationFrameScheduler),\n withLatestFrom(header$)\n )\n .subscribe({\n\n /* Update height and offset */\n next([{ height }, { height: offset }]) {\n setSidebarHeight(el, height)\n setSidebarOffset(el, offset)\n },\n\n /* Reset on complete */\n complete() {\n resetSidebarOffset(el)\n resetSidebarHeight(el)\n }\n })\n\n /* Create and return component */\n return watchSidebar(el, options)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set sidebar offset\n *\n * @param el - Sidebar element\n * @param value - Sidebar offset\n */\nexport function setSidebarOffset(\n el: HTMLElement, value: number\n): void {\n el.style.top = `${value}px`\n}\n\n/**\n * Reset sidebar offset\n *\n * @param el - Sidebar element\n */\nexport function resetSidebarOffset(\n el: HTMLElement\n): void {\n el.style.top = \"\"\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Set sidebar height\n *\n * This function doesn't set the height of the actual sidebar, but of its first\n * child – the `.md-sidebar__scrollwrap` element in order to mitigiate jittery\n * sidebars when the footer is scrolled into view. At some point we switched\n * from `absolute` / `fixed` positioning to `sticky` positioning, significantly\n * reducing jitter in some browsers (respectively Firefox and Safari) when\n * scrolling from the top. However, top-aligned sticky positioning means that\n * the sidebar snaps to the bottom when the end of the container is reached.\n * This is what leads to the mentioned jitter, as the sidebar's height may be\n * updated too slowly.\n *\n * This behaviour can be mitigiated by setting the height of the sidebar to `0`\n * while preserving the padding, and the height on its first element.\n *\n * @param el - Sidebar element\n * @param value - Sidebar height\n */\nexport function setSidebarHeight(\n el: HTMLElement, value: number\n): void {\n const scrollwrap = el.firstElementChild as HTMLElement\n scrollwrap.style.height = `${value - 2 * scrollwrap.offsetTop}px`\n}\n\n/**\n * Reset sidebar height\n *\n * @param el - Sidebar element\n */\nexport function resetSidebarHeight(\n el: HTMLElement\n): void {\n const scrollwrap = el.firstElementChild as HTMLElement\n scrollwrap.style.height = \"\"\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { NEVER, Observable } from \"rxjs\"\n\nimport { fetchSourceFactsFromGitHub } from \"../github\"\nimport { fetchSourceFactsFromGitLab } from \"../gitlab\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Repository facts\n */\nexport type SourceFacts = string[]\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch repository facts\n *\n * @param url - Repository URL\n *\n * @returns Repository facts observable\n */\nexport function fetchSourceFacts(\n url: string\n): Observable {\n const [type] = url.match(/(git(?:hub|lab))/i) || []\n switch (type.toLowerCase()) {\n\n /* GitHub repository */\n case \"github\":\n const [, user, repo] = url.match(/^.+github\\.com\\/([^/]+)\\/?([^/]+)?/i)!\n return fetchSourceFactsFromGitHub(user, repo)\n\n /* GitLab repository */\n case \"gitlab\":\n const [, base, slug] = url.match(/^.+?([^/]*gitlab[^/]+)\\/(.+?)\\/?$/i)!\n return fetchSourceFactsFromGitLab(base, slug)\n\n /* Everything else */\n default:\n return NEVER\n }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Repo, User } from \"github-types\"\nimport { Observable } from \"rxjs\"\nimport { defaultIfEmpty, map } from \"rxjs/operators\"\n\nimport { requestJSON } from \"~/browser\"\nimport { round } from \"~/utilities\"\n\nimport { SourceFacts } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch GitHub repository facts\n *\n * @param user - GitHub user\n * @param repo - GitHub repository\n *\n * @returns Repository facts observable\n */\nexport function fetchSourceFactsFromGitHub(\n user: string, repo?: string\n): Observable {\n const url = typeof repo !== \"undefined\"\n ? `https://api.github.com/repos/${user}/${repo}`\n : `https://api.github.com/users/${user}`\n return requestJSON(url)\n .pipe(\n map(data => {\n\n /* GitHub repository */\n if (typeof repo !== \"undefined\") {\n const { stargazers_count, forks_count }: Repo = data\n return [\n `${round(stargazers_count!)} Stars`,\n `${round(forks_count!)} Forks`\n ]\n\n /* GitHub user/organization */\n } else {\n const { public_repos }: User = data\n return [\n `${round(public_repos!)} Repositories`\n ]\n }\n }),\n defaultIfEmpty([])\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { ProjectSchema } from \"gitlab\"\nimport { Observable } from \"rxjs\"\nimport { defaultIfEmpty, map } from \"rxjs/operators\"\n\nimport { requestJSON } from \"~/browser\"\nimport { round } from \"~/utilities\"\n\nimport { SourceFacts } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch GitLab repository facts\n *\n * @param base - GitLab base\n * @param project - GitLab project\n *\n * @returns Repository facts observable\n */\nexport function fetchSourceFactsFromGitLab(\n base: string, project: string\n): Observable {\n const url = `https://${base}/api/v4/projects/${encodeURIComponent(project)}`\n return requestJSON(url)\n .pipe(\n map(({ star_count, forks_count }) => ([\n `${round(star_count)} Stars`,\n `${round(forks_count)} Forks`\n ])),\n defaultIfEmpty([])\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { NEVER, Observable, Subject, defer, of } from \"rxjs\"\nimport {\n catchError,\n filter,\n finalize,\n map,\n shareReplay,\n tap\n} from \"rxjs/operators\"\n\nimport { setSourceFacts, setSourceState } from \"~/actions\"\nimport { renderSourceFacts } from \"~/templates\"\nimport { hash } from \"~/utilities\"\n\nimport { Component } from \"../../_\"\nimport { SourceFacts, fetchSourceFacts } from \"../facts\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Repository information\n */\nexport interface Source {\n facts: SourceFacts /* Repository facts */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Repository facts observable\n */\nlet fetch$: Observable\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch repository information\n *\n * @param el - Repository information element\n *\n * @returns Repository information observable\n */\nexport function watchSource(\n el: HTMLAnchorElement\n): Observable {\n const digest = hash(el.href).toString()\n\n /* Fetch repository facts once */\n return fetch$ ||= defer(() => {\n const data = sessionStorage.getItem(digest)\n if (data) {\n return of(JSON.parse(data))\n } else {\n const value$ = fetchSourceFacts(el.href)\n value$.subscribe(value => {\n try {\n sessionStorage.setItem(digest, JSON.stringify(value))\n } catch (err) {\n /* Uncritical, just swallow */\n }\n })\n\n /* Return value */\n return value$\n }\n })\n .pipe(\n catchError(() => NEVER),\n filter(facts => facts.length > 0),\n map(facts => ({ facts })),\n shareReplay(1)\n )\n}\n\n/**\n * Mount repository information\n *\n * @param el - Repository information element\n *\n * @returns Repository information component observable\n */\nexport function mountSource(\n el: HTMLAnchorElement\n): Observable> {\n const internal$ = new Subject()\n internal$.subscribe(({ facts }) => {\n setSourceFacts(el, renderSourceFacts(facts))\n setSourceState(el, \"done\")\n })\n\n /* Create and return component */\n return watchSource(el)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set repository facts\n *\n * @param el - Repository element\n * @param child - Repository facts element\n */\nexport function setSourceFacts(\n el: HTMLElement, child: Element\n): void {\n el.lastElementChild!.appendChild(child)\n}\n\n/**\n * Set repository state\n *\n * @param el - Repository element\n * @param state - Repository state\n */\nexport function setSourceState(\n el: HTMLElement, state: \"done\"\n): void {\n el.lastElementChild!.setAttribute(\"data-md-state\", state)\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SourceFacts } from \"~/components\"\nimport { h } from \"~/utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render repository facts\n *\n * @param facts - Repository facts\n *\n * @returns Element\n */\nexport function renderSourceFacts(facts: SourceFacts) {\n return (\n
      \n {facts.map(fact => (\n
    • {fact}
    • \n ))}\n
    \n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, Subject, animationFrameScheduler } from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n finalize,\n map,\n observeOn,\n tap\n} from \"rxjs/operators\"\n\nimport { resetTabsState, setTabsState } from \"~/actions\"\nimport { Viewport, watchViewportAt } from \"~/browser\"\n\nimport { Component } from \"../_\"\nimport { Header } from \"../header\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Navigation tabs\n */\nexport interface Tabs {\n hidden: boolean /* User scrolled past tabs */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch navigation tabs\n *\n * @param el - Navigation tabs element\n * @param options - Options\n *\n * @returns Navigation tabs observable\n */\nexport function watchTabs(\n el: HTMLElement, { viewport$, header$ }: WatchOptions\n): Observable {\n return watchViewportAt(el, { header$, viewport$ })\n .pipe(\n map(({ offset: { y } }) => {\n return {\n hidden: y >= 10\n }\n }),\n distinctUntilKeyChanged(\"hidden\")\n )\n}\n\n/**\n * Mount navigation tabs\n *\n * @param el - Navigation tabs element\n * @param options - Options\n *\n * @returns Navigation tabs component observable\n */\nexport function mountTabs(\n el: HTMLElement, options: MountOptions\n): Observable> {\n const internal$ = new Subject()\n internal$\n .pipe(\n observeOn(animationFrameScheduler)\n )\n .subscribe({\n\n /* Update state */\n next({ hidden }) {\n if (hidden)\n setTabsState(el, \"hidden\")\n else\n resetTabsState(el)\n },\n\n /* Reset on complete */\n complete() {\n resetTabsState(el)\n }\n })\n\n /* Create and return component */\n return watchTabs(el, options)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n animationFrameScheduler,\n combineLatest\n} from \"rxjs\"\nimport {\n bufferCount,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n finalize,\n map,\n observeOn,\n scan,\n startWith,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\nimport {\n resetAnchorActive,\n resetAnchorState,\n setAnchorActive,\n setAnchorState\n} from \"~/actions\"\nimport {\n Viewport,\n getElement,\n getElements,\n watchElementSize\n} from \"~/browser\"\n\nimport { Component } from \"../_\"\nimport { Header } from \"../header\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Table of contents\n */\nexport interface TableOfContents {\n prev: HTMLAnchorElement[][] /* Anchors (previous) */\n next: HTMLAnchorElement[][] /* Anchors (next) */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch table of contents\n *\n * This is effectively a scroll spy implementation which will account for the\n * fixed header and automatically re-calculate anchor offsets when the viewport\n * is resized. The returned observable will only emit if the table of contents\n * needs to be repainted.\n *\n * This implementation tracks an anchor element's entire path starting from its\n * level up to the top-most anchor element, e.g. `[h3, h2, h1]`. Although the\n * Material theme currently doesn't make use of this information, it enables\n * the styling of the entire hierarchy through customization.\n *\n * Note that the current anchor is the last item of the `prev` anchor list.\n *\n * @param anchors - Anchor elements\n * @param options - Options\n *\n * @returns Table of contents observable\n */\nexport function watchTableOfContents(\n anchors: HTMLAnchorElement[], { viewport$, header$ }: WatchOptions\n): Observable {\n const table = new Map()\n for (const anchor of anchors) {\n const id = decodeURIComponent(anchor.hash.substring(1))\n const target = getElement(`[id=\"${id}\"]`)\n if (typeof target !== \"undefined\")\n table.set(anchor, target)\n }\n\n /* Compute necessary adjustment for header */\n const adjust$ = header$\n .pipe(\n map(header => 24 + header.height)\n )\n\n /* Compute partition of previous and next anchors */\n const partition$ = watchElementSize(document.body)\n .pipe(\n distinctUntilKeyChanged(\"height\"),\n\n /* Build index to map anchor paths to vertical offsets */\n map(() => {\n let path: HTMLAnchorElement[] = []\n return [...table].reduce((index, [anchor, target]) => {\n while (path.length) {\n const last = table.get(path[path.length - 1])!\n if (last.tagName >= target.tagName) {\n path.pop()\n } else {\n break\n }\n }\n\n /* If the current anchor is hidden, continue with its parent */\n let offset = target.offsetTop\n while (!offset && target.parentElement) {\n target = target.parentElement\n offset = target.offsetTop\n }\n\n /* Map reversed anchor path to vertical offset */\n return index.set(\n [...path = [...path, anchor]].reverse(),\n offset\n )\n }, new Map())\n }),\n\n /* Re-compute partition when viewport offset changes */\n switchMap(index => combineLatest([adjust$, viewport$])\n .pipe(\n scan(([prev, next], [adjust, { offset: { y } }]) => {\n\n /* Look forward */\n while (next.length) {\n const [, offset] = next[0]\n if (offset - adjust < y) {\n prev = [...prev, next.shift()!]\n } else {\n break\n }\n }\n\n /* Look backward */\n while (prev.length) {\n const [, offset] = prev[prev.length - 1]\n if (offset - adjust >= y) {\n next = [prev.pop()!, ...next]\n } else {\n break\n }\n }\n\n /* Return partition */\n return [prev, next]\n }, [[], [...index]]),\n distinctUntilChanged((a, b) => (\n a[0] === b[0] &&\n a[1] === b[1]\n ))\n )\n )\n )\n\n /* Compute and return anchor list migrations */\n return partition$\n .pipe(\n map(([prev, next]) => ({\n prev: prev.map(([path]) => path),\n next: next.map(([path]) => path)\n })),\n\n /* Extract anchor list migrations */\n startWith({ prev: [], next: [] }),\n bufferCount(2, 1),\n map(([a, b]) => {\n\n /* Moving down */\n if (a.prev.length < b.prev.length) {\n return {\n prev: b.prev.slice(Math.max(0, a.prev.length - 1), b.prev.length),\n next: []\n }\n\n /* Moving up */\n } else {\n return {\n prev: b.prev.slice(-1),\n next: b.next.slice(0, b.next.length - a.next.length)\n }\n }\n })\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Mount table of contents\n *\n * @param el - Anchor list element\n * @param options - Options\n *\n * @returns Table of contents component observable\n */\nexport function mountTableOfContents(\n el: HTMLElement, options: MountOptions\n): Observable> {\n const internal$ = new Subject()\n internal$\n .pipe(\n observeOn(animationFrameScheduler),\n )\n .subscribe(({ prev, next }) => {\n\n /* Look forward */\n for (const [anchor] of next) {\n resetAnchorActive(anchor)\n resetAnchorState(anchor)\n }\n\n /* Look backward */\n for (const [index, [anchor]] of prev.entries()) {\n setAnchorActive(anchor, index === prev.length - 1)\n setAnchorState(anchor, \"blur\")\n }\n })\n\n /* Create and return component */\n const anchors = getElements(\"[href^=\\\\#]\", el)\n return watchTableOfContents(anchors, options)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport \"focus-visible\"\nimport { Subject, defer, merge } from \"rxjs\"\nimport {\n map,\n mergeWith,\n shareReplay,\n switchMap\n} from \"rxjs/operators\"\n\nimport { feature } from \"./_\"\nimport {\n at,\n getElementOrThrow,\n getElements,\n watchDocument,\n watchLocation,\n watchLocationTarget,\n watchMedia,\n watchPrint,\n watchViewport\n} from \"./browser\"\nimport {\n mountContent,\n mountDialog,\n mountHeader,\n mountHeaderTitle,\n mountSearch,\n mountSidebar,\n mountSource,\n mountTableOfContents,\n mountTabs,\n watchHeader,\n watchMain\n} from \"./components\"\nimport {\n setupClipboardJS,\n setupInstantLoading\n} from \"./integrations\"\nimport {\n patchIndeterminate,\n patchScrollfix\n} from \"./patches\"\n\n/* ----------------------------------------------------------------------------\n * Program\n * ------------------------------------------------------------------------- */\n\n/* Yay, JavaScript is available */\ndocument.documentElement.classList.remove(\"no-js\")\ndocument.documentElement.classList.add(\"js\")\n\n/* Set up navigation observables */\nconst document$ = watchDocument()\nconst location$ = watchLocation()\nconst target$ = watchLocationTarget()\n\n/* Set up media observables */\nconst viewport$ = watchViewport()\nconst tablet$ = watchMedia(\"(min-width: 960px)\")\nconst screen$ = watchMedia(\"(min-width: 1220px)\")\nconst print$ = watchPrint()\n\n/* Set up Clipboard.js integration */\nconst alert$ = new Subject()\nsetupClipboardJS({ alert$ })\n\n/* Set up instant loading, if enabled */\nif (feature(\"navigation.instant\"))\n setupInstantLoading({ document$, location$, viewport$ })\n\n/* Set up patches */\npatchIndeterminate({ document$ })\npatchScrollfix({ document$ })\n\n/* Set up header observable */\nconst header$ = watchHeader(\n getElementOrThrow(\"[data-md-component=header]\"),\n { viewport$ }\n)\n\n/* Set up main area observable */\nconst main$ = document$\n .pipe(\n map(() => getElementOrThrow(\"[data-md-component=main]\")),\n switchMap(el => watchMain(el, { viewport$, header$ })),\n shareReplay(1)\n )\n\n/* Set up control component observables */\nconst control$ = merge(\n\n /* Dialog */\n ...getElements(\"[data-md-component=dialog]\")\n .map(child => mountDialog(child, { alert$ })),\n\n /* Header */\n ...getElements(\"[data-md-component=header]\")\n .map(child => mountHeader(child, { viewport$, header$, main$ })),\n\n /* Search */\n ...getElements(\"[data-md-component=search]\")\n .map(child => mountSearch(child)),\n\n /* Repository information */\n ...getElements(\"[data-md-component=source]\")\n .map(child => mountSource(child as HTMLAnchorElement)),\n\n /* Navigation tabs */\n ...getElements(\"[data-md-component=tabs]\")\n .map(child => mountTabs(child, { viewport$, header$ })),\n)\n\n/* Set up content component observables */\nconst content$ = defer(() => merge(\n\n /* Content */\n ...getElements(\"[data-md-component=content]\")\n .map(child => mountContent(child, { target$, viewport$, print$ })),\n\n /* Header title */\n ...getElements(\"[data-md-component=header-title]\")\n .map(child => mountHeaderTitle(child, { viewport$, header$ })),\n\n /* Sidebar */\n ...getElements(\"[data-md-component=sidebar]\")\n .map(child => child.getAttribute(\"data-md-type\") === \"navigation\"\n ? at(screen$, () => mountSidebar(child, { viewport$, header$, main$ }))\n : at(tablet$, () => mountSidebar(child, { viewport$, header$, main$ }))\n ),\n\n /* Table of contents */\n ...getElements(\"[data-md-component=toc]\")\n .map(child => mountTableOfContents(child, { viewport$, header$ })),\n))\n\n/* Set up component observables */\nconst component$ = document$\n .pipe(\n switchMap(() => content$),\n mergeWith(control$)\n )\n\ncomponent$.subscribe()\n\n/* Export to window */\nexport {\n document$,\n component$,\n viewport$,\n location$,\n target$,\n screen$,\n tablet$,\n print$\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { ReplaySubject, Subject, fromEvent } from \"rxjs\"\nimport { mapTo } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch document\n *\n * Documents must be implemented as subjects, so all downstream observables are\n * automatically updated when a new document is emitted. This enabled features\n * like instant loading.\n *\n * @returns Document subject\n */\nexport function watchDocument(): Subject {\n const document$ = new ReplaySubject()\n fromEvent(document, \"DOMContentLoaded\")\n .pipe(\n mapTo(document)\n )\n .subscribe(document$)\n\n /* Return document */\n return document$\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport ClipboardJS from \"clipboard\"\nimport { Observable, Subject } from \"rxjs\"\n\nimport { translation } from \"~/_\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n alert$: Subject /* Alert subject */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up Clipboard.js integration\n *\n * @param options - Options\n */\nexport function setupClipboardJS(\n { alert$ }: SetupOptions\n): void {\n if (ClipboardJS.isSupported()) {\n new Observable(subscriber => {\n new ClipboardJS(\"[data-clipboard-target], [data-clipboard-text]\")\n .on(\"success\", ev => subscriber.next(ev))\n })\n .subscribe(() => alert$.next(translation(\"clipboard.copied\")))\n }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n EMPTY,\n NEVER,\n Observable,\n Subject,\n fromEvent,\n merge,\n of\n} from \"rxjs\"\nimport {\n bufferCount,\n catchError,\n concatMap,\n debounceTime,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n filter,\n map,\n sample,\n share,\n skip,\n skipUntil,\n switchMap\n} from \"rxjs/operators\"\n\nimport { configuration } from \"~/_\"\nimport {\n Viewport,\n ViewportOffset,\n createElement,\n getElement,\n getElementOrThrow,\n getElements,\n replaceElement,\n request,\n requestXML,\n setLocation,\n setLocationHash,\n setViewportOffset\n} from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * History state\n */\nexport interface HistoryState {\n url: URL /* State URL */\n offset?: ViewportOffset /* State viewport offset */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n document$: Subject /* Document subject */\n location$: Subject /* Location subject */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Preprocess a list of URLs\n *\n * This function replaces the `site_url` in the sitemap with the actual base\n * URL, to allow instant loading to work in occasions like Netlify previews.\n *\n * @param urls - URLs\n *\n * @returns Processed URLs\n */\nfunction preprocess(urls: string[]): string[] {\n if (urls.length < 2)\n return urls\n\n /* Compute references URLs */\n const [root, next] = urls.sort((a, b) => a.length - b.length)\n\n /* Compute common prefix */\n let index = 0\n if (root === next)\n index = root.length\n else\n while (root.charCodeAt(index) === root.charCodeAt(index))\n index++\n\n /* Replace common prefix (i.e. base) with effective base */\n const config = configuration()\n return urls.map(url => (\n url.replace(root.slice(0, index), `${config.base}/`)\n ))\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up instant loading\n *\n * When fetching, theoretically, we could use `responseType: \"document\"`, but\n * since all MkDocs links are relative, we need to make sure that the current\n * location matches the document we just loaded. Otherwise any relative links\n * in the document could use the old location.\n *\n * This is the reason why we need to synchronize history events and the process\n * of fetching the document for navigation changes (except `popstate` events):\n *\n * 1. Fetch document via `XMLHTTPRequest`\n * 2. Set new location via `history.pushState`\n * 3. Parse and emit fetched document\n *\n * For `popstate` events, we must not use `history.pushState`, or the forward\n * history will be irreversibly overwritten. In case the request fails, the\n * location change is dispatched regularly.\n *\n * @param options - Options\n */\nexport function setupInstantLoading(\n { document$, location$, viewport$ }: SetupOptions\n): void {\n const config = configuration()\n if (location.protocol === \"file:\")\n return\n\n /* Disable automatic scroll restoration */\n if (\"scrollRestoration\" in history) {\n history.scrollRestoration = \"manual\"\n\n /* Hack: ensure that reloads restore viewport offset */\n fromEvent(window, \"beforeunload\")\n .subscribe(() => {\n history.scrollRestoration = \"auto\"\n })\n }\n\n /* Hack: ensure absolute favicon link to omit 404s when switching */\n const favicon = getElement(\"link[rel='shortcut icon']\")\n if (typeof favicon !== \"undefined\")\n favicon.href = favicon.href\n\n /* Intercept internal navigation */\n const push$ = requestXML(`${config.base}/sitemap.xml`)\n .pipe(\n map(sitemap => preprocess(getElements(\"loc\", sitemap)\n .map(node => node.textContent!)\n )),\n switchMap(urls => fromEvent(document.body, \"click\")\n .pipe(\n filter(ev => !ev.metaKey && !ev.ctrlKey),\n switchMap(ev => {\n if (ev.target instanceof HTMLElement) {\n const el = ev.target.closest(\"a\")\n if (el && !el.target && urls.includes(el.href)) {\n ev.preventDefault()\n return of({\n url: new URL(el.href)\n })\n }\n }\n return NEVER\n })\n )\n ),\n share()\n )\n\n /* Intercept history back and forward */\n const pop$ = fromEvent(window, \"popstate\")\n .pipe(\n filter(ev => ev.state !== null),\n map(ev => ({\n url: new URL(location.href),\n offset: ev.state\n } as HistoryState)),\n share()\n )\n\n /* Emit location change */\n merge(push$, pop$)\n .pipe(\n distinctUntilChanged((a, b) => a.url.href === b.url.href),\n map(({ url }) => url)\n )\n .subscribe(location$)\n\n /* Fetch document via `XMLHTTPRequest` */\n const response$ = location$\n .pipe(\n distinctUntilKeyChanged(\"pathname\"),\n skip(1),\n switchMap(url => request(url.href)\n .pipe(\n catchError(() => {\n setLocation(url)\n return NEVER\n })\n )\n ),\n share()\n )\n\n /* Set new location via `history.pushState` */\n push$\n .pipe(\n sample(response$)\n )\n .subscribe(({ url }) => {\n history.pushState({}, \"\", url.toString())\n })\n\n /* Parse and emit fetched document */\n const dom = new DOMParser()\n response$\n .pipe(\n switchMap(res => res.text()),\n map(res => dom.parseFromString(res, \"text/html\"))\n )\n .subscribe(document$)\n\n /* Emit history state change */\n merge(push$, pop$)\n .pipe(\n sample(document$)\n )\n .subscribe(({ url, offset }) => {\n if (url.hash && !offset)\n setLocationHash(url.hash)\n else\n setViewportOffset(offset || { y: 0 })\n })\n\n /* Replace components */\n document$\n .pipe(\n skip(1)\n )\n .subscribe(replacement => {\n\n /* Replace meta tags and components */\n for (const selector of [\n\n /* Meta tags */\n \"title\",\n \"link[rel='canonical']\",\n \"meta[name='author']\",\n \"meta[name='description']\",\n\n /* Components */\n \"[data-md-component=announce]\",\n \"[data-md-component=header-title]\",\n \"[data-md-component=container]\",\n \"[data-md-component=skip]\"\n ]) {\n const source = getElement(selector)\n const target = getElement(selector, replacement)\n if (\n typeof source !== \"undefined\" &&\n typeof target !== \"undefined\"\n ) {\n replaceElement(source, target)\n }\n }\n })\n\n /* Re-evaluate scripts */\n document$\n .pipe(\n skip(1),\n map(() => getElementOrThrow(\"[data-md-component=container]\")),\n switchMap(el => of(...getElements(\"script\", el))),\n concatMap(el => {\n const script = createElement(\"script\")\n if (el.src) {\n script.src = el.src\n replaceElement(el, script)\n\n /* Complete when script is loaded */\n return new Observable(observer => {\n script.onload = () => observer.complete()\n })\n\n /* Complete immediately */\n } else {\n script.textContent = el.textContent!\n replaceElement(el, script)\n return EMPTY\n }\n })\n )\n .subscribe()\n\n /* Debounce update of viewport offset */\n viewport$\n .pipe(\n skipUntil(push$),\n debounceTime(250),\n distinctUntilKeyChanged(\"offset\")\n )\n .subscribe(({ offset }) => {\n history.replaceState(offset, \"\")\n })\n\n /* Set viewport offset from history */\n merge(push$, pop$)\n .pipe(\n bufferCount(2, 1),\n filter(([a, b]) => a.url.pathname === b.url.pathname),\n map(([, state]) => state)\n )\n .subscribe(({ offset }) => {\n setViewportOffset(offset || { y: 0 })\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable } from \"rxjs\"\n\nimport { getElements } from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch options\n */\ninterface PatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch indeterminate checkboxes\n *\n * @param options - Options\n */\nexport function patchIndeterminate(\n { document$ }: PatchOptions\n): void {\n document$.subscribe(() => {\n for (const el of getElements(\n \"[data-md-state=indeterminate]\"\n )) {\n el.setAttribute(\"data-md-state\", \"\")\n el.indeterminate = true\n el.checked = false\n }\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, of } from \"rxjs\"\nimport { mapTo, mergeMap, switchMap, tap } from \"rxjs/operators\"\n\nimport { getElements } from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch options\n */\ninterface PatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Check whether the given device is an Apple device\n *\n * @returns Test result\n */\nfunction isAppleDevice(): boolean {\n return /(iPad|iPhone|iPod)/.test(navigator.userAgent)\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch all elements with `data-md-scrollfix` attributes\n *\n * This is a year-old patch which ensures that overflow scrolling works at the\n * top and bottom of containers on iOS by ensuring a `1px` scroll offset upon\n * the start of a touch event.\n *\n * @see https://bit.ly/2SCtAOO - Original source\n *\n * @param options - Options\n */\nexport function patchScrollfix(\n { document$ }: PatchOptions\n): void {\n if (isAppleDevice()) {\n document$\n .pipe(\n switchMap(() => of(...getElements(\"[data-md-scrollfix]\"))),\n tap(el => el.removeAttribute(\"data-md-scrollfix\")),\n mergeMap(el => fromEvent(el, \"touchstart\")\n .pipe(\n mapTo(el)\n )\n )\n )\n .subscribe(el => {\n const top = el.scrollTop\n\n /* We're at the top of the container */\n if (top === 0) {\n el.scrollTop = 1\n\n /* We're at the bottom of the container */\n } else if (top + el.offsetHeight === el.scrollHeight) {\n el.scrollTop = top - 1\n }\n })\n }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n combineLatest\n} from \"rxjs\"\nimport {\n distinctUntilChanged,\n distinctUntilKeyChanged,\n map,\n switchMap\n} from \"rxjs/operators\"\n\nimport { Viewport, watchElementSize } from \"~/browser\"\n\nimport { Header } from \"../header\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Main area\n */\nexport interface Main {\n offset: number /* Main area top offset */\n height: number /* Main area visible height */\n active: boolean /* User scrolled past header */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch main area\n *\n * This function returns an observable that computes the visual parameters of\n * the main area which depends on the viewport vertical offset and height, as\n * well as the height of the header element, if the header is fixed.\n *\n * @param el - Main area element\n * @param options - Options\n *\n * @returns Main area observable\n */\nexport function watchMain(\n el: HTMLElement, { viewport$, header$ }: WatchOptions\n): Observable
    {\n\n /* Compute necessary adjustment for header */\n const adjust$ = header$\n .pipe(\n map(({ height }) => height),\n distinctUntilChanged()\n )\n\n /* Compute the main area's top and bottom borders */\n const border$ = adjust$\n .pipe(\n switchMap(() => watchElementSize(el)\n .pipe(\n map(({ height }) => ({\n top: el.offsetTop,\n bottom: el.offsetTop + height\n })),\n distinctUntilKeyChanged(\"bottom\")\n )\n )\n )\n\n /* Compute the main area's offset, visible height and if we scrolled past */\n return combineLatest([adjust$, border$, viewport$])\n .pipe(\n map(([header, { top, bottom }, { offset: { y }, size: { height } }]) => {\n height = Math.max(0, height\n - Math.max(0, top - y, header)\n - Math.max(0, height + y - bottom)\n )\n return {\n offset: top - header,\n height,\n active: top - header <= y\n }\n }),\n distinctUntilChanged((a, b) => (\n a.offset === b.offset &&\n a.height === b.height &&\n a.active === b.active\n ))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set header state\n *\n * @param el - Header element\n * @param state - Header state\n */\nexport function setHeaderState(\n el: HTMLElement, state: \"shadow\" | \"hidden\"\n): void {\n el.setAttribute(\"data-md-state\", state)\n}\n\n/**\n * Reset header state\n *\n * @param el - Header element\n */\nexport function resetHeaderState(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, merge } from \"rxjs\"\n\nimport { Viewport, getElements } from \"~/browser\"\n\nimport { Component } from \"../../_\"\nimport { CodeBlock, mountCodeBlock } from \"../code\"\nimport { Details, mountDetails } from \"../details\"\nimport { DataTable, mountDataTable } from \"../table\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Content\n */\nexport type Content =\n | CodeBlock\n | DataTable\n | Details\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n target$: Observable /* Location target observable */\n viewport$: Observable /* Viewport observable */\n print$: Observable /* Print observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount content\n *\n * @param el - Content element\n * @param options - Options\n *\n * @returns Content component observable\n */\nexport function mountContent(\n el: HTMLElement, { target$, viewport$, print$ }: MountOptions\n): Observable> {\n return merge(\n\n /* Code blocks */\n ...getElements(\"pre > code\", el)\n .map(child => mountCodeBlock(child, { viewport$ })),\n\n /* Data tables */\n ...getElements(\"table:not([class])\", el)\n .map(child => mountDataTable(child)),\n\n /* Details */\n ...getElements(\"details\", el)\n .map(child => mountDetails(child, { target$, print$ }))\n )\n}\n"],"sourceRoot":""} \ No newline at end of file diff --git a/material/assets/javascripts/bundle.d8c6976f.min.js b/material/assets/javascripts/bundle.d8c6976f.min.js new file mode 100644 index 000000000..8e95b81bc --- /dev/null +++ b/material/assets/javascripts/bundle.d8c6976f.min.js @@ -0,0 +1,2 @@ +!function(e,t){for(var n in t)e[n]=t[n]}(window,function(e){function t(t){for(var a,o,i=t[0],s=t[1],p=t[2],u=0,l=[];uObject($.a)(new ResizeObserver(e=>{for(const t of e)E.next(t)}))).pipe(Object(s.a)(e=>y.a.pipe(Object(v.a)(e)).pipe(Object(x.a)(()=>e.disconnect()))),Object(p.a)(1));function A(e){return{width:e.offsetWidth,height:e.offsetHeight}}function S(e){return k.pipe(Object(_.a)(t=>t.observe(e)),Object(s.a)(t=>E.pipe(Object(o.a)(({target:t})=>t===e),Object(x.a)(()=>t.unobserve(e)),Object(i.a)(({contentRect:e})=>({width:e.width,height:e.height})))),Object(v.a)(A(e)))}var T=n(42);const R={drawer:h("[data-md-toggle=drawer]"),search:h("[data-md-toggle=search]")};function M(e,t){R[e].checked!==t&&R[e].click()}var C=n(60);function L(){return new URL(location.href)}function P(){return location.hash.substring(1)}function U(e){const t=matchMedia(e);return Object(l.a)(t,"change").pipe(Object(i.a)(e=>e.matches),Object(v.a)(t.matches))}function N(e,t){return e.pipe(Object(s.a)(e=>e?t():y.a))}var H=n(6);function I(e,t={credentials:"same-origin"}){return Object(H.a)(fetch(e,t)).pipe(Object(o.a)(e=>200===e.status))}function z(e,t){return I(e,t).pipe(Object(s.a)(e=>e.json()),Object(p.a)(1))}var D=n(46),Y=n(61);function F(){return{x:Math.max(0,pageXOffset),y:Math.max(0,pageYOffset)}}function q({x:e,y:t}){window.scrollTo(e||0,t||0)}function J(){return{width:innerWidth,height:innerHeight}}function W(e,{viewport$:t,header$:n}){const a=t.pipe(Object(Y.a)("size")),c=Object(D.a)([a,n]).pipe(Object(i.a)(()=>({x:e.offsetLeft,y:e.offsetTop})));return Object(D.a)([n,t,c]).pipe(Object(i.a)(([{height:e},{offset:t,size:n},{x:a,y:c}])=>({offset:{x:t.x-a,y:t.y-c+e},size:n})))}var K=n(62),Q=n(63);const B=h("#__config"),X=JSON.parse(B.textContent);function V(){return X}function G(e){return X.features.includes(e)}function Z(e,t){return void 0!==t?X.translations[e].replace("#",t.toString()):X.translations[e]}X.base=new URL(X.base,L()).toString().replace(/\/$/,"");var ee,te=n(26),ne=n.n(te),ae=n(64);function ce(e,t){e.setAttribute("data-md-state",t)}function re(e){e.removeAttribute("data-md-state")}function oe(e,t){e.classList.toggle("md-nav__link--active",t)}function ie(e){e.classList.remove("md-nav__link--active")}function se(e,t){e.appendChild(t)}function pe(e){e.removeAttribute("data-md-state")}function be(e,t){if("string"==typeof t||"number"==typeof t)e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(const n of t)be(e,n)}function ue(e,t,...n){const a=document.createElement(e);if(t)for(const e of Object.keys(t))"boolean"!=typeof t[e]?a.setAttribute(e,t[e]):t[e]&&a.setAttribute(e,"");for(const e of n)be(a,e);return a}function le(e){if(e>999){return((e+1e-6)/1e3).toFixed(+((e-950)%1e3>99))+"k"}return e.toString()}function fe(e,t){const n=t&ee.PARENT,a=t&ee.TEASER,c=Object.keys(e.terms).filter(t=>!e.terms[t]).map(e=>[ue("del",null,e)," "]).flat().slice(0,-1);return ue("a",{href:e.location,class:"md-search-result__link",tabIndex:-1},ue("article",{class:["md-search-result__article",...n?["md-search-result__article--document"]:[]].join(" "),"data-md-score":e.score.toFixed(2)},n>0&&ue("div",{class:"md-search-result__icon md-icon"}),ue("h1",{class:"md-search-result__title"},e.title),a>0&&e.text.length>0&&ue("p",{class:"md-search-result__teaser"},function(e,t){let n=t;if(e.length>n){for(;" "!==e[n]&&--n>0;);return e.substring(0,n)+"..."}return e}(e.text,320)),a>0&&c.length>0&&ue("p",{class:"md-search-result__terms"},Z("search.result.term.missing"),": ",c)))}function de(e,t=1/0){const n=[...e],a=n.findIndex(e=>!e.location.includes("#")),[c]=n.splice(a,1);let r=n.findIndex(e=>e.scorefe(e,ee.TEASER)),...i.length?[ue("details",{class:"md-search-result__more"},ue("summary",{tabIndex:-1},i.length>0&&1===i.length?Z("search.result.more.one"):Z("search.result.more.other",i.length)),i.map(e=>fe(e,ee.TEASER)))]:[]];return ue("li",{class:"md-search-result__item"},s)}!function(e){e[e.TEASER=1]="TEASER",e[e.PARENT=2]="PARENT"}(ee||(ee={}));let he=0;function Oe(e,t){const n=new a.a;if(n.pipe(Object(ae.a)(U("(hover)"))).subscribe(([{scroll:t},n])=>{t&&n?function(e,t=0){e.setAttribute("tabindex",t.toString())}(e):function(e){e.removeAttribute("tabindex")}(e)}),ne.a.isSupported()){const t=e.closest("pre");t.id="__code_"+he++,t.insertBefore((c=t.id,ue("button",{class:"md-clipboard md-icon",title:Z("clipboard.copy"),"data-clipboard-target":`#${c} > code`})),e)}var c;return function(e,{viewport$:t}){return t.pipe(Object(Y.a)("size"),Object(i.a)(()=>{const t=A(e);return{scroll:function(e){return{width:e.scrollWidth,height:e.scrollHeight}}(e).width>t.width}}),Object(Y.a)("scroll"))}(e,t).pipe(Object(_.a)(n),Object(x.a)(()=>n.complete()),Object(i.a)(t=>Object.assign({ref:e},t)))}function je(e,t){const n=new a.a;return n.subscribe(()=>{e.setAttribute("open",""),e.scrollIntoView()}),function(e,{target$:t,print$:n}){return t.pipe(Object(i.a)(e=>e.closest("details:not([open])")),Object(o.a)(t=>e===t),Object(b.a)(n),Object(f.a)(e))}(e,t).pipe(Object(_.a)(n),Object(x.a)(()=>n.complete()),Object(f.a)({ref:e}))}const me=m("table");function ge(e){return g(e,me),g(me,ue("div",{class:"md-typeset__scrollwrap"},ue("div",{class:"md-typeset__table"},e))),Object($.a)({ref:e})}var ve=n(77),we=n(78),$e=n(66);function ye(e,t){const n=new a.a;return n.pipe(Object($e.a)(ve.a)).subscribe(({message:t,open:n})=>{!function(e,t){e.firstElementChild.innerHTML=t}(e,t),n?function(e,t){e.setAttribute("data-md-state",t)}(e,"open"):function(e){e.removeAttribute("data-md-state")}(e)}),function(e,{alert$:t}){return t.pipe(Object(s.a)(e=>Object(c.a)(Object($.a)(!0),Object($.a)(!1).pipe(Object(we.a)(2e3))).pipe(Object(i.a)(t=>({message:e,open:t})))))}(0,t).pipe(Object(_.a)(n),Object(x.a)(()=>n.complete()),Object(i.a)(t=>Object.assign({ref:e},t)))}var xe=n(67),_e=n(44),Ee=n(68);function ke({viewport$:e}){if(!G("header.autohide"))return Object($.a)(!1);const t=e.pipe(Object(i.a)(({offset:{y:e}})=>e),Object(xe.a)(2,1),Object(i.a)(([e,t])=>[eMath.abs(t-e.y)>100),Object(i.a)(([,[e]])=>e),Object(_e.a)()),a=function(e){const t=R[e];return Object(l.a)(t,"change").pipe(Object(i.a)(()=>t.checked),Object(v.a)(t.checked))}("search");return Object(D.a)([e,a]).pipe(Object(i.a)(([{offset:e},t])=>e.y>400&&!t),Object(_e.a)(),Object(s.a)(e=>e?n:y.a),Object(v.a)(!1))}function Ae(e,t){const n=new a.a;n.pipe(Object($e.a)(ve.a)).subscribe(({active:t})=>{t?function(e,t){e.setAttribute("data-md-state",t)}(e,"active"):function(e){e.removeAttribute("data-md-state")}(e)});const c=d("article h1");return void 0===c?y.a:function(e,{viewport$:t,header$:n}){return W(e,{header$:n,viewport$:t}).pipe(Object(i.a)(({offset:{y:t}})=>{const{height:n}=A(e);return{active:t>=n}}),Object(Y.a)("active"))}(c,t).pipe(Object(_.a)(n),Object(x.a)(()=>n.complete()),Object(i.a)(t=>Object.assign({ref:e},t)))}var Se=n(71),Te=n(39),Re=n(4);var Me=n(21),Ce=n(69),Le=n(70),Pe=n(72),Ue=n(73),Ne=n(79);var He;n(45);function Ie(e){return e.split(/"([^"]+)"/g).map((e,t)=>1&t?e.replace(/^\b|^(?![^\x00-\x7F]|$)|\s+/g," +"):e).join("").replace(/"|(?:^|\s+)[*+\-:^~]+(?=\s+|$)/g,"").trim()}function ze(e){return e.type===He.READY}function De(e){return e.type===He.QUERY}function Ye(e){return e.type===He.RESULT}function Fe({config:e,docs:t,index:n}){1===e.lang.length&&"en"===e.lang[0]&&(e.lang=[Z("search.config.lang")]),"[\\s\\-]+"===e.separator&&(e.separator=Z("search.config.separator"));return{config:e,docs:t,index:n,pipeline:Z("search.config.pipeline").split(/\s*,\s*/).filter(Boolean)}}function qe(e,t){const n=V(),c=new Worker(e),r=new a.a,o=function(e,{tx$:t}){const n=Object(l.a)(e,"message").pipe(Object(i.a)(({data:e})=>e));return t.pipe(Object(K.a)(()=>n,{leading:!0,trailing:!0}),Object(_.a)(t=>e.postMessage(t)),Object(Q.a)(n),Object(T.a)())}(c,{tx$:r}).pipe(Object(i.a)(e=>{if(Ye(e))for(const t of e.data)for(const e of t)e.location=`${n.base}/${e.location}`;return e}),Object(T.a)());return Object(H.a)(t).pipe(Object(i.a)(e=>({type:He.SETUP,data:Fe(e)}))).subscribe(r.next.bind(r)),{tx$:r,rx$:o}}!function(e){e[e.SETUP=0]="SETUP",e[e.READY=1]="READY",e[e.QUERY=2]="QUERY",e[e.RESULT=3]="RESULT"}(He||(He={}));var Je=n(74),We=n(75);function Ke(e){const t=(null===__search||void 0===__search?void 0:__search.transform)||Ie,n=function(e){return Object(c.a)(Object(l.a)(e,"focus"),Object(l.a)(e,"blur")).pipe(Object(i.a)(({type:e})=>"focus"===e),Object(v.a)(e===O()))}(e),a=Object(c.a)(Object(l.a)(e,"keyup"),Object(l.a)(e,"focus").pipe(Object(we.a)(1))).pipe(Object(i.a)(()=>t(e.value)),Object(v.a)(t(e.value)),Object(_e.a)());return Object(D.a)([a,n]).pipe(Object(i.a)(([e,t])=>({value:e,focus:t})))}function Qe(e,{tx$:t}){const n=new a.a;return n.pipe(Object(Y.a)("value"),Object(i.a)(({value:e})=>({type:He.QUERY,data:e}))).subscribe(t.next.bind(t)),n.pipe(Object(Y.a)("focus")).subscribe(({focus:t})=>{t?(M("search",t),function(e,t){e.placeholder=t}(e,"")):function(e){e.placeholder=Z("search.placeholder")}(e)}),Object(l.a)(e.form,"reset").pipe(Object(Je.a)(n.pipe(Object(We.a)(1)))).subscribe(()=>w(e)),Ke(e).pipe(Object(_.a)(n),Object(x.a)(()=>n.complete()),Object(i.a)(t=>Object.assign({ref:e},t)))}function Be(e,{rx$:t},{query$:n}){const c=new a.a,r=h(":scope > :first-child",e);c.pipe(Object(ae.a)(n)).subscribe(([{data:e},{value:t}])=>{t?function(e,t){switch(t){case 0:e.textContent=Z("search.result.none");break;case 1:e.textContent=Z("search.result.one");break;default:e.textContent=Z("search.result.other",t)}}(r,e.length):function(e){e.textContent=Z("search.result.placeholder")}(r)});const s=h(":scope > :last-child",e);c.subscribe(({data:e})=>{!function(e){e.innerHTML=""}(s);const t=[...e.map(([e])=>e.score),0];for(let n=0;n({data:e})),Object(v.a)({data:[]})).pipe(Object(_.a)(c),Object(x.a)(()=>c.complete()),Object(i.a)(t=>Object.assign({ref:e},t)))}function Xe(e,{keyboard$:t}){const n=V(),a=qe(n.search,(r=n.base+"/search/search_index.json",(null===__search||void 0===__search?void 0:__search.index)||z(r)));var r;const i=h("[data-md-component=search-query]",e),s=h("[data-md-component=search-result]",e),{tx$:p,rx$:b}=a;p.pipe(Object(o.a)(De),Object(Se.a)(b.pipe(Object(o.a)(ze))),Object(Te.a)(1)).subscribe(p.next.bind(p)),t.pipe(Object(o.a)(({mode:e})=>"search"===e)).subscribe(e=>{const t=O();switch(e.type){case"Enter":t===i&&e.claim();break;case"Escape":case"Tab":M("search",!1),w(i,!1);break;case"ArrowUp":case"ArrowDown":if(void 0===t)w(i);else{const n=[i,...j(":not(details) > [href], summary, details[open] [href]",s)],a=Math.max(0,(Math.max(0,n.indexOf(t))+n.length+("ArrowUp"===e.type?-1:1))%n.length);w(n[a])}e.claim();break;default:i!==O()&&w(i)}}),t.pipe(Object(o.a)(({mode:e})=>"global"===e)).subscribe(e=>{switch(e.type){case"f":case"s":case"/":w(i),function(e){if(!(e instanceof HTMLInputElement))throw new Error("Not implemented");e.select()}(i),e.claim()}});const u=Qe(i,a);return Object(c.a)(u,Be(s,a,{query$:u}))}var Ve=n(25);function Ge(e,t){var{header$:n}=t,c=Object(Ve.c)(t,["header$"]);const r=new a.a;return r.pipe(Object($e.a)(ve.a),Object(ae.a)(n)).subscribe({next([{height:t},{height:n}]){!function(e,t){const n=e.firstElementChild;n.style.height=t-2*n.offsetTop+"px"}(e,t),function(e,t){e.style.top=t+"px"}(e,n)},complete(){!function(e){e.style.top=""}(e),function(e){e.firstElementChild.style.height=""}(e)}}),function(e,{viewport$:t,main$:n}){const a=e.parentElement.offsetTop-e.parentElement.parentElement.offsetTop;return Object(D.a)([n,t]).pipe(Object(i.a)(([{offset:e,height:t},{offset:{y:n}}])=>({height:t=t+Math.min(a,Math.max(0,n-e))-a,locked:n>=e+a})),Object(_e.a)((e,t)=>e.height===t.height&&e.locked===t.locked))}(e,c).pipe(Object(_.a)(r),Object(x.a)(()=>r.complete()),Object(i.a)(t=>Object.assign({ref:e},t)))}var Ze=n(76);function et(e){const[t]=e.match(/(git(?:hub|lab))/i)||[];switch(t.toLowerCase()){case"github":const[,t,n]=e.match(/^.+github\.com\/([^/]+)\/?([^/]+)?/i);return function(e,t){return z(void 0!==t?`https://api.github.com/repos/${e}/${t}`:"https://api.github.com/users/"+e).pipe(Object(i.a)(e=>{if(void 0!==t){const{stargazers_count:t,forks_count:n}=e;return[le(t)+" Stars",le(n)+" Forks"]}{const{public_repos:t}=e;return[le(t)+" Repositories"]}}),Object(Ze.a)([]))}(t,n);case"gitlab":const[,a,c]=e.match(/^.+?([^/]*gitlab[^/]+)\/(.+?)\/?$/i);return function(e,t){return z(`https://${e}/api/v4/projects/${encodeURIComponent(t)}`).pipe(Object(i.a)(({star_count:e,forks_count:t})=>[le(e)+" Stars",le(t)+" Forks"]),Object(Ze.a)([]))}(a,c);default:return y.a}}let tt;function nt(e){const t=new a.a;return t.subscribe(({facts:t})=>{!function(e,t){e.lastElementChild.appendChild(t)}(e,function(e){return ue("ul",{class:"md-source__facts"},e.map(e=>ue("li",{class:"md-source__fact"},e)))}(t)),function(e,t){e.lastElementChild.setAttribute("data-md-state",t)}(e,"done")}),function(e){const t=function(e){let t=0;for(let n=0,a=e.length;n{const n=sessionStorage.getItem(t);if(n)return Object($.a)(JSON.parse(n));{const n=et(e.href);return n.subscribe(e=>{try{sessionStorage.setItem(t,JSON.stringify(e))}catch(e){}}),n}}).pipe(Object(Le.a)(()=>y.a),Object(o.a)(e=>e.length>0),Object(i.a)(e=>({facts:e})),Object(p.a)(1)))}(e).pipe(Object(_.a)(t),Object(x.a)(()=>t.complete()),Object(i.a)(t=>Object.assign({ref:e},t)))}function at(e,t){const n=new a.a;return n.pipe(Object($e.a)(ve.a)).subscribe({next({hidden:t}){t?function(e,t){e.setAttribute("data-md-state",t)}(e,"hidden"):pe(e)},complete(){pe(e)}}),function(e,{viewport$:t,header$:n}){return W(e,{header$:n,viewport$:t}).pipe(Object(i.a)(({offset:{y:e}})=>({hidden:e>=10})),Object(Y.a)("hidden"))}(e,t).pipe(Object(_.a)(n),Object(x.a)(()=>n.complete()),Object(i.a)(t=>Object.assign({ref:e},t)))}var ct=n(80);function rt(e,t){const n=new a.a;n.pipe(Object($e.a)(ve.a)).subscribe(({prev:e,next:t})=>{for(const[e]of t)ie(e),re(e);for(const[t,[n]]of e.entries())oe(n,t===e.length-1),ce(n,"blur")});return function(e,{viewport$:t,header$:n}){const a=new Map;for(const t of e){const e=d(`[id="${decodeURIComponent(t.hash.substring(1))}"]`);void 0!==e&&a.set(t,e)}const c=n.pipe(Object(i.a)(e=>24+e.height));return S(document.body).pipe(Object(Y.a)("height"),Object(i.a)(()=>{let e=[];return[...a].reduce((t,[n,c])=>{for(;e.length;){if(!(a.get(e[e.length-1]).tagName>=c.tagName))break;e.pop()}let r=c.offsetTop;for(;!r&&c.parentElement;)r=(c=c.parentElement).offsetTop;return t.set([...e=[...e,n]].reverse(),r)},new Map)}),Object(s.a)(e=>Object(D.a)([c,t]).pipe(Object(ct.a)(([e,t],[n,{offset:{y:a}}])=>{for(;t.length;){const[,c]=t[0];if(!(c-n=a))break;t=[e.pop(),...t]}return[e,t]},[[],[...e]]),Object(_e.a)((e,t)=>e[0]===t[0]&&e[1]===t[1])))).pipe(Object(i.a)(([e,t])=>({prev:e.map(([e])=>e),next:t.map(([e])=>e)})),Object(v.a)({prev:[],next:[]}),Object(xe.a)(2,1),Object(i.a)(([e,t])=>e.prev.lengthn.complete()),Object(i.a)(t=>Object.assign({ref:e},t)))}var ot=n(14);document.documentElement.classList.remove("no-js"),document.documentElement.classList.add("js");const it=function(){const e=new u.a;return Object(l.a)(document,"DOMContentLoaded").pipe(Object(f.a)(document)).subscribe(e),e}(),st=new C.a(L()),pt=Object(l.a)(window,"hashchange").pipe(Object(i.a)(P),Object(v.a)(P()),Object(o.a)(e=>e.length>0),Object(T.a)()).pipe(Object(s.a)(e=>Object($.a)(d(`[id="${e}"]`)))),bt=Object(l.a)(window,"keydown").pipe(Object(o.a)(e=>!(e.metaKey||e.ctrlKey)),Object(i.a)(e=>{return{mode:(t="search",R[t].checked?"search":"global"),type:e.key,claim(){e.preventDefault(),e.stopPropagation()}};var t}),Object(o.a)(({mode:e})=>{if("global"===e){const e=O();if(void 0!==e)return!function(e){switch(e.tagName){case"INPUT":case"SELECT":case"TEXTAREA":return!0;default:return e.isContentEditable}}(e)}return!0}),Object(T.a)()),ut=Object(D.a)([Object(c.a)(Object(l.a)(window,"scroll",{passive:!0}),Object(l.a)(window,"resize",{passive:!0})).pipe(Object(i.a)(F),Object(v.a)(F())),Object(l.a)(window,"resize",{passive:!0}).pipe(Object(i.a)(J),Object(v.a)(J()))]).pipe(Object(i.a)(([e,t])=>({offset:e,size:t})),Object(p.a)(1)),lt=U("(min-width: 960px)"),ft=U("(min-width: 1220px)"),dt=Object(c.a)(U("print").pipe(Object(o.a)(Boolean)),Object(l.a)(window,"beforeprint")).pipe(Object(f.a)(void 0)),ht=new a.a;!function({alert$:e}){ne.a.isSupported()&&new Re.a(e=>{new ne.a("[data-clipboard-target], [data-clipboard-text]").on("success",t=>e.next(t))}).subscribe(()=>e.next(Z("clipboard.copied")))}({alert$:ht}),G("navigation.instant")&&function({document$:e,location$:t,viewport$:n}){const a=V();if("file:"===location.protocol)return;"scrollRestoration"in history&&(history.scrollRestoration="manual",Object(l.a)(window,"beforeunload").subscribe(()=>{history.scrollRestoration="auto"}));const r=d("link[rel='shortcut icon']");void 0!==r&&(r.href=r.href);const b=function(e,t){const n=new DOMParser;return I(e,t).pipe(Object(s.a)(e=>e.text()),Object(i.a)(e=>n.parseFromString(e,"text/xml")),Object(p.a)(1))}(a.base+"/sitemap.xml").pipe(Object(i.a)(e=>function(e){if(e.length<2)return e;const[t,n]=e.sort((e,t)=>e.length-t.length);let a=0;if(t===n)a=t.length;else for(;t.charCodeAt(a)==t.charCodeAt(a);)a++;const c=V();return e.map(e=>e.replace(t.slice(0,a),c.base+"/"))}(j("loc",e).map(e=>e.textContent))),Object(s.a)(e=>Object(l.a)(document.body,"click").pipe(Object(o.a)(e=>!e.metaKey&&!e.ctrlKey),Object(s.a)(t=>{if(t.target instanceof HTMLElement){const n=t.target.closest("a");if(n&&!n.target&&e.includes(n.href))return t.preventDefault(),Object($.a)({url:new URL(n.href)})}return y.a}))),Object(T.a)()),u=Object(l.a)(window,"popstate").pipe(Object(o.a)(e=>null!==e.state),Object(i.a)(e=>({url:new URL(location.href),offset:e.state})),Object(T.a)());Object(c.a)(b,u).pipe(Object(_e.a)((e,t)=>e.url.href===t.url.href),Object(i.a)(({url:e})=>e)).subscribe(t);const f=t.pipe(Object(Y.a)("pathname"),Object(Ce.a)(1),Object(s.a)(e=>I(e.href).pipe(Object(Le.a)(()=>(function(e){location.href=e.href}(e),y.a)))),Object(T.a)());b.pipe(Object(Se.a)(f)).subscribe(({url:e})=>{history.pushState({},"",e.toString())});const O=new DOMParser;f.pipe(Object(s.a)(e=>e.text()),Object(i.a)(e=>O.parseFromString(e,"text/html"))).subscribe(e),Object(c.a)(b,u).pipe(Object(Se.a)(e)).subscribe(({url:e,offset:t})=>{e.hash&&!t?function(e){const t=m("a");t.href=e,t.addEventListener("click",e=>e.stopPropagation()),t.click()}(e.hash):q(t||{y:0})}),e.pipe(Object(Ce.a)(1)).subscribe(e=>{for(const t of["title","link[rel='canonical']","meta[name='author']","meta[name='description']","[data-md-component=announce]","[data-md-component=header-title]","[data-md-component=container]","[data-md-component=skip]"]){const n=d(t),a=d(t,e);void 0!==n&&void 0!==a&&g(n,a)}}),e.pipe(Object(Ce.a)(1),Object(i.a)(()=>h("[data-md-component=container]")),Object(s.a)(e=>Object($.a)(...j("script",e))),Object(Pe.a)(e=>{const t=m("script");return e.src?(t.src=e.src,g(e,t),new Re.a(e=>{t.onload=()=>e.complete()})):(t.textContent=e.textContent,g(e,t),Me.a)})).subscribe(),n.pipe(Object(Ue.a)(b),Object(Ne.a)(250),Object(Y.a)("offset")).subscribe(({offset:e})=>{history.replaceState(e,"")}),Object(c.a)(b,u).pipe(Object(xe.a)(2,1),Object(o.a)(([e,t])=>e.url.pathname===t.url.pathname),Object(i.a)(([,e])=>e)).subscribe(({offset:e})=>{q(e||{y:0})})}({document$:it,location$:st,viewport$:ut}),bt.pipe(Object(o.a)(({mode:e})=>"global"===e)).subscribe(e=>{switch(e.type){case"p":case",":const e=d("[href][rel=prev]");void 0!==e&&e.click();break;case"n":case".":const t=d("[href][rel=next]");void 0!==t&&t.click()}}),function({document$:e}){e.subscribe(()=>{for(const e of j("[data-md-state=indeterminate]"))e.setAttribute("data-md-state",""),e.indeterminate=!0,e.checked=!1})}({document$:it}),function({document$:e}){/(iPad|iPhone|iPod)/.test(navigator.userAgent)&&e.pipe(Object(s.a)(()=>Object($.a)(...j("[data-md-scrollfix]"))),Object(_.a)(e=>e.removeAttribute("data-md-scrollfix")),Object(ot.a)(e=>Object(l.a)(e,"touchstart").pipe(Object(f.a)(e)))).subscribe(e=>{const t=e.scrollTop;0===t?e.scrollTop=1:t+e.offsetHeight===e.scrollHeight&&(e.scrollTop=t-1)})}({document$:it});const Ot=(jt=h("[data-md-component=header]"),mt={viewport$:ut},Object(r.a)(()=>{const e=getComputedStyle(jt);return Object($.a)("sticky"===e.position||"-webkit-sticky"===e.position)}).pipe(Object(Ee.a)(S(jt),ke(mt)),Object(i.a)(([e,{height:t},n])=>({height:e?t:0,sticky:e,hidden:n})),Object(_e.a)((e,t)=>e.sticky===t.sticky&&e.height===t.height&&e.hidden===t.hidden),Object(p.a)(1)));var jt,mt;const gt=it.pipe(Object(i.a)(()=>h("[data-md-component=main]")),Object(s.a)(e=>function(e,{viewport$:t,header$:n}){const a=n.pipe(Object(i.a)(({height:e})=>e),Object(_e.a)()),c=a.pipe(Object(s.a)(()=>S(e).pipe(Object(i.a)(({height:t})=>({top:e.offsetTop,bottom:e.offsetTop+t})),Object(Y.a)("bottom"))));return Object(D.a)([a,c,t]).pipe(Object(i.a)(([e,{top:t,bottom:n},{offset:{y:a},size:{height:c}}])=>({offset:t-e,height:c=Math.max(0,c-Math.max(0,t-a,e)-Math.max(0,c+a-n)),active:t-e<=a})),Object(_e.a)((e,t)=>e.offset===t.offset&&e.height===t.height&&e.active===t.active))}(e,{viewport$:ut,header$:Ot})),Object(p.a)(1)),vt=Object(c.a)(...j("[data-md-component=dialog]").map(e=>ye(e,{alert$:ht})),...j("[data-md-component=header]").map(e=>function(e,{header$:t,main$:n}){const c=new a.a;return c.pipe(Object(Y.a)("active"),Object(Ee.a)(t),Object($e.a)(ve.a)).subscribe(([{active:t},{hidden:n}])=>{t?function(e,t){e.setAttribute("data-md-state",t)}(e,n?"hidden":"shadow"):function(e){e.removeAttribute("data-md-state")}(e)}),n.subscribe(e=>c.next(e)),t.pipe(Object(i.a)(t=>Object.assign({ref:e},t)))}(e,{viewport$:ut,header$:Ot,main$:gt})),...j("[data-md-component=search]").map(e=>Xe(e,{keyboard$:bt})),...j("[data-md-component=source]").map(e=>nt(e)),...j("[data-md-component=tabs]").map(e=>at(e,{viewport$:ut,header$:Ot}))),wt=Object(r.a)(()=>Object(c.a)(...j("[data-md-component=content]").map(e=>function(e,{target$:t,viewport$:n,print$:a}){return Object(c.a)(...j("pre > code",e).map(e=>Oe(e,{viewport$:n})),...j("table:not([class])",e).map(e=>ge(e)),...j("details",e).map(e=>je(e,{target$:t,print$:a})))}(e,{target$:pt,viewport$:ut,print$:dt})),...j("[data-md-component=header-title]").map(e=>Ae(e,{viewport$:ut,header$:Ot})),...j("[data-md-component=sidebar]").map(e=>"navigation"===e.getAttribute("data-md-type")?N(ft,()=>Ge(e,{viewport$:ut,header$:Ot,main$:gt})):N(lt,()=>Ge(e,{viewport$:ut,header$:Ot,main$:gt}))),...j("[data-md-component=toc]").map(e=>rt(e,{viewport$:ut,header$:Ot})))),$t=it.pipe(Object(s.a)(()=>wt),Object(b.a)(vt));$t.subscribe()}})); +//# sourceMappingURL=bundle.d8c6976f.min.js.map \ No newline at end of file diff --git a/material/assets/javascripts/bundle.d8c6976f.min.js.map b/material/assets/javascripts/bundle.d8c6976f.min.js.map new file mode 100644 index 000000000..0cdfa4508 --- /dev/null +++ b/material/assets/javascripts/bundle.d8c6976f.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/assets/javascripts/browser/element/_/index.ts","webpack:///./src/assets/javascripts/browser/element/focus/index.ts","webpack:///./src/assets/javascripts/browser/element/size/index.ts","webpack:///./src/assets/javascripts/browser/toggle/index.ts","webpack:///./src/assets/javascripts/browser/location/_/index.ts","webpack:///./src/assets/javascripts/browser/location/hash/index.ts","webpack:///./src/assets/javascripts/browser/media/index.ts","webpack:///./src/assets/javascripts/browser/request/index.ts","webpack:///./src/assets/javascripts/browser/viewport/offset/index.ts","webpack:///./src/assets/javascripts/browser/viewport/size/index.ts","webpack:///./src/assets/javascripts/browser/viewport/_/index.ts","webpack:///./src/assets/javascripts/_/index.ts","webpack:///./src/assets/javascripts/templates/search/index.tsx","webpack:///./src/assets/javascripts/actions/anchor/index.ts","webpack:///./src/assets/javascripts/actions/search/result/index.ts","webpack:///./src/assets/javascripts/actions/tabs/index.ts","webpack:///./src/assets/javascripts/utilities/jsx/index.ts","webpack:///./src/assets/javascripts/utilities/string/index.ts","webpack:///./src/assets/javascripts/components/content/code/index.ts","webpack:///./src/assets/javascripts/actions/_/index.ts","webpack:///./src/assets/javascripts/templates/clipboard/index.tsx","webpack:///./src/assets/javascripts/components/content/details/index.ts","webpack:///./src/assets/javascripts/components/content/table/index.ts","webpack:///./src/assets/javascripts/templates/table/index.tsx","webpack:///./src/assets/javascripts/components/dialog/index.ts","webpack:///./src/assets/javascripts/actions/dialog/index.ts","webpack:///./src/assets/javascripts/components/header/_/index.ts","webpack:///./src/assets/javascripts/components/header/title/index.ts","webpack:///./src/assets/javascripts/actions/header/title/index.ts","webpack:///./src/assets/javascripts/integrations/search/worker/message/index.ts","webpack:///./src/assets/javascripts/integrations/search/query/transform/index.ts","webpack:///./src/assets/javascripts/integrations/search/worker/_/index.ts","webpack:///./src/assets/javascripts/browser/worker/index.ts","webpack:///./src/assets/javascripts/components/search/query/index.ts","webpack:///./src/assets/javascripts/actions/search/query/index.ts","webpack:///./src/assets/javascripts/components/search/result/index.ts","webpack:///./src/assets/javascripts/components/search/_/index.ts","webpack:///./src/assets/javascripts/browser/element/selection/index.ts","webpack:///./src/assets/javascripts/components/sidebar/index.ts","webpack:///./src/assets/javascripts/actions/sidebar/index.ts","webpack:///./src/assets/javascripts/components/source/facts/_/index.ts","webpack:///./src/assets/javascripts/components/source/facts/github/index.ts","webpack:///./src/assets/javascripts/components/source/facts/gitlab/index.ts","webpack:///./src/assets/javascripts/components/source/_/index.ts","webpack:///./src/assets/javascripts/actions/source/index.ts","webpack:///./src/assets/javascripts/templates/source/index.tsx","webpack:///./src/assets/javascripts/components/tabs/index.ts","webpack:///./src/assets/javascripts/components/toc/index.ts","webpack:///./src/assets/javascripts/index.ts","webpack:///./src/assets/javascripts/browser/document/index.ts","webpack:///./src/assets/javascripts/browser/keyboard/index.ts","webpack:///./src/assets/javascripts/integrations/clipboard/index.ts","webpack:///./src/assets/javascripts/integrations/instant/index.ts","webpack:///./src/assets/javascripts/patches/indeterminate/index.ts","webpack:///./src/assets/javascripts/patches/scrollfix/index.ts","webpack:///./src/assets/javascripts/components/main/index.ts","webpack:///./src/assets/javascripts/actions/header/_/index.ts","webpack:///./src/assets/javascripts/components/content/_/index.ts"],"names":["webpackJsonpCallback","data","moduleId","chunkId","chunkIds","moreModules","executeModules","i","resolves","length","Object","prototype","hasOwnProperty","call","installedChunks","push","modules","parentJsonpFunction","shift","deferredModules","apply","checkDeferredModules","result","deferredModule","fulfilled","j","depId","splice","__webpack_require__","s","installedModules","0","exports","module","l","m","c","d","name","getter","o","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","p","jsonpArray","window","oldJsonpFunction","slice","getElement","selector","node","document","querySelector","undefined","getElementOrThrow","el","ReferenceError","getActiveElement","activeElement","HTMLElement","getElements","Array","from","querySelectorAll","createElement","tagName","replaceElement","source","target","replaceWith","setElementFocus","focus","blur","entry$","Subject","observer$","defer","of","ResizeObserver","entries","entry","next","pipe","switchMap","resize","startWith","finalize","disconnect","shareReplay","getElementSize","width","offsetWidth","height","offsetHeight","watchElementSize","tap","observer","observe","filter","unobserve","map","contentRect","toggles","drawer","search","setToggle","checked","click","getLocation","URL","location","href","getLocationHash","hash","substring","watchMedia","query","media","matchMedia","fromEvent","ev","matches","at","toggle$","factory","active","request","url","options","credentials","fetch","res","status","requestJSON","json","getViewportOffset","x","Math","max","pageXOffset","y","pageYOffset","setViewportOffset","scrollTo","getViewportSize","innerWidth","innerHeight","watchViewportAt","viewport$","header$","size$","distinctUntilKeyChanged","offset$","combineLatest","offsetLeft","offsetTop","offset","size","JSON","parse","textContent","configuration","feature","flag","features","includes","translation","translations","replace","toString","base","Flag","setAnchorState","state","setAttribute","resetAnchorState","removeAttribute","setAnchorActive","classList","toggle","resetAnchorActive","remove","addToSearchResultList","child","appendChild","resetTabsState","innerHTML","Node","isArray","h","tag","attributes","children","attr","keys","round","toFixed","renderSearchDocument","parent","PARENT","teaser","TEASER","missing","terms","flat","class","tabIndex","join","score","title","text","truncate","renderSearchResult","threshold","Infinity","docs","findIndex","doc","article","index","best","more","section","mountCodeBlock","internal$","withLatestFrom","subscribe","scroll","hover","setFocusable","resetFocusable","isSupported","closest","id","insertBefore","visible","scrollWidth","scrollHeight","getElementContentSize","watchCodeBlock","complete","ref","mountDetails","scrollIntoView","target$","print$","details","mergeWith","mapTo","watchDetails","sentinel","mountDataTable","mountDialog","observeOn","animationFrame","message","open","firstElementChild","setDialogMessage","setDialogState","resetDialogState","_el","alert$","merge","delay","watchDialog","isHidden","direction$","bufferCount","a","b","hidden$","abs","direction","distinctUntilChanged","search$","watchToggle","mountHeaderTitle","setHeaderTitleState","resetHeaderTitleState","headline","watchHeaderTitle","SearchMessageType","defaultTransform","split","trim","isSearchReadyMessage","type","READY","isSearchQueryMessage","QUERY","isSearchResultMessage","RESULT","setupSearchIndex","config","lang","separator","pipeline","Boolean","setupSearchWorker","worker","Worker","tx$","rx$","throttle","leading","trailing","postMessage","switchMapTo","share","watchWorker","SETUP","watchSearchQuery","fn","__search","transform","focus$","watchElementFocus","value$","mountSearchQuery","placeholder","setSearchQueryPlaceholder","resetSearchQueryPlaceholder","form","takeUntil","takeLast","mountSearchResult","query$","meta","setSearchResultMeta","resetSearchResultMeta","list","resetSearchResultList","thresholds","mountSearch","keyboard$","sample","take","claim","els","indexOf","HTMLInputElement","Error","select","setElementSelection","mountSidebar","scrollwrap","style","setSidebarHeight","top","setSidebarOffset","resetSidebarOffset","resetSidebarHeight","main$","adjust","parentElement","min","locked","watchSidebar","fetchSourceFacts","match","toLowerCase","user","repo","stargazers_count","forks_count","public_repos","defaultIfEmpty","fetchSourceFactsFromGitHub","slug","project","encodeURIComponent","star_count","fetchSourceFactsFromGitLab","fetch$","mountSource","facts","lastElementChild","setSourceFacts","fact","renderSourceFacts","setSourceState","digest","len","charCodeAt","sessionStorage","getItem","setItem","stringify","err","catchError","watchSource","mountTabs","hidden","setTabsState","watchTabs","mountTableOfContents","prev","anchor","anchors","table","Map","decodeURIComponent","set","adjust$","header","body","path","reduce","pop","reverse","scan","watchTableOfContents","documentElement","add","document$","ReplaySubject","watchDocument","BehaviorSubject","metaKey","ctrlKey","preventDefault","stopPropagation","isContentEditable","isSusceptibleToKeyboard","passive","tablet$","screen$","Observable","subscriber","on","setupClipboardJS","location$","protocol","history","scrollRestoration","favicon","push$","dom","DOMParser","parseFromString","requestXML","sitemap","urls","root","sort","preprocess","pop$","response$","skip","setLocation","pushState","addEventListener","setLocationHash","replacement","concatMap","script","src","onload","skipUntil","debounceTime","replaceState","pathname","setupInstantLoading","indeterminate","patchIndeterminate","test","navigator","userAgent","mergeMap","scrollTop","patchScrollfix","styles","getComputedStyle","position","combineLatestWith","sticky","border$","bottom","watchMain","control$","setHeaderState","resetHeaderState","main","mountHeader","content$","mountContent","getAttribute","component$"],"mappings":"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","file":"assets/javascripts/bundle.d8c6976f.min.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t0: 0\n \t};\n\n \tvar deferredModules = [];\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \tvar jsonpArray = window[\"webpackJsonp\"] = window[\"webpackJsonp\"] || [];\n \tvar oldJsonpFunction = jsonpArray.push.bind(jsonpArray);\n \tjsonpArray.push = webpackJsonpCallback;\n \tjsonpArray = jsonpArray.slice();\n \tfor(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);\n \tvar parentJsonpFunction = oldJsonpFunction;\n\n\n \t// add entry module to deferred list\n \tdeferredModules.push([50,1]);\n \t// run deferred modules when ready\n \treturn checkDeferredModules();\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve an element matching the query selector\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @returns Element or nothing\n */\nexport function getElement(\n selector: T, node?: ParentNode\n): HTMLElementTagNameMap[T]\n\nexport function getElement(\n selector: string, node?: ParentNode\n): T | undefined\n\nexport function getElement(\n selector: string, node: ParentNode = document\n): T | undefined {\n return node.querySelector(selector) || undefined\n}\n\n/**\n * Retrieve an element matching a query selector or throw a reference error\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @returns Element\n */\nexport function getElementOrThrow(\n selector: T, node?: ParentNode\n): HTMLElementTagNameMap[T]\n\nexport function getElementOrThrow(\n selector: string, node?: ParentNode\n): T\n\nexport function getElementOrThrow(\n selector: string, node: ParentNode = document\n): T {\n const el = getElement(selector, node)\n if (typeof el === \"undefined\")\n throw new ReferenceError(\n `Missing element: expected \"${selector}\" to be present`\n )\n return el\n}\n\n/**\n * Retrieve the currently active element\n *\n * @returns Element or nothing\n */\nexport function getActiveElement(): HTMLElement | undefined {\n return document.activeElement instanceof HTMLElement\n ? document.activeElement\n : undefined\n}\n\n/**\n * Retrieve all elements matching the query selector\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @returns Elements\n */\nexport function getElements(\n selector: T, node?: ParentNode\n): HTMLElementTagNameMap[T][]\n\nexport function getElements(\n selector: string, node?: ParentNode\n): T[]\n\nexport function getElements(\n selector: string, node: ParentNode = document\n): T[] {\n return Array.from(node.querySelectorAll(selector))\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Create an element\n *\n * @template T - Tag name type\n *\n * @param tagName - Tag name\n *\n * @returns Element\n */\nexport function createElement(\n tagName: T\n): HTMLElementTagNameMap[T] {\n return document.createElement(tagName)\n}\n\n/**\n * Replace an element with another element\n *\n * @param source - Source element\n * @param target - Target element\n */\nexport function replaceElement(\n source: HTMLElement, target: Node\n): void {\n source.replaceWith(target)\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, merge } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\nimport { getActiveElement } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set element focus\n *\n * @param el - Element\n * @param value - Whether the element should be focused\n */\nexport function setElementFocus(\n el: HTMLElement, value = true\n): void {\n if (value)\n el.focus()\n else\n el.blur()\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element focus\n *\n * @param el - Element\n *\n * @returns Element focus observable\n */\nexport function watchElementFocus(\n el: HTMLElement\n): Observable {\n return merge(\n fromEvent(el, \"focus\"),\n fromEvent(el, \"blur\")\n )\n .pipe(\n map(({ type }) => type === \"focus\"),\n startWith(el === getActiveElement())\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n NEVER,\n Observable,\n Subject,\n defer,\n of\n} from \"rxjs\"\nimport {\n filter,\n finalize,\n map,\n shareReplay,\n startWith,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Element offset\n */\nexport interface ElementSize {\n width: number /* Element width */\n height: number /* Element height */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Resize observer entry subject\n */\nconst entry$ = new Subject()\n\n/**\n * Resize observer observable\n *\n * This observable will create a `ResizeObserver` on the first subscription\n * and will automatically terminate it when there are no more subscribers.\n * It's quite important to centralize observation in a single `ResizeObserver`,\n * as the performance difference can be quite dramatic, as the link shows.\n *\n * @see https://bit.ly/3iIYfEm - Google Groups on performance\n */\nconst observer$ = defer(() => of(\n new ResizeObserver(entries => {\n for (const entry of entries)\n entry$.next(entry)\n })\n))\n .pipe(\n switchMap(resize => NEVER.pipe(startWith(resize))\n .pipe(\n finalize(() => resize.disconnect())\n )\n ),\n shareReplay(1)\n )\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve element size\n *\n * @param el - Element\n *\n * @returns Element size\n */\nexport function getElementSize(el: HTMLElement): ElementSize {\n return {\n width: el.offsetWidth,\n height: el.offsetHeight\n }\n}\n\n/**\n * Retrieve element content size, i.e. including overflowing content\n *\n * @param el - Element\n *\n * @returns Element size\n */\nexport function getElementContentSize(el: HTMLElement): ElementSize {\n return {\n width: el.scrollWidth,\n height: el.scrollHeight\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element size\n *\n * This function returns an observable that will subscribe to a single internal\n * instance of `ResizeObserver` upon subscription, and emit resize events until\n * termination. Note that this function should not be called with the same\n * element twice, as the first unsubscription will terminate observation.\n *\n * @param el - Element\n *\n * @returns Element size observable\n */\nexport function watchElementSize(\n el: HTMLElement\n): Observable {\n return observer$\n .pipe(\n tap(observer => observer.observe(el)),\n switchMap(observer => entry$\n .pipe(\n filter(({ target }) => target === el),\n finalize(() => observer.unobserve(el)),\n map(({ contentRect }) => ({\n width: contentRect.width,\n height: contentRect.height\n }))\n )\n ),\n startWith(getElementSize(el))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\nimport { getElementOrThrow } from \"../element\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Toggle\n */\nexport type Toggle =\n | \"drawer\" /* Toggle for drawer */\n | \"search\" /* Toggle for search */\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Toggle map\n */\nconst toggles: Record = {\n drawer: getElementOrThrow(\"[data-md-toggle=drawer]\"),\n search: getElementOrThrow(\"[data-md-toggle=search]\")\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve the value of a toggle\n *\n * @param name - Toggle\n *\n * @returns Toggle value\n */\nexport function getToggle(name: Toggle): boolean {\n return toggles[name].checked\n}\n\n/**\n * Set toggle\n *\n * Simulating a click event seems to be the most cross-browser compatible way\n * of changing the value while also emitting a `change` event. Before, Material\n * used `CustomEvent` to programmatically change the value of a toggle, but this\n * is a much simpler and cleaner solution which doesn't require a polyfill.\n *\n * @param name - Toggle\n * @param value - Toggle value\n */\nexport function setToggle(name: Toggle, value: boolean): void {\n if (toggles[name].checked !== value)\n toggles[name].click()\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch toggle\n *\n * @param name - Toggle\n *\n * @returns Toggle value observable\n */\nexport function watchToggle(name: Toggle): Observable {\n const el = toggles[name]\n return fromEvent(el, \"change\")\n .pipe(\n map(() => el.checked),\n startWith(el.checked)\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { BehaviorSubject, Subject } from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve location\n *\n * This function will return a `URL` object (and not `Location`) in order to\n * normalize typings across the application. Furthermore, locations need to be\n * tracked without setting them and `Location` is a singleton which represents\n * the current location.\n *\n * @returns URL\n */\nexport function getLocation(): URL {\n return new URL(location.href)\n}\n\n/**\n * Set location\n *\n * @param url - URL to change to\n */\nexport function setLocation(url: URL): void {\n location.href = url.href\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch location\n *\n * @returns Location subject\n */\nexport function watchLocation(): Subject {\n return new BehaviorSubject(getLocation())\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, of } from \"rxjs\"\nimport { filter, map, share, startWith, switchMap } from \"rxjs/operators\"\n\nimport { createElement, getElement } from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve location hash\n *\n * @returns Location hash\n */\nexport function getLocationHash(): string {\n return location.hash.substring(1)\n}\n\n/**\n * Set location hash\n *\n * Setting a new fragment identifier via `location.hash` will have no effect\n * if the value doesn't change. When a new fragment identifier is set, we want\n * the browser to target the respective element at all times, which is why we\n * use this dirty little trick.\n *\n * @param hash - Location hash\n */\nexport function setLocationHash(hash: string): void {\n const el = createElement(\"a\")\n el.href = hash\n el.addEventListener(\"click\", ev => ev.stopPropagation())\n el.click()\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch location hash\n *\n * @returns Location hash observable\n */\nexport function watchLocationHash(): Observable {\n return fromEvent(window, \"hashchange\")\n .pipe(\n map(getLocationHash),\n startWith(getLocationHash()),\n filter(hash => hash.length > 0),\n share()\n )\n}\n\n/**\n * Watch location target\n *\n * @returns Location target observable\n */\nexport function watchLocationTarget(): Observable {\n return watchLocationHash()\n .pipe(\n switchMap(id => of(getElement(`[id=\"${id}\"]`)!))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { NEVER, Observable, fromEvent, merge } from \"rxjs\"\nimport {\n filter,\n map,\n mapTo,\n startWith,\n switchMap\n} from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch media query\n *\n * @param query - Media query\n *\n * @returns Media observable\n */\nexport function watchMedia(query: string): Observable {\n const media = matchMedia(query)\n return fromEvent(media, \"change\")\n .pipe(\n map(ev => ev.matches),\n startWith(media.matches)\n )\n}\n\n/**\n * Watch print mode, cross-browser\n *\n * @returns Print observable\n */\nexport function watchPrint(): Observable {\n return merge(\n watchMedia(\"print\").pipe(filter(Boolean)), /* Webkit */\n fromEvent(window, \"beforeprint\") /* IE, FF */\n )\n .pipe(\n mapTo(undefined)\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Toggle an observable with another one\n *\n * @template T - Data type\n *\n * @param toggle$ - Toggle observable\n * @param factory - Observable factory\n *\n * @returns Toggled observable\n */\nexport function at(\n toggle$: Observable, factory: () => Observable\n): Observable {\n return toggle$\n .pipe(\n switchMap(active => active ? factory() : NEVER)\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, from } from \"rxjs\"\nimport {\n filter,\n map,\n shareReplay,\n switchMap\n} from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch the given URL\n *\n * @param url - Request URL\n * @param options - Request options\n *\n * @returns Response observable\n */\nexport function request(\n url: string, options: RequestInit = { credentials: \"same-origin\" }\n): Observable {\n return from(fetch(url, options))\n .pipe(\n filter(res => res.status === 200),\n )\n}\n\n/**\n * Fetch JSON from the given URL\n *\n * @template T - Data type\n *\n * @param url - Request URL\n * @param options - Request options\n *\n * @returns Data observable\n */\nexport function requestJSON(\n url: string, options?: RequestInit\n): Observable {\n return request(url, options)\n .pipe(\n switchMap(res => res.json()),\n shareReplay(1)\n )\n}\n\n/**\n * Fetch XML from the given URL\n *\n * @param url - Request URL\n * @param options - Request options\n *\n * @returns Data observable\n */\nexport function requestXML(\n url: string, options?: RequestInit\n): Observable {\n const dom = new DOMParser()\n return request(url, options)\n .pipe(\n switchMap(res => res.text()),\n map(res => dom.parseFromString(res, \"text/xml\")),\n shareReplay(1)\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, merge } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Viewport offset\n */\nexport interface ViewportOffset {\n x: number /* Horizontal offset */\n y: number /* Vertical offset */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve viewport offset\n *\n * On iOS Safari, viewport offset can be negative due to overflow scrolling.\n * As this may induce strange behaviors downstream, we'll just limit it to 0.\n *\n * @returns Viewport offset\n */\nexport function getViewportOffset(): ViewportOffset {\n return {\n x: Math.max(0, pageXOffset),\n y: Math.max(0, pageYOffset)\n }\n}\n\n/**\n * Set viewport offset\n *\n * @param offset - Viewport offset\n */\nexport function setViewportOffset(\n { x, y }: Partial\n): void {\n window.scrollTo(x || 0, y || 0)\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport offset\n *\n * @returns Viewport offset observable\n */\nexport function watchViewportOffset(): Observable {\n return merge(\n fromEvent(window, \"scroll\", { passive: true }),\n fromEvent(window, \"resize\", { passive: true })\n )\n .pipe(\n map(getViewportOffset),\n startWith(getViewportOffset())\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Viewport size\n */\nexport interface ViewportSize {\n width: number /* Viewport width */\n height: number /* Viewport height */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve viewport size\n *\n * @returns Viewport size\n */\nexport function getViewportSize(): ViewportSize {\n return {\n width: innerWidth,\n height: innerHeight\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport size\n *\n * @returns Viewport size observable\n */\nexport function watchViewportSize(): Observable {\n return fromEvent(window, \"resize\", { passive: true })\n .pipe(\n map(getViewportSize),\n startWith(getViewportSize())\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, combineLatest } from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n map,\n shareReplay\n} from \"rxjs/operators\"\n\nimport { Header } from \"~/components\"\n\nimport {\n ViewportOffset,\n watchViewportOffset\n} from \"../offset\"\nimport {\n ViewportSize,\n watchViewportSize\n} from \"../size\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Viewport\n */\nexport interface Viewport {\n offset: ViewportOffset /* Viewport offset */\n size: ViewportSize /* Viewport size */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch at options\n */\ninterface WatchAtOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport\n *\n * @returns Viewport observable\n */\nexport function watchViewport(): Observable {\n return combineLatest([\n watchViewportOffset(),\n watchViewportSize()\n ])\n .pipe(\n map(([offset, size]) => ({ offset, size })),\n shareReplay(1)\n )\n}\n\n/**\n * Watch viewport relative to element\n *\n * @param el - Element\n * @param options - Options\n *\n * @returns Viewport observable\n */\nexport function watchViewportAt(\n el: HTMLElement, { viewport$, header$ }: WatchAtOptions\n): Observable {\n const size$ = viewport$\n .pipe(\n distinctUntilKeyChanged(\"size\")\n )\n\n /* Compute element offset */\n const offset$ = combineLatest([size$, header$])\n .pipe(\n map((): ViewportOffset => ({\n x: el.offsetLeft,\n y: el.offsetTop\n }))\n )\n\n /* Compute relative viewport, return hot observable */\n return combineLatest([header$, viewport$, offset$])\n .pipe(\n map(([{ height }, { offset, size }, { x, y }]) => ({\n offset: {\n x: offset.x - x,\n y: offset.y - y + height\n },\n size\n }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { getElementOrThrow, getLocation } from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Feature flag\n */\nexport type Flag =\n | \"header.autohide\" /* Hide header */\n | \"navigation.tabs\" /* Tabs navigation */\n | \"navigation.instant\" /* Instant loading */\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Translation\n */\nexport type Translation =\n | \"clipboard.copy\" /* Copy to clipboard */\n | \"clipboard.copied\" /* Copied to clipboard */\n | \"search.config.lang\" /* Search language */\n | \"search.config.pipeline\" /* Search pipeline */\n | \"search.config.separator\" /* Search separator */\n | \"search.placeholder\" /* Search */\n | \"search.result.placeholder\" /* Type to start searching */\n | \"search.result.none\" /* No matching documents */\n | \"search.result.one\" /* 1 matching document */\n | \"search.result.other\" /* # matching documents */\n | \"search.result.more.one\" /* 1 more on this page */\n | \"search.result.more.other\" /* # more on this page */\n | \"search.result.term.missing\" /* Missing */\n\n/**\n * Translations\n */\nexport type Translations = Record\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Configuration\n */\nexport interface Config {\n base: string /* Base URL */\n features: Flag[] /* Feature flags */\n translations: Translations /* Translations */\n search: string /* Search worker URL */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve global configuration and make base URL absolute\n */\nconst script = getElementOrThrow(\"#__config\")\nconst config: Config = JSON.parse(script.textContent!)\nconfig.base = new URL(config.base, getLocation())\n .toString()\n .replace(/\\/$/, \"\")\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve global configuration\n *\n * @returns Global configuration\n */\nexport function configuration(): Config {\n return config\n}\n\n/**\n * Check whether a feature flag is enabled\n *\n * @param flag - Feature flag\n *\n * @returns Test result\n */\nexport function feature(flag: Flag): boolean {\n return config.features.includes(flag)\n}\n\n/**\n * Retrieve the translation for the given key\n *\n * @param key - Key to be translated\n * @param value - Value to be replaced\n *\n * @returns Translation\n */\nexport function translation(\n key: Translation, value?: string | number\n): string {\n return typeof value !== \"undefined\"\n ? config.translations[key].replace(\"#\", value.toString())\n : config.translations[key]\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { translation } from \"~/_\"\nimport {\n SearchDocument,\n SearchMetadata,\n SearchResult\n} from \"~/integrations/search\"\nimport { h, truncate } from \"~/utilities\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Render flag\n */\nconst enum Flag {\n TEASER = 1, /* Render teaser */\n PARENT = 2 /* Render as parent */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper function\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a search document\n *\n * @param section - Search document\n * @param flag - Render flags\n *\n * @returns Element\n */\nfunction renderSearchDocument(\n document: SearchDocument & SearchMetadata, flag: Flag\n) {\n const parent = flag & Flag.PARENT\n const teaser = flag & Flag.TEASER\n\n /* Render missing query terms */\n const missing = Object.keys(document.terms)\n .filter(key => !document.terms[key])\n .map(key => [{key}, \" \"])\n .flat()\n .slice(0, -1)\n\n /* Render article or section, depending on flags */\n const url = document.location\n return (\n \n \n {parent > 0 &&
    }\n

    {document.title}

    \n {teaser > 0 && document.text.length > 0 &&\n

    \n {truncate(document.text, 320)}\n

    \n }\n {teaser > 0 && missing.length > 0 &&\n

    \n {translation(\"search.result.term.missing\")}: {...missing}\n

    \n }\n \n
    \n )\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a search result\n *\n * @param result - Search result\n * @param threshold - Score threshold\n *\n * @returns Element\n */\nexport function renderSearchResult(\n result: SearchResult, threshold: number = Infinity\n) {\n const docs = [...result]\n\n /* Find and extract parent article */\n const parent = docs.findIndex(doc => !doc.location.includes(\"#\"))\n const [article] = docs.splice(parent, 1)\n\n /* Determine last index above threshold */\n let index = docs.findIndex(doc => doc.score < threshold)\n if (index === -1)\n index = docs.length\n\n /* Partition sections */\n const best = docs.slice(0, index)\n const more = docs.slice(index)\n\n /* Render children */\n const children = [\n renderSearchDocument(article, Flag.PARENT | +(!parent && index === 0)),\n ...best.map(section => renderSearchDocument(section, Flag.TEASER)),\n ...more.length ? [\n
    \n \n {more.length > 0 && more.length === 1\n ? translation(\"search.result.more.one\")\n : translation(\"search.result.more.other\", more.length)\n }\n \n {...more.map(section => renderSearchDocument(section, Flag.TEASER))}\n
    \n ] : []\n ]\n\n /* Render search result */\n return (\n
  • \n {children}\n
  • \n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set anchor state\n *\n * @param el - Anchor element\n * @param state - Anchor state\n */\nexport function setAnchorState(\n el: HTMLElement, state: \"blur\"\n): void {\n el.setAttribute(\"data-md-state\", state)\n}\n\n/**\n * Reset anchor state\n *\n * @param el - Anchor element\n */\nexport function resetAnchorState(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Set anchor active\n *\n * @param el - Anchor element\n * @param value - Whether the anchor is active\n */\nexport function setAnchorActive(\n el: HTMLElement, value: boolean\n): void {\n el.classList.toggle(\"md-nav__link--active\", value)\n}\n\n/**\n * Reset anchor active\n *\n * @param el - Anchor element\n */\nexport function resetAnchorActive(\n el: HTMLElement\n): void {\n el.classList.remove(\"md-nav__link--active\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { translation } from \"~/_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set number of search results\n *\n * @param el - Search result metadata element\n * @param value - Number of results\n */\nexport function setSearchResultMeta(\n el: HTMLElement, value: number\n): void {\n switch (value) {\n\n /* No results */\n case 0:\n el.textContent = translation(\"search.result.none\")\n break\n\n /* One result */\n case 1:\n el.textContent = translation(\"search.result.one\")\n break\n\n /* Multiple result */\n default:\n el.textContent = translation(\"search.result.other\", value)\n }\n}\n\n/**\n * Reset number of search results\n *\n * @param el - Search result metadata element\n */\nexport function resetSearchResultMeta(\n el: HTMLElement\n): void {\n el.textContent = translation(\"search.result.placeholder\")\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Add an element to the search result list\n *\n * @param el - Search result list element\n * @param child - Search result element\n */\nexport function addToSearchResultList(\n el: HTMLElement, child: Element\n): void {\n el.appendChild(child)\n}\n\n/**\n * Reset search result list\n *\n * @param el - Search result list element\n */\nexport function resetSearchResultList(\n el: HTMLElement\n): void {\n el.innerHTML = \"\"\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set tabs state\n *\n * @param el - Tabs element\n * @param state - Tabs state\n */\nexport function setTabsState(\n el: HTMLElement, state: \"hidden\"\n): void {\n el.setAttribute(\"data-md-state\", state)\n}\n\n/**\n * Reset tabs state\n *\n * @param el - Tabs element\n */\nexport function resetTabsState(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { JSX as JSXInternal } from \"preact\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * HTML attributes\n */\ntype Attributes =\n & JSXInternal.HTMLAttributes\n & JSXInternal.SVGAttributes\n & Record\n\n/**\n * Child element\n */\ntype Child =\n | HTMLElement\n | Text\n | string\n | number\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Append a child node to an element\n *\n * @param el - Element\n * @param child - Child node(s)\n */\nfunction appendChild(el: HTMLElement, child: Child | Child[]): void {\n\n /* Handle primitive types (including raw HTML) */\n if (typeof child === \"string\" || typeof child === \"number\") {\n el.innerHTML += child.toString()\n\n /* Handle nodes */\n } else if (child instanceof Node) {\n el.appendChild(child)\n\n /* Handle nested children */\n } else if (Array.isArray(child)) {\n for (const node of child)\n appendChild(el, node)\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * JSX factory\n *\n * @param tag - HTML tag\n * @param attributes - HTML attributes\n * @param children - Child elements\n *\n * @returns Element\n */\nexport function h(\n tag: string, attributes: Attributes | null, ...children: Child[]\n): HTMLElement {\n const el = document.createElement(tag)\n\n /* Set attributes, if any */\n if (attributes)\n for (const attr of Object.keys(attributes))\n if (typeof attributes[attr] !== \"boolean\")\n el.setAttribute(attr, attributes[attr])\n else if (attributes[attr])\n el.setAttribute(attr, \"\")\n\n /* Append child nodes */\n for (const child of children)\n appendChild(el, child)\n\n /* Return element */\n return el\n}\n\n/* ----------------------------------------------------------------------------\n * Namespace\n * ------------------------------------------------------------------------- */\n\nexport declare namespace h {\n namespace JSX {\n type Element = HTMLElement\n type IntrinsicElements = JSXInternal.IntrinsicElements\n }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Truncate a string after the given number of characters\n *\n * This is not a very reasonable approach, since the summaries kind of suck.\n * It would be better to create something more intelligent, highlighting the\n * search occurrences and making a better summary out of it, but this note was\n * written three years ago, so who knows if we'll ever fix it.\n *\n * @param value - Value to be truncated\n * @param n - Number of characters\n *\n * @returns Truncated value\n */\nexport function truncate(value: string, n: number): string {\n let i = n\n if (value.length > i) {\n while (value[i] !== \" \" && --i > 0) { /* keep eating */ }\n return `${value.substring(0, i)}...`\n }\n return value\n}\n\n/**\n * Round a number for display with repository facts\n *\n * This is a reverse-engineered version of GitHub's weird rounding algorithm\n * for stars, forks and all other numbers. While all numbers below `1,000` are\n * returned as-is, bigger numbers are converted to fixed numbers:\n *\n * - `1,049` => `1k`\n * - `1,050` => `1.1k`\n * - `1,949` => `1.9k`\n * - `1,950` => `2k`\n *\n * @param value - Original value\n *\n * @returns Rounded value\n */\nexport function round(value: number): string {\n if (value > 999) {\n const digits = +((value - 950) % 1000 > 99)\n return `${((value + 0.000001) / 1000).toFixed(digits)}k`\n } else {\n return value.toString()\n }\n}\n\n/**\n * Simple hash function\n *\n * @see https://bit.ly/2wsVjJ4 - Original source\n *\n * @param value - Value to be hashed\n *\n * @returns Hash as 32bit integer\n */\nexport function hash(value: string): number {\n let h = 0\n for (let i = 0, len = value.length; i < len; i++) {\n h = ((h << 5) - h) + value.charCodeAt(i)\n h |= 0 // Convert to 32bit integer\n }\n return h\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport ClipboardJS from \"clipboard\"\nimport { Observable, Subject } from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n finalize,\n map,\n tap,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport { resetFocusable, setFocusable } from \"~/actions\"\nimport {\n Viewport,\n getElementContentSize,\n getElementSize,\n watchMedia\n} from \"~/browser\"\nimport { renderClipboardButton } from \"~/templates\"\n\nimport { Component } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Code block\n */\nexport interface CodeBlock {\n scroll: boolean /* Code block overflows */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Global index for Clipboard.js integration\n */\nlet index = 0\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch code block\n *\n * @param el - Code block element\n * @param options - Options\n *\n * @returns Code block observable\n */\nexport function watchCodeBlock(\n el: HTMLElement, { viewport$ }: WatchOptions\n): Observable {\n return viewport$\n .pipe(\n distinctUntilKeyChanged(\"size\"),\n map(() => {\n const visible = getElementSize(el)\n const content = getElementContentSize(el)\n return {\n scroll: content.width > visible.width\n }\n }),\n distinctUntilKeyChanged(\"scroll\")\n )\n}\n\n/**\n * Mount code block\n *\n * This function ensures that overflowing code blocks are focusable by keyboard,\n * so they can be scrolled without a mouse to improve on accessibility.\n *\n * @param el - Code block element\n * @param options - Options\n *\n * @returns Code block component observable\n */\nexport function mountCodeBlock(\n el: HTMLElement, options: MountOptions\n): Observable> {\n const internal$ = new Subject()\n internal$\n .pipe(\n withLatestFrom(watchMedia(\"(hover)\"))\n )\n .subscribe(([{ scroll }, hover]) => {\n if (scroll && hover)\n setFocusable(el)\n else\n resetFocusable(el)\n })\n\n /* Inject button for Clipboard.js integration */\n if (ClipboardJS.isSupported()) {\n const parent = el.closest(\"pre\")!\n parent.id = `__code_${index++}`\n parent.insertBefore(\n renderClipboardButton(parent.id),\n el\n )\n }\n\n /* Create and return component */\n return watchCodeBlock(el, options)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set focusable property\n *\n * @param el - Element\n * @param value - Tabindex value\n */\nexport function setFocusable(\n el: HTMLElement, value = 0\n): void {\n el.setAttribute(\"tabindex\", value.toString())\n}\n\n/**\n * Reset focusable property\n *\n * @param el - Element\n */\nexport function resetFocusable(\n el: HTMLElement\n): void {\n el.removeAttribute(\"tabindex\")\n}\n\n/**\n * Set scroll lock\n *\n * @param el - Scrollable element\n * @param value - Vertical offset\n */\nexport function setScrollLock(\n el: HTMLElement, value: number\n): void {\n el.setAttribute(\"data-md-state\", \"lock\")\n el.style.top = `-${value}px`\n}\n\n/**\n * Reset scroll lock\n *\n * @param el - Scrollable element\n */\nexport function resetScrollLock(\n el: HTMLElement\n): void {\n const value = -1 * parseInt(el.style.top, 10)\n el.removeAttribute(\"data-md-state\")\n el.style.top = \"\"\n if (value)\n window.scrollTo(0, value)\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { translation } from \"~/_\"\nimport { h } from \"~/utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a 'copy-to-clipboard' button\n *\n * @param id - Unique identifier\n *\n * @returns Element\n */\nexport function renderClipboardButton(id: string) {\n return (\n code`}\n >\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, Subject } from \"rxjs\"\nimport {\n filter,\n finalize,\n map,\n mapTo,\n mergeWith,\n tap\n} from \"rxjs/operators\"\n\nimport { Component } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Details\n */\nexport interface Details {}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n target$: Observable /* Location target observable */\n print$: Observable /* Print observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n target$: Observable /* Location target observable */\n print$: Observable /* Print observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch details\n *\n * @param el - Details element\n * @param options - Options\n *\n * @returns Details observable\n */\nexport function watchDetails(\n el: HTMLDetailsElement, { target$, print$ }: WatchOptions\n): Observable
    {\n return target$\n .pipe(\n map(target => target.closest(\"details:not([open])\")!),\n filter(details => el === details),\n mergeWith(print$),\n mapTo(el)\n )\n}\n\n/**\n * Mount details\n *\n * This function ensures that `details` tags are opened prior to printing, so\n * the whole content of the page is included and on anchor jumps.\n *\n * @param el - Details element\n * @param options - Options\n *\n * @returns Details component observable\n */\nexport function mountDetails(\n el: HTMLDetailsElement, options: MountOptions\n): Observable> {\n const internal$ = new Subject
    ()\n internal$.subscribe(() => {\n el.setAttribute(\"open\", \"\")\n el.scrollIntoView()\n })\n\n /* Create and return component */\n return watchDetails(el, options)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n mapTo({ ref: el })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, of } from \"rxjs\"\n\nimport { createElement, replaceElement } from \"~/browser\"\nimport { renderTable } from \"~/templates\"\n\nimport { Component } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Data table\n */\nexport interface DataTable {}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Sentinel for replacement\n */\nconst sentinel = createElement(\"table\")\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount data table\n *\n * @param el - Data table element\n *\n * @returns Data table component observable\n */\nexport function mountDataTable(\n el: HTMLElement\n): Observable> {\n replaceElement(el, sentinel)\n replaceElement(sentinel, renderTable(el))\n\n /* Create and return component */\n return of({ ref: el })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { h } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a table inside a wrapper to improve scrolling on mobile\n *\n * @param table - Table element\n *\n * @returns Element\n */\nexport function renderTable(table: HTMLElement) {\n return (\n
    \n
    \n {table}\n
    \n
    \n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n animationFrameScheduler,\n merge,\n of\n} from \"rxjs\"\nimport {\n delay,\n finalize,\n map,\n observeOn,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\nimport {\n resetDialogState,\n setDialogMessage,\n setDialogState\n} from \"~/actions\"\n\nimport { Component } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Dialog\n */\nexport interface Dialog {\n message: string /* Dialog message */\n open: boolean /* Dialog is visible */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n alert$: Subject /* Alert subject */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n alert$: Subject /* Alert subject */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch dialog\n *\n * @param _el - Dialog element\n * @param options - Options\n *\n * @returns Dialog observable\n */\nexport function watchDialog(\n _el: HTMLElement, { alert$ }: WatchOptions\n): Observable {\n return alert$\n .pipe(\n switchMap(message => merge(\n of(true),\n of(false).pipe(delay(2000))\n )\n .pipe(\n map(open => ({ message, open }))\n )\n )\n )\n}\n\n/**\n * Mount dialog\n *\n * @param el - Dialog element\n * @param options - Options\n *\n * @returns Dialog component observable\n */\nexport function mountDialog(\n el: HTMLElement, options: MountOptions\n): Observable> {\n const internal$ = new Subject()\n internal$\n .pipe(\n observeOn(animationFrameScheduler)\n )\n .subscribe(({ message, open }) => {\n setDialogMessage(el, message)\n if (open)\n setDialogState(el, \"open\")\n else\n resetDialogState(el)\n })\n\n /* Create and return component */\n return watchDialog(el, options)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set dialog message\n *\n * @param el - Dialog element\n * @param value - Dialog message\n */\nexport function setDialogMessage(\n el: HTMLElement, value: string\n): void {\n el.firstElementChild!.innerHTML = value\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Set dialog state\n *\n * @param el - Dialog element\n * @param state - Dialog state\n */\nexport function setDialogState(\n el: HTMLElement, state: \"open\"\n): void {\n el.setAttribute(\"data-md-state\", state)\n}\n\n/**\n * Reset dialog state\n *\n * @param el - Dialog element\n */\nexport function resetDialogState(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n NEVER,\n Observable,\n Subject,\n animationFrameScheduler,\n combineLatest,\n defer,\n of\n} from \"rxjs\"\nimport {\n bufferCount,\n combineLatestWith,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n filter,\n map,\n observeOn,\n shareReplay,\n startWith,\n switchMap\n} from \"rxjs/operators\"\n\nimport { feature } from \"~/_\"\nimport { resetHeaderState, setHeaderState } from \"~/actions\"\nimport {\n Viewport,\n watchElementSize,\n watchToggle\n} from \"~/browser\"\n\nimport { Component } from \"../../_\"\nimport { Main } from \"../../main\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Header\n */\nexport interface Header {\n height: number /* Header visible height */\n sticky: boolean /* Header stickyness */\n hidden: boolean /* User scrolled past threshold */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n main$: Observable
    /* Main area observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Compute whether the header is hidden\n *\n * If the user scrolls past a certain threshold, the header can be hidden when\n * scrolling down, and shown when scrolling up.\n *\n * @param options - Options\n *\n * @returns Toggle observable\n */\nfunction isHidden({ viewport$ }: WatchOptions): Observable {\n if (!feature(\"header.autohide\"))\n return of(false)\n\n /* Compute direction and turning point */\n const direction$ = viewport$\n .pipe(\n map(({ offset: { y } }) => y),\n bufferCount(2, 1),\n map(([a, b]) => [a < b, b] as const),\n distinctUntilKeyChanged(0)\n )\n\n /* Compute whether header should be hidden */\n const hidden$ = combineLatest([viewport$, direction$])\n .pipe(\n filter(([{ offset }, [, y]]) => Math.abs(y - offset.y) > 100),\n map(([, [direction]]) => direction),\n distinctUntilChanged(),\n )\n\n /* Compute threshold for autohiding */\n const search$ = watchToggle(\"search\")\n return combineLatest([viewport$, search$])\n .pipe(\n map(([{ offset }, search]) => offset.y > 400 && !search),\n distinctUntilChanged(),\n switchMap(active => active ? hidden$ : NEVER),\n startWith(false)\n )\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch header\n *\n * @param el - Header element\n * @param options - Options\n *\n * @returns Header observable\n */\nexport function watchHeader(\n el: HTMLElement, options: WatchOptions\n): Observable
    {\n return defer(() => {\n const styles = getComputedStyle(el)\n return of(\n styles.position === \"sticky\" ||\n styles.position === \"-webkit-sticky\"\n )\n })\n .pipe(\n combineLatestWith(watchElementSize(el), isHidden(options)),\n map(([sticky, { height }, hidden]) => ({\n height: sticky ? height : 0,\n sticky,\n hidden\n })),\n distinctUntilChanged((a, b) => (\n a.sticky === b.sticky &&\n a.height === b.height &&\n a.hidden === b.hidden\n )),\n shareReplay(1)\n )\n}\n\n/**\n * Mount header\n *\n * The header must be connected to the main area observable outside of the\n * operator function, as the header will persist in-between document switches\n * while the main area is replaced. However, the header observable must be\n * passed to this function, so we connect both via a long-living subject.\n *\n * @param el - Header element\n * @param options - Options\n *\n * @returns Header component observable\n */\nexport function mountHeader(\n el: HTMLElement, { header$, main$ }: MountOptions\n): Observable> {\n const internal$ = new Subject
    ()\n internal$\n .pipe(\n distinctUntilKeyChanged(\"active\"),\n combineLatestWith(header$),\n observeOn(animationFrameScheduler)\n )\n .subscribe(([{ active }, { hidden }]) => {\n if (active)\n setHeaderState(el, hidden ? \"hidden\" : \"shadow\")\n else\n resetHeaderState(el)\n })\n\n /* Connect to long-living subject and return component */\n main$.subscribe(main => internal$.next(main))\n return header$\n .pipe(\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { NEVER, Observable, Subject, animationFrameScheduler } from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n finalize,\n map,\n observeOn,\n tap\n} from \"rxjs/operators\"\n\nimport {\n resetHeaderTitleState,\n setHeaderTitleState\n} from \"~/actions\"\nimport {\n Viewport,\n getElement,\n getElementSize,\n watchViewportAt\n} from \"~/browser\"\n\nimport { Component } from \"../../_\"\nimport { Header } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Header\n */\nexport interface HeaderTitle {\n active: boolean /* User scrolled past first headline */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch header title\n *\n * @param el - Heading element\n * @param options - Options\n *\n * @returns Header title observable\n */\nexport function watchHeaderTitle(\n el: HTMLHeadingElement, { viewport$, header$ }: WatchOptions\n): Observable {\n return watchViewportAt(el, { header$, viewport$ })\n .pipe(\n map(({ offset: { y } }) => {\n const { height } = getElementSize(el)\n return {\n active: y >= height\n }\n }),\n distinctUntilKeyChanged(\"active\")\n )\n}\n\n/**\n * Mount header title\n *\n * @param el - Header title element\n * @param options - Options\n *\n * @returns Header title component observable\n */\nexport function mountHeaderTitle(\n el: HTMLElement, options: MountOptions\n): Observable> {\n const internal$ = new Subject()\n internal$\n .pipe(\n observeOn(animationFrameScheduler),\n )\n .subscribe(({ active }) => {\n if (active)\n setHeaderTitleState(el, \"active\")\n else\n resetHeaderTitleState(el)\n })\n\n /* Obtain headline, if any */\n const headline = getElement(\"article h1\")\n if (typeof headline === \"undefined\")\n return NEVER\n\n /* Create and return component */\n return watchHeaderTitle(headline, options)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set header title state\n *\n * @param el - Header title element\n * @param state - Header title state\n */\nexport function setHeaderTitleState(\n el: HTMLElement, state: \"active\"\n): void {\n el.setAttribute(\"data-md-state\", state)\n}\n\n/**\n * Reset header title state\n *\n * @param el - Header title element\n */\nexport function resetHeaderTitleState(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SearchIndex, SearchResult } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search message type\n */\nexport const enum SearchMessageType {\n SETUP, /* Search index setup */\n READY, /* Search index ready */\n QUERY, /* Search query */\n RESULT /* Search results */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * A message containing the data necessary to setup the search index\n */\nexport interface SearchSetupMessage {\n type: SearchMessageType.SETUP /* Message type */\n data: SearchIndex /* Message data */\n}\n\n/**\n * A message indicating the search index is ready\n */\nexport interface SearchReadyMessage {\n type: SearchMessageType.READY /* Message type */\n}\n\n/**\n * A message containing a search query\n */\nexport interface SearchQueryMessage {\n type: SearchMessageType.QUERY /* Message type */\n data: string /* Message data */\n}\n\n/**\n * A message containing results for a search query\n */\nexport interface SearchResultMessage {\n type: SearchMessageType.RESULT /* Message type */\n data: SearchResult[] /* Message data */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * A message exchanged with the search worker\n */\nexport type SearchMessage =\n | SearchSetupMessage\n | SearchReadyMessage\n | SearchQueryMessage\n | SearchResultMessage\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Type guard for search setup messages\n *\n * @param message - Search worker message\n *\n * @returns Test result\n */\nexport function isSearchSetupMessage(\n message: SearchMessage\n): message is SearchSetupMessage {\n return message.type === SearchMessageType.SETUP\n}\n\n/**\n * Type guard for search ready messages\n *\n * @param message - Search worker message\n *\n * @returns Test result\n */\nexport function isSearchReadyMessage(\n message: SearchMessage\n): message is SearchReadyMessage {\n return message.type === SearchMessageType.READY\n}\n\n/**\n * Type guard for search query messages\n *\n * @param message - Search worker message\n *\n * @returns Test result\n */\nexport function isSearchQueryMessage(\n message: SearchMessage\n): message is SearchQueryMessage {\n return message.type === SearchMessageType.QUERY\n}\n\n/**\n * Type guard for search result messages\n *\n * @param message - Search worker message\n *\n * @returns Test result\n */\nexport function isSearchResultMessage(\n message: SearchMessage\n): message is SearchResultMessage {\n return message.type === SearchMessageType.RESULT\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search transformation function\n *\n * @param value - Query value\n *\n * @returns Transformed query value\n */\nexport type SearchTransformFn = (value: string) => string\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Default transformation function\n *\n * 1. Search for terms in quotation marks and prepend a `+` modifier to denote\n * that the resulting document must contain all terms, converting the query\n * to an `AND` query (as opposed to the default `OR` behavior). While users\n * may expect terms enclosed in quotation marks to map to span queries, i.e.\n * for which order is important, `lunr` doesn't support them, so the best\n * we can do is to convert the terms to an `AND` query.\n *\n * 2. Replace control characters which are not located at the beginning of the\n * query or preceded by white space, or are not followed by a non-whitespace\n * character or are at the end of the query string. Furthermore, filter\n * unmatched quotation marks.\n *\n * 3. Trim excess whitespace from left and right.\n *\n * @param query - Query value\n *\n * @returns Transformed query value\n */\nexport function defaultTransform(query: string): string {\n return query\n .split(/\"([^\"]+)\"/g) /* => 1 */\n .map((terms, index) => index & 1\n ? terms.replace(/^\\b|^(?![^\\x00-\\x7F]|$)|\\s+/g, \" +\")\n : terms\n )\n .join(\"\")\n .replace(/\"|(?:^|\\s+)[*+\\-:^~]+(?=\\s+|$)/g, \"\") /* => 2 */\n .trim() /* => 3 */\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A RTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { ObservableInput, Subject, from } from \"rxjs\"\nimport { map, share } from \"rxjs/operators\"\n\nimport { configuration, translation } from \"~/_\"\nimport { WorkerHandler, watchWorker } from \"~/browser\"\n\nimport { SearchIndex, SearchIndexPipeline } from \"../../_\"\nimport {\n SearchMessage,\n SearchMessageType,\n SearchSetupMessage,\n isSearchResultMessage\n} from \"../message\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search worker\n */\nexport type SearchWorker = WorkerHandler\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up search index\n *\n * @param data - Search index\n *\n * @returns Search index\n */\nfunction setupSearchIndex(\n { config, docs, index }: SearchIndex\n): SearchIndex {\n\n /* Override default language with value from translation */\n if (config.lang.length === 1 && config.lang[0] === \"en\")\n config.lang = [\n translation(\"search.config.lang\")\n ]\n\n /* Override default separator with value from translation */\n if (config.separator === \"[\\\\s\\\\-]+\")\n config.separator = translation(\"search.config.separator\")\n\n /* Set pipeline from translation */\n const pipeline = translation(\"search.config.pipeline\")\n .split(/\\s*,\\s*/)\n .filter(Boolean) as SearchIndexPipeline\n\n /* Return search index after defaulting */\n return { config, docs, index, pipeline }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up search worker\n *\n * This function will create a web worker to set up and query the search index\n * which is done using `lunr`. The index must be passed as an observable to\n * enable hacks like _localsearch_ via search index embedding as JSON.\n *\n * @param url - Worker URL\n * @param index - Search index observable input\n *\n * @returns Search worker\n */\nexport function setupSearchWorker(\n url: string, index: ObservableInput\n): SearchWorker {\n const config = configuration()\n const worker = new Worker(url)\n\n /* Create communication channels and resolve relative links */\n const tx$ = new Subject()\n const rx$ = watchWorker(worker, { tx$ })\n .pipe(\n map(message => {\n if (isSearchResultMessage(message)) {\n for (const result of message.data)\n for (const document of result)\n document.location = `${config.base}/${document.location}`\n }\n return message\n }),\n share()\n )\n\n /* Set up search index */\n from(index)\n .pipe(\n map(data => ({\n type: SearchMessageType.SETUP,\n data: setupSearchIndex(data)\n }))\n )\n .subscribe(tx$.next.bind(tx$))\n\n /* Return search worker */\n return { tx$, rx$ }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, Subject, fromEvent } from \"rxjs\"\nimport {\n map,\n share,\n switchMapTo,\n tap,\n throttle\n} from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Worker message\n */\nexport interface WorkerMessage {\n type: unknown /* Message type */\n data?: unknown /* Message data */\n}\n\n/**\n * Worker handler\n *\n * @template T - Message type\n */\nexport interface WorkerHandler<\n T extends WorkerMessage\n> {\n tx$: Subject /* Message transmission subject */\n rx$: Observable /* Message receive observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n *\n * @template T - Worker message type\n */\ninterface WatchOptions {\n tx$: Observable /* Message transmission observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch a web worker\n *\n * This function returns an observable that will send all values emitted by the\n * message observable to the web worker. Web worker communication is expected\n * to be bidirectional (request-response) and synchronous. Messages that are\n * emitted during a pending request are throttled, the last one is emitted.\n *\n * @param worker - Web worker\n * @param options - Options\n *\n * @returns Worker message observable\n */\nexport function watchWorker(\n worker: Worker, { tx$ }: WatchOptions\n): Observable {\n\n /* Intercept messages from worker-like objects */\n const rx$ = fromEvent(worker, \"message\")\n .pipe(\n map(({ data }) => data)\n )\n\n /* Send and receive messages, return hot observable */\n return tx$\n .pipe(\n throttle(() => rx$, { leading: true, trailing: true }),\n tap(message => worker.postMessage(message)),\n switchMapTo(rx$),\n share()\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n combineLatest,\n fromEvent,\n merge\n} from \"rxjs\"\nimport {\n delay,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n finalize,\n map,\n startWith,\n takeLast,\n takeUntil,\n tap\n} from \"rxjs/operators\"\n\nimport {\n resetSearchQueryPlaceholder,\n setSearchQueryPlaceholder\n} from \"~/actions\"\nimport {\n setElementFocus,\n setToggle,\n watchElementFocus\n} from \"~/browser\"\nimport {\n SearchMessageType,\n SearchQueryMessage,\n SearchWorker,\n defaultTransform\n} from \"~/integrations\"\n\nimport { Component } from \"../../_\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search query\n */\nexport interface SearchQuery {\n value: string /* Query value */\n focus: boolean /* Query focus */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch search query\n *\n * Note that the focus event which triggers re-reading the current query value\n * is delayed by `1ms` so the input's empty state is allowed to propagate.\n *\n * @param el - Search query element\n *\n * @returns Search query observable\n */\nexport function watchSearchQuery(\n el: HTMLInputElement\n): Observable {\n const fn = __search?.transform || defaultTransform\n\n /* Intercept focus and input events */\n const focus$ = watchElementFocus(el)\n const value$ = merge(\n fromEvent(el, \"keyup\"),\n fromEvent(el, \"focus\").pipe(delay(1))\n )\n .pipe(\n map(() => fn(el.value)),\n startWith(fn(el.value)),\n distinctUntilChanged()\n )\n\n /* Combine into single observable */\n return combineLatest([value$, focus$])\n .pipe(\n map(([value, focus]) => ({ value, focus }))\n )\n}\n\n/**\n * Mount search query\n *\n * @param el - Search query element\n * @param worker - Search worker\n *\n * @returns Search query component observable\n */\nexport function mountSearchQuery(\n el: HTMLInputElement, { tx$ }: SearchWorker\n): Observable> {\n const internal$ = new Subject()\n\n /* Handle value changes */\n internal$\n .pipe(\n distinctUntilKeyChanged(\"value\"),\n map(({ value }): SearchQueryMessage => ({\n type: SearchMessageType.QUERY,\n data: value\n }))\n )\n .subscribe(tx$.next.bind(tx$))\n\n /* Handle focus changes */\n internal$\n .pipe(\n distinctUntilKeyChanged(\"focus\")\n )\n .subscribe(({ focus }) => {\n if (focus) {\n setToggle(\"search\", focus)\n setSearchQueryPlaceholder(el, \"\")\n } else {\n resetSearchQueryPlaceholder(el)\n }\n })\n\n /* Handle reset */\n fromEvent(el.form!, \"reset\")\n .pipe(\n takeUntil(internal$.pipe(takeLast(1)))\n )\n .subscribe(() => setElementFocus(el))\n\n /* Create and return component */\n return watchSearchQuery(el)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { translation } from \"~/_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set search query placeholder\n *\n * @param el - Search query element\n * @param value - Placeholder\n */\nexport function setSearchQueryPlaceholder(\n el: HTMLInputElement, value: string\n): void {\n el.placeholder = value\n}\n\n/**\n * Reset search query placeholder\n *\n * @param el - Search query element\n */\nexport function resetSearchQueryPlaceholder(\n el: HTMLInputElement\n): void {\n el.placeholder = translation(\"search.placeholder\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, Subject } from \"rxjs\"\nimport {\n filter,\n finalize,\n map,\n startWith,\n tap,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport {\n addToSearchResultList,\n resetSearchResultList,\n resetSearchResultMeta,\n setSearchResultMeta\n} from \"~/actions\"\nimport { getElementOrThrow } from \"~/browser\"\nimport {\n SearchResult as SearchResultData,\n SearchWorker,\n isSearchResultMessage\n} from \"~/integrations\"\nimport { renderSearchResult } from \"~/templates\"\n\nimport { Component } from \"../../_\"\nimport { SearchQuery } from \"../query\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search result\n */\nexport interface SearchResult {\n data: SearchResultData[] /* Search result data */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n query$: Observable /* Search query observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search result list\n *\n * @param el - Search result list element\n * @param worker - Search worker\n * @param options - Options\n *\n * @returns Search result list component observable\n */\nexport function mountSearchResult(\n el: HTMLElement, { rx$ }: SearchWorker, { query$ }: MountOptions\n): Observable> {\n const internal$ = new Subject()\n\n /* Update search result metadata */\n const meta = getElementOrThrow(\":scope > :first-child\", el)\n internal$\n .pipe(\n withLatestFrom(query$)\n )\n .subscribe(([{ data }, { value }]) => {\n if (value)\n setSearchResultMeta(meta, data.length)\n else\n resetSearchResultMeta(meta)\n })\n\n /* Update search result list */\n const list = getElementOrThrow(\":scope > :last-child\", el)\n internal$\n .subscribe(({ data }) => {\n resetSearchResultList(list)\n\n /* Compute thresholds and search results */\n const thresholds = [...data.map(([best]) => best.score), 0]\n for (let index = 0; index < data.length; index++)\n addToSearchResultList(list, renderSearchResult(\n data[index++], thresholds[index]\n ))\n })\n\n /* Filter search result list */\n const result$ = rx$\n .pipe(\n filter(isSearchResultMessage),\n map(({ data }) => ({ data })),\n startWith({ data: [] })\n )\n\n /* Create and return component */\n return result$\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, merge } from \"rxjs\"\nimport { filter, sample, take } from \"rxjs/operators\"\n\nimport { configuration } from \"~/_\"\nimport {\n Keyboard,\n getActiveElement,\n getElementOrThrow,\n getElements,\n requestJSON,\n setElementFocus,\n setElementSelection,\n setToggle\n} from \"~/browser\"\nimport {\n SearchIndex,\n isSearchQueryMessage,\n isSearchReadyMessage,\n setupSearchWorker\n} from \"~/integrations\"\n\nimport { Component } from \"../../_\"\nimport { SearchQuery, mountSearchQuery } from \"../query\"\nimport { SearchResult, mountSearchResult } from \"../result\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Search\n */\nexport type Search =\n | SearchQuery\n | SearchResult\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n keyboard$: Observable /* Keyboard observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch search index\n *\n * @param url - Search index URL\n *\n * @returns Promise resolving with search index\n */\nfunction fetchSearchIndex(url: string) {\n return __search?.index || requestJSON(url)\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount search\n *\n * @param el - Search element\n * @param options - Options\n *\n * @returns Search component observable\n */\nexport function mountSearch(\n el: HTMLElement, { keyboard$ }: MountOptions\n): Observable> {\n const config = configuration()\n const worker = setupSearchWorker(config.search, fetchSearchIndex(\n `${config.base}/search/search_index.json`\n ))\n\n /* Retrieve elements */\n const query = getElementOrThrow(\"[data-md-component=search-query]\", el)\n const result = getElementOrThrow(\"[data-md-component=search-result]\", el)\n\n /* Re-emit query when search is ready */\n const { tx$, rx$ } = worker\n tx$\n .pipe(\n filter(isSearchQueryMessage),\n sample(rx$.pipe(filter(isSearchReadyMessage))),\n take(1)\n )\n .subscribe(tx$.next.bind(tx$))\n\n /* Set up search keyboard handlers */\n keyboard$\n .pipe(\n filter(({ mode }) => mode === \"search\")\n )\n .subscribe(key => {\n const active = getActiveElement()\n switch (key.type) {\n\n /* Enter: prevent form submission */\n case \"Enter\":\n if (active === query)\n key.claim()\n break\n\n /* Escape or Tab: close search */\n case \"Escape\":\n case \"Tab\":\n setToggle(\"search\", false)\n setElementFocus(query, false)\n break\n\n /* Vertical arrows: select previous or next search result */\n case \"ArrowUp\":\n case \"ArrowDown\":\n if (typeof active === \"undefined\") {\n setElementFocus(query)\n } else {\n const els = [query, ...getElements(\n \":not(details) > [href], summary, details[open] [href]\",\n result\n )]\n const i = Math.max(0, (\n Math.max(0, els.indexOf(active)) + els.length + (\n key.type === \"ArrowUp\" ? -1 : +1\n )\n ) % els.length)\n setElementFocus(els[i])\n }\n\n /* Prevent scrolling of page */\n key.claim()\n break\n\n /* All other keys: hand to search query */\n default:\n if (query !== getActiveElement())\n setElementFocus(query)\n }\n })\n\n /* Set up global keyboard handlers */\n keyboard$\n .pipe(\n filter(({ mode }) => mode === \"global\"),\n )\n .subscribe(key => {\n switch (key.type) {\n\n /* Open search and select query */\n case \"f\":\n case \"s\":\n case \"/\":\n setElementFocus(query)\n setElementSelection(query)\n key.claim()\n break\n }\n })\n\n /* Create and return component */\n const query$ = mountSearchQuery(query as HTMLInputElement, worker)\n return merge(\n query$,\n mountSearchResult(result, worker, { query$ })\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set element text selection\n *\n * @param el - Element\n */\nexport function setElementSelection(\n el: HTMLElement\n): void {\n if (el instanceof HTMLInputElement)\n el.select()\n else\n throw new Error(\"Not implemented\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n animationFrameScheduler,\n combineLatest\n} from \"rxjs\"\nimport {\n distinctUntilChanged,\n finalize,\n map,\n observeOn,\n tap,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport {\n resetSidebarHeight,\n resetSidebarOffset,\n setSidebarHeight,\n setSidebarOffset\n} from \"~/actions\"\nimport { Viewport } from \"~/browser\"\n\nimport { Component } from \"../_\"\nimport { Header } from \"../header\"\nimport { Main } from \"../main\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Sidebar\n */\nexport interface Sidebar {\n height: number /* Sidebar height */\n locked: boolean /* User scrolled past header */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n main$: Observable
    /* Main area observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n main$: Observable
    /* Main area observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch sidebar\n *\n * This function returns an observable that computes the visual parameters of\n * the sidebar which depends on the vertical viewport offset, as well as the\n * height of the main area. When the page is scrolled beyond the header, the\n * sidebar is locked and fills the remaining space.\n *\n * @param el - Sidebar element\n * @param options - Options\n *\n * @returns Sidebar observable\n */\nexport function watchSidebar(\n el: HTMLElement, { viewport$, main$ }: WatchOptions\n): Observable {\n const adjust =\n el.parentElement!.offsetTop -\n el.parentElement!.parentElement!.offsetTop\n\n /* Compute the sidebar's available height and if it should be locked */\n return combineLatest([main$, viewport$])\n .pipe(\n map(([{ offset, height }, { offset: { y } }]) => {\n height = height\n + Math.min(adjust, Math.max(0, y - offset))\n - adjust\n return {\n height,\n locked: y >= offset + adjust\n }\n }),\n distinctUntilChanged((a, b) => (\n a.height === b.height &&\n a.locked === b.locked\n ))\n )\n}\n\n/**\n * Mount sidebar\n *\n * @param el - Sidebar element\n * @param options - Options\n *\n * @returns Sidebar component observable\n */\nexport function mountSidebar(\n el: HTMLElement, { header$, ...options }: MountOptions\n): Observable> {\n const internal$ = new Subject()\n internal$\n .pipe(\n observeOn(animationFrameScheduler),\n withLatestFrom(header$)\n )\n .subscribe({\n\n /* Update height and offset */\n next([{ height }, { height: offset }]) {\n setSidebarHeight(el, height)\n setSidebarOffset(el, offset)\n },\n\n /* Reset on complete */\n complete() {\n resetSidebarOffset(el)\n resetSidebarHeight(el)\n }\n })\n\n /* Create and return component */\n return watchSidebar(el, options)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set sidebar offset\n *\n * @param el - Sidebar element\n * @param value - Sidebar offset\n */\nexport function setSidebarOffset(\n el: HTMLElement, value: number\n): void {\n el.style.top = `${value}px`\n}\n\n/**\n * Reset sidebar offset\n *\n * @param el - Sidebar element\n */\nexport function resetSidebarOffset(\n el: HTMLElement\n): void {\n el.style.top = \"\"\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Set sidebar height\n *\n * This function doesn't set the height of the actual sidebar, but of its first\n * child – the `.md-sidebar__scrollwrap` element in order to mitigiate jittery\n * sidebars when the footer is scrolled into view. At some point we switched\n * from `absolute` / `fixed` positioning to `sticky` positioning, significantly\n * reducing jitter in some browsers (respectively Firefox and Safari) when\n * scrolling from the top. However, top-aligned sticky positioning means that\n * the sidebar snaps to the bottom when the end of the container is reached.\n * This is what leads to the mentioned jitter, as the sidebar's height may be\n * updated too slowly.\n *\n * This behaviour can be mitigiated by setting the height of the sidebar to `0`\n * while preserving the padding, and the height on its first element.\n *\n * @param el - Sidebar element\n * @param value - Sidebar height\n */\nexport function setSidebarHeight(\n el: HTMLElement, value: number\n): void {\n const scrollwrap = el.firstElementChild as HTMLElement\n scrollwrap.style.height = `${value - 2 * scrollwrap.offsetTop}px`\n}\n\n/**\n * Reset sidebar height\n *\n * @param el - Sidebar element\n */\nexport function resetSidebarHeight(\n el: HTMLElement\n): void {\n const scrollwrap = el.firstElementChild as HTMLElement\n scrollwrap.style.height = \"\"\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { NEVER, Observable } from \"rxjs\"\n\nimport { fetchSourceFactsFromGitHub } from \"../github\"\nimport { fetchSourceFactsFromGitLab } from \"../gitlab\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Repository facts\n */\nexport type SourceFacts = string[]\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch repository facts\n *\n * @param url - Repository URL\n *\n * @returns Repository facts observable\n */\nexport function fetchSourceFacts(\n url: string\n): Observable {\n const [type] = url.match(/(git(?:hub|lab))/i) || []\n switch (type.toLowerCase()) {\n\n /* GitHub repository */\n case \"github\":\n const [, user, repo] = url.match(/^.+github\\.com\\/([^/]+)\\/?([^/]+)?/i)!\n return fetchSourceFactsFromGitHub(user, repo)\n\n /* GitLab repository */\n case \"gitlab\":\n const [, base, slug] = url.match(/^.+?([^/]*gitlab[^/]+)\\/(.+?)\\/?$/i)!\n return fetchSourceFactsFromGitLab(base, slug)\n\n /* Everything else */\n default:\n return NEVER\n }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Repo, User } from \"github-types\"\nimport { Observable } from \"rxjs\"\nimport { defaultIfEmpty, map } from \"rxjs/operators\"\n\nimport { requestJSON } from \"~/browser\"\nimport { round } from \"~/utilities\"\n\nimport { SourceFacts } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch GitHub repository facts\n *\n * @param user - GitHub user\n * @param repo - GitHub repository\n *\n * @returns Repository facts observable\n */\nexport function fetchSourceFactsFromGitHub(\n user: string, repo?: string\n): Observable {\n const url = typeof repo !== \"undefined\"\n ? `https://api.github.com/repos/${user}/${repo}`\n : `https://api.github.com/users/${user}`\n return requestJSON(url)\n .pipe(\n map(data => {\n\n /* GitHub repository */\n if (typeof repo !== \"undefined\") {\n const { stargazers_count, forks_count }: Repo = data\n return [\n `${round(stargazers_count!)} Stars`,\n `${round(forks_count!)} Forks`\n ]\n\n /* GitHub user/organization */\n } else {\n const { public_repos }: User = data\n return [\n `${round(public_repos!)} Repositories`\n ]\n }\n }),\n defaultIfEmpty([])\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { ProjectSchema } from \"gitlab\"\nimport { Observable } from \"rxjs\"\nimport { defaultIfEmpty, map } from \"rxjs/operators\"\n\nimport { requestJSON } from \"~/browser\"\nimport { round } from \"~/utilities\"\n\nimport { SourceFacts } from \"../_\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Fetch GitLab repository facts\n *\n * @param base - GitLab base\n * @param project - GitLab project\n *\n * @returns Repository facts observable\n */\nexport function fetchSourceFactsFromGitLab(\n base: string, project: string\n): Observable {\n const url = `https://${base}/api/v4/projects/${encodeURIComponent(project)}`\n return requestJSON(url)\n .pipe(\n map(({ star_count, forks_count }) => ([\n `${round(star_count)} Stars`,\n `${round(forks_count)} Forks`\n ])),\n defaultIfEmpty([])\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { NEVER, Observable, Subject, defer, of } from \"rxjs\"\nimport {\n catchError,\n filter,\n finalize,\n map,\n shareReplay,\n tap\n} from \"rxjs/operators\"\n\nimport { setSourceFacts, setSourceState } from \"~/actions\"\nimport { renderSourceFacts } from \"~/templates\"\nimport { hash } from \"~/utilities\"\n\nimport { Component } from \"../../_\"\nimport { SourceFacts, fetchSourceFacts } from \"../facts\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Repository information\n */\nexport interface Source {\n facts: SourceFacts /* Repository facts */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Repository facts observable\n */\nlet fetch$: Observable\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch repository information\n *\n * @param el - Repository information element\n *\n * @returns Repository information observable\n */\nexport function watchSource(\n el: HTMLAnchorElement\n): Observable {\n const digest = hash(el.href).toString()\n\n /* Fetch repository facts once */\n return fetch$ ||= defer(() => {\n const data = sessionStorage.getItem(digest)\n if (data) {\n return of(JSON.parse(data))\n } else {\n const value$ = fetchSourceFacts(el.href)\n value$.subscribe(value => {\n try {\n sessionStorage.setItem(digest, JSON.stringify(value))\n } catch (err) {\n /* Uncritical, just swallow */\n }\n })\n\n /* Return value */\n return value$\n }\n })\n .pipe(\n catchError(() => NEVER),\n filter(facts => facts.length > 0),\n map(facts => ({ facts })),\n shareReplay(1)\n )\n}\n\n/**\n * Mount repository information\n *\n * @param el - Repository information element\n *\n * @returns Repository information component observable\n */\nexport function mountSource(\n el: HTMLAnchorElement\n): Observable> {\n const internal$ = new Subject()\n internal$.subscribe(({ facts }) => {\n setSourceFacts(el, renderSourceFacts(facts))\n setSourceState(el, \"done\")\n })\n\n /* Create and return component */\n return watchSource(el)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set repository facts\n *\n * @param el - Repository element\n * @param child - Repository facts element\n */\nexport function setSourceFacts(\n el: HTMLElement, child: Element\n): void {\n el.lastElementChild!.appendChild(child)\n}\n\n/**\n * Set repository state\n *\n * @param el - Repository element\n * @param state - Repository state\n */\nexport function setSourceState(\n el: HTMLElement, state: \"done\"\n): void {\n el.lastElementChild!.setAttribute(\"data-md-state\", state)\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { SourceFacts } from \"~/components\"\nimport { h } from \"~/utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render repository facts\n *\n * @param facts - Repository facts\n *\n * @returns Element\n */\nexport function renderSourceFacts(facts: SourceFacts) {\n return (\n
      \n {facts.map(fact => (\n
    • {fact}
    • \n ))}\n
    \n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, Subject, animationFrameScheduler } from \"rxjs\"\nimport {\n distinctUntilKeyChanged,\n finalize,\n map,\n observeOn,\n tap\n} from \"rxjs/operators\"\n\nimport { resetTabsState, setTabsState } from \"~/actions\"\nimport { Viewport, watchViewportAt } from \"~/browser\"\n\nimport { Component } from \"../_\"\nimport { Header } from \"../header\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Navigation tabs\n */\nexport interface Tabs {\n hidden: boolean /* User scrolled past tabs */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch navigation tabs\n *\n * @param el - Navigation tabs element\n * @param options - Options\n *\n * @returns Navigation tabs observable\n */\nexport function watchTabs(\n el: HTMLElement, { viewport$, header$ }: WatchOptions\n): Observable {\n return watchViewportAt(el, { header$, viewport$ })\n .pipe(\n map(({ offset: { y } }) => {\n return {\n hidden: y >= 10\n }\n }),\n distinctUntilKeyChanged(\"hidden\")\n )\n}\n\n/**\n * Mount navigation tabs\n *\n * @param el - Navigation tabs element\n * @param options - Options\n *\n * @returns Navigation tabs component observable\n */\nexport function mountTabs(\n el: HTMLElement, options: MountOptions\n): Observable> {\n const internal$ = new Subject()\n internal$\n .pipe(\n observeOn(animationFrameScheduler)\n )\n .subscribe({\n\n /* Update state */\n next({ hidden }) {\n if (hidden)\n setTabsState(el, \"hidden\")\n else\n resetTabsState(el)\n },\n\n /* Reset on complete */\n complete() {\n resetTabsState(el)\n }\n })\n\n /* Create and return component */\n return watchTabs(el, options)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n Subject,\n animationFrameScheduler,\n combineLatest\n} from \"rxjs\"\nimport {\n bufferCount,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n finalize,\n map,\n observeOn,\n scan,\n startWith,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\nimport {\n resetAnchorActive,\n resetAnchorState,\n setAnchorActive,\n setAnchorState\n} from \"~/actions\"\nimport {\n Viewport,\n getElement,\n getElements,\n watchElementSize\n} from \"~/browser\"\n\nimport { Component } from \"../_\"\nimport { Header } from \"../header\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Table of contents\n */\nexport interface TableOfContents {\n prev: HTMLAnchorElement[][] /* Anchors (previous) */\n next: HTMLAnchorElement[][] /* Anchors (next) */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/**\n * Mount options\n */\ninterface MountOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch table of contents\n *\n * This is effectively a scroll spy implementation which will account for the\n * fixed header and automatically re-calculate anchor offsets when the viewport\n * is resized. The returned observable will only emit if the table of contents\n * needs to be repainted.\n *\n * This implementation tracks an anchor element's entire path starting from its\n * level up to the top-most anchor element, e.g. `[h3, h2, h1]`. Although the\n * Material theme currently doesn't make use of this information, it enables\n * the styling of the entire hierarchy through customization.\n *\n * Note that the current anchor is the last item of the `prev` anchor list.\n *\n * @param anchors - Anchor elements\n * @param options - Options\n *\n * @returns Table of contents observable\n */\nexport function watchTableOfContents(\n anchors: HTMLAnchorElement[], { viewport$, header$ }: WatchOptions\n): Observable {\n const table = new Map()\n for (const anchor of anchors) {\n const id = decodeURIComponent(anchor.hash.substring(1))\n const target = getElement(`[id=\"${id}\"]`)\n if (typeof target !== \"undefined\")\n table.set(anchor, target)\n }\n\n /* Compute necessary adjustment for header */\n const adjust$ = header$\n .pipe(\n map(header => 24 + header.height)\n )\n\n /* Compute partition of previous and next anchors */\n const partition$ = watchElementSize(document.body)\n .pipe(\n distinctUntilKeyChanged(\"height\"),\n\n /* Build index to map anchor paths to vertical offsets */\n map(() => {\n let path: HTMLAnchorElement[] = []\n return [...table].reduce((index, [anchor, target]) => {\n while (path.length) {\n const last = table.get(path[path.length - 1])!\n if (last.tagName >= target.tagName) {\n path.pop()\n } else {\n break\n }\n }\n\n /* If the current anchor is hidden, continue with its parent */\n let offset = target.offsetTop\n while (!offset && target.parentElement) {\n target = target.parentElement\n offset = target.offsetTop\n }\n\n /* Map reversed anchor path to vertical offset */\n return index.set(\n [...path = [...path, anchor]].reverse(),\n offset\n )\n }, new Map())\n }),\n\n /* Re-compute partition when viewport offset changes */\n switchMap(index => combineLatest([adjust$, viewport$])\n .pipe(\n scan(([prev, next], [adjust, { offset: { y } }]) => {\n\n /* Look forward */\n while (next.length) {\n const [, offset] = next[0]\n if (offset - adjust < y) {\n prev = [...prev, next.shift()!]\n } else {\n break\n }\n }\n\n /* Look backward */\n while (prev.length) {\n const [, offset] = prev[prev.length - 1]\n if (offset - adjust >= y) {\n next = [prev.pop()!, ...next]\n } else {\n break\n }\n }\n\n /* Return partition */\n return [prev, next]\n }, [[], [...index]]),\n distinctUntilChanged((a, b) => (\n a[0] === b[0] &&\n a[1] === b[1]\n ))\n )\n )\n )\n\n /* Compute and return anchor list migrations */\n return partition$\n .pipe(\n map(([prev, next]) => ({\n prev: prev.map(([path]) => path),\n next: next.map(([path]) => path)\n })),\n\n /* Extract anchor list migrations */\n startWith({ prev: [], next: [] }),\n bufferCount(2, 1),\n map(([a, b]) => {\n\n /* Moving down */\n if (a.prev.length < b.prev.length) {\n return {\n prev: b.prev.slice(Math.max(0, a.prev.length - 1), b.prev.length),\n next: []\n }\n\n /* Moving up */\n } else {\n return {\n prev: b.prev.slice(-1),\n next: b.next.slice(0, b.next.length - a.next.length)\n }\n }\n })\n )\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Mount table of contents\n *\n * @param el - Anchor list element\n * @param options - Options\n *\n * @returns Table of contents component observable\n */\nexport function mountTableOfContents(\n el: HTMLElement, options: MountOptions\n): Observable> {\n const internal$ = new Subject()\n internal$\n .pipe(\n observeOn(animationFrameScheduler),\n )\n .subscribe(({ prev, next }) => {\n\n /* Look forward */\n for (const [anchor] of next) {\n resetAnchorActive(anchor)\n resetAnchorState(anchor)\n }\n\n /* Look backward */\n for (const [index, [anchor]] of prev.entries()) {\n setAnchorActive(anchor, index === prev.length - 1)\n setAnchorState(anchor, \"blur\")\n }\n })\n\n /* Create and return component */\n const anchors = getElements(\"[href^=\\\\#]\", el)\n return watchTableOfContents(anchors, options)\n .pipe(\n tap(internal$),\n finalize(() => internal$.complete()),\n map(state => ({ ref: el, ...state }))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport \"focus-visible\"\nimport { Subject, defer, merge } from \"rxjs\"\nimport {\n filter,\n map,\n mergeWith,\n shareReplay,\n switchMap\n} from \"rxjs/operators\"\n\nimport { feature } from \"./_\"\nimport {\n at,\n getElement,\n getElementOrThrow,\n getElements,\n watchDocument,\n watchKeyboard,\n watchLocation,\n watchLocationTarget,\n watchMedia,\n watchPrint,\n watchViewport\n} from \"./browser\"\nimport {\n mountContent,\n mountDialog,\n mountHeader,\n mountHeaderTitle,\n mountSearch,\n mountSidebar,\n mountSource,\n mountTableOfContents,\n mountTabs,\n watchHeader,\n watchMain\n} from \"./components\"\nimport {\n setupClipboardJS,\n setupInstantLoading\n} from \"./integrations\"\nimport {\n patchIndeterminate,\n patchScrollfix\n} from \"./patches\"\n\n/* ----------------------------------------------------------------------------\n * Application\n * ------------------------------------------------------------------------- */\n\n/* Yay, JavaScript is available */\ndocument.documentElement.classList.remove(\"no-js\")\ndocument.documentElement.classList.add(\"js\")\n\n/* Set up navigation observables */\nconst document$ = watchDocument()\nconst location$ = watchLocation()\nconst target$ = watchLocationTarget()\nconst keyboard$ = watchKeyboard()\n\n/* Set up media observables */\nconst viewport$ = watchViewport()\nconst tablet$ = watchMedia(\"(min-width: 960px)\")\nconst screen$ = watchMedia(\"(min-width: 1220px)\")\nconst print$ = watchPrint()\n\n/* Set up Clipboard.js integration */\nconst alert$ = new Subject()\nsetupClipboardJS({ alert$ })\n\n/* Set up instant loading, if enabled */\nif (feature(\"navigation.instant\"))\n setupInstantLoading({ document$, location$, viewport$ })\n\n/* Set up global keyboard handlers */\nkeyboard$\n .pipe(\n filter(({ mode }) => mode === \"global\")\n )\n .subscribe(key => {\n switch (key.type) {\n\n /* Go to previous page */\n case \"p\":\n case \",\":\n const prev = getElement(\"[href][rel=prev]\")\n if (typeof prev !== \"undefined\")\n prev.click()\n break\n\n /* Go to next page */\n case \"n\":\n case \".\":\n const next = getElement(\"[href][rel=next]\")\n if (typeof next !== \"undefined\")\n next.click()\n break\n }\n })\n\n/* Set up patches */\npatchIndeterminate({ document$ })\npatchScrollfix({ document$ })\n\n/* Set up header observable */\nconst header$ = watchHeader(\n getElementOrThrow(\"[data-md-component=header]\"),\n { viewport$ }\n)\n\n/* Set up main area observable */\nconst main$ = document$\n .pipe(\n map(() => getElementOrThrow(\"[data-md-component=main]\")),\n switchMap(el => watchMain(el, { viewport$, header$ })),\n shareReplay(1)\n )\n\n/* Set up control component observables */\nconst control$ = merge(\n\n /* Dialog */\n ...getElements(\"[data-md-component=dialog]\")\n .map(child => mountDialog(child, { alert$ })),\n\n /* Header */\n ...getElements(\"[data-md-component=header]\")\n .map(child => mountHeader(child, { viewport$, header$, main$ })),\n\n /* Search */\n ...getElements(\"[data-md-component=search]\")\n .map(child => mountSearch(child, { keyboard$ })),\n\n /* Repository information */\n ...getElements(\"[data-md-component=source]\")\n .map(child => mountSource(child as HTMLAnchorElement)),\n\n /* Navigation tabs */\n ...getElements(\"[data-md-component=tabs]\")\n .map(child => mountTabs(child, { viewport$, header$ })),\n)\n\n/* Set up content component observables */\nconst content$ = defer(() => merge(\n\n /* Content */\n ...getElements(\"[data-md-component=content]\")\n .map(child => mountContent(child, { target$, viewport$, print$ })),\n\n /* Header title */\n ...getElements(\"[data-md-component=header-title]\")\n .map(child => mountHeaderTitle(child, { viewport$, header$ })),\n\n /* Sidebar */\n ...getElements(\"[data-md-component=sidebar]\")\n .map(child => child.getAttribute(\"data-md-type\") === \"navigation\"\n ? at(screen$, () => mountSidebar(child, { viewport$, header$, main$ }))\n : at(tablet$, () => mountSidebar(child, { viewport$, header$, main$ }))\n ),\n\n /* Table of contents */\n ...getElements(\"[data-md-component=toc]\")\n .map(child => mountTableOfContents(child, { viewport$, header$ })),\n))\n\n/* Set up component observables */\nconst component$ = document$\n .pipe(\n switchMap(() => content$),\n mergeWith(control$)\n )\n\n/* Subscribe to all components */\ncomponent$.subscribe()\n\n/* Export to window */\nexport {\n document$,\n location$,\n target$,\n keyboard$,\n viewport$,\n tablet$,\n screen$,\n print$,\n component$\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { ReplaySubject, Subject, fromEvent } from \"rxjs\"\nimport { mapTo } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch document\n *\n * Documents must be implemented as subjects, so all downstream observables are\n * automatically updated when a new document is emitted. This enabled features\n * like instant loading.\n *\n * @returns Document subject\n */\nexport function watchDocument(): Subject {\n const document$ = new ReplaySubject()\n fromEvent(document, \"DOMContentLoaded\")\n .pipe(\n mapTo(document)\n )\n .subscribe(document$)\n\n /* Return document */\n return document$\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { filter, map, share } from \"rxjs/operators\"\n\nimport { getActiveElement } from \"../element\"\nimport { getToggle } from \"../toggle\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Keyboard mode\n */\nexport type KeyboardMode =\n | \"global\" /* Global */\n | \"search\" /* Search is open */\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Keyboard\n */\nexport interface Keyboard {\n mode: KeyboardMode /* Keyboard mode */\n type: string /* Key type */\n claim(): void /* Key claim */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Check whether an element may receive keyboard input\n *\n * @param el - Element\n *\n * @returns Test result\n */\nfunction isSusceptibleToKeyboard(el: HTMLElement): boolean {\n switch (el.tagName) {\n\n /* Form elements */\n case \"INPUT\":\n case \"SELECT\":\n case \"TEXTAREA\":\n return true\n\n /* Everything else */\n default:\n return el.isContentEditable\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch keyboard\n *\n * @returns Keyboard observable\n */\nexport function watchKeyboard(): Observable {\n return fromEvent(window, \"keydown\")\n .pipe(\n filter(ev => !(ev.metaKey || ev.ctrlKey)),\n map(ev => ({\n mode: getToggle(\"search\") ? \"search\" : \"global\",\n type: ev.key,\n claim() {\n ev.preventDefault()\n ev.stopPropagation()\n }\n } as Keyboard)),\n filter(({ mode }) => {\n if (mode === \"global\") {\n const active = getActiveElement()\n if (typeof active !== \"undefined\")\n return !isSusceptibleToKeyboard(active)\n }\n return true\n }),\n share()\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport ClipboardJS from \"clipboard\"\nimport { Observable, Subject } from \"rxjs\"\n\nimport { translation } from \"~/_\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n alert$: Subject /* Alert subject */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up Clipboard.js integration\n *\n * @param options - Options\n */\nexport function setupClipboardJS(\n { alert$ }: SetupOptions\n): void {\n if (ClipboardJS.isSupported()) {\n new Observable(subscriber => {\n new ClipboardJS(\"[data-clipboard-target], [data-clipboard-text]\")\n .on(\"success\", ev => subscriber.next(ev))\n })\n .subscribe(() => alert$.next(translation(\"clipboard.copied\")))\n }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n EMPTY,\n NEVER,\n Observable,\n Subject,\n fromEvent,\n merge,\n of\n} from \"rxjs\"\nimport {\n bufferCount,\n catchError,\n concatMap,\n debounceTime,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n filter,\n map,\n sample,\n share,\n skip,\n skipUntil,\n switchMap\n} from \"rxjs/operators\"\n\nimport { configuration } from \"~/_\"\nimport {\n Viewport,\n ViewportOffset,\n createElement,\n getElement,\n getElementOrThrow,\n getElements,\n replaceElement,\n request,\n requestXML,\n setLocation,\n setLocationHash,\n setViewportOffset\n} from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * History state\n */\nexport interface HistoryState {\n url: URL /* State URL */\n offset?: ViewportOffset /* State viewport offset */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n document$: Subject /* Document subject */\n location$: Subject /* Location subject */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Preprocess a list of URLs\n *\n * This function replaces the `site_url` in the sitemap with the actual base\n * URL, to allow instant loading to work in occasions like Netlify previews.\n *\n * @param urls - URLs\n *\n * @returns Processed URLs\n */\nfunction preprocess(urls: string[]): string[] {\n if (urls.length < 2)\n return urls\n\n /* Compute references URLs */\n const [root, next] = urls.sort((a, b) => a.length - b.length)\n\n /* Compute common prefix */\n let index = 0\n if (root === next)\n index = root.length\n else\n while (root.charCodeAt(index) === root.charCodeAt(index))\n index++\n\n /* Replace common prefix (i.e. base) with effective base */\n const config = configuration()\n return urls.map(url => (\n url.replace(root.slice(0, index), `${config.base}/`)\n ))\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up instant loading\n *\n * When fetching, theoretically, we could use `responseType: \"document\"`, but\n * since all MkDocs links are relative, we need to make sure that the current\n * location matches the document we just loaded. Otherwise any relative links\n * in the document could use the old location.\n *\n * This is the reason why we need to synchronize history events and the process\n * of fetching the document for navigation changes (except `popstate` events):\n *\n * 1. Fetch document via `XMLHTTPRequest`\n * 2. Set new location via `history.pushState`\n * 3. Parse and emit fetched document\n *\n * For `popstate` events, we must not use `history.pushState`, or the forward\n * history will be irreversibly overwritten. In case the request fails, the\n * location change is dispatched regularly.\n *\n * @param options - Options\n */\nexport function setupInstantLoading(\n { document$, location$, viewport$ }: SetupOptions\n): void {\n const config = configuration()\n if (location.protocol === \"file:\")\n return\n\n /* Disable automatic scroll restoration */\n if (\"scrollRestoration\" in history) {\n history.scrollRestoration = \"manual\"\n\n /* Hack: ensure that reloads restore viewport offset */\n fromEvent(window, \"beforeunload\")\n .subscribe(() => {\n history.scrollRestoration = \"auto\"\n })\n }\n\n /* Hack: ensure absolute favicon link to omit 404s when switching */\n const favicon = getElement(\"link[rel='shortcut icon']\")\n if (typeof favicon !== \"undefined\")\n favicon.href = favicon.href\n\n /* Intercept internal navigation */\n const push$ = requestXML(`${config.base}/sitemap.xml`)\n .pipe(\n map(sitemap => preprocess(getElements(\"loc\", sitemap)\n .map(node => node.textContent!)\n )),\n switchMap(urls => fromEvent(document.body, \"click\")\n .pipe(\n filter(ev => !ev.metaKey && !ev.ctrlKey),\n switchMap(ev => {\n if (ev.target instanceof HTMLElement) {\n const el = ev.target.closest(\"a\")\n if (el && !el.target && urls.includes(el.href)) {\n ev.preventDefault()\n return of({\n url: new URL(el.href)\n })\n }\n }\n return NEVER\n })\n )\n ),\n share()\n )\n\n /* Intercept history back and forward */\n const pop$ = fromEvent(window, \"popstate\")\n .pipe(\n filter(ev => ev.state !== null),\n map(ev => ({\n url: new URL(location.href),\n offset: ev.state\n } as HistoryState)),\n share()\n )\n\n /* Emit location change */\n merge(push$, pop$)\n .pipe(\n distinctUntilChanged((a, b) => a.url.href === b.url.href),\n map(({ url }) => url)\n )\n .subscribe(location$)\n\n /* Fetch document via `XMLHTTPRequest` */\n const response$ = location$\n .pipe(\n distinctUntilKeyChanged(\"pathname\"),\n skip(1),\n switchMap(url => request(url.href)\n .pipe(\n catchError(() => {\n setLocation(url)\n return NEVER\n })\n )\n ),\n share()\n )\n\n /* Set new location via `history.pushState` */\n push$\n .pipe(\n sample(response$)\n )\n .subscribe(({ url }) => {\n history.pushState({}, \"\", url.toString())\n })\n\n /* Parse and emit fetched document */\n const dom = new DOMParser()\n response$\n .pipe(\n switchMap(res => res.text()),\n map(res => dom.parseFromString(res, \"text/html\"))\n )\n .subscribe(document$)\n\n /* Emit history state change */\n merge(push$, pop$)\n .pipe(\n sample(document$)\n )\n .subscribe(({ url, offset }) => {\n if (url.hash && !offset)\n setLocationHash(url.hash)\n else\n setViewportOffset(offset || { y: 0 })\n })\n\n /* Replace components */\n document$\n .pipe(\n skip(1)\n )\n .subscribe(replacement => {\n\n /* Replace meta tags and components */\n for (const selector of [\n\n /* Meta tags */\n \"title\",\n \"link[rel='canonical']\",\n \"meta[name='author']\",\n \"meta[name='description']\",\n\n /* Components */\n \"[data-md-component=announce]\",\n \"[data-md-component=header-title]\",\n \"[data-md-component=container]\",\n \"[data-md-component=skip]\"\n ]) {\n const source = getElement(selector)\n const target = getElement(selector, replacement)\n if (\n typeof source !== \"undefined\" &&\n typeof target !== \"undefined\"\n ) {\n replaceElement(source, target)\n }\n }\n })\n\n /* Re-evaluate scripts */\n document$\n .pipe(\n skip(1),\n map(() => getElementOrThrow(\"[data-md-component=container]\")),\n switchMap(el => of(...getElements(\"script\", el))),\n concatMap(el => {\n const script = createElement(\"script\")\n if (el.src) {\n script.src = el.src\n replaceElement(el, script)\n\n /* Complete when script is loaded */\n return new Observable(observer => {\n script.onload = () => observer.complete()\n })\n\n /* Complete immediately */\n } else {\n script.textContent = el.textContent!\n replaceElement(el, script)\n return EMPTY\n }\n })\n )\n .subscribe()\n\n /* Debounce update of viewport offset */\n viewport$\n .pipe(\n skipUntil(push$),\n debounceTime(250),\n distinctUntilKeyChanged(\"offset\")\n )\n .subscribe(({ offset }) => {\n history.replaceState(offset, \"\")\n })\n\n /* Set viewport offset from history */\n merge(push$, pop$)\n .pipe(\n bufferCount(2, 1),\n filter(([a, b]) => a.url.pathname === b.url.pathname),\n map(([, state]) => state)\n )\n .subscribe(({ offset }) => {\n setViewportOffset(offset || { y: 0 })\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable } from \"rxjs\"\n\nimport { getElements } from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch options\n */\ninterface PatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch indeterminate checkboxes\n *\n * @param options - Options\n */\nexport function patchIndeterminate(\n { document$ }: PatchOptions\n): void {\n document$.subscribe(() => {\n for (const el of getElements(\n \"[data-md-state=indeterminate]\"\n )) {\n el.setAttribute(\"data-md-state\", \"\")\n el.indeterminate = true\n el.checked = false\n }\n })\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent, of } from \"rxjs\"\nimport { mapTo, mergeMap, switchMap, tap } from \"rxjs/operators\"\n\nimport { getElements } from \"~/browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch options\n */\ninterface PatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Check whether the given device is an Apple device\n *\n * @returns Test result\n */\nfunction isAppleDevice(): boolean {\n return /(iPad|iPhone|iPod)/.test(navigator.userAgent)\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Patch all elements with `data-md-scrollfix` attributes\n *\n * This is a year-old patch which ensures that overflow scrolling works at the\n * top and bottom of containers on iOS by ensuring a `1px` scroll offset upon\n * the start of a touch event.\n *\n * @see https://bit.ly/2SCtAOO - Original source\n *\n * @param options - Options\n */\nexport function patchScrollfix(\n { document$ }: PatchOptions\n): void {\n if (isAppleDevice()) {\n document$\n .pipe(\n switchMap(() => of(...getElements(\"[data-md-scrollfix]\"))),\n tap(el => el.removeAttribute(\"data-md-scrollfix\")),\n mergeMap(el => fromEvent(el, \"touchstart\")\n .pipe(\n mapTo(el)\n )\n )\n )\n .subscribe(el => {\n const top = el.scrollTop\n\n /* We're at the top of the container */\n if (top === 0) {\n el.scrollTop = 1\n\n /* We're at the bottom of the container */\n } else if (top + el.offsetHeight === el.scrollHeight) {\n el.scrollTop = top - 1\n }\n })\n }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n Observable,\n combineLatest\n} from \"rxjs\"\nimport {\n distinctUntilChanged,\n distinctUntilKeyChanged,\n map,\n switchMap\n} from \"rxjs/operators\"\n\nimport { Viewport, watchElementSize } from \"~/browser\"\n\nimport { Header } from \"../header\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Main area\n */\nexport interface Main {\n offset: number /* Main area top offset */\n height: number /* Main area visible height */\n active: boolean /* User scrolled past header */\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n viewport$: Observable /* Viewport observable */\n header$: Observable
    /* Header observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch main area\n *\n * This function returns an observable that computes the visual parameters of\n * the main area which depends on the viewport vertical offset and height, as\n * well as the height of the header element, if the header is fixed.\n *\n * @param el - Main area element\n * @param options - Options\n *\n * @returns Main area observable\n */\nexport function watchMain(\n el: HTMLElement, { viewport$, header$ }: WatchOptions\n): Observable
    {\n\n /* Compute necessary adjustment for header */\n const adjust$ = header$\n .pipe(\n map(({ height }) => height),\n distinctUntilChanged()\n )\n\n /* Compute the main area's top and bottom borders */\n const border$ = adjust$\n .pipe(\n switchMap(() => watchElementSize(el)\n .pipe(\n map(({ height }) => ({\n top: el.offsetTop,\n bottom: el.offsetTop + height\n })),\n distinctUntilKeyChanged(\"bottom\")\n )\n )\n )\n\n /* Compute the main area's offset, visible height and if we scrolled past */\n return combineLatest([adjust$, border$, viewport$])\n .pipe(\n map(([header, { top, bottom }, { offset: { y }, size: { height } }]) => {\n height = Math.max(0, height\n - Math.max(0, top - y, header)\n - Math.max(0, height + y - bottom)\n )\n return {\n offset: top - header,\n height,\n active: top - header <= y\n }\n }),\n distinctUntilChanged((a, b) => (\n a.offset === b.offset &&\n a.height === b.height &&\n a.active === b.active\n ))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set header state\n *\n * @param el - Header element\n * @param state - Header state\n */\nexport function setHeaderState(\n el: HTMLElement, state: \"shadow\" | \"hidden\"\n): void {\n el.setAttribute(\"data-md-state\", state)\n}\n\n/**\n * Reset header state\n *\n * @param el - Header element\n */\nexport function resetHeaderState(\n el: HTMLElement\n): void {\n el.removeAttribute(\"data-md-state\")\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, merge } from \"rxjs\"\n\nimport { Viewport, getElements } from \"~/browser\"\n\nimport { Component } from \"../../_\"\nimport { CodeBlock, mountCodeBlock } from \"../code\"\nimport { Details, mountDetails } from \"../details\"\nimport { DataTable, mountDataTable } from \"../table\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Content\n */\nexport type Content =\n | CodeBlock\n | DataTable\n | Details\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount options\n */\ninterface MountOptions {\n target$: Observable /* Location target observable */\n viewport$: Observable /* Viewport observable */\n print$: Observable /* Print observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Mount content\n *\n * @param el - Content element\n * @param options - Options\n *\n * @returns Content component observable\n */\nexport function mountContent(\n el: HTMLElement, { target$, viewport$, print$ }: MountOptions\n): Observable> {\n return merge(\n\n /* Code blocks */\n ...getElements(\"pre > code\", el)\n .map(child => mountCodeBlock(child, { viewport$ })),\n\n /* Data tables */\n ...getElements(\"table:not([class])\", el)\n .map(child => mountDataTable(child)),\n\n /* Details */\n ...getElements(\"details\", el)\n .map(child => mountDetails(child, { target$, print$ }))\n )\n}\n"],"sourceRoot":""} \ No newline at end of file diff --git a/material/assets/manifest.json b/material/assets/manifest.json index e81d96a6a..de2b44bf0 100644 --- a/material/assets/manifest.json +++ b/material/assets/manifest.json @@ -1,6 +1,6 @@ { - "assets/javascripts/bundle.js": "assets/javascripts/bundle.4fa4ebaf.min.js", - "assets/javascripts/bundle.js.map": "assets/javascripts/bundle.4fa4ebaf.min.js.map", + "assets/javascripts/bundle.js": "assets/javascripts/bundle.d8c6976f.min.js", + "assets/javascripts/bundle.js.map": "assets/javascripts/bundle.d8c6976f.min.js.map", "assets/javascripts/vendor.js": "assets/javascripts/vendor.e32ed4d0.min.js", "assets/javascripts/vendor.js.map": "assets/javascripts/vendor.e32ed4d0.min.js.map", "assets/javascripts/worker/search.js": "assets/javascripts/worker/search.b9424174.min.js", @@ -9,8 +9,8 @@ "assets/stylesheets/main.css.map": "assets/stylesheets/main.a86e6725.min.css.map", "assets/stylesheets/palette.css": "assets/stylesheets/palette.e70b70b6.min.css", "assets/stylesheets/palette.css.map": "assets/stylesheets/palette.e70b70b6.min.css.map", - "overrides/assets/javascripts/bundle.js": "overrides/assets/javascripts/bundle.9f9f98ea.min.js", - "overrides/assets/javascripts/bundle.js.map": "overrides/assets/javascripts/bundle.9f9f98ea.min.js.map", + "overrides/assets/javascripts/bundle.js": "overrides/assets/javascripts/bundle.63116035.min.js", + "overrides/assets/javascripts/bundle.js.map": "overrides/assets/javascripts/bundle.63116035.min.js.map", "overrides/assets/javascripts/vendor.js": "overrides/assets/javascripts/vendor.1aa446d9.min.js", "overrides/assets/javascripts/vendor.js.map": "overrides/assets/javascripts/vendor.1aa446d9.min.js.map", "overrides/assets/stylesheets/main.css": "overrides/assets/stylesheets/main.8e98f424.min.css", diff --git a/material/base.html b/material/base.html index 1a3d6f012..aa12ffcd6 100644 --- a/material/base.html +++ b/material/base.html @@ -217,7 +217,7 @@ {% endblock %} {% block scripts %} - + {% for path in config["extra_javascript"] %} {% endfor %} diff --git a/material/overrides/assets/javascripts/bundle.9f9f98ea.min.js b/material/overrides/assets/javascripts/bundle.63116035.min.js similarity index 95% rename from material/overrides/assets/javascripts/bundle.9f9f98ea.min.js rename to material/overrides/assets/javascripts/bundle.63116035.min.js index 05e18ca58..7c03fa2ff 100644 --- a/material/overrides/assets/javascripts/bundle.9f9f98ea.min.js +++ b/material/overrides/assets/javascripts/bundle.63116035.min.js @@ -1,2 +1,2 @@ -!function(e,t){for(var n in t)e[n]=t[n]}(window,function(e){function t(t){for(var r,i,a=t[0],s=t[1],u=t[2],f=0,p=[];fObject(d.a)(new ResizeObserver(e=>{for(const t of e)v.next(t)}))).pipe(Object(i.a)(e=>b.a.pipe(Object(l.a)(e)).pipe(Object(g.a)(()=>e.disconnect()))),Object(h.a)(1));n(31);n(47);u("[data-md-toggle=drawer]"),u("[data-md-toggle=search]");n(52),n(53);n(48),n(49);function O(e,t){if("string"==typeof t||"number"==typeof t)e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(const n of t)O(e,n)}function j(e,t,...n){const r=document.createElement(e);if(t)for(const e of Object.keys(t))"boolean"!=typeof t[e]?r.setAttribute(e,t[e]):t[e]&&r.setAttribute(e,"");for(const e of n)O(r,e);return r}function m(e,t){return t.length?j("div",{class:""},j("span",null,function(e){if(e>999){return((e+1e-6)/1e3).toFixed(+((e-950)%1e3>99))+"k"}return e.toString()}(e.length)," results"),j("ul",{class:"tx-icon-search__list"},e.slice(0,10).map(e=>j("li",{class:"tx-icon-search__item"},j("span",{class:"twemoji"},j("img",{src:"https://raw.githubusercontent.com/squidfunk/mkdocs-material/master/material/.icons/"+e,style:"width: 18px; height: 18px"}))," – ",j("button",{class:"md-clipboard--inline","data-clipboard-text":":"+e.replace(/\.svg$/,"").replace(/\//g,"-")+":"},j("code",null,function(e,t){return`:${Object(r.wrap)(e.replace(/\.svg$/,"").replace(/\//g,"-"),t,{wrap:{tagOpen:"",tagClose:""}})}:`}(e,t))))))):j("div",{class:""})}const y=u("#__config"),w=JSON.parse(y.textContent),x=Object(o.a)(fetch(w.base+"/overrides/assets/javascripts/icons.json").then(e=>e.json())),_=s("#icon-search");_&&x.pipe(Object(i.a)(e=>Object(c.a)(_,"keyup").pipe(Object(a.a)(()=>Object(r.filter)(e,_.value))))).subscribe(e=>{const t=u(".tx-icon-result");t.innerHTML="",t.appendChild(m(e,_.value))}),Object(c.a)(document.body,"click").subscribe(e=>{if(e.target instanceof HTMLElement){e.target.closest("a[href^=http]")instanceof HTMLLinkElement&&ga("send","event","outbound","click",y.href)}})}})); -//# sourceMappingURL=bundle.9f9f98ea.min.js.map \ No newline at end of file +!function(e,t){for(var n in t)e[n]=t[n]}(window,function(e){function t(t){for(var r,i,a=t[0],s=t[1],u=t[2],f=0,p=[];fObject(d.a)(new ResizeObserver(e=>{for(const t of e)v.next(t)}))).pipe(Object(i.a)(e=>b.a.pipe(Object(l.a)(e)).pipe(Object(g.a)(()=>e.disconnect()))),Object(h.a)(1));n(31);u("[data-md-toggle=drawer]"),u("[data-md-toggle=search]");n(47);n(52),n(53);n(48),n(49);function O(e,t){if("string"==typeof t||"number"==typeof t)e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(const n of t)O(e,n)}function j(e,t,...n){const r=document.createElement(e);if(t)for(const e of Object.keys(t))"boolean"!=typeof t[e]?r.setAttribute(e,t[e]):t[e]&&r.setAttribute(e,"");for(const e of n)O(r,e);return r}function m(e,t){return t.length?j("div",{class:""},j("span",null,function(e){if(e>999){return((e+1e-6)/1e3).toFixed(+((e-950)%1e3>99))+"k"}return e.toString()}(e.length)," results"),j("ul",{class:"tx-icon-search__list"},e.slice(0,10).map(e=>j("li",{class:"tx-icon-search__item"},j("span",{class:"twemoji"},j("img",{src:"https://raw.githubusercontent.com/squidfunk/mkdocs-material/master/material/.icons/"+e,style:"width: 18px; height: 18px"}))," – ",j("button",{class:"md-clipboard--inline","data-clipboard-text":":"+e.replace(/\.svg$/,"").replace(/\//g,"-")+":"},j("code",null,function(e,t){return`:${Object(r.wrap)(e.replace(/\.svg$/,"").replace(/\//g,"-"),t,{wrap:{tagOpen:"",tagClose:""}})}:`}(e,t))))))):j("div",{class:""})}const y=u("#__config"),w=JSON.parse(y.textContent),x=Object(o.a)(fetch(w.base+"/overrides/assets/javascripts/icons.json").then(e=>e.json())),_=s("#icon-search");_&&x.pipe(Object(i.a)(e=>Object(c.a)(_,"keyup").pipe(Object(a.a)(()=>Object(r.filter)(e,_.value))))).subscribe(e=>{const t=u(".tx-icon-result");t.innerHTML="",t.appendChild(m(e,_.value))}),Object(c.a)(document.body,"click").subscribe(e=>{if(e.target instanceof HTMLElement){e.target.closest("a[href^=http]")instanceof HTMLLinkElement&&ga("send","event","outbound","click",y.href)}})}})); +//# sourceMappingURL=bundle.63116035.min.js.map \ No newline at end of file diff --git a/material/overrides/assets/javascripts/bundle.63116035.min.js.map b/material/overrides/assets/javascripts/bundle.63116035.min.js.map new file mode 100644 index 000000000..c710c8d48 --- /dev/null +++ b/material/overrides/assets/javascripts/bundle.63116035.min.js.map @@ -0,0 +1 @@ +{"version":3,"sources":["webpack:///webpack/bootstrap","webpack:///./src/assets/javascripts/browser/element/_/index.ts","webpack:///./src/assets/javascripts/browser/element/size/index.ts","webpack:///./src/assets/javascripts/browser/toggle/index.ts","webpack:///./src/assets/javascripts/utilities/jsx/index.ts","webpack:///./src/overrides/assets/javascripts/templates/icon/index.tsx","webpack:///./src/assets/javascripts/utilities/string/index.ts","webpack:///./src/overrides/assets/javascripts/index.ts"],"names":["webpackJsonpCallback","data","moduleId","chunkId","chunkIds","moreModules","executeModules","i","resolves","length","Object","prototype","hasOwnProperty","call","installedChunks","push","modules","parentJsonpFunction","shift","deferredModules","apply","checkDeferredModules","result","deferredModule","fulfilled","j","depId","splice","__webpack_require__","s","installedModules","0","exports","module","l","m","c","d","name","getter","o","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","p","jsonpArray","window","oldJsonpFunction","slice","getElement","selector","node","document","querySelector","undefined","getElementOrThrow","el","ReferenceError","entry$","Subject","defer","of","ResizeObserver","entries","entry","next","pipe","switchMap","resize","startWith","finalize","disconnect","shareReplay","appendChild","child","innerHTML","toString","Node","Array","isArray","h","tag","attributes","children","createElement","attr","keys","setAttribute","renderIconSearch","results","query","class","toFixed","round","map","src","style","replace","wrap","tagOpen","tagClose","transform","config","JSON","parse","textContent","icons$","from","fetch","base","then","res","json","search","icons","fromEvent","subscribe","list","body","ev","target","HTMLElement","closest","HTMLLinkElement","ga","href"],"mappings":"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","file":"overrides/assets/javascripts/bundle.63116035.min.js","sourcesContent":[" \t// install a JSONP callback for chunk loading\n \tfunction webpackJsonpCallback(data) {\n \t\tvar chunkIds = data[0];\n \t\tvar moreModules = data[1];\n \t\tvar executeModules = data[2];\n\n \t\t// add \"moreModules\" to the modules object,\n \t\t// then flag all \"chunkIds\" as loaded and fire callback\n \t\tvar moduleId, chunkId, i = 0, resolves = [];\n \t\tfor(;i < chunkIds.length; i++) {\n \t\t\tchunkId = chunkIds[i];\n \t\t\tif(Object.prototype.hasOwnProperty.call(installedChunks, chunkId) && installedChunks[chunkId]) {\n \t\t\t\tresolves.push(installedChunks[chunkId][0]);\n \t\t\t}\n \t\t\tinstalledChunks[chunkId] = 0;\n \t\t}\n \t\tfor(moduleId in moreModules) {\n \t\t\tif(Object.prototype.hasOwnProperty.call(moreModules, moduleId)) {\n \t\t\t\tmodules[moduleId] = moreModules[moduleId];\n \t\t\t}\n \t\t}\n \t\tif(parentJsonpFunction) parentJsonpFunction(data);\n\n \t\twhile(resolves.length) {\n \t\t\tresolves.shift()();\n \t\t}\n\n \t\t// add entry modules from loaded chunk to deferred list\n \t\tdeferredModules.push.apply(deferredModules, executeModules || []);\n\n \t\t// run deferred modules when all chunks ready\n \t\treturn checkDeferredModules();\n \t};\n \tfunction checkDeferredModules() {\n \t\tvar result;\n \t\tfor(var i = 0; i < deferredModules.length; i++) {\n \t\t\tvar deferredModule = deferredModules[i];\n \t\t\tvar fulfilled = true;\n \t\t\tfor(var j = 1; j < deferredModule.length; j++) {\n \t\t\t\tvar depId = deferredModule[j];\n \t\t\t\tif(installedChunks[depId] !== 0) fulfilled = false;\n \t\t\t}\n \t\t\tif(fulfilled) {\n \t\t\t\tdeferredModules.splice(i--, 1);\n \t\t\t\tresult = __webpack_require__(__webpack_require__.s = deferredModule[0]);\n \t\t\t}\n \t\t}\n\n \t\treturn result;\n \t}\n\n \t// The module cache\n \tvar installedModules = {};\n\n \t// object to store loaded and loading chunks\n \t// undefined = chunk not loaded, null = chunk preloaded/prefetched\n \t// Promise = chunk loading, 0 = chunk loaded\n \tvar installedChunks = {\n \t\t0: 0\n \t};\n\n \tvar deferredModules = [];\n\n \t// The require function\n \tfunction __webpack_require__(moduleId) {\n\n \t\t// Check if module is in cache\n \t\tif(installedModules[moduleId]) {\n \t\t\treturn installedModules[moduleId].exports;\n \t\t}\n \t\t// Create a new module (and put it into the cache)\n \t\tvar module = installedModules[moduleId] = {\n \t\t\ti: moduleId,\n \t\t\tl: false,\n \t\t\texports: {}\n \t\t};\n\n \t\t// Execute the module function\n \t\tmodules[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n \t\t// Flag the module as loaded\n \t\tmodule.l = true;\n\n \t\t// Return the exports of the module\n \t\treturn module.exports;\n \t}\n\n\n \t// expose the modules object (__webpack_modules__)\n \t__webpack_require__.m = modules;\n\n \t// expose the module cache\n \t__webpack_require__.c = installedModules;\n\n \t// define getter function for harmony exports\n \t__webpack_require__.d = function(exports, name, getter) {\n \t\tif(!__webpack_require__.o(exports, name)) {\n \t\t\tObject.defineProperty(exports, name, { enumerable: true, get: getter });\n \t\t}\n \t};\n\n \t// define __esModule on exports\n \t__webpack_require__.r = function(exports) {\n \t\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n \t\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n \t\t}\n \t\tObject.defineProperty(exports, '__esModule', { value: true });\n \t};\n\n \t// create a fake namespace object\n \t// mode & 1: value is a module id, require it\n \t// mode & 2: merge all properties of value into the ns\n \t// mode & 4: return value when already ns object\n \t// mode & 8|1: behave like require\n \t__webpack_require__.t = function(value, mode) {\n \t\tif(mode & 1) value = __webpack_require__(value);\n \t\tif(mode & 8) return value;\n \t\tif((mode & 4) && typeof value === 'object' && value && value.__esModule) return value;\n \t\tvar ns = Object.create(null);\n \t\t__webpack_require__.r(ns);\n \t\tObject.defineProperty(ns, 'default', { enumerable: true, value: value });\n \t\tif(mode & 2 && typeof value != 'string') for(var key in value) __webpack_require__.d(ns, key, function(key) { return value[key]; }.bind(null, key));\n \t\treturn ns;\n \t};\n\n \t// getDefaultExport function for compatibility with non-harmony modules\n \t__webpack_require__.n = function(module) {\n \t\tvar getter = module && module.__esModule ?\n \t\t\tfunction getDefault() { return module['default']; } :\n \t\t\tfunction getModuleExports() { return module; };\n \t\t__webpack_require__.d(getter, 'a', getter);\n \t\treturn getter;\n \t};\n\n \t// Object.prototype.hasOwnProperty.call\n \t__webpack_require__.o = function(object, property) { return Object.prototype.hasOwnProperty.call(object, property); };\n\n \t// __webpack_public_path__\n \t__webpack_require__.p = \"\";\n\n \tvar jsonpArray = window[\"webpackJsonp\"] = window[\"webpackJsonp\"] || [];\n \tvar oldJsonpFunction = jsonpArray.push.bind(jsonpArray);\n \tjsonpArray.push = webpackJsonpCallback;\n \tjsonpArray = jsonpArray.slice();\n \tfor(var i = 0; i < jsonpArray.length; i++) webpackJsonpCallback(jsonpArray[i]);\n \tvar parentJsonpFunction = oldJsonpFunction;\n\n\n \t// add entry module to deferred list\n \tdeferredModules.push([37,1]);\n \t// run deferred modules when ready\n \treturn checkDeferredModules();\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve an element matching the query selector\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @returns Element or nothing\n */\nexport function getElement(\n selector: T, node?: ParentNode\n): HTMLElementTagNameMap[T]\n\nexport function getElement(\n selector: string, node?: ParentNode\n): T | undefined\n\nexport function getElement(\n selector: string, node: ParentNode = document\n): T | undefined {\n return node.querySelector(selector) || undefined\n}\n\n/**\n * Retrieve an element matching a query selector or throw a reference error\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @returns Element\n */\nexport function getElementOrThrow(\n selector: T, node?: ParentNode\n): HTMLElementTagNameMap[T]\n\nexport function getElementOrThrow(\n selector: string, node?: ParentNode\n): T\n\nexport function getElementOrThrow(\n selector: string, node: ParentNode = document\n): T {\n const el = getElement(selector, node)\n if (typeof el === \"undefined\")\n throw new ReferenceError(\n `Missing element: expected \"${selector}\" to be present`\n )\n return el\n}\n\n/**\n * Retrieve the currently active element\n *\n * @returns Element or nothing\n */\nexport function getActiveElement(): HTMLElement | undefined {\n return document.activeElement instanceof HTMLElement\n ? document.activeElement\n : undefined\n}\n\n/**\n * Retrieve all elements matching the query selector\n *\n * @template T - Element type\n *\n * @param selector - Query selector\n * @param node - Node of reference\n *\n * @returns Elements\n */\nexport function getElements(\n selector: T, node?: ParentNode\n): HTMLElementTagNameMap[T][]\n\nexport function getElements(\n selector: string, node?: ParentNode\n): T[]\n\nexport function getElements(\n selector: string, node: ParentNode = document\n): T[] {\n return Array.from(node.querySelectorAll(selector))\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Create an element\n *\n * @template T - Tag name type\n *\n * @param tagName - Tag name\n *\n * @returns Element\n */\nexport function createElement(\n tagName: T\n): HTMLElementTagNameMap[T] {\n return document.createElement(tagName)\n}\n\n/**\n * Replace an element with another element\n *\n * @param source - Source element\n * @param target - Target element\n */\nexport function replaceElement(\n source: HTMLElement, target: Node\n): void {\n source.replaceWith(target)\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport {\n NEVER,\n Observable,\n Subject,\n defer,\n of\n} from \"rxjs\"\nimport {\n filter,\n finalize,\n map,\n shareReplay,\n startWith,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Element offset\n */\nexport interface ElementSize {\n width: number /* Element width */\n height: number /* Element height */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Resize observer entry subject\n */\nconst entry$ = new Subject()\n\n/**\n * Resize observer observable\n *\n * This observable will create a `ResizeObserver` on the first subscription\n * and will automatically terminate it when there are no more subscribers.\n * It's quite important to centralize observation in a single `ResizeObserver`,\n * as the performance difference can be quite dramatic, as the link shows.\n *\n * @see https://bit.ly/3iIYfEm - Google Groups on performance\n */\nconst observer$ = defer(() => of(\n new ResizeObserver(entries => {\n for (const entry of entries)\n entry$.next(entry)\n })\n))\n .pipe(\n switchMap(resize => NEVER.pipe(startWith(resize))\n .pipe(\n finalize(() => resize.disconnect())\n )\n ),\n shareReplay(1)\n )\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve element size\n *\n * @param el - Element\n *\n * @returns Element size\n */\nexport function getElementSize(el: HTMLElement): ElementSize {\n return {\n width: el.offsetWidth,\n height: el.offsetHeight\n }\n}\n\n/**\n * Retrieve element content size, i.e. including overflowing content\n *\n * @param el - Element\n *\n * @returns Element size\n */\nexport function getElementContentSize(el: HTMLElement): ElementSize {\n return {\n width: el.scrollWidth,\n height: el.scrollHeight\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element size\n *\n * This function returns an observable that will subscribe to a single internal\n * instance of `ResizeObserver` upon subscription, and emit resize events until\n * termination. Note that this function should not be called with the same\n * element twice, as the first unsubscription will terminate observation.\n *\n * @param el - Element\n *\n * @returns Element size observable\n */\nexport function watchElementSize(\n el: HTMLElement\n): Observable {\n return observer$\n .pipe(\n tap(observer => observer.observe(el)),\n switchMap(observer => entry$\n .pipe(\n filter(({ target }) => target === el),\n finalize(() => observer.unobserve(el)),\n map(({ contentRect }) => ({\n width: contentRect.width,\n height: contentRect.height\n }))\n )\n ),\n startWith(getElementSize(el))\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { Observable, fromEvent } from \"rxjs\"\nimport { map, startWith } from \"rxjs/operators\"\n\nimport { getElementOrThrow } from \"../element\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Toggle\n */\nexport type Toggle =\n | \"drawer\" /* Toggle for drawer */\n | \"search\" /* Toggle for search */\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Toggle map\n */\nconst toggles: Record = {\n drawer: getElementOrThrow(\"[data-md-toggle=drawer]\"),\n search: getElementOrThrow(\"[data-md-toggle=search]\")\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve the value of a toggle\n *\n * @param name - Toggle\n *\n * @returns Toggle value\n */\nexport function getToggle(name: Toggle): boolean {\n return toggles[name].checked\n}\n\n/**\n * Set toggle\n *\n * Simulating a click event seems to be the most cross-browser compatible way\n * of changing the value while also emitting a `change` event. Before, Material\n * used `CustomEvent` to programmatically change the value of a toggle, but this\n * is a much simpler and cleaner solution which doesn't require a polyfill.\n *\n * @param name - Toggle\n * @param value - Toggle value\n */\nexport function setToggle(name: Toggle, value: boolean): void {\n if (toggles[name].checked !== value)\n toggles[name].click()\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch toggle\n *\n * @param name - Toggle\n *\n * @returns Toggle value observable\n */\nexport function watchToggle(name: Toggle): Observable {\n const el = toggles[name]\n return fromEvent(el, \"change\")\n .pipe(\n map(() => el.checked),\n startWith(el.checked)\n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\nimport { JSX as JSXInternal } from \"preact\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * HTML attributes\n */\ntype Attributes =\n & JSXInternal.HTMLAttributes\n & JSXInternal.SVGAttributes\n & Record\n\n/**\n * Child element\n */\ntype Child =\n | HTMLElement\n | Text\n | string\n | number\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Append a child node to an element\n *\n * @param el - Element\n * @param child - Child node(s)\n */\nfunction appendChild(el: HTMLElement, child: Child | Child[]): void {\n\n /* Handle primitive types (including raw HTML) */\n if (typeof child === \"string\" || typeof child === \"number\") {\n el.innerHTML += child.toString()\n\n /* Handle nodes */\n } else if (child instanceof Node) {\n el.appendChild(child)\n\n /* Handle nested children */\n } else if (Array.isArray(child)) {\n for (const node of child)\n appendChild(el, node)\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * JSX factory\n *\n * @param tag - HTML tag\n * @param attributes - HTML attributes\n * @param children - Child elements\n *\n * @returns Element\n */\nexport function h(\n tag: string, attributes: Attributes | null, ...children: Child[]\n): HTMLElement {\n const el = document.createElement(tag)\n\n /* Set attributes, if any */\n if (attributes)\n for (const attr of Object.keys(attributes))\n if (typeof attributes[attr] !== \"boolean\")\n el.setAttribute(attr, attributes[attr])\n else if (attributes[attr])\n el.setAttribute(attr, \"\")\n\n /* Append child nodes */\n for (const child of children)\n appendChild(el, child)\n\n /* Return element */\n return el\n}\n\n/* ----------------------------------------------------------------------------\n * Namespace\n * ------------------------------------------------------------------------- */\n\nexport declare namespace h {\n namespace JSX {\n type Element = HTMLElement\n type IntrinsicElements = JSXInternal.IntrinsicElements\n }\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* eslint-disable */\n\nimport { wrap } from \"fuzzaldrin-plus\"\nimport { h, round } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\nfunction transform(value: string, query: string) {\n return `:${wrap(value.replace(/\\.svg$/, \"\").replace(/\\//g, \"-\"), query, {\n wrap: {\n tagOpen: \"\",\n tagClose: \"\"\n }\n })}:`\n}\n\nconst base = \"https://raw.githubusercontent.com/squidfunk/mkdocs-material/master/material/.icons/\"\n\nexport function renderIconSearch(\n results: string[], query: string\n) {\n if (!query.length)\n return
    \n return (\n
    \n {round(results.length)} results\n
      \n {results.slice(0, 10).map(result => (\n
    • \n \n \n \n {transform(result, query)}\n \n
    • \n ))}\n
    \n
    \n )\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Truncate a string after the given number of characters\n *\n * This is not a very reasonable approach, since the summaries kind of suck.\n * It would be better to create something more intelligent, highlighting the\n * search occurrences and making a better summary out of it, but this note was\n * written three years ago, so who knows if we'll ever fix it.\n *\n * @param value - Value to be truncated\n * @param n - Number of characters\n *\n * @returns Truncated value\n */\nexport function truncate(value: string, n: number): string {\n let i = n\n if (value.length > i) {\n while (value[i] !== \" \" && --i > 0) { /* keep eating */ }\n return `${value.substring(0, i)}...`\n }\n return value\n}\n\n/**\n * Round a number for display with repository facts\n *\n * This is a reverse-engineered version of GitHub's weird rounding algorithm\n * for stars, forks and all other numbers. While all numbers below `1,000` are\n * returned as-is, bigger numbers are converted to fixed numbers:\n *\n * - `1,049` => `1k`\n * - `1,050` => `1.1k`\n * - `1,949` => `1.9k`\n * - `1,950` => `2k`\n *\n * @param value - Original value\n *\n * @returns Rounded value\n */\nexport function round(value: number): string {\n if (value > 999) {\n const digits = +((value - 950) % 1000 > 99)\n return `${((value + 0.000001) / 1000).toFixed(digits)}k`\n } else {\n return value.toString()\n }\n}\n\n/**\n * Simple hash function\n *\n * @see https://bit.ly/2wsVjJ4 - Original source\n *\n * @param value - Value to be hashed\n *\n * @returns Hash as 32bit integer\n */\nexport function hash(value: string): number {\n let h = 0\n for (let i = 0, len = value.length; i < len; i++) {\n h = ((h << 5) - h) + value.charCodeAt(i)\n h |= 0 // Convert to 32bit integer\n }\n return h\n}\n","/*\n * Copyright (c) 2016-2020 Martin Donath \n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to\n * deal in the Software without restriction, including without limitation the\n * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or\n * sell copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in\n * all copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING\n * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS\n * IN THE SOFTWARE.\n */\n\n/* eslint-disable */\nimport { filter } from \"fuzzaldrin-plus\"\nimport { from, fromEvent } from \"rxjs\"\nimport { map, switchMap } from \"rxjs/operators\"\n\nimport { getElement, getElementOrThrow } from \"~/browser\"\n\nimport { renderIconSearch } from \"./templates/icon\"\n\n// Obtain configuration\nconst el = getElementOrThrow(\"#__config\")\nconst config = JSON.parse(el.textContent!)\n\n// Now, load icons.json\nconst icons$ =\n from(fetch(`${config.base}/overrides/assets/javascripts/icons.json`)\n .then(res => res.json())\n )\n\n// Render icon search, if present\nconst search = getElement(\"#icon-search\")\nif (search) {\n icons$\n .pipe(\n switchMap(icons => fromEvent(search, \"keyup\")\n .pipe(\n map(() => filter(icons, search.value))\n )\n )\n )\n .subscribe((result: any[]) => {\n const list = getElementOrThrow(\".tx-icon-result\")\n list.innerHTML = \"\"\n list.appendChild(renderIconSearch(result, search.value))\n })\n}\n\n// Track click events\nfromEvent(document.body, \"click\")\n .subscribe(ev => {\n if (ev.target instanceof HTMLElement) {\n const el2 = ev.target.closest(\"a[href^=http]\")\n if (el2 instanceof HTMLLinkElement)\n // @ts-ignore\n ga(\"send\", \"event\", \"outbound\", \"click\", el.href)\n }\n })\n\n"],"sourceRoot":""} \ No newline at end of file diff --git a/material/overrides/assets/javascripts/bundle.9f9f98ea.min.js.map b/material/overrides/assets/javascripts/bundle.9f9f98ea.min.js.map deleted file mode 100644 index c5b4d0dcf..000000000 --- a/material/overrides/assets/javascripts/bundle.9f9f98ea.min.js.map +++ /dev/null @@ -1 +0,0 @@ -{"version":3,"sources":["webpack:///assets/javascripts/bundle.2a65850d.min.js"],"names":["e","a","i","window","modules","webpackJsonpCallback","data","moduleId","chunkId","chunkIds","moreModules","executeModules","resolves","length","Object","prototype","hasOwnProperty","call","installedChunks","push","parentJsonpFunction","shift","deferredModules","apply","checkDeferredModules","result","deferredModule","fulfilled","j","depId","splice","__webpack_require__","s","installedModules","0","exports","module","l","m","c","d","name","getter","o","defineProperty","enumerable","get","r","Symbol","toStringTag","value","t","mode","__esModule","ns","create","key","bind","n","object","property","p","jsonpArray","oldJsonpFunction","slice","37","__webpack_exports__","fuzzaldrin","from","fromEvent","switchMap","map","getElement","selector","node","document","querySelector","undefined","getElementOrThrow","el","ReferenceError","startWith","Subject","defer","of","never","finalize","shareReplay","entry$","ResizeObserver","entries","entry","next","pipe","resize","disconnect","appendChild","child","innerHTML","toString","Node","Array","isArray","h","tag","attributes","children","createElement","attr","keys","setAttribute","renderIconSearch","results","query","class","toFixed","round","src","style","data-clipboard-text","replace","wrap","tagOpen","tagClose","transform","javascripts_el","config","JSON","parse","textContent","icons$","fetch","base","then","res","json","search","icons","subscribe","list","body","ev","target","HTMLElement","closest","HTMLLinkElement","ga","href"],"mappings":"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","file":"overrides/assets/javascripts/bundle.9f9f98ea.min.js","sourceRoot":""} \ No newline at end of file diff --git a/material/overrides/main.html b/material/overrides/main.html index 9404a7664..76aa06869 100644 --- a/material/overrides/main.html +++ b/material/overrides/main.html @@ -54,5 +54,5 @@ {% block scripts %} {{ super() }} - + {% endblock %} diff --git a/src/assets/javascripts/browser/keyboard/index.ts b/src/assets/javascripts/browser/keyboard/index.ts index 972552fb3..96bb98d83 100644 --- a/src/assets/javascripts/browser/keyboard/index.ts +++ b/src/assets/javascripts/browser/keyboard/index.ts @@ -23,20 +23,33 @@ import { Observable, fromEvent } from "rxjs" import { filter, map, share } from "rxjs/operators" +import { getActiveElement } from "../element" +import { getToggle } from "../toggle" + /* ---------------------------------------------------------------------------- * Types * ------------------------------------------------------------------------- */ /** - * Key + * Keyboard mode */ -export interface Key { +export type KeyboardMode = + | "global" /* Global */ + | "search" /* Search is open */ + +/* ------------------------------------------------------------------------- */ + +/** + * Keyboard + */ +export interface Keyboard { + mode: KeyboardMode /* Keyboard mode */ type: string /* Key type */ claim(): void /* Key claim */ } /* ---------------------------------------------------------------------------- - * Functions + * Helper functions * ------------------------------------------------------------------------- */ /** @@ -46,7 +59,7 @@ export interface Key { * * @returns Test result */ -export function isSusceptibleToKeyboard(el: HTMLElement): boolean { +function isSusceptibleToKeyboard(el: HTMLElement): boolean { switch (el.tagName) { /* Form elements */ @@ -61,24 +74,35 @@ export function isSusceptibleToKeyboard(el: HTMLElement): boolean { } } -/* ------------------------------------------------------------------------- */ +/* ---------------------------------------------------------------------------- + * Functions + * ------------------------------------------------------------------------- */ /** * Watch keyboard * * @returns Keyboard observable */ -export function watchKeyboard(): Observable { +export function watchKeyboard(): Observable { return fromEvent(window, "keydown") .pipe( filter(ev => !(ev.metaKey || ev.ctrlKey)), map(ev => ({ + mode: getToggle("search") ? "search" : "global", type: ev.key, claim() { ev.preventDefault() ev.stopPropagation() } - })), + } as Keyboard)), + filter(({ mode }) => { + if (mode === "global") { + const active = getActiveElement() + if (typeof active !== "undefined") + return !isSusceptibleToKeyboard(active) + } + return true + }), share() ) } diff --git a/src/assets/javascripts/components/search/_/index.ts b/src/assets/javascripts/components/search/_/index.ts index d46bdcbf8..45b3206c1 100644 --- a/src/assets/javascripts/components/search/_/index.ts +++ b/src/assets/javascripts/components/search/_/index.ts @@ -25,8 +25,14 @@ import { filter, sample, take } from "rxjs/operators" import { configuration } from "~/_" import { + Keyboard, + getActiveElement, getElementOrThrow, - requestJSON + getElements, + requestJSON, + setElementFocus, + setElementSelection, + setToggle } from "~/browser" import { SearchIndex, @@ -50,6 +56,17 @@ export type Search = | SearchQuery | SearchResult +/* ---------------------------------------------------------------------------- + * Helper types + * ------------------------------------------------------------------------- */ + +/** + * Mount options + */ +interface MountOptions { + keyboard$: Observable /* Keyboard observable */ +} + /* ---------------------------------------------------------------------------- * Helper functions * ------------------------------------------------------------------------- */ @@ -73,17 +90,22 @@ function fetchSearchIndex(url: string) { * Mount search * * @param el - Search element + * @param options - Options * * @returns Search component observable */ export function mountSearch( - el: HTMLElement + el: HTMLElement, { keyboard$ }: MountOptions ): Observable> { const config = configuration() const worker = setupSearchWorker(config.search, fetchSearchIndex( `${config.base}/search/search_index.json` )) + /* Retrieve elements */ + const query = getElementOrThrow("[data-md-component=search-query]", el) + const result = getElementOrThrow("[data-md-component=search-result]", el) + /* Re-emit query when search is ready */ const { tx$, rx$ } = worker tx$ @@ -94,18 +116,80 @@ export function mountSearch( ) .subscribe(tx$.next.bind(tx$)) - /* Mount search query component */ - const query$ = mountSearchQuery( - getElementOrThrow("[data-md-component=search-query]", el), - worker - ) + /* Set up search keyboard handlers */ + keyboard$ + .pipe( + filter(({ mode }) => mode === "search") + ) + .subscribe(key => { + const active = getActiveElement() + switch (key.type) { - /* Mount search result and return component */ + /* Enter: prevent form submission */ + case "Enter": + if (active === query) + key.claim() + break + + /* Escape or Tab: close search */ + case "Escape": + case "Tab": + setToggle("search", false) + setElementFocus(query, false) + break + + /* Vertical arrows: select previous or next search result */ + case "ArrowUp": + case "ArrowDown": + if (typeof active === "undefined") { + setElementFocus(query) + } else { + const els = [query, ...getElements( + ":not(details) > [href], summary, details[open] [href]", + result + )] + const i = Math.max(0, ( + Math.max(0, els.indexOf(active)) + els.length + ( + key.type === "ArrowUp" ? -1 : +1 + ) + ) % els.length) + setElementFocus(els[i]) + } + + /* Prevent scrolling of page */ + key.claim() + break + + /* All other keys: hand to search query */ + default: + if (query !== getActiveElement()) + setElementFocus(query) + } + }) + + /* Set up global keyboard handlers */ + keyboard$ + .pipe( + filter(({ mode }) => mode === "global"), + ) + .subscribe(key => { + switch (key.type) { + + /* Open search and select query */ + case "f": + case "s": + case "/": + setElementFocus(query) + setElementSelection(query) + key.claim() + break + } + }) + + /* Create and return component */ + const query$ = mountSearchQuery(query as HTMLInputElement, worker) return merge( query$, - mountSearchResult( - getElementOrThrow("[data-md-component=search-result]", el), - worker, { query$ } - ) + mountSearchResult(result, worker, { query$ }) ) } diff --git a/src/assets/javascripts/index.ts b/src/assets/javascripts/index.ts index bf4555397..b6569a918 100644 --- a/src/assets/javascripts/index.ts +++ b/src/assets/javascripts/index.ts @@ -23,6 +23,7 @@ import "focus-visible" import { Subject, defer, merge } from "rxjs" import { + filter, map, mergeWith, shareReplay, @@ -32,9 +33,11 @@ import { import { feature } from "./_" import { at, + getElement, getElementOrThrow, getElements, watchDocument, + watchKeyboard, watchLocation, watchLocationTarget, watchMedia, @@ -64,7 +67,7 @@ import { } from "./patches" /* ---------------------------------------------------------------------------- - * Program + * Application * ------------------------------------------------------------------------- */ /* Yay, JavaScript is available */ @@ -75,6 +78,7 @@ document.documentElement.classList.add("js") const document$ = watchDocument() const location$ = watchLocation() const target$ = watchLocationTarget() +const keyboard$ = watchKeyboard() /* Set up media observables */ const viewport$ = watchViewport() @@ -90,6 +94,32 @@ setupClipboardJS({ alert$ }) if (feature("navigation.instant")) setupInstantLoading({ document$, location$, viewport$ }) +/* Set up global keyboard handlers */ +keyboard$ + .pipe( + filter(({ mode }) => mode === "global") + ) + .subscribe(key => { + switch (key.type) { + + /* Go to previous page */ + case "p": + case ",": + const prev = getElement("[href][rel=prev]") + if (typeof prev !== "undefined") + prev.click() + break + + /* Go to next page */ + case "n": + case ".": + const next = getElement("[href][rel=next]") + if (typeof next !== "undefined") + next.click() + break + } + }) + /* Set up patches */ patchIndeterminate({ document$ }) patchScrollfix({ document$ }) @@ -121,7 +151,7 @@ const control$ = merge( /* Search */ ...getElements("[data-md-component=search]") - .map(child => mountSearch(child)), + .map(child => mountSearch(child, { keyboard$ })), /* Repository information */ ...getElements("[data-md-component=source]") @@ -162,16 +192,18 @@ const component$ = document$ mergeWith(control$) ) +/* Subscribe to all components */ component$.subscribe() /* Export to window */ export { document$, - component$, - viewport$, location$, target$, - screen$, + keyboard$, + viewport$, tablet$, - print$ + screen$, + print$, + component$ }