Added more inline comments and simplified component mounting

This commit is contained in:
squidfunk 2021-02-13 17:03:15 +01:00
parent 96797b471f
commit aacb5ca5a7
45 changed files with 155 additions and 84 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -1,16 +1,16 @@
{ {
"assets/javascripts/bundle.js": "assets/javascripts/bundle.6b6cf576.min.js", "assets/javascripts/bundle.js": "assets/javascripts/bundle.b0aa5de8.min.js",
"assets/javascripts/bundle.js.map": "assets/javascripts/bundle.6b6cf576.min.js.map", "assets/javascripts/bundle.js.map": "assets/javascripts/bundle.b0aa5de8.min.js.map",
"assets/javascripts/vendor.js": "assets/javascripts/vendor.e32ed4d0.min.js", "assets/javascripts/vendor.js": "assets/javascripts/vendor.e32ed4d0.min.js",
"assets/javascripts/vendor.js.map": "assets/javascripts/vendor.e32ed4d0.min.js.map", "assets/javascripts/vendor.js.map": "assets/javascripts/vendor.e32ed4d0.min.js.map",
"assets/javascripts/worker/search.js": "assets/javascripts/worker/search.b9424174.min.js", "assets/javascripts/worker/search.js": "assets/javascripts/worker/search.b9424174.min.js",
"assets/javascripts/worker/search.js.map": "assets/javascripts/worker/search.b9424174.min.js.map", "assets/javascripts/worker/search.js.map": "assets/javascripts/worker/search.b9424174.min.js.map",
"assets/stylesheets/main.css": "assets/stylesheets/main.c55d56a9.min.css", "assets/stylesheets/main.css": "assets/stylesheets/main.25519675.min.css",
"assets/stylesheets/main.css.map": "assets/stylesheets/main.c55d56a9.min.css.map", "assets/stylesheets/main.css.map": "assets/stylesheets/main.25519675.min.css.map",
"assets/stylesheets/palette.css": "assets/stylesheets/palette.e70b70b6.min.css", "assets/stylesheets/palette.css": "assets/stylesheets/palette.e70b70b6.min.css",
"assets/stylesheets/palette.css.map": "assets/stylesheets/palette.e70b70b6.min.css.map", "assets/stylesheets/palette.css.map": "assets/stylesheets/palette.e70b70b6.min.css.map",
"overrides/assets/javascripts/bundle.js": "overrides/assets/javascripts/bundle.63116035.min.js", "overrides/assets/javascripts/bundle.js": "overrides/assets/javascripts/bundle.c607e7b3.min.js",
"overrides/assets/javascripts/bundle.js.map": "overrides/assets/javascripts/bundle.63116035.min.js.map", "overrides/assets/javascripts/bundle.js.map": "overrides/assets/javascripts/bundle.c607e7b3.min.js.map",
"overrides/assets/javascripts/vendor.js": "overrides/assets/javascripts/vendor.1aa446d9.min.js", "overrides/assets/javascripts/vendor.js": "overrides/assets/javascripts/vendor.1aa446d9.min.js",
"overrides/assets/javascripts/vendor.js.map": "overrides/assets/javascripts/vendor.1aa446d9.min.js.map", "overrides/assets/javascripts/vendor.js.map": "overrides/assets/javascripts/vendor.1aa446d9.min.js.map",
"overrides/assets/stylesheets/main.css": "overrides/assets/stylesheets/main.d67efea2.min.css", "overrides/assets/stylesheets/main.css": "overrides/assets/stylesheets/main.d67efea2.min.css",

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -39,7 +39,7 @@
{% endif %} {% endif %}
{% endblock %} {% endblock %}
{% block styles %} {% block styles %}
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.c55d56a9.min.css' | url }}"> <link rel="stylesheet" href="{{ 'assets/stylesheets/main.25519675.min.css' | url }}">
{% if config.theme.palette %} {% if config.theme.palette %}
{% set palette = config.theme.palette %} {% set palette = config.theme.palette %}
<link rel="stylesheet" href="{{ 'assets/stylesheets/palette.e70b70b6.min.css' | url }}"> <link rel="stylesheet" href="{{ 'assets/stylesheets/palette.e70b70b6.min.css' | url }}">
@ -217,7 +217,7 @@
{% endblock %} {% endblock %}
{% block scripts %} {% block scripts %}
<script src="{{ 'assets/javascripts/vendor.e32ed4d0.min.js' | url }}"></script> <script src="{{ 'assets/javascripts/vendor.e32ed4d0.min.js' | url }}"></script>
<script src="{{ 'assets/javascripts/bundle.6b6cf576.min.js' | url }}"></script> <script src="{{ 'assets/javascripts/bundle.b0aa5de8.min.js' | url }}"></script>
{% for path in config["extra_javascript"] %} {% for path in config["extra_javascript"] %}
<script src="{{ path | url }}"></script> <script src="{{ path | url }}"></script>
{% endfor %} {% endfor %}

View File

@ -1,2 +0,0 @@
!function(e,t){for(var n in t)e[n]=t[n]}(window,function(e){function t(t){for(var r,i,a=t[0],s=t[1],u=t[2],f=0,p=[];f<a.length;f++)i=a[f],Object.prototype.hasOwnProperty.call(o,i)&&o[i]&&p.push(o[i][0]),o[i]=0;for(r in s)Object.prototype.hasOwnProperty.call(s,r)&&(e[r]=s[r]);for(l&&l(t);p.length;)p.shift()();return c.push.apply(c,u||[]),n()}function n(){for(var e,t=0;t<c.length;t++){for(var n=c[t],r=!0,a=1;a<n.length;a++){var s=n[a];0!==o[s]&&(r=!1)}r&&(c.splice(t--,1),e=i(i.s=n[0]))}return e}var r={},o={0:0},c=[];function i(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,i),n.l=!0,n.exports}i.m=e,i.c=r,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(n,r,function(t){return e[t]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="";var a=window.webpackJsonp=window.webpackJsonp||[],s=a.push.bind(a);a.push=t,a=a.slice();for(var u=0;u<a.length;u++)t(a[u]);var l=s;return c.push([37,1]),n()}({37:function(e,t,n){"use strict";n.r(t);var r=n(20),o=n(3),c=n(38),i=n(29),a=n(25);n(32),n(39);function s(e,t=document){return t.querySelector(e)||void 0}function u(e,t=document){const n=s(e,t);if(void 0===n)throw new ReferenceError(`Missing element: expected "${e}" to be present`);return n}n(50);var l=n(51);var f=n(17),p=n(40),d=n(41),b=n(42),g=n(43),h=n(44);n(45),n(46);const v=new f.a;Object(p.a)(()=>Object(d.a)(new ResizeObserver(e=>{for(const t of e)v.next(t)}))).pipe(Object(i.a)(e=>b.a.pipe(Object(l.a)(e)).pipe(Object(g.a)(()=>e.disconnect()))),Object(h.a)(1));n(31);u("[data-md-toggle=drawer]"),u("[data-md-toggle=search]");n(47);n(52),n(53);n(48),n(49);function O(e,t){if("string"==typeof t||"number"==typeof t)e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(const n of t)O(e,n)}function j(e,t,...n){const r=document.createElement(e);if(t)for(const e of Object.keys(t))"boolean"!=typeof t[e]?r.setAttribute(e,t[e]):t[e]&&r.setAttribute(e,"");for(const e of n)O(r,e);return r}function m(e,t){return t.length?j("div",{class:""},j("span",null,function(e){if(e>999){return((e+1e-6)/1e3).toFixed(+((e-950)%1e3>99))+"k"}return e.toString()}(e.length)," results"),j("ul",{class:"tx-icon-search__list"},e.slice(0,10).map(e=>j("li",{class:"tx-icon-search__item"},j("span",{class:"twemoji"},j("img",{src:"https://raw.githubusercontent.com/squidfunk/mkdocs-material/master/material/.icons/"+e,style:"width: 18px; height: 18px"}))," ",j("button",{class:"md-clipboard--inline","data-clipboard-text":":"+e.replace(/\.svg$/,"").replace(/\//g,"-")+":"},j("code",null,function(e,t){return`:${Object(r.wrap)(e.replace(/\.svg$/,"").replace(/\//g,"-"),t,{wrap:{tagOpen:"<b>",tagClose:"</b>"}})}:`}(e,t))))))):j("div",{class:""})}const y=u("#__config"),w=JSON.parse(y.textContent),x=Object(o.a)(fetch(w.base+"/overrides/assets/javascripts/icons.json").then(e=>e.json())),_=s("#icon-search");_&&x.pipe(Object(i.a)(e=>Object(c.a)(_,"keyup").pipe(Object(a.a)(()=>Object(r.filter)(e,_.value))))).subscribe(e=>{const t=u(".tx-icon-result");t.innerHTML="",t.appendChild(m(e,_.value))}),Object(c.a)(document.body,"click").subscribe(e=>{if(e.target instanceof HTMLElement){e.target.closest("a[href^=http]")instanceof HTMLLinkElement&&ga("send","event","outbound","click",y.href)}})}}));
//# sourceMappingURL=bundle.63116035.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,2 @@
!function(e,t){for(var n in t)e[n]=t[n]}(window,function(e){function t(t){for(var r,i,a=t[0],s=t[1],u=t[2],f=0,p=[];f<a.length;f++)i=a[f],Object.prototype.hasOwnProperty.call(o,i)&&o[i]&&p.push(o[i][0]),o[i]=0;for(r in s)Object.prototype.hasOwnProperty.call(s,r)&&(e[r]=s[r]);for(l&&l(t);p.length;)p.shift()();return c.push.apply(c,u||[]),n()}function n(){for(var e,t=0;t<c.length;t++){for(var n=c[t],r=!0,a=1;a<n.length;a++){var s=n[a];0!==o[s]&&(r=!1)}r&&(c.splice(t--,1),e=i(i.s=n[0]))}return e}var r={},o={0:0},c=[];function i(t){if(r[t])return r[t].exports;var n=r[t]={i:t,l:!1,exports:{}};return e[t].call(n.exports,n,n.exports,i),n.l=!0,n.exports}i.m=e,i.c=r,i.d=function(e,t,n){i.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:n})},i.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.t=function(e,t){if(1&t&&(e=i(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var n=Object.create(null);if(i.r(n),Object.defineProperty(n,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var r in e)i.d(n,r,function(t){return e[t]}.bind(null,r));return n},i.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return i.d(t,"a",t),t},i.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},i.p="";var a=window.webpackJsonp=window.webpackJsonp||[],s=a.push.bind(a);a.push=t,a=a.slice();for(var u=0;u<a.length;u++)t(a[u]);var l=s;return c.push([37,1]),n()}({37:function(e,t,n){"use strict";n.r(t);var r=n(20),o=n(3),c=n(38),i=n(29),a=n(25);n(32),n(39);function s(e,t=document){return t.querySelector(e)||void 0}function u(e,t=document){const n=s(e,t);if(void 0===n)throw new ReferenceError(`Missing element: expected "${e}" to be present`);return n}n(50);var l=n(51);var f=n(17),p=n(40),b=n(41),d=n(42),g=n(43),h=n(44);n(45),n(46);const v=new f.a;Object(p.a)(()=>Object(b.a)(new ResizeObserver(e=>{for(const t of e)v.next(t)}))).pipe(Object(i.a)(e=>d.a.pipe(Object(l.a)(e)).pipe(Object(g.a)(()=>e.disconnect()))),Object(h.a)(1));n(31);u("[data-md-toggle=drawer]"),u("[data-md-toggle=search]");n(47);function O(){return new URL(location.href)}n(52),n(53);n(48),n(49);const j=u("#__config"),m=JSON.parse(j.textContent);function y(e,t){if("string"==typeof t||"number"==typeof t)e.innerHTML+=t.toString();else if(t instanceof Node)e.appendChild(t);else if(Array.isArray(t))for(const n of t)y(e,n)}function w(e,t,...n){const r=document.createElement(e);if(t)for(const e of Object.keys(t))"boolean"!=typeof t[e]?r.setAttribute(e,t[e]):t[e]&&r.setAttribute(e,"");for(const e of n)y(r,e);return r}m.base=new URL(m.base,O()).toString().replace(/\/$/,"");function x(e,t){return t.length?w("div",{class:""},w("span",null,function(e){if(e>999){return((e+1e-6)/1e3).toFixed(+((e-950)%1e3>99))+"k"}return e.toString()}(e.length)," results"),w("ul",{class:"tx-icon-search__list"},e.slice(0,10).map(e=>w("li",{class:"tx-icon-search__item"},w("span",{class:"twemoji"},w("img",{src:"https://raw.githubusercontent.com/squidfunk/mkdocs-material/master/material/.icons/"+e,style:"width: 18px; height: 18px"}))," ",w("button",{class:"md-clipboard--inline","data-clipboard-text":":"+e.replace(/\.svg$/,"").replace(/\//g,"-")+":"},w("code",null,function(e,t){return`:${Object(r.wrap)(e.replace(/\.svg$/,"").replace(/\//g,"-"),t,{wrap:{tagOpen:"<b>",tagClose:"</b>"}})}:`}(e,t))))))):w("div",{class:""})}const _=m,k=Object(o.a)(fetch(_.base+"/overrides/assets/javascripts/icons.json").then(e=>e.json())),S=s("#icon-search");S&&k.pipe(Object(i.a)(e=>Object(c.a)(S,"keyup").pipe(Object(a.a)(()=>Object(r.filter)(e,S.value))))).subscribe(e=>{const t=u(".tx-icon-result");t.innerHTML="",t.appendChild(x(e,S.value))}),Object(c.a)(document.body,"click").subscribe(e=>{if(e.target instanceof HTMLElement){e.target.closest("a[href^=http]")instanceof HTMLLinkElement&&ga("send","event","outbound","click",el.href)}})}}));
//# sourceMappingURL=bundle.c607e7b3.min.js.map

File diff suppressed because one or more lines are too long

View File

@ -54,5 +54,5 @@
{% block scripts %} {% block scripts %}
{{ super() }} {{ super() }}
<script src="{{ 'overrides/assets/javascripts/vendor.1aa446d9.min.js' | url }}"></script> <script src="{{ 'overrides/assets/javascripts/vendor.1aa446d9.min.js' | url }}"></script>
<script src="{{ 'overrides/assets/javascripts/bundle.63116035.min.js' | url }}"></script> <script src="{{ 'overrides/assets/javascripts/bundle.c607e7b3.min.js' | url }}"></script>
{% endblock %} {% endblock %}

View File

@ -31,8 +31,11 @@ import { getElementOrThrow, getLocation } from "~/browser"
*/ */
export type Flag = export type Flag =
| "header.autohide" /* Hide header */ | "header.autohide" /* Hide header */
| "navigation.tabs" /* Tabs navigation */ | "navigation.expand" /* Automatic expansion */
| "navigation.instant" /* Instant loading */ | "navigation.instant" /* Instant loading */
| "navigation.sections" /* Sections navigation */
| "navigation.tabs" /* Tabs navigation */
| "toc.integrate" /* Integrated table of contents */
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */

View File

@ -67,19 +67,19 @@ export function watchPrint(): Observable<void> {
/* ------------------------------------------------------------------------- */ /* ------------------------------------------------------------------------- */
/** /**
* Toggle an observable with another one * Toggle an observable with a media observable
* *
* @template T - Data type * @template T - Data type
* *
* @param toggle$ - Toggle observable * @param query$ - Media observable
* @param factory - Observable factory * @param factory - Observable factory
* *
* @returns Toggled observable * @returns Toggled observable
*/ */
export function at<T>( export function at<T>(
toggle$: Observable<boolean>, factory: () => Observable<T> query$: Observable<boolean>, factory: () => Observable<T>
): Observable<T> { ): Observable<T> {
return toggle$ return query$
.pipe( .pipe(
switchMap(active => active ? factory() : NEVER) switchMap(active => active ? factory() : NEVER)
) )

View File

@ -20,6 +20,8 @@
* IN THE SOFTWARE. * IN THE SOFTWARE.
*/ */
import { getElementOrThrow, getElements } from "~/browser"
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* Types * Types
* ------------------------------------------------------------------------- */ * ------------------------------------------------------------------------- */
@ -31,12 +33,14 @@ export type ComponentType =
| "announce" /* Announcement bar */ | "announce" /* Announcement bar */
| "container" /* Container */ | "container" /* Container */
| "content" /* Content */ | "content" /* Content */
| "dialog" /* Dialog */
| "header" /* Header */ | "header" /* Header */
| "header-title" /* Header title */ | "header-title" /* Header title */
| "main" /* Main area */ | "main" /* Main area */
| "search" /* Search */ | "search" /* Search */
| "search-query" /* Search input */ | "search-query" /* Search input */
| "search-result" /* Search results */ | "search-result" /* Search results */
| "sidebar" /* Sidebar */
| "skip" /* Skip link */ | "skip" /* Skip link */
| "source" /* Repository information */ | "source" /* Repository information */
| "tabs" /* Navigation tabs */ | "tabs" /* Navigation tabs */
@ -55,3 +59,39 @@ export type Component<
T & { T & {
ref: U /* Component reference */ ref: U /* Component reference */
} }
/* ----------------------------------------------------------------------------
* Functions
* ------------------------------------------------------------------------- */
/**
* Retrieve the element for a given component or throw a reference error
*
* @template T - Element type
*
* @param type - Component type
* @param node - Node of reference
*
* @returns Element
*/
export function getComponentElement<T extends HTMLElement>(
type: ComponentType, node: ParentNode = document
): T {
return getElementOrThrow(`[data-md-component=${type}]`, node)
}
/**
* Retrieve all elements for a given component
*
* @template T - Element type
*
* @param type - Component type
* @param node - Node of reference
*
* @returns Elements
*/
export function getComponentElements<T extends HTMLElement>(
type: ComponentType, node: ParentNode = document
): T[] {
return getElements(`[data-md-component=${type}]`, node)
}

View File

@ -61,6 +61,9 @@ interface MountOptions {
/** /**
* Mount content * Mount content
* *
* This function mounts all components that are found in the content of the
* actual article, including code blocks, data tables and details.
*
* @param el - Content element * @param el - Content element
* @param options - Options * @param options - Options
* *

View File

@ -111,8 +111,8 @@ export function watchCodeBlock(
/** /**
* Mount code block * Mount code block
* *
* This function ensures that overflowing code blocks are focusable by keyboard, * This function ensures that an overflowing code block is focusable through
* so they can be scrolled without a mouse to improve on accessibility. * keyboard, so it can be scrolled without a mouse to improve on accessibility.
* *
* @param el - Code block element * @param el - Code block element
* @param options - Options * @param options - Options

View File

@ -88,8 +88,8 @@ export function watchDetails(
/** /**
* Mount details * Mount details
* *
* This function ensures that `details` tags are opened prior to printing, so * This function ensures that `details` tags are opened on anchor jumps and
* the whole content of the page is included and on anchor jumps. * prior to printing, so the whole content of the page is visible.
* *
* @param el - Details element * @param el - Details element
* @param options - Options * @param options - Options

View File

@ -52,6 +52,9 @@ const sentinel = createElement("table")
/** /**
* Mount data table * Mount data table
* *
* This function wraps a data table in another scrollable container, so they
* can be scrolled on smaller screen sizes and won't break the layout.
*
* @param el - Data table element * @param el - Data table element
* *
* @returns Data table component observable * @returns Data table component observable

View File

@ -105,6 +105,9 @@ export function watchDialog(
/** /**
* Mount dialog * Mount dialog
* *
* This function makes the dialog in the right corner appear when a new alert
* is emitted through the subject that is passed as part of the options.
*
* @param el - Dialog element * @param el - Dialog element
* @param options - Options * @param options - Options
* *

View File

@ -34,12 +34,15 @@ import {
combineLatestWith, combineLatestWith,
distinctUntilChanged, distinctUntilChanged,
distinctUntilKeyChanged, distinctUntilKeyChanged,
endWith,
filter, filter,
finalize,
map, map,
observeOn, observeOn,
shareReplay, shareReplay,
startWith, startWith,
switchMap switchMap,
tap
} from "rxjs/operators" } from "rxjs/operators"
import { feature } from "~/_" import { feature } from "~/_"
@ -118,7 +121,7 @@ function isHidden({ viewport$ }: WatchOptions): Observable<boolean> {
.pipe( .pipe(
filter(([{ offset }, [, y]]) => Math.abs(y - offset.y) > 100), filter(([{ offset }, [, y]]) => Math.abs(y - offset.y) > 100),
map(([, [direction]]) => direction), map(([, [direction]]) => direction),
distinctUntilChanged(), distinctUntilChanged()
) )
/* Compute threshold for autohiding */ /* Compute threshold for autohiding */
@ -127,7 +130,7 @@ function isHidden({ viewport$ }: WatchOptions): Observable<boolean> {
.pipe( .pipe(
map(([{ offset }, search]) => offset.y > 400 && !search), map(([{ offset }, search]) => offset.y > 400 && !search),
distinctUntilChanged(), distinctUntilChanged(),
switchMap(active => active ? hidden$ : NEVER), switchMap(active => active ? hidden$ : of(false)),
startWith(false) startWith(false)
) )
} }
@ -173,10 +176,8 @@ export function watchHeader(
/** /**
* Mount header * Mount header
* *
* The header must be connected to the main area observable outside of the * This function manages the different states of the header, i.e. whether it's
* operator function, as the header will persist in-between document switches * hidden or rendered with a shadow. This depends heavily on the main area.
* while the main area is replaced. However, the header observable must be
* passed to this function, so we connect both via a long-living subject.
* *
* @param el - Header element * @param el - Header element
* @param options - Options * @param options - Options

View File

@ -20,7 +20,12 @@
* IN THE SOFTWARE. * IN THE SOFTWARE.
*/ */
import { NEVER, Observable, Subject, animationFrameScheduler } from "rxjs" import {
NEVER,
Observable,
Subject,
animationFrameScheduler
} from "rxjs"
import { import {
distinctUntilKeyChanged, distinctUntilKeyChanged,
finalize, finalize,
@ -104,6 +109,9 @@ export function watchHeaderTitle(
/** /**
* Mount header title * Mount header title
* *
* This function swaps the header title from the site title to the title of the
* current page when the user scrolls past the first headline.
*
* @param el - Header title element * @param el - Header title element
* @param options - Options * @param options - Options
* *

View File

@ -27,7 +27,6 @@ import { configuration } from "~/_"
import { import {
Keyboard, Keyboard,
getActiveElement, getActiveElement,
getElementOrThrow,
getElements, getElements,
requestJSON, requestJSON,
setElementFocus, setElementFocus,
@ -41,7 +40,7 @@ import {
setupSearchWorker setupSearchWorker
} from "~/integrations" } from "~/integrations"
import { Component } from "../../_" import { Component, getComponentElement } from "../../_"
import { SearchQuery, mountSearchQuery } from "../query" import { SearchQuery, mountSearchQuery } from "../query"
import { SearchResult, mountSearchResult } from "../result" import { SearchResult, mountSearchResult } from "../result"
@ -89,6 +88,9 @@ function fetchSearchIndex(url: string) {
/** /**
* Mount search * Mount search
* *
* This function sets up the search functionality, including the underlying
* web worker and all keyboard bindings.
*
* @param el - Search element * @param el - Search element
* @param options - Options * @param options - Options
* *
@ -103,8 +105,8 @@ export function mountSearch(
)) ))
/* Retrieve elements */ /* Retrieve elements */
const query = getElementOrThrow("[data-md-component=search-query]", el) const query = getComponentElement("search-query", el)
const result = getElementOrThrow("[data-md-component=search-result]", el) const result = getComponentElement("search-result", el)
/* Re-emit query when search is ready */ /* Re-emit query when search is ready */
const { tx$, rx$ } = worker const { tx$, rx$ } = worker

View File

@ -64,6 +64,9 @@ let fetch$: Observable<Source>
/** /**
* Watch repository information * Watch repository information
* *
* This function will try to read the repository facts from session storage,
* and if unsuccessful, fetch them from the underlying provider.
*
* @param el - Repository information element * @param el - Repository information element
* *
* @returns Repository information observable * @returns Repository information observable

View File

@ -95,6 +95,9 @@ export function watchTabs(
/** /**
* Mount navigation tabs * Mount navigation tabs
* *
* This function hides the navigation tabs when scrolling past the threshold
* and makes them reappear in a nice CSS animation when scrolling back up.
*
* @param el - Navigation tabs element * @param el - Navigation tabs element
* @param options - Options * @param options - Options
* *

View File

@ -34,8 +34,6 @@ import { feature } from "./_"
import { import {
at, at,
getElement, getElement,
getElementOrThrow,
getElements,
setToggle, setToggle,
watchDocument, watchDocument,
watchKeyboard, watchKeyboard,
@ -46,6 +44,8 @@ import {
watchViewport watchViewport
} from "./browser" } from "./browser"
import { import {
getComponentElement,
getComponentElements,
mountContent, mountContent,
mountDialog, mountDialog,
mountHeader, mountHeader,
@ -129,16 +129,11 @@ keyboard$
patchIndeterminate({ document$ }) patchIndeterminate({ document$ })
patchScrollfix({ document$ }) patchScrollfix({ document$ })
/* Set up header observable */ /* Set up header and main area observable */
const header$ = watchHeader( const header$ = watchHeader(getComponentElement("header"), { viewport$ })
getElementOrThrow("[data-md-component=header]"),
{ viewport$ }
)
/* Set up main area observable */
const main$ = document$ const main$ = document$
.pipe( .pipe(
map(() => getElementOrThrow("[data-md-component=main]")), map(() => getComponentElement("main")),
switchMap(el => watchMain(el, { viewport$, header$ })), switchMap(el => watchMain(el, { viewport$, header$ })),
shareReplay(1) shareReplay(1)
) )
@ -147,23 +142,23 @@ const main$ = document$
const control$ = merge( const control$ = merge(
/* Dialog */ /* Dialog */
...getElements("[data-md-component=dialog]") ...getComponentElements("dialog")
.map(child => mountDialog(child, { alert$ })), .map(child => mountDialog(child, { alert$ })),
/* Header */ /* Header */
...getElements("[data-md-component=header]") ...getComponentElements("header")
.map(child => mountHeader(child, { viewport$, header$, main$ })), .map(child => mountHeader(child, { viewport$, header$, main$ })),
/* Search */ /* Search */
...getElements("[data-md-component=search]") ...getComponentElements("search")
.map(child => mountSearch(child, { keyboard$ })), .map(child => mountSearch(child, { keyboard$ })),
/* Repository information */ /* Repository information */
...getElements("[data-md-component=source]") ...getComponentElements("source")
.map(child => mountSource(child as HTMLAnchorElement)), .map(child => mountSource(child as HTMLAnchorElement)),
/* Navigation tabs */ /* Navigation tabs */
...getElements("[data-md-component=tabs]") ...getComponentElements("tabs")
.map(child => mountTabs(child, { viewport$, header$ })), .map(child => mountTabs(child, { viewport$, header$ })),
) )
@ -171,22 +166,22 @@ const control$ = merge(
const content$ = defer(() => merge( const content$ = defer(() => merge(
/* Content */ /* Content */
...getElements("[data-md-component=content]") ...getComponentElements("content")
.map(child => mountContent(child, { target$, viewport$, print$ })), .map(child => mountContent(child, { target$, viewport$, print$ })),
/* Header title */ /* Header title */
...getElements("[data-md-component=header-title]") ...getComponentElements("header-title")
.map(child => mountHeaderTitle(child, { viewport$, header$ })), .map(child => mountHeaderTitle(child, { viewport$, header$ })),
/* Sidebar */ /* Sidebar */
...getElements("[data-md-component=sidebar]") ...getComponentElements("sidebar")
.map(child => child.getAttribute("data-md-type") === "navigation" .map(child => child.getAttribute("data-md-type") === "navigation"
? at(screen$, () => mountSidebar(child, { viewport$, header$, main$ })) ? at(screen$, () => mountSidebar(child, { viewport$, header$, main$ }))
: at(tablet$, () => mountSidebar(child, { viewport$, header$, main$ })) : at(tablet$, () => mountSidebar(child, { viewport$, header$, main$ }))
), ),
/* Table of contents */ /* Table of contents */
...getElements("[data-md-component=toc]") ...getComponentElements("toc")
.map(child => mountTableOfContents(child, { viewport$, header$ })), .map(child => mountTableOfContents(child, { viewport$, header$ })),
)) ))
@ -194,7 +189,8 @@ const content$ = defer(() => merge(
const component$ = document$ const component$ = document$
.pipe( .pipe(
switchMap(() => content$), switchMap(() => content$),
mergeWith(control$) mergeWith(control$),
shareReplay(1)
) )
/* Subscribe to all components */ /* Subscribe to all components */

View File

@ -51,7 +51,6 @@ import {
ViewportOffset, ViewportOffset,
createElement, createElement,
getElement, getElement,
getElementOrThrow,
getElements, getElements,
replaceElement, replaceElement,
request, request,
@ -60,6 +59,7 @@ import {
setLocationHash, setLocationHash,
setViewportOffset setViewportOffset
} from "~/browser" } from "~/browser"
import { getComponentElement } from "~/components"
/* ---------------------------------------------------------------------------- /* ----------------------------------------------------------------------------
* Types * Types
@ -261,14 +261,12 @@ export function setupInstantLoading(
setViewportOffset(offset || { y: 0 }) setViewportOffset(offset || { y: 0 })
}) })
/* Replace components */ /* Replace meta tags and components */
document$ document$
.pipe( .pipe(
skip(1) skip(1)
) )
.subscribe(replacement => { .subscribe(replacement => {
/* Replace meta tags and components */
for (const selector of [ for (const selector of [
/* Meta tags */ /* Meta tags */
@ -298,7 +296,7 @@ export function setupInstantLoading(
document$ document$
.pipe( .pipe(
skip(1), skip(1),
map(() => getElementOrThrow("[data-md-component=container]")), map(() => getComponentElement("container")),
switchMap(el => of(...getElements("script", el))), switchMap(el => of(...getElements("script", el))),
concatMap(el => { concatMap(el => {
const script = createElement("script") const script = createElement("script")

View File

@ -42,6 +42,9 @@ interface PatchOptions {
/** /**
* Patch indeterminate checkboxes * Patch indeterminate checkboxes
* *
* This function will replace the indeterminate "pseudo state" with the actual
* indeterminate state, which is used to keep navigation always expanded.
*
* @param options - Options * @param options - Options
*/ */
export function patchIndeterminate( export function patchIndeterminate(

View File

@ -34,7 +34,7 @@ import { h } from "~/utilities"
* *
* @returns Element * @returns Element
*/ */
export function renderClipboardButton(id: string) { export function renderClipboardButton(id: string): HTMLElement {
return ( return (
<button <button
class="md-clipboard md-icon" class="md-clipboard md-icon"

View File

@ -47,7 +47,7 @@ const enum Flag {
/** /**
* Render a search document * Render a search document
* *
* @param section - Search document * @param document - Search document
* @param flag - Render flags * @param flag - Render flags
* *
* @returns Element * @returns Element
@ -106,8 +106,8 @@ function renderSearchDocument(
* @returns Element * @returns Element
*/ */
export function renderSearchResult( export function renderSearchResult(
result: SearchResult, threshold: number = Infinity result: SearchResult, threshold = Infinity
) { ): HTMLElement {
const docs = [...result] const docs = [...result]
/* Find and extract parent article */ /* Find and extract parent article */

View File

@ -34,7 +34,7 @@ import { h } from "~/utilities"
* *
* @returns Element * @returns Element
*/ */
export function renderSourceFacts(facts: SourceFacts) { export function renderSourceFacts(facts: SourceFacts): HTMLElement {
return ( return (
<ul class="md-source__facts"> <ul class="md-source__facts">
{facts.map(fact => ( {facts.map(fact => (

View File

@ -33,7 +33,7 @@ import { h } from "utilities"
* *
* @returns Element * @returns Element
*/ */
export function renderTable(table: HTMLElement) { export function renderTable(table: HTMLElement): HTMLElement {
return ( return (
<div class="md-typeset__scrollwrap"> <div class="md-typeset__scrollwrap">
<div class="md-typeset__table"> <div class="md-typeset__table">

View File

@ -20,5 +20,5 @@
* IN THE SOFTWARE. * IN THE SOFTWARE.
*/ */
export * from "./jsx" export * from "./h"
export * from "./string" export * from "./string"

View File

@ -164,7 +164,7 @@ kbd {
} }
} }
// Code blocks // Code block
code, code,
pre, pre,
kbd { kbd {
@ -177,7 +177,7 @@ kbd {
} }
} }
// Inline code blocks // Inline code block
code { code {
padding: 0 px2em(4px, 13.6px); padding: 0 px2em(4px, 13.6px);
font-size: px2em(13.6px); font-size: px2em(13.6px);

View File

@ -39,7 +39,8 @@
// Arithmatex content // Arithmatex content
> * { > * {
width: min-content; width: min-content;
margin: 1em auto !important; // stylelint-disable-line // stylelint-disable-next-line declaration-no-important
margin: 1em auto !important;
padding: 0 px2rem(16px); padding: 0 px2rem(16px);
touch-action: auto; touch-action: auto;
} }

View File

@ -27,7 +27,7 @@
// Scoped in typesetted content to match specificity of regular content // Scoped in typesetted content to match specificity of regular content
.md-typeset { .md-typeset {
// Deletions, additions and comments // Deletion, addition or comment
del.critic, del.critic,
ins.critic, ins.critic,
.critic.comment { .critic.comment {

View File

@ -80,11 +80,11 @@
content: ""; content: "";
} }
// Inline copy to clipboard // Inline button
&--inline { &--inline {
cursor: pointer; cursor: pointer;
// Code blocks // Code block
code { code {
transition: transition:
color 250ms, color 250ms,

View File

@ -27,7 +27,7 @@
// Scoped in typesetted content to match specificity of regular content // Scoped in typesetted content to match specificity of regular content
.md-typeset { .md-typeset {
// Button // Form button
.md-button { .md-button {
display: inline-block; display: inline-block;
padding: px2em(10px) px2em(32px); padding: px2em(10px) px2em(32px);
@ -56,9 +56,8 @@
} }
} }
// Input // Form input
.md-input { .md-input {
width: 100%;
height: px2rem(36px); height: px2rem(36px);
padding: 0 px2rem(12px); padding: 0 px2rem(12px);
font-size: px2rem(16px); font-size: px2rem(16px);
@ -75,5 +74,10 @@
0 px2rem(8px) px2rem(20px) hsla(0, 0%, 0%, 0.15), 0 px2rem(8px) px2rem(20px) hsla(0, 0%, 0%, 0.15),
0 px2rem(0.5px) px2rem(1px) hsla(0, 0%, 0%, 0.15); 0 px2rem(0.5px) px2rem(1px) hsla(0, 0%, 0%, 0.15);
} }
// Stretch to full width
&--stretch {
width: 100%;
}
} }
} }

View File

@ -72,7 +72,7 @@
} }
// Header navigation - if the header exceeds the default height of `48px`, i.e. // Header navigation - if the header exceeds the default height of `48px`, i.e.
// by adding a bigger logo, the items are agned at the center // by adding a bigger logo, the items are aligned at the center
.md-header-nav { .md-header-nav {
display: flex; display: flex;
align-items: center; align-items: center;

View File

@ -25,13 +25,13 @@ import { filter } from "fuzzaldrin-plus"
import { from, fromEvent } from "rxjs" import { from, fromEvent } from "rxjs"
import { map, switchMap } from "rxjs/operators" import { map, switchMap } from "rxjs/operators"
import { configuration } from "~/_"
import { getElement, getElementOrThrow } from "~/browser" import { getElement, getElementOrThrow } from "~/browser"
import { renderIconSearch } from "./templates/icon" import { renderIconSearch } from "./templates/icon"
// Obtain configuration // Obtain configuration
const el = getElementOrThrow("#__config") const config = configuration()
const config = JSON.parse(el.textContent!)
// Now, load icons.json // Now, load icons.json
const icons$ = const icons$ =