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