+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/assets/images/favicon.png b/assets/images/favicon.png
new file mode 100644
index 0000000..1cf13b9
Binary files /dev/null and b/assets/images/favicon.png differ
diff --git a/assets/javascripts/bundle.b39636ac.min.js b/assets/javascripts/bundle.b39636ac.min.js
new file mode 100644
index 0000000..e7f7c8c
--- /dev/null
+++ b/assets/javascripts/bundle.b39636ac.min.js
@@ -0,0 +1,2 @@
+!function(t,e){for(var n in e)t[n]=e[n]}(window,function(t){function e(e){for(var r,i,o=e[0],u=e[1],b=e[2],s=0,O=[];s0}function H(){return new E.a(new URL(location.href))}var R=n(117);function P(t,e){return e.location$.pipe(Object(R.a)(1),Object(j.a)((function(e){var n=e.href;return new URL(t,n).toString().replace(/\/$/,"")})),Object(p.a)(1))}function U(){return location.hash.substring(1)}function q(t){var e=s("a");e.href=t,e.addEventListener("click",(function(t){return t.stopPropagation()})),e.click()}function N(){return Object(c.a)(window,"hashchange").pipe(Object(j.a)(U),Object(d.a)(U()),Object(S.a)((function(t){return t.length>0})),Object(C.a)())}function z(t){var e=matchMedia(t);return Object($.a)((function(t){return e.addListener((function(){return t(e.matches)}))})).pipe(Object(d.a)(e.matches),Object(p.a)(1))}var I={drawer:u("[data-md-toggle=drawer]"),search:u("[data-md-toggle=search]")};function V(t){return I[t].checked}function D(t,e){I[t].checked!==e&&I[t].click()}function B(t){var e=I[t];return Object(c.a)(e,"change").pipe(Object(j.a)((function(){return e.checked})),Object(d.a)(e.checked))}var Y=n(62),F=n(90);function J(){return{x:Math.max(0,pageXOffset),y:Math.max(0,pageYOffset)}}function W(t){var e=t.x,n=t.y;window.scrollTo(e||0,n||0)}function K(){return{width:innerWidth,height:innerHeight}}function Q(){return Object(Y.a)([Object(l.a)(Object(c.a)(window,"scroll",{passive:!0}),Object(c.a)(window,"resize",{passive:!0})).pipe(Object(j.a)(J),Object(d.a)(J())),Object(c.a)(window,"resize",{passive:!0}).pipe(Object(j.a)(K),Object(d.a)(K()))]).pipe(Object(j.a)((function(t){var e=Object(w.h)(t,2);return{offset:e[0],size:e[1]}})),Object(p.a)(1))}function X(t,e){var n=e.header$,r=e.viewport$,c=r.pipe(Object(F.a)("size")),a=Object(Y.a)([c,n]).pipe(Object(j.a)((function(){return{x:t.offsetLeft,y:t.offsetTop}})));return Object(Y.a)([n,r,a]).pipe(Object(j.a)((function(t){var e=Object(w.h)(t,3),n=e[0].height,r=e[1],c=r.offset,a=r.size,i=e[2],o=i.x,u=i.y;return{offset:{x:c.x-o,y:c.y-u+n},size:a}})),Object(p.a)(1))}var Z=n(101),G=n(102),tt=n(82),et=n(103);function nt(t,e){var n=e.tx$,r=Object($.a)((function(e){return t.addEventListener("message",e)})).pipe(Object(Z.a)("data"));return n.pipe(Object(G.a)((function(){return r}),{leading:!0,trailing:!0}),Object(tt.a)((function(e){return t.postMessage(e)})),Object(et.a)(r),Object(C.a)())}},,,function(t,e,n){"use strict";function r(t){return"object"==typeof t&&"string"==typeof t.base&&"object"==typeof t.features&&"object"==typeof t.search}n.d(e,"d",(function(){return r})),n.d(e,"b",(function(){return b})),n.d(e,"a",(function(){return O})),n.d(e,"f",(function(){return d})),n.d(e,"g",(function(){return p})),n.d(e,"e",(function(){return h})),n.d(e,"c",(function(){return v}));var c=n(0),a=n(81);function i(t){switch(t){case"svg":case"path":return document.createElementNS("http://www.w3.org/2000/svg",t);default:return document.createElement(t)}}function o(t,e,n){switch(e){case"xmlns":break;case"viewBox":case"d":"boolean"!=typeof n?t.setAttributeNS(null,e,n):n&&t.setAttributeNS(null,e,"");break;default:"boolean"!=typeof n?t.setAttribute(e,n):n&&t.setAttribute(e,"")}}function u(t,e){var n,r;if("string"==typeof e||"number"==typeof e)t.innerHTML+=e.toString();else if(e instanceof Node)t.appendChild(e);else if(Array.isArray(e))try{for(var a=Object(c.k)(e),i=a.next();!i.done;i=a.next()){u(t,i.value)}}catch(t){n={error:t}}finally{try{i&&!i.done&&(r=a.return)&&r.call(a)}finally{if(n)throw n.error}}}function b(t,e){for(var n,r,b,f,s=[],O=2;On){for(;" "!==t[n]&&--n>0;);return t.substring(0,n)+"..."}return t}function h(t){return t>999?((t+1e-6)/1e3).toFixed(+((t-950)%1e3>99))+"k":t.toString()}function v(t){for(var e=0,n=0,r=t.length;n code").forEach((function(t,e){var n=t.parentElement;n.id="__code_"+e,n.insertBefore(Object(f.a)(n.id),t)}))}));var O=Object(a.a)((function(t){new r(".md-clipboard").on("success",t)})).pipe(Object(i.a)());return O.pipe(Object(o.a)((function(t){return t.clearSelection()})),Object(u.a)(Object(s.f)("clipboard.copied"))).subscribe(n),O}var l=n(27),j=n(41),d=n(85),p=n(35),h=n(9),v=n(59),m=n(114);function y(t){var e=(void 0===t?{}:t).duration,n=new l.a,r=Object(b.a)("div");return r.classList.add("md-dialog","md-typeset"),n.pipe(Object(p.a)((function(t){return Object(j.a)(document.body).pipe(Object(h.a)((function(t){return t.appendChild(r)})),Object(v.b)(d.a),Object(m.a)(1),Object(o.a)((function(e){e.innerHTML=t,e.setAttribute("data-md-state","open")})),Object(m.a)(e||2e3),Object(o.a)((function(t){return t.removeAttribute("data-md-state")})),Object(m.a)(400),Object(o.a)((function(t){t.innerHTML="",t.remove()})))}))).subscribe(),n}var g=n(0),w=n(95),x=n(97),$=n(116),k=n(99),S=n(48),C=n(101),A=n(90),T=n(106),E=n(107),_=n(104),L=n(91),M=n(108),H=n(92);function R(t,e){var n=e.document$,r=e.viewport$,a=e.location$;"scrollRestoration"in history&&(history.scrollRestoration="manual"),Object(w.a)(window,"beforeunload").subscribe((function(){history.scrollRestoration="auto"}));var o=Object(b.c)('link[rel="shortcut icon"]');void 0!==o&&(o.href=o.href);var u=Object(w.a)(document.body,"click").pipe(Object(k.a)((function(t){return!(t.metaKey||t.ctrlKey)})),Object(p.a)((function(e){if(e.target instanceof HTMLElement){var n=e.target.closest("a");if(n&&!n.target&&Object(b.h)(n)&&t.includes(n.href))return Object(b.g)(n)||e.preventDefault(),Object(j.a)(n)}return c.a})),Object(h.a)((function(t){return{url:new URL(t.href)}})),Object(i.a)());u.subscribe((function(){Object(b.o)("search",!1)}));var f=u.pipe(Object(k.a)((function(t){var e=t.url;return!Object(b.g)(e)})),Object(i.a)()),s=Object(w.a)(window,"popstate").pipe(Object(k.a)((function(t){return null!==t.state})),Object(h.a)((function(t){return{url:new URL(location.href),offset:t.state}})),Object(i.a)());Object(x.a)(f,s).pipe(Object(S.a)((function(t,e){return t.url.href===e.url.href})),Object(C.a)("url")).subscribe(a);var O=a.pipe(Object(A.a)("pathname"),Object(T.a)(1),Object(p.a)((function(t){return Object($.a)({url:t.href,responseType:"text",withCredentials:!0}).pipe(Object(E.a)((function(){return Object(b.m)(t),c.a})))})));f.pipe(Object(_.a)(O)).subscribe((function(t){var e=t.url;history.pushState({},"",e.toString())}));var l=new DOMParser;O.pipe(Object(h.a)((function(t){var e=t.response;return l.parseFromString(e,"text/html")}))).subscribe(n);var d=Object(x.a)(f,s).pipe(Object(_.a)(n));d.subscribe((function(t){var e=t.url,n=t.offset;e.hash&&!n?Object(b.n)(e.hash):Object(b.p)(n||{y:0})})),d.pipe(Object(L.a)(n)).subscribe((function(t){var e,n,r=Object(g.h)(t,2)[1],c=r.title,a=r.head;document.dispatchEvent(new CustomEvent("DOMContentSwitch")),document.title=c;try{for(var i=Object(g.k)(['link[rel="canonical"]','meta[name="author"]','meta[name="description"]']),o=i.next();!o.done;o=i.next()){var u=o.value,f=Object(b.c)(u,a),s=Object(b.c)(u,document.head);void 0!==f&&void 0!==s&&Object(b.j)(s,f)}}catch(t){e={error:t}}finally{try{o&&!o.done&&(n=i.return)&&n.call(i)}finally{if(e)throw e.error}}})),r.pipe(Object(M.a)(250),Object(A.a)("offset")).subscribe((function(t){var e=t.offset;history.replaceState(e,"")})),Object(x.a)(u,s).pipe(Object(H.a)(2,1),Object(k.a)((function(t){var e=Object(g.h)(t,2),n=e[0],r=e[1];return n.url.pathname===r.url.pathname&&!Object(b.g)(r.url)})),Object(h.a)((function(t){return Object(g.h)(t,2)[1]}))).subscribe((function(t){var e=t.offset;Object(b.p)(e||{y:0})}))}var P=n(7);function U(){var t=Object(b.u)().pipe(Object(h.a)((function(t){return Object(g.a)({mode:Object(b.f)("search")?"search":"global"},t)})),Object(k.a)((function(t){if("global"===t.mode){var e=Object(b.b)();if(void 0!==e)return!Object(b.i)(e)}return!0})),Object(i.a)());return t.pipe(Object(k.a)((function(t){return"search"===t.mode})),Object(L.a)(Object(P.useComponent)("search-query"),Object(P.useComponent)("search-result"))).subscribe((function(t){var e=Object(g.h)(t,3),n=e[0],r=e[1],c=e[2],a=Object(b.b)();switch(n.type){case"Enter":a===r&&n.claim();break;case"Escape":case"Tab":Object(b.o)("search",!1),Object(b.k)(r,!1);break;case"ArrowUp":case"ArrowDown":if(void 0===a)Object(b.k)(r);else{var i=Object(g.i)([r],Object(b.e)("[href]",c)),o=Math.max(0,(Math.max(0,i.indexOf(a))+i.length+("ArrowUp"===n.type?-1:1))%i.length);Object(b.k)(i[o])}n.claim();break;default:r!==Object(b.b)()&&Object(b.k)(r)}})),t.pipe(Object(k.a)((function(t){return"global"===t.mode})),Object(L.a)(Object(P.useComponent)("search-query"))).subscribe((function(t){var e=Object(g.h)(t,2),n=e[0],r=e[1];switch(n.type){case"f":case"s":case"/":Object(b.k)(r),Object(b.l)(r),n.claim();break;case"p":case",":var c=Object(b.c)("[href][rel=prev]");void 0!==c&&c.click();break;case"n":case".":var a=Object(b.c)("[href][rel=next]");void 0!==a&&a.click()}})),t}var q=n(46)},,,,,,,function(t,e,n){"use strict";n.d(e,"a",(function(){return l})),n.d(e,"b",(function(){return j}));var r,c=n(0),a=n(41),i=n(20),o=n(9),u=n(83),b=n(89),f=n(35),s=n(48),O=n(1);function l(t,e){var n=e.document$;r=n.pipe(Object(o.a)((function(e){return t.reduce((function(t,n){var r,a=Object(O.c)("[data-md-component="+n+"]",e);return Object(c.a)(Object(c.a)({},t),void 0!==a?((r={})[n]=a,r):{})}),{})})),Object(u.a)((function(e,n){var r,a;try{for(var i=Object(c.k)(t),o=i.next();!o.done;o=i.next()){var u=o.value;switch(u){case"announce":case"header-title":case"container":case"skip":u in e&&void 0!==e[u]&&(Object(O.j)(e[u],n[u]),e[u]=n[u]);break;default:void 0!==n[u]?e[u]=Object(O.c)("[data-md-component="+u+"]"):delete e[u]}}}catch(t){r={error:t}}finally{try{o&&!o.done&&(a=i.return)&&a.call(i)}finally{if(r)throw r.error}}return e})),Object(b.a)(1))}function j(t){return r.pipe(Object(f.a)((function(e){return void 0!==e[t]?Object(a.a)(e[t]):i.a})),Object(s.a)())}},,function(t,e,n){"use strict";function r(t,e){t.setAttribute("data-md-state",e?"blur":"")}function c(t){t.removeAttribute("data-md-state")}function a(t,e){t.classList.toggle("md-nav__link--active",e)}function i(t){t.classList.remove("md-nav__link--active")}n.d(e,"d",(function(){return r})),n.d(e,"b",(function(){return c})),n.d(e,"c",(function(){return a})),n.d(e,"a",(function(){return i}))},,,,,,function(t,e,n){"use strict";var r=n(64);n.o(r,"applySidebar")&&n.d(e,"applySidebar",(function(){return r.applySidebar})),n.o(r,"mountTableOfContents")&&n.d(e,"mountTableOfContents",(function(){return r.mountTableOfContents})),n.o(r,"mountTabs")&&n.d(e,"mountTabs",(function(){return r.mountTabs})),n.o(r,"watchSidebar")&&n.d(e,"watchSidebar",(function(){return r.watchSidebar}))},function(t,e,n){"use strict";n.d(e,"a",(function(){return a})),n.d(e,"b",(function(){return l})),n.d(e,"c",(function(){return p})),n.d(e,"d",(function(){return m}));var r=n(4),c="md-clipboard md-icon";function a(t){return Object(r.b)("button",{class:c,title:Object(r.f)("clipboard.copy"),"data-clipboard-target":"#"+t+" > code"},Object(r.b)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},Object(r.b)("path",{d:"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z"})))}var i=n(0),o="md-search-result__item",u="md-search-result__link",b="md-search-result__article md-search-result__article--document",f="md-search-result__article",s="md-search-result__title",O="md-search-result__teaser";function l(t){var e=t.article,n=t.sections,c=Object(r.b)("div",{class:"md-search-result__icon md-icon"},Object(r.b)("svg",{xmlns:"http://www.w3.org/2000/svg",viewBox:"0 0 24 24"},Object(r.b)("path",{d:"M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H13C12.59,21.75 12.2,21.44 11.86,21.1C11.53,20.77 11.25,20.4 11,20H6V4H13V9H18V10.18C18.71,10.34 19.39,10.61 20,11V8L14,2M20.31,18.9C21.64,16.79 21,14 18.91,12.68C16.8,11.35 14,12 12.69,14.08C11.35,16.19 12,18.97 14.09,20.3C15.55,21.23 17.41,21.23 18.88,20.32L22,23.39L23.39,22L20.31,18.9M16.5,19A2.5,2.5 0 0,1 14,16.5A2.5,2.5 0 0,1 16.5,14A2.5,2.5 0 0,1 19,16.5A2.5,2.5 0 0,1 16.5,19Z"}))),a=Object(i.i)([e],n).map((function(t){var e=t.location,n=t.title,a=t.text;return Object(r.b)("a",{href:e,class:u,tabIndex:-1},Object(r.b)("article",{class:"parent"in t?f:b},!("parent"in t)&&c,Object(r.b)("h1",{class:s},n),a.length>0&&Object(r.b)("p",{class:O},Object(r.g)(a,320))))}));return Object(r.b)("li",{class:o},a)}var j="md-source__facts",d="md-source__fact";function p(t){var e=t.map((function(t){return Object(r.b)("li",{class:d},t)}));return Object(r.b)("ul",{class:j},e)}var h="md-typeset__scrollwrap",v="md-typeset__table";function m(t){return Object(r.b)("div",{class:h},Object(r.b)("div",{class:v},t))}},function(t,e,n){"use strict";function r(t,e){t.style.top=e+"px"}function c(t){t.style.top=""}function a(t,e){t.style.height=e+"px"}function i(t){t.style.height=""}n.d(e,"d",(function(){return r})),n.d(e,"b",(function(){return c})),n.d(e,"c",(function(){return a})),n.d(e,"a",(function(){return i}))},,,,,,,,,,,,,function(t,e,n){"use strict";var r=n(69);n.o(r,"applyAnchorList")&&n.d(e,"applyAnchorList",(function(){return r.applyAnchorList})),n.o(r,"watchAnchorList")&&n.d(e,"watchAnchorList",(function(){return r.watchAnchorList}));var c=n(70);n.d(e,"applyAnchorList",(function(){return c.a})),n.d(e,"watchAnchorList",(function(){return c.b}));n(24)},function(t,e,n){"use strict";n.d(e,"b",(function(){return a})),n.d(e,"f",(function(){return y})),n.d(e,"a",(function(){return i})),n.d(e,"d",(function(){return p})),n.d(e,"c",(function(){return h})),n.d(e,"e",(function(){return v}));var r=n(0),c=n(78);!function(){function t(t){var e=t.config,n=t.docs,a=t.pipeline,i=t.index;this.documents=function(t){var e,n,a=new Map;try{for(var i=Object(r.k)(t),o=i.next();!o.done;o=i.next()){var u=o.value,b=Object(r.h)(u.location.split("#"),2),f=b[0],s=b[1],O=u.location,l=u.title,j=c(u.text).replace(/\s+(?=[,.:;!?])/g,"").replace(/\s+/g," ");if(s){var d=a.get(f);d.linked?a.set(O,{location:O,title:l,text:j,parent:d}):(d.title=u.title,d.text=j,d.linked=!0)}else a.set(O,{location:O,title:l,text:j,linked:!1})}}catch(t){e={error:t}}finally{try{o&&!o.done&&(n=i.return)&&n.call(i)}finally{if(e)throw e.error}}return a}(n),this.highlight=function(t){var e=new RegExp(t.separator,"img"),n=function(t,e,n){return e+""+n+""};return function(c){c=c.replace(/[\s*+\-:~^]+/g," ").trim();var a=new RegExp("(^|"+t.separator+")("+c.replace(/[|\\{}()[\]^$+*?.-]/g,"\\$&").replace(e,"|")+")","img");return function(t){return Object(r.a)(Object(r.a)({},t),{title:t.title.replace(a,n),text:t.text.replace(a,n)})}}}(e),lunr.tokenizer.separator=new RegExp(e.separator),this.index=void 0===i?lunr((function(){var t,c,i,o,u,b,f;1===e.lang.length&&"en"!==e.lang[0]?this.use(lunr[e.lang[0]]):e.lang.length>1&&this.use((t=lunr).multiLanguage.apply(t,Object(r.i)(e.lang)));var s=function(t,e){var n=Object(r.h)([new Set(t),new Set(e)],2),c=n[0],a=n[1];return Object(r.i)(new Set(Object(r.i)(c).filter((function(t){return!a.has(t)}))))}(["trimmer","stopWordFilter","stemmer"],a);try{for(var O=Object(r.k)(e.lang.map((function(t){return"en"===t?lunr:lunr[t]}))),l=O.next();!l.done;l=O.next()){var j=l.value;try{for(var d=(o=void 0,Object(r.k)(s)),p=d.next();!p.done;p=d.next()){var h=p.value;this.pipeline.remove(j[h]),this.searchPipeline.remove(j[h])}}catch(t){o={error:t}}finally{try{p&&!p.done&&(u=d.return)&&u.call(d)}finally{if(o)throw o.error}}}}catch(t){c={error:t}}finally{try{l&&!l.done&&(i=O.return)&&i.call(O)}finally{if(c)throw c.error}}this.field("title",{boost:1e3}),this.field("text"),this.ref("location");try{for(var v=Object(r.k)(n),m=v.next();!m.done;m=v.next()){var y=m.value;this.add(y)}}catch(t){b={error:t}}finally{try{m&&!m.done&&(f=v.return)&&f.call(v)}finally{if(b)throw b.error}}})):lunr.Index.load("string"==typeof i?JSON.parse(i):i)}t.prototype.query=function(t){var e=this;if(t)try{var n=this.index.search(t).reduce((function(t,n){var c=e.documents.get(n.ref);if(void 0!==c)if("parent"in c){var a=c.parent.location;t.set(a,Object(r.i)(t.get(a)||[],[n]))}else{a=c.location;t.set(a,t.get(a)||[])}return t}),new Map),c=this.highlight(t);return Object(r.i)(n).map((function(t){var n=Object(r.h)(t,2),a=n[0],i=n[1];return{article:c(e.documents.get(a)),sections:i.map((function(t){return c(e.documents.get(t.ref))}))}}))}catch(e){console.warn("Invalid query: "+t+" – see https://bit.ly/2s3ChXG")}return[]}}();function a(t){return t.split(/"([^"]+)"/g).map((function(t,e){return 1&e?t.replace(/^\b|^(?![^\x00-\x7F]|$)|\s+/g," +"):t})).join("").replace(/"|(?:^|\s+)[*+\-:^~]+(?=\s+|$)/g,"").trim().replace(/\s+|(?![^\x00-\x7F]|^)$|\b$/g,"* ")}var i,o=n(115),u=n(27),b=n(55),f=n(91),s=n(9),O=n(89),l=n(59),j=n(1),d=n(4);function p(t){return t.type===i.READY}function h(t){return t.type===i.QUERY}function v(t){return t.type===i.RESULT}function m(t){var e=t.config,n=t.docs,r=t.index;return 1===e.lang.length&&"en"===e.lang[0]&&(e.lang=[Object(d.f)("search.config.lang")]),"[\\s\\-]+"===e.separator&&(e.separator=Object(d.f)("search.config.separator")),{config:e,docs:n,index:r,pipeline:Object(d.f)("search.config.pipeline").split(/\s*,\s*/).filter(o.a)}}function y(t,e){var n=e.index$,c=e.base$,a=new Worker(t),o=new u.a,d=Object(j.C)(a,{tx$:o}).pipe(Object(f.a)(c),Object(s.a)((function(t){var e,n,c,a,i=Object(r.h)(t,2),o=i[0],u=i[1];if(v(o))try{for(var b=Object(r.k)(o.data),f=b.next();!f.done;f=b.next()){var s=f.value,O=s.article,l=s.sections;O.location=u+"/"+O.location;try{for(var j=(c=void 0,Object(r.k)(l)),d=j.next();!d.done;d=j.next()){var p=d.value;p.location=u+"/"+p.location}}catch(t){c={error:t}}finally{try{d&&!d.done&&(a=j.return)&&a.call(j)}finally{if(c)throw c.error}}}}catch(t){e={error:t}}finally{try{f&&!f.done&&(n=b.return)&&n.call(b)}finally{if(e)throw e.error}}return o})),Object(O.a)(1));return n.pipe(Object(s.a)((function(t){return{type:i.SETUP,data:m(t)}})),Object(l.b)(b.a)).subscribe(o.next.bind(o)),{tx$:o,rx$:d}}!function(t){t[t.SETUP=0]="SETUP",t[t.READY=1]="READY",t[t.QUERY=2]="QUERY",t[t.RESULT=3]="RESULT"}(i||(i={}))},,,,,,,,,,,,,,,,,,function(t,e,n){"use strict";var r=n(65);n.o(r,"applySidebar")&&n.d(e,"applySidebar",(function(){return r.applySidebar})),n.o(r,"mountTableOfContents")&&n.d(e,"mountTableOfContents",(function(){return r.mountTableOfContents})),n.o(r,"mountTabs")&&n.d(e,"mountTabs",(function(){return r.mountTabs})),n.o(r,"watchSidebar")&&n.d(e,"watchSidebar",(function(){return r.watchSidebar}));var c=n(66);n.d(e,"applySidebar",(function(){return c.a})),n.d(e,"watchSidebar",(function(){return c.b}));n(32)},function(t,e){},function(t,e,n){"use strict";n.d(e,"b",(function(){return j})),n.d(e,"a",(function(){return d}));var r=n(0),c=n(62),a=n(47),i=n(85),o=n(9),u=n(48),b=n(59),f=n(91),s=n(82),O=n(84),l=n(32);function j(t,e){var n=e.main$,a=e.viewport$,i=t.parentElement.offsetTop-t.parentElement.parentElement.offsetTop;return Object(c.a)([n,a]).pipe(Object(o.a)((function(t){var e=Object(r.h)(t,2),n=e[0],c=n.offset,a=n.height,o=e[1].offset.y;return{height:a=a+Math.min(i,Math.max(0,o-c))-i,lock:o>=c+i}})),Object(u.a)((function(t,e){return t.height===e.height&&t.lock===e.lock})))}function d(t,e){var n=e.header$;return Object(a.a)(Object(b.b)(i.a),Object(f.a)(n),Object(s.a)((function(e){var n=Object(r.h)(e,2),c=n[0],a=c.height,i=c.lock,o=n[1].height;Object(l.c)(t,a),i?Object(l.d)(t,o):Object(l.b)(t)})),Object(o.a)((function(t){return Object(r.h)(t,1)[0]})),Object(O.a)((function(){Object(l.b)(t),Object(l.a)(t)})))}},function(t,e,n){"use strict";var r=n(68);n.d(e,"mountTableOfContents",(function(){return r.a}));n(45)},function(t,e,n){"use strict";n.d(e,"a",(function(){return O}));var r=n(0),c=n(47),a=n(62),i=n(41),o=n(35),u=n(9),b=n(1),f=n(30),s=n(45);function O(t){var e=t.header$,n=t.main$,O=t.viewport$,l=t.tablet$;return Object(c.a)(Object(o.a)((function(t){return l.pipe(Object(o.a)((function(c){if(c){var o=Object(b.e)(".md-nav__link",t),l=Object(f.watchSidebar)(t,{main$:n,viewport$:O}).pipe(Object(f.applySidebar)(t,{header$:e})),j=Object(s.watchAnchorList)(o,{header$:e,viewport$:O}).pipe(Object(s.applyAnchorList)(o));return Object(a.a)([l,j]).pipe(Object(u.a)((function(t){var e=Object(r.h)(t,2);return{sidebar:e[0],anchors:e[1]}})))}return Object(i.a)({})})))})))}},function(t,e){},function(t,e,n){"use strict";n.d(e,"b",(function(){return y})),n.d(e,"a",(function(){return g}));var r=n(0),c=n(93),a=n(62),i=n(47),o=n(85),u=n(9),b=n(90),f=n(35),s=n(83),O=n(48),l=n(94),j=n(92),d=n(59),p=n(82),h=n(84),v=n(1),m=n(24);function y(t,e){var n,i,o=e.header$,d=e.viewport$,p=new Map;try{for(var h=Object(r.k)(t),m=h.next();!m.done;m=h.next()){var y=m.value,g=decodeURIComponent(y.hash.substring(1)),w=Object(v.c)('[id="'+g+'"]');void 0!==w&&p.set(y,w)}}catch(t){n={error:t}}finally{try{m&&!m.done&&(i=h.return)&&i.call(h)}finally{if(n)throw n.error}}var x=o.pipe(Object(u.a)((function(t){return 18+t.height})));return Object(v.t)(document.body).pipe(Object(b.a)("height"),Object(u.a)((function(){var t=[];return Object(r.i)(p).reduce((function(e,n){for(var a=Object(r.h)(n,2),i=a[0],o=a[1];t.length;){if(!(p.get(t[t.length-1]).tagName>=o.tagName))break;t.pop()}for(var u=o.offsetTop;!u&&o.parentElement;)u=(o=o.parentElement).offsetTop;return e.set(Object(c.a)(t=Object(r.i)(t,[i])),u)}),new Map)})),Object(f.a)((function(t){return Object(a.a)([x,d]).pipe(Object(s.a)((function(t,e){for(var n=Object(r.h)(t,2),c=n[0],a=n[1],i=Object(r.h)(e,2),o=i[0],u=i[1].offset.y;a.length;){if(!(Object(r.h)(a[0],2)[1]-o=u))break;a=Object(r.i)([c.pop()],a)}return[c,a]}),[[],Object(r.i)(t)]),Object(O.a)((function(t,e){return t[0]===e[0]&&t[1]===e[1]})))}))).pipe(Object(u.a)((function(t){var e=Object(r.h)(t,2),n=e[0],c=e[1];return{prev:n.map((function(t){return Object(r.h)(t,1)[0]})),next:c.map((function(t){return Object(r.h)(t,1)[0]}))}})),Object(l.a)({prev:[],next:[]}),Object(j.a)(2,1),Object(u.a)((function(t){var e=Object(r.h)(t,2),n=e[0],c=e[1];return n.prev.length16)););return n}),0),Object(u.a)(e),Object(M.a)((function(){!function(t){t.innerHTML=""}(b)})))})))}function q(t,e){var n=t.rx$,r=e.query$;return Object(c.a)(Object(i.a)((function(t){var e=t.parentElement,c=n.pipe(Object(o.a)(h.c),Object(u.a)(!0)),a=Object(p.s)(e).pipe(Object(O.a)((function(t){return t.y>=e.scrollHeight-e.offsetHeight-16})),Object(g.a)(),Object(o.a)(C.a));return n.pipe(Object(o.a)(h.d),Object(A.a)("data"),U(t,{query$:r,ready$:c,fetch$:a}),Object(b.a)([]))})))}},function(t,e,n){"use strict";n.d(e,"a",(function(){return m}));var r=n(27),c=n(47),a=n(35),i=n(90),o=n(82),u=n(22),b=n(0),f=n(62),s=n(85),O=n(101),l=n(48),j=n(89),d=n(9),p=n(59),h=n(84),v=n(1);function m(t){var e=t.header$,n=t.viewport$,m=new r.a;return Object(u.b)("header").pipe(Object(a.a)((function(t){return m.pipe(Object(i.a)("active"),(e=t,Object(c.a)(Object(p.b)(s.a),Object(o.a)((function(t){var n=t.active;!function(t,e){t.setAttribute("data-md-state",e?"shadow":"")}(e,n)})),Object(h.a)((function(){!function(t){t.removeAttribute("data-md-state")}(e)})))));var e}))).subscribe(),Object(c.a)(Object(a.a)((function(t){return function(t,e){var n=e.header$,r=e.viewport$,c=n.pipe(Object(O.a)("height"),Object(l.a)(),Object(j.a)(1)),o=c.pipe(Object(a.a)((function(){return Object(v.t)(t).pipe(Object(d.a)((function(e){var n=e.height;return{top:t.offsetTop,bottom:t.offsetTop+n}})))})),Object(i.a)("bottom"),Object(j.a)(1));return Object(f.a)([c,o,r]).pipe(Object(d.a)((function(t){var e=Object(b.h)(t,3),n=e[0],r=e[1],c=r.top,a=r.bottom,i=e[2],o=i.offset.y,u=i.size.height;return{offset:c-n,height:u=Math.max(0,u-Math.max(0,c-o,n)-Math.max(0,u+o-a)),active:c-n<=o}})),Object(l.a)((function(t,e){return t.offset===e.offset&&t.height===e.height&&t.active===e.active})))}(t,{header$:e,viewport$:n})})),Object(o.a)((function(t){return m.next(t)})))}},function(t,e,n){"use strict";n.d(e,"a",(function(){return O}));var r=n(47),c=n(35),a=n(9),i=n(90),o=n(1),u=n(85),b=n(59),f=n(82),s=n(84);function O(t){var e=t.header$,n=t.viewport$;return Object(r.a)(Object(c.a)((function(t){return Object(o.B)(t,{header$:e,viewport$:n}).pipe(Object(a.a)((function(t){return{hidden:t.offset.y>=20}})),Object(i.a)("hidden"),function(t){return Object(r.a)(Object(b.b)(u.a),Object(f.a)((function(e){var n=e.hidden;!function(t,e){t.setAttribute("data-md-state",e?"hidden":"")}(t,n)})),Object(s.a)((function(){!function(t){t.removeAttribute("data-md-state")}(t)})))}(t))})))}},function(t,e,n){"use strict";n.d(e,"a",(function(){return y}));var r=n(0),c=n(47),a=n(62),i=n(35),o=n(9),u=n(99),b=n(91),f=n(48),s=n(94),O=n(89),l=n(1),j=n(22),d=n(41),p=n(85),h=n(59),v=n(82),m=n(84);function y(t){var e=t.document$,n=t.viewport$;return Object(c.a)(Object(i.a)((function(t){var y=function(t,e){return e.document$.pipe(Object(o.a)((function(){var e=getComputedStyle(t);return["sticky","-webkit-sticky"].includes(e.position)})),Object(f.a)(),Object(i.a)((function(e){return e?Object(l.t)(t).pipe(Object(o.a)((function(t){return{sticky:!0,height:t.height}}))):Object(d.a)({sticky:!1,height:0})})),Object(O.a)(1))}(t,{document$:e}),g=Object(j.b)("main").pipe(Object(o.a)((function(t){return Object(l.c)("h1, h2, h3, h4, h5, h6",t)})),Object(u.a)((function(t){return void 0!==t})),Object(b.a)(Object(j.b)("header-title")),Object(i.a)((function(t){var e=Object(r.h)(t,2),a=e[0],i=e[1];return Object(l.B)(a,{header$:y,viewport$:n}).pipe(Object(o.a)((function(t){return t.offset.y>=a.offsetHeight?"page":"site"})),Object(f.a)(),function(t){return Object(c.a)(Object(h.b)(p.a),Object(v.a)((function(e){!function(t,e){t.setAttribute("data-md-state",e?"active":"")}(t,"page"===e)})),Object(m.a)((function(){!function(t){t.removeAttribute("data-md-state")}(t)})))}(i))})),Object(s.a)("site"));return Object(a.a)([y,g]).pipe(Object(o.a)((function(t){var e=Object(r.h)(t,2),n=e[0],c=e[1];return Object(r.a)({type:c},n)})),Object(O.a)(1))})))}},function(t,e,n){"use strict";n.d(e,"a",(function(){return l}));var r=n(47),c=n(41),a=n(35),i=n(9),o=n(90),u=n(1),b=n(85),f=n(59),s=n(82),O=n(84);function l(t){var e=t.header$,n=t.viewport$,l=t.screen$;return Object(r.a)(Object(a.a)((function(t){return l.pipe(Object(a.a)((function(a){return a?Object(u.B)(t,{header$:e,viewport$:n}).pipe(Object(i.a)((function(t){return{hidden:t.offset.y>=10}})),Object(o.a)("hidden"),function(t){return Object(r.a)(Object(f.b)(b.a),Object(s.a)((function(e){var n=e.hidden;!function(t,e){t.setAttribute("data-md-state",e?"hidden":"")}(t,n)})),Object(O.a)((function(){!function(t){t.removeAttribute("data-md-state")}(t)})))}(t)):Object(c.a)({hidden:!0})})))})))}},function(t,e,n){"use strict";n.d(e,"a",(function(){return u}));var r=n(47),c=n(41),a=n(35),i=n(9),o=n(30);function u(t){var e=t.header$,n=t.main$,u=t.viewport$,b=t.screen$;return Object(r.a)(Object(a.a)((function(t){return b.pipe(Object(a.a)((function(r){return r?Object(o.watchSidebar)(t,{main$:n,viewport$:u}).pipe(Object(o.applySidebar)(t,{header$:e}),Object(i.a)((function(t){return{sidebar:t}}))):Object(c.a)({})})))})))}},,,,,,,,,,,,function(t,e,n){"use strict";n.r(e),n.d(e,"setScrollLock",(function(){return z})),n.d(e,"resetScrollLock",(function(){return I})),n.d(e,"initialize",(function(){return V}));var r=n(0),c=n(110),a=n(112),i=n(111),o=n(79),u=n(38),b=n(41),f=n(105),s=n(62),O=n(85),l=n(95),j=n(97),d=n(116),p=n(89),h=n(35),v=n(101),m=n(107),y=n(82),g=n(114),w=n(91),x=n(59),$=n(99),k=n(9),S=n(117),C=n(1),A=n(7),T=n(15),E=n(90);var _=n(115),L=n(103);var M=n(106);var H=n(109),R=n(96);function P(){return/(iPad|iPhone|iPod)/.test(navigator.userAgent)}var U=n(31),q=n(4);function N(t){switch(Object(r.h)(t.match(/(git(?:hub|lab))/i)||[],1)[0].toLowerCase()){case"github":var e=Object(r.h)(t.match(/^.+github\.com\/([^\/]+)\/?([^\/]+)/i),3);return function(t,e){return Object(d.a)({url:void 0!==e?"https://api.github.com/repos/"+t+"/"+e:"https://api.github.com/users/"+t,responseType:"json"}).pipe(Object($.a)((function(t){return 200===t.status})),Object(v.a)("response"),Object(h.a)((function(t){if(void 0!==e){var n=t.stargazers_count,r=t.forks_count;return Object(b.a)([Object(q.e)(n||0)+" Stars",Object(q.e)(r||0)+" Forks"])}var c=t.public_repos;return Object(b.a)([Object(q.e)(c||0)+" Repositories"])})))}(e[1],e[2]);case"gitlab":var n=Object(r.h)(t.match(/^.+?([^\/]*gitlab[^\/]+)\/(.+?)\/?$/i),3);return function(t,e){return Object(d.a)({url:"https://"+t+"/api/v4/projects/"+encodeURIComponent(e),responseType:"json"}).pipe(Object($.a)((function(t){return 200===t.status})),Object(v.a)("response"),Object(k.a)((function(t){var e=t.star_count,n=t.forks_count;return[Object(q.e)(e)+" Stars",Object(q.e)(n)+" Forks"]})))}(n[1],n[2]);default:return f.a}}function z(t,e){t.setAttribute("data-md-state","lock"),t.style.top="-"+e+"px"}function I(t){var e=-1*parseInt(t.style.top,10);t.removeAttribute("data-md-state"),t.style.top="",e&&window.scrollTo(0,e)}function V(t){if(!Object(q.d)(t))throw new SyntaxError("Invalid configuration: "+JSON.stringify(t));var e=Object(C.q)(),n=Object(C.v)(),V=Object(C.w)(t.base,{location$:n}),D=Object(C.x)(),B=Object(C.A)(),Y=Object(C.y)("(min-width: 960px)"),F=Object(C.y)("(min-width: 1220px)");Object(A.setupComponents)(["announce","container","header","header-title","hero","main","navigation","search","search-query","search-reset","search-result","skip","tabs","toc"],{document$:e});var J=Object(T.h)();!function(t){var e=t.document$,n=t.viewport$,c=e.pipe(Object(k.a)((function(){return Object(C.e)("pre > code")}))),a=n.pipe(Object(E.a)("size"));Object(s.a)([c,a]).subscribe((function(t){var e,n,c=Object(r.h)(t,1)[0];try{for(var a=Object(r.k)(c),i=a.next();!i.done;i=a.next()){var o=i.value;o.scrollWidth>o.clientWidth?o.setAttribute("tabindex","0"):o.removeAttribute("tabindex")}}catch(t){e={error:t}}finally{try{i&&!i.done&&(n=a.return)&&n.call(a)}finally{if(e)throw e.error}}}))}({document$:e,viewport$:B}),function(t){var e=t.document$,n=t.hash$,c=e.pipe(Object(k.a)((function(){return Object(C.e)("details")})));Object(j.a)(Object(C.y)("print").pipe(Object($.a)(_.a)),Object(l.a)(window,"beforeprint")).pipe(Object(L.a)(c)).subscribe((function(t){var e,n;try{for(var c=Object(r.k)(t),a=c.next();!a.done;a=c.next()){a.value.setAttribute("open","")}}catch(t){e={error:t}}finally{try{a&&!a.done&&(n=c.return)&&n.call(c)}finally{if(e)throw e.error}}})),n.pipe(Object(k.a)((function(t){return Object(C.c)('[id="'+t+'"]')})),Object($.a)((function(t){return void 0!==t})),Object(y.a)((function(t){var e=t.closest("details");e&&!e.open&&e.setAttribute("open","")}))).subscribe((function(t){return t.scrollIntoView()}))}({document$:e,hash$:D}),{document$:e}.document$.pipe(Object(M.a)(1),Object(w.a)(Object(A.useComponent)("container")),Object(k.a)((function(t){var e=Object(r.h)(t,2)[1];return Object(C.e)("script",e)}))).subscribe((function(t){var e,n;try{for(var c=Object(r.k)(t),a=c.next();!a.done;a=c.next()){var i=a.value;if(i.src||/(^|\/javascript)$/i.test(i.type)){var o=Object(C.a)("script"),u=i.src?"src":"textContent";o[u]=i[u],Object(C.j)(i,o)}}}catch(t){e={error:t}}finally{try{a&&!a.done&&(n=c.return)&&n.call(c)}finally{if(e)throw e.error}}})),function(t){t.document$.pipe(Object(k.a)((function(){return Object(C.d)(".md-source[href]")})),Object(h.a)((function(t){var e=t.href;return Object(q.a)(""+Object(q.c)(e),(function(){return N(e)}))})),Object(m.a)((function(){return f.a}))).subscribe((function(t){var e,n;try{for(var c=Object(r.k)(Object(C.e)(".md-source__repository")),a=c.next();!a.done;a=c.next()){var i=a.value;i.hasAttribute("data-md-state")||(i.setAttribute("data-md-state","done"),i.appendChild(Object(U.c)(t)))}}catch(t){e={error:t}}finally{try{a&&!a.done&&(n=c.return)&&n.call(c)}finally{if(e)throw e.error}}}))}({document$:e}),function(t){var e=t.document$,n=Object(C.a)("table");e.pipe(Object(k.a)((function(){return Object(C.e)("table:not([class])")}))).subscribe((function(t){var e,c;try{for(var a=Object(r.k)(t),i=a.next();!i.done;i=a.next()){var o=i.value;Object(C.j)(o,n),Object(C.j)(n,Object(U.d)(o))}}catch(t){e={error:t}}finally{try{i&&!i.done&&(c=a.return)&&c.call(a)}finally{if(e)throw e.error}}}))}({document$:e}),function(t){var e=t.document$.pipe(Object(k.a)((function(){return Object(C.e)("[data-md-scrollfix]")})),Object(p.a)(1));e.subscribe((function(t){var e,n;try{for(var c=Object(r.k)(t),a=c.next();!a.done;a=c.next()){a.value.removeAttribute("data-md-scrollfix")}}catch(t){e={error:t}}finally{try{a&&!a.done&&(n=c.return)&&n.call(c)}finally{if(e)throw e.error}}})),Object(H.a)(P,e,f.a).pipe(Object(h.a)((function(t){return j.a.apply(void 0,Object(r.i)(t.map((function(t){return Object(l.a)(t,"touchstart",{passive:!0}).pipe(Object(R.a)(t))}))))}))).subscribe((function(t){var e=t.scrollTop;0===e?t.scrollTop=1:e+t.offsetHeight===t.scrollHeight&&(t.scrollTop=e-1)}))}({document$:e});var W=Object(T.f)(),K=Object(T.e)({document$:e,dialog$:W}),Q=Object(A.useComponent)("header").pipe(Object(A.mountHeader)({document$:e,viewport$:B}),Object(p.a)(1)),X=Object(A.useComponent)("main").pipe(Object(A.mountMain)({header$:Q,viewport$:B}),Object(p.a)(1)),Z=Object(A.useComponent)("navigation").pipe(Object(A.mountNavigation)({header$:Q,main$:X,viewport$:B,screen$:F}),Object(p.a)(1)),G=Object(A.useComponent)("toc").pipe(Object(A.mountTableOfContents)({header$:Q,main$:X,viewport$:B,tablet$:Y}),Object(p.a)(1)),tt=Object(A.useComponent)("tabs").pipe(Object(A.mountTabs)({header$:Q,viewport$:B,screen$:F}),Object(p.a)(1)),et=Object(A.useComponent)("hero").pipe(Object(A.mountHero)({header$:Q,viewport$:B}),Object(p.a)(1)),nt=Object(o.a)((function(){var e=t.search&&t.search.index?t.search.index:void 0,n=void 0!==e?Object(u.a)(e):V.pipe(Object(h.a)((function(t){return Object(d.a)({url:t+"/search/search_index.json",responseType:"json",withCredentials:!0}).pipe(Object(v.a)("response"))})));return Object(b.a)(Object(T.i)(t.search.worker,{base$:V,index$:n}))})).pipe(Object(h.a)((function(e){var n=Object(A.useComponent)("search-query").pipe(Object(A.mountSearchQuery)(e,{transform:t.search.transform}),Object(p.a)(1)),r=Object(A.useComponent)("search-reset").pipe(Object(A.mountSearchReset)(),Object(p.a)(1)),c=Object(A.useComponent)("search-result").pipe(Object(A.mountSearchResult)(e,{query$:n}),Object(p.a)(1));return Object(A.useComponent)("search").pipe(Object(A.mountSearch)(e,{query$:n,reset$:r,result$:c}))})),Object(m.a)((function(){return Object(A.useComponent)("search").subscribe((function(t){return t.hidden=!0})),f.a})),Object(p.a)(1));D.pipe(Object(y.a)((function(){return Object(C.o)("search",!1)})),Object(g.a)(125)).subscribe((function(t){return Object(C.n)("#"+t)})),Object(s.a)([Object(C.z)("search"),Y]).pipe(Object(w.a)(B),Object(h.a)((function(t){var n=Object(r.h)(t,2),c=Object(r.h)(n[0],2),a=c[0],i=c[1],o=n[1].offset.y,u=a&&!i;return e.pipe(Object(g.a)(u?400:100),Object(x.b)(O.a),Object(y.a)((function(t){var e=t.body;return u?z(e,o):I(e)})))}))).subscribe(),Object(l.a)(document.body,"click").pipe(Object($.a)((function(t){return!(t.metaKey||t.ctrlKey)})),Object($.a)((function(t){if(t.target instanceof HTMLElement){var e=t.target.closest("a");if(e&&Object(C.h)(e))return!0}return!1}))).subscribe((function(){Object(C.o)("drawer",!1)})),t.features.includes("instant")&&"file:"!==location.protocol&&V.pipe(Object(h.a)((function(t){return Object(d.a)({url:t+"/sitemap.xml",responseType:"document",withCredentials:!0}).pipe(Object(v.a)("response"))})),Object(w.a)(V),Object(k.a)((function(t){var e=Object(r.h)(t,2),n=e[0],i=e[1],o=Object(C.e)("loc",n).map((function(t){return t.textContent}));if(o.length>1){var u=Object(r.h)(Object(c.a)(Object(a.a)("length"),o),2),b=u[0],f=u[1],s=0;if(b===f)s=b.length;else for(;b.charAt(s)===f.charAt(s);)s++;for(var O=0;O\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 * @return 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\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 * @return Element or nothing\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 * @return Element\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 * @return 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 * @return Elements\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 * @return Element\n */\nexport function createElement<\n T extends keyof HTMLElementTagNameMap\n>(tagName: T): 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, shareReplay, 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(\nel: HTMLElement, value: boolean = 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 * @return 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 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, shareReplay, startWith } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Element offset\n */\nexport interface ElementOffset {\n x: number /* Horizontal offset */\n y: number /* Vertical offset */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve element offset\n *\n * @param el - Element\n *\n * @return Element offset\n */\nexport function getElementOffset(el: HTMLElement): ElementOffset {\n return {\n x: el.scrollLeft,\n y: el.scrollTop\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element offset\n *\n * @param el - Element\n *\n * @return Element offset observable\n */\nexport function watchElementOffset(\n el: HTMLElement\n): Observable {\n return merge(\n fromEvent(el, \"scroll\"),\n fromEvent(window, \"resize\")\n )\n .pipe(\n map(() => getElementOffset(el)),\n startWith(getElementOffset(el)),\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\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 ResizeObserver from \"resize-observer-polyfill\"\nimport { Observable, fromEventPattern } from \"rxjs\"\nimport { shareReplay, startWith } 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 * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve element size\n *\n * @param el - Element\n *\n * @return Element size\n */\nexport function getElementSize(el: HTMLElement): ElementSize {\n return {\n width: el.offsetWidth,\n height: el.offsetHeight\n }\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch element size\n *\n * @param el - Element\n *\n * @return Element size observable\n */\nexport function watchElementSize(\n el: HTMLElement\n): Observable {\n return fromEventPattern(next => {\n new ResizeObserver(([{ contentRect }]) => next({\n width: Math.round(contentRect.width),\n height: Math.round(contentRect.height)\n }))\n .observe(el)\n })\n .pipe(\n startWith(getElementSize(el)),\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 { filter, map, share } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Key\n */\nexport interface Key {\n type: string /* Key type */\n claim(): void /* Key claim */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Check whether an element may receive keyboard input\n *\n * @param el - Element\n *\n * @return Test result\n */\nexport function 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\n/**\n * Watch keyboard\n *\n * @return 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 type: ev.key,\n claim() {\n ev.preventDefault()\n ev.stopPropagation()\n }\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 { 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 * @return 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 * Check whether a URL is a local link or a file (except `.html`)\n *\n * @param url - URL or HTML anchor element\n * @param ref - Reference URL\n *\n * @return Test result\n */\nexport function isLocalLocation(\n url: URL | HTMLAnchorElement,\n ref: URL | Location = location\n): boolean {\n return url.host === ref.host\n && /^(?:\\/[\\w-]+)*(?:\\/?|\\.html)$/i.test(url.pathname)\n}\n\n/**\n * Check whether a URL is an anchor link on the current page\n *\n * @param url - URL or HTML anchor element\n * @param ref - Reference URL\n *\n * @return Test result\n */\nexport function isAnchorLocation(\n url: URL | HTMLAnchorElement,\n ref: URL | Location = location\n): boolean {\n return url.pathname === ref.pathname\n && url.hash.length > 0\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch location\n *\n * @return 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 } from \"rxjs\"\nimport { map, shareReplay, take } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n location$: Observable /* Location observable */\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Watch location base\n *\n * @return Location base observable\n */\nexport function watchLocationBase(\n base: string, { location$ }: WatchOptions\n): Observable {\n return location$\n .pipe(\n take(1),\n map(({ href }) => new URL(base, href)\n .toString()\n .replace(/\\/$/, \"\")\n ),\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 { filter, map, share, startWith } from \"rxjs/operators\"\n\nimport { createElement } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Retrieve location hash\n *\n * @return 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 * @return 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 * 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, fromEventPattern } from \"rxjs\"\nimport { shareReplay, startWith } from \"rxjs/operators\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch media query\n *\n * @param query - Media query\n *\n * @return Media observable\n */\nexport function watchMedia(query: string): Observable {\n const media = matchMedia(query)\n return fromEventPattern(next =>\n media.addListener(() => next(media.matches))\n )\n .pipe(\n startWith(media.matches),\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 * @return 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 * @return 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 * @return 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 * @return 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 * @return 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 * @return 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 header$: Observable /* Header observable */\n viewport$: Observable /* Viewport observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch viewport\n *\n * @return 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 * @return Viewport observable\n */\nexport function watchViewportAt(\n el: HTMLElement, { header$, viewport$ }: 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 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, Subject, fromEventPattern } from \"rxjs\"\nimport {\n pluck,\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 * @return 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$ = fromEventPattern(next =>\n worker.addEventListener(\"message\", next)\n )\n .pipe(\n pluck(\"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 { SearchIndex, SearchTransformFn } from \"integrations\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Feature flags\n */\nexport type Feature =\n | \"tabs\" /* Tabs navigation */\n | \"instant\" /* Instant loading\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Configuration\n */\nexport interface Config {\n base: string /* Base URL */\n features: Feature[] /* Feature flags */\n search: {\n worker: string /* Worker URL */\n index?: Promise /* Promise resolving with index */\n transform?: SearchTransformFn /* Transformation function */\n }\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Ensure that the given value is a valid configuration\n *\n * We could use `jsonschema` or any other schema validation framework, but that\n * would just add more bloat to the bundle, so we'll keep it plain and simple.\n *\n * @param config - Configuration\n *\n * @return Test result\n */\nexport function isConfig(config: any): config is Config {\n return typeof config === \"object\"\n && typeof config.base === \"string\"\n && typeof config.features === \"object\"\n && typeof config.search === \"object\"\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// tslint:disable no-null-keyword\n\nimport { JSX as JSXInternal } from \"preact\"\nimport { keys } from \"ramda\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * HTML and SVG attributes\n */\ntype Attributes =\n & JSXInternal.HTMLAttributes\n & JSXInternal.SVGAttributes\n & Record\n\n/**\n * Child element\n */\ntype Child =\n | HTMLElement\n | SVGElement\n | Text\n | string\n | number\n\n/* ----------------------------------------------------------------------------\n * Helper functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Create an element\n *\n * @param tagName - HTML or SVG tag\n *\n * @return Element\n */\nfunction createElement(tagName: string): HTMLElement | SVGElement {\n switch (tagName) {\n\n /* SVG elements */\n case \"svg\":\n case \"path\":\n return document.createElementNS(\"http://www.w3.org/2000/svg\", tagName)\n\n /* HTML elements */\n default:\n return document.createElement(tagName)\n }\n}\n\n/**\n * Set an attribute\n *\n * @param el - Element\n * @param name - Attribute name\n * @param value - Attribute value\n */\nfunction setAttribute(\n el: HTMLElement | SVGElement, name: string, value: string) {\n switch (name) {\n\n /* Attributes to be ignored */\n case \"xmlns\":\n break\n\n /* Attributes of SVG elements */\n case \"viewBox\":\n case \"d\":\n if (typeof value !== \"boolean\")\n el.setAttributeNS(null, name, value)\n else if (value)\n el.setAttributeNS(null, name, \"\")\n break\n\n /* Attributes of HTML elements */\n default:\n if (typeof value !== \"boolean\")\n el.setAttribute(name, value)\n else if (value)\n el.setAttribute(name, \"\")\n }\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(\n el: HTMLElement | SVGElement, child: Child | Child[]\n): 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 tagName - HTML or SVG tag\n * @param attributes - HTML attributes\n * @param children - Child elements\n *\n * @return Element\n */\nexport function h(\n tagName: string, attributes: Attributes | null, ...children: Child[]\n): HTMLElement | SVGElement {\n const el = createElement(tagName)\n\n /* Set attributes, if any */\n if (attributes)\n for (const attr of keys(attributes))\n setAttribute(el, attr, attributes[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 | SVGElement\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\nimport { Observable, defer, of } from \"rxjs\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Cache the last value emitted by an observable in session storage\n *\n * If the key is not found in session storage, the factory is executed and the\n * latest value emitted will automatically be persisted to sessions storage.\n * Note that the values emitted by the returned observable must be serializable\n * as `JSON`, or data will be lost.\n *\n * @template T - Value type\n *\n * @param key - Cache key\n * @param factory - Observable factory\n *\n * @return Value observable\n */\nexport function cache(\n key: string, factory: () => Observable\n): Observable {\n return defer(() => {\n const data = sessionStorage.getItem(key)\n if (data) {\n return of(JSON.parse(data) as T)\n\n /* Retrieve value from observable factory and write to storage */\n } else {\n const value$ = factory()\n value$.subscribe(value => {\n try {\n sessionStorage.setItem(key, JSON.stringify(value))\n } catch (err) {\n /* Uncritical, just swallow */\n }\n })\n\n /* Return value */\n return value$\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 } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Translation keys\n */\ntype TranslateKey =\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.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\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Translations\n */\nlet lang: Record\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Translate the given key\n *\n * @param key - Key to be translated\n * @param value - Value to be replaced\n *\n * @return Translation\n */\nexport function translate(key: TranslateKey, value?: string): string {\n if (typeof lang === \"undefined\") {\n const el = getElementOrThrow(\"#__lang\")\n lang = JSON.parse(el.textContent!)\n }\n if (typeof lang[key] === \"undefined\") {\n throw new ReferenceError(`Invalid translation: ${key}`)\n }\n return typeof value !== \"undefined\"\n ? lang[key].replace(\"#\", value)\n : lang[key]\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 * @return 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); // tslint:disable-line\n return `${value.substring(0, i)}...`\n }\n return value\n}\n\n/**\n * Round a number for display with source 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 * @return 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 * @return 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\nexport * from \"./_\"\nexport * from \"./header\"\nexport * from \"./hero\"\nexport * from \"./main\"\nexport * from \"./navigation\"\nexport * from \"./search\"\nexport * from \"./shared\"\nexport * from \"./tabs\"\nexport * from \"./toc\"\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 * as ClipboardJS from \"clipboard\"\nimport { NEVER, Observable, Subject, fromEventPattern } from \"rxjs\"\nimport { mapTo, share, tap } from \"rxjs/operators\"\n\nimport { getElements } from \"browser\"\nimport { renderClipboardButton } from \"templates\"\nimport { translate } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n document$: Observable /* Document observable */\n dialog$: Subject /* Dialog subject */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up clipboard\n *\n * This function implements the Clipboard.js integration and injects a button\n * into all code blocks when the document changes.\n *\n * @param options - Options\n *\n * @return Clipboard observable\n */\nexport function setupClipboard(\n { document$, dialog$ }: SetupOptions\n): Observable {\n if (!ClipboardJS.isSupported())\n return NEVER\n\n /* Inject 'copy-to-clipboard' buttons */\n document$.subscribe(() => {\n const blocks = getElements(\"pre > code\")\n blocks.forEach((block, index) => {\n const parent = block.parentElement!\n parent.id = `__code_${index}`\n parent.insertBefore(renderClipboardButton(parent.id), block)\n })\n })\n\n /* Initialize clipboard */\n const clipboard$ = fromEventPattern(next => {\n new ClipboardJS(\".md-clipboard\").on(\"success\", next)\n })\n .pipe(\n share()\n )\n\n /* Display notification for clipboard event */\n clipboard$\n .pipe(\n tap(ev => ev.clearSelection()),\n mapTo(translate(\"clipboard.copied\"))\n )\n .subscribe(dialog$)\n\n /* Return clipboard */\n return clipboard$\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 { Subject, animationFrameScheduler, of } from \"rxjs\"\nimport {\n delay,\n map,\n observeOn,\n switchMap,\n tap\n} from \"rxjs/operators\"\n\nimport { createElement } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Setup options\n */\ninterface SetupOptions {\n duration?: number /* Display duration (default: 2s) */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up dialog\n *\n * @param options - Options\n *\n * @return Dialog observable\n */\nexport function setupDialog(\n { duration }: SetupOptions = {}\n): Subject {\n const dialog$ = new Subject()\n\n /* Create dialog */\n const dialog = createElement(\"div\") // TODO: improve scoping\n dialog.classList.add(\"md-dialog\", \"md-typeset\")\n\n /* Display dialog */\n dialog$\n .pipe(\n switchMap(text => of(document.body) // useComponent(\"container\")\n .pipe(\n map(container => container.appendChild(dialog)),\n observeOn(animationFrameScheduler),\n delay(1), // Strangley it doesnt work when we push things to the new animation frame...\n tap(el => {\n el.innerHTML = text\n el.setAttribute(\"data-md-state\", \"open\")\n }),\n delay(duration || 2000),\n tap(el => el.removeAttribute(\"data-md-state\")),\n delay(400),\n tap(el => {\n el.innerHTML = \"\"\n el.remove()\n })\n )\n )\n )\n .subscribe()\n\n /* Return dialog */\n return dialog$\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, fromEvent, merge, of } from \"rxjs\"\nimport { ajax } from \"rxjs//ajax\"\nimport {\n bufferCount,\n catchError,\n debounceTime,\n distinctUntilChanged,\n distinctUntilKeyChanged,\n filter,\n map,\n pluck,\n sample,\n share,\n skip,\n switchMap,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport {\n Viewport,\n ViewportOffset,\n getElement,\n isAnchorLocation,\n isLocalLocation,\n replaceElement,\n setLocation,\n setLocationHash,\n setToggle,\n setViewportOffset\n} from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * History state\n */\ninterface State {\n url: URL /* State URL */\n offset?: ViewportOffset /* State viewport offset */\n}\n\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 * 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 urls: string[], { document$, viewport$, location$ }: SetupOptions\n): void {\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 /* Hack: ensure absolute favicon link to omit 404s on document switch */\n const favicon = getElement(`link[rel=\"shortcut icon\"]`)\n if (typeof favicon !== \"undefined\")\n favicon.href = favicon.href // tslint:disable-line no-self-assignment\n\n /* Intercept link clicks and convert to state change */\n const state$ = 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 (\n el && !el.target &&\n isLocalLocation(el) &&\n urls.includes(el.href)\n ) {\n if (!isAnchorLocation(el))\n ev.preventDefault()\n return of(el)\n }\n }\n return NEVER\n }),\n map(el => ({ url: new URL(el.href) })),\n share()\n )\n\n /* Always close search on link click */\n state$.subscribe(() => {\n setToggle(\"search\", false)\n })\n\n /* Filter state changes to dispatch */\n const push$ = state$\n .pipe(\n filter(({ url }) => !isAnchorLocation(url)),\n share()\n )\n\n /* Intercept popstate events (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 })),\n share()\n )\n\n /* Emit location change */\n merge(push$, pop$)\n .pipe(\n distinctUntilChanged((prev, next) => prev.url.href === next.url.href),\n pluck(\"url\")\n )\n .subscribe(location$)\n\n /* Fetch document on location change */\n const ajax$ = location$\n .pipe(\n distinctUntilKeyChanged(\"pathname\"),\n skip(1),\n switchMap(url => ajax({\n url: url.href,\n responseType: \"text\",\n withCredentials: true\n })\n .pipe(\n catchError(() => {\n setLocation(url)\n return NEVER\n })\n )\n )\n )\n\n /* Set new location as soon as the document was fetched */\n push$\n .pipe(\n sample(ajax$)\n )\n .subscribe(({ url }) => {\n history.pushState({}, \"\", url.toString())\n })\n\n /* Parse and emit document */\n const dom = new DOMParser()\n ajax$\n .pipe(\n map(({ response }) => dom.parseFromString(response, \"text/html\"))\n )\n .subscribe(document$)\n\n /* Intercept instant loading */\n const instant$ = merge(push$, pop$)\n .pipe(\n sample(document$)\n )\n\n // TODO: this must be combined with search scroll restoration on mobile\n instant$.subscribe(({ url, offset }) => {\n if (url.hash && !offset) {\n setLocationHash(url.hash)\n } else {\n setViewportOffset(offset || { y: 0 })\n }\n })\n\n /* Replace document metadata */\n instant$\n .pipe(\n withLatestFrom(document$)\n )\n .subscribe(([, { title, head }]) => {\n document.dispatchEvent(new CustomEvent(\"DOMContentSwitch\"))\n document.title = title\n\n /* Replace meta tags */\n for (const selector of [\n `link[rel=\"canonical\"]`,\n `meta[name=\"author\"]`,\n `meta[name=\"description\"]`\n ]) {\n const next = getElement(selector, head)\n const prev = getElement(selector, document.head)\n if (\n typeof next !== \"undefined\" &&\n typeof prev !== \"undefined\"\n ) {\n replaceElement(prev, next)\n }\n }\n })\n\n /* Debounce update of viewport offset */\n viewport$\n .pipe(\n debounceTime(250),\n distinctUntilKeyChanged(\"offset\")\n )\n .subscribe(({ offset }) => {\n history.replaceState(offset, \"\")\n })\n\n /* Set viewport offset from history */\n merge(state$, pop$)\n .pipe(\n bufferCount(2, 1),\n filter(([prev, next]) => {\n return prev.url.pathname === next.url.pathname\n && !isAnchorLocation(next.url)\n }),\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\"\nimport {\n filter,\n map,\n share,\n withLatestFrom\n} from \"rxjs/operators\"\n\nimport {\n Key,\n getActiveElement,\n getElement,\n getElements,\n getToggle,\n isSusceptibleToKeyboard,\n setElementFocus,\n setElementSelection,\n setToggle,\n watchKeyboard\n} from \"browser\"\nimport { useComponent } from \"components\"\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 extends Key {\n mode: KeyboardMode /* Keyboard mode */\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up keyboard\n *\n * This function will set up the keyboard handlers and ensure that keys are\n * correctly propagated. Currently there are two modes:\n *\n * - `global`: This mode is active when the search is closed. It is intended\n * to assign hotkeys to specific functions of the site. Currently the search,\n * previous and next page can be triggered.\n *\n * - `search`: This mode is active when the search is open. It maps certain\n * navigational keys to offer search results that can be entirely navigated\n * through keyboard input.\n *\n * The keyboard observable is returned and can be used to monitor the keyboard\n * in order toassign further hotkeys to custom functions.\n *\n * @return Keyboard observable\n */\nexport function setupKeyboard(): Observable {\n const keyboard$ = watchKeyboard()\n .pipe(\n map(key => ({\n mode: getToggle(\"search\") ? \"search\" : \"global\",\n ...key\n })),\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 /* Set up search keyboard handlers */\n keyboard$\n .pipe(\n filter(({ mode }) => mode === \"search\"),\n withLatestFrom(\n useComponent(\"search-query\"),\n useComponent(\"search-result\")\n )\n )\n .subscribe(([key, query, result]) => {\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(\"[href]\", result)]\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 withLatestFrom(useComponent(\"search-query\"))\n )\n .subscribe(([key, query]) => {\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 /* 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 /* Return keyboard */\n return keyboard$\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 { EMPTY, Observable, of } from \"rxjs\"\nimport {\n distinctUntilChanged,\n map,\n scan,\n shareReplay,\n switchMap\n} from \"rxjs/operators\"\n\nimport { getElement, replaceElement } from \"browser\"\n\n/* ----------------------------------------------------------------------------\n * Types\n * ------------------------------------------------------------------------- */\n\n/**\n * Component\n */\nexport type Component =\n | \"announce\" /* Announcement bar */\n | \"container\" /* Container */\n | \"header\" /* Header */\n | \"header-title\" /* Header title */\n | \"hero\" /* Hero */\n | \"main\" /* Main area */\n | \"navigation\" /* Navigation */\n | \"search\" /* Search */\n | \"search-query\" /* Search input */\n | \"search-reset\" /* Search reset */\n | \"search-result\" /* Search results */\n | \"skip\" /* Skip link */\n | \"tabs\" /* Tabs */\n | \"toc\" /* Table of contents */\n\n/**\n * Component map\n */\nexport type ComponentMap = {\n [P in Component]?: HTMLElement\n}\n\n/* ----------------------------------------------------------------------------\n * Helper types\n * ------------------------------------------------------------------------- */\n\n/**\n * Watch options\n */\ninterface WatchOptions {\n document$: Observable /* Document observable */\n}\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * Component map observable\n */\nlet components$: Observable\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Set up bindings to components with given names\n *\n * This function will maintain bindings to the elements identified by the given\n * names in-between document switches and update the elements in-place.\n *\n * @param names - Component names\n * @param options - Options\n */\nexport function setupComponents(\n names: Component[], { document$ }: WatchOptions\n): void {\n components$ = document$\n .pipe(\n\n /* Build component map */\n map(document => names.reduce((components, name) => {\n const el = getElement(`[data-md-component=${name}]`, document)\n return {\n ...components,\n ...typeof el !== \"undefined\" ? { [name]: el } : {}\n }\n }, {})),\n\n /* Re-compute component map on document switch */\n scan((prev, next) => {\n for (const name of names) {\n switch (name) {\n\n /* Top-level components: update */\n case \"announce\":\n case \"header-title\":\n case \"container\":\n case \"skip\":\n if (name in prev && typeof prev[name] !== \"undefined\") {\n replaceElement(prev[name]!, next[name]!)\n prev[name] = next[name]\n }\n break\n\n /* All other components: rebind */\n default:\n if (typeof next[name] !== \"undefined\")\n prev[name] = getElement(`[data-md-component=${name}]`)\n else\n delete prev[name]\n }\n }\n return prev\n }),\n\n /* Convert to hot observable */\n shareReplay(1)\n )\n}\n\n/**\n * Retrieve a component\n *\n * The returned observable will only re-emit if the element changed, i.e. if\n * it was replaced from a document which was switched to.\n *\n * @template T - Element type\n *\n * @param name - Component name\n *\n * @return Component observable\n */\nexport function useComponent(\n name: \"search-query\"\n): Observable\nexport function useComponent(\n name: Component\n): Observable\nexport function useComponent(\n name: Component\n): Observable {\n return components$\n .pipe(\n switchMap(components => (\n typeof components[name] !== \"undefined\"\n ? of(components[name] as T)\n : EMPTY\n )),\n distinctUntilChanged()\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 blur\n *\n * @param el - Anchor element\n * @param value - Whether the anchor is blurred\n */\nexport function setAnchorBlur(\n el: HTMLElement, value: boolean\n): void {\n el.setAttribute(\"data-md-state\", value ? \"blur\" : \"\")\n}\n\n/**\n * Reset anchor blur\n *\n * @param el - Anchor element\n */\nexport function resetAnchorBlur(\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\nexport * from \"./sidebar\"\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, translate } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * CSS classes\n */\nconst css = {\n container: \"md-clipboard md-icon\"\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Path of `file-search-outline` icon\n */\nconst path =\n \"M19,21H8V7H19M19,5H8A2,2 0 0,0 6,7V21A2,2 0 0,0 8,23H19A2,2 0 0,0 \" +\n \"21,21V7A2,2 0 0,0 19,5M16,1H4A2,2 0 0,0 2,3V17H4V3H16V1Z\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a 'copy-to-clipboard' button\n *\n * @param id - Unique identifier\n *\n * @return Element\n */\nexport function renderClipboardButton(\n id: string\n) {\n return (\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 { SearchResult } from \"integrations/search\"\nimport { h, truncate } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * CSS classes\n */\nconst css = {\n item: \"md-search-result__item\",\n link: \"md-search-result__link\",\n article: \"md-search-result__article md-search-result__article--document\",\n section: \"md-search-result__article\",\n title: \"md-search-result__title\",\n teaser: \"md-search-result__teaser\"\n}\n\n/* ------------------------------------------------------------------------- */\n\n/**\n * Path of `content-copy` icon\n */\nconst path =\n \"M14,2H6A2,2 0 0,0 4,4V20A2,2 0 0,0 6,22H13C12.59,21.75 12.2,21.44 \" +\n \"11.86,21.1C11.53,20.77 11.25,20.4 11,20H6V4H13V9H18V10.18C18.71,10.34 \" +\n \"19.39,10.61 20,11V8L14,2M20.31,18.9C21.64,16.79 21,14 \" +\n \"18.91,12.68C16.8,11.35 14,12 12.69,14.08C11.35,16.19 12,18.97 \" +\n \"14.09,20.3C15.55,21.23 17.41,21.23 \" +\n \"18.88,20.32L22,23.39L23.39,22L20.31,18.9M16.5,19A2.5,2.5 0 0,1 \" +\n \"14,16.5A2.5,2.5 0 0,1 16.5,14A2.5,2.5 0 0,1 19,16.5A2.5,2.5 0 0,1 16.5,19Z\"\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render a search result\n *\n * @param result - Search result\n *\n * @return Element\n */\nexport function renderSearchResult(\n { article, sections }: SearchResult\n) {\n\n /* Render icon */\n const icon = (\n
\n \n
\n )\n\n /* Render article and sections */\n const children = [article, ...sections].map(document => {\n const { location, title, text } = document\n return (\n \n \n {!(\"parent\" in document) && icon}\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 { SourceFacts } from \"patches/source\"\nimport { h } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * CSS classes\n */\nconst css = {\n facts: \"md-source__facts\",\n fact: \"md-source__fact\"\n}\n\n/* ----------------------------------------------------------------------------\n * Functions\n * ------------------------------------------------------------------------- */\n\n/**\n * Render source facts\n *\n * @param facts - Source facts\n *\n * @return Element\n */\nexport function renderSource(\n facts: SourceFacts\n) {\n const children = facts.map(fact => (\n
{fact}
\n ))\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\nimport { h } from \"utilities\"\n\n/* ----------------------------------------------------------------------------\n * Data\n * ------------------------------------------------------------------------- */\n\n/**\n * CSS classes\n */\nconst css = {\n wrapper: \"md-typeset__scrollwrap\",\n table: \"md-typeset__table\"\n}\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 * @return Element\n */\nexport function renderTable(\n table: HTMLTableElement\n) {\n return (\n