mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2024-11-27 17:00:54 +01:00
Refactored project structure
This commit is contained in:
parent
ad1b964aaa
commit
88ba609ee1
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
29
material/assets/javascripts/bundle.4fa4ff07.min.js
vendored
Normal file
29
material/assets/javascripts/bundle.4fa4ff07.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7
material/assets/javascripts/bundle.4fa4ff07.min.js.map
Normal file
7
material/assets/javascripts/bundle.4fa4ff07.min.js.map
Normal file
File diff suppressed because one or more lines are too long
@ -34,7 +34,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block styles %}
|
{% block styles %}
|
||||||
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.b5f74394.min.css' | url }}">
|
<link rel="stylesheet" href="{{ 'assets/stylesheets/main.b29cf17d.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.9204c3b2.min.css' | url }}">
|
<link rel="stylesheet" href="{{ 'assets/stylesheets/palette.9204c3b2.min.css' | url }}">
|
||||||
@ -211,7 +211,7 @@
|
|||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script src="{{ 'assets/javascripts/bundle.0d86bc28.min.js' | url }}"></script>
|
<script src="{{ 'assets/javascripts/bundle.4fa4ff07.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 %}
|
||||||
|
File diff suppressed because one or more lines are too long
18
material/overrides/assets/javascripts/bundle.5ee92cf1.min.js
vendored
Normal file
18
material/overrides/assets/javascripts/bundle.5ee92cf1.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@ -16,5 +16,5 @@
|
|||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
{{ super() }}
|
{{ super() }}
|
||||||
<script src="{{ 'overrides/assets/javascripts/bundle.2a83b894.min.js' | url }}"></script>
|
<script src="{{ 'overrides/assets/javascripts/bundle.5ee92cf1.min.js' | url }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
* IN THE SOFTWARE.
|
* IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getElementOrThrow, getLocation } from "~/browser"
|
import { getElement, getLocation } from "~/browser"
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
* Types
|
* Types
|
||||||
@ -99,7 +99,7 @@ export interface Config {
|
|||||||
/**
|
/**
|
||||||
* Retrieve global configuration and make base URL absolute
|
* Retrieve global configuration and make base URL absolute
|
||||||
*/
|
*/
|
||||||
const script = getElementOrThrow("#__config")
|
const script = getElement("#__config")
|
||||||
const config: Config = JSON.parse(script.textContent!)
|
const config: Config = JSON.parse(script.textContent!)
|
||||||
config.base = `${new URL(config.base, getLocation())}`
|
config.base = `${new URL(config.base, getLocation())}`
|
||||||
|
|
||||||
|
@ -23,8 +23,7 @@
|
|||||||
import {
|
import {
|
||||||
ReplaySubject,
|
ReplaySubject,
|
||||||
Subject,
|
Subject,
|
||||||
fromEvent,
|
fromEvent
|
||||||
mapTo
|
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
@ -40,12 +39,9 @@ import {
|
|||||||
* @returns Document subject
|
* @returns Document subject
|
||||||
*/
|
*/
|
||||||
export function watchDocument(): Subject<Document> {
|
export function watchDocument(): Subject<Document> {
|
||||||
const document$ = new ReplaySubject<Document>()
|
const document$ = new ReplaySubject<Document>(1)
|
||||||
fromEvent(document, "DOMContentLoaded")
|
fromEvent(document, "DOMContentLoaded", { once: true })
|
||||||
.pipe(
|
.subscribe(() => document$.next(document))
|
||||||
mapTo(document)
|
|
||||||
)
|
|
||||||
.subscribe(document$)
|
|
||||||
|
|
||||||
/* Return document */
|
/* Return document */
|
||||||
return document$
|
return document$
|
||||||
|
@ -24,72 +24,6 @@
|
|||||||
* Functions
|
* Functions
|
||||||
* ------------------------------------------------------------------------- */
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve an element matching the query selector
|
|
||||||
*
|
|
||||||
* @template T - Element type
|
|
||||||
*
|
|
||||||
* @param selector - Query selector
|
|
||||||
* @param node - Node of reference
|
|
||||||
*
|
|
||||||
* @returns Element or nothing
|
|
||||||
*/
|
|
||||||
export function getElement<T extends keyof HTMLElementTagNameMap>(
|
|
||||||
selector: T, node?: ParentNode
|
|
||||||
): HTMLElementTagNameMap[T] | undefined
|
|
||||||
|
|
||||||
export function getElement<T extends HTMLElement>(
|
|
||||||
selector: string, node?: ParentNode
|
|
||||||
): T | undefined
|
|
||||||
|
|
||||||
export function getElement<T extends HTMLElement>(
|
|
||||||
selector: string, node: ParentNode = document
|
|
||||||
): T | undefined {
|
|
||||||
return node.querySelector<T>(selector) || undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve an element matching a query selector or throw a reference error
|
|
||||||
*
|
|
||||||
* @template T - Element type
|
|
||||||
*
|
|
||||||
* @param selector - Query selector
|
|
||||||
* @param node - Node of reference
|
|
||||||
*
|
|
||||||
* @returns Element
|
|
||||||
*/
|
|
||||||
export function getElementOrThrow<T extends keyof HTMLElementTagNameMap>(
|
|
||||||
selector: T, node?: ParentNode
|
|
||||||
): HTMLElementTagNameMap[T]
|
|
||||||
|
|
||||||
export function getElementOrThrow<T extends HTMLElement>(
|
|
||||||
selector: string, node?: ParentNode
|
|
||||||
): T
|
|
||||||
|
|
||||||
export function getElementOrThrow<T extends HTMLElement>(
|
|
||||||
selector: string, node: ParentNode = document
|
|
||||||
): T {
|
|
||||||
const el = getElement<T>(selector, node)
|
|
||||||
if (typeof el === "undefined")
|
|
||||||
throw new ReferenceError(
|
|
||||||
`Missing element: expected "${selector}" to be present`
|
|
||||||
)
|
|
||||||
|
|
||||||
/* Return element */
|
|
||||||
return el
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve the currently active element
|
|
||||||
*
|
|
||||||
* @returns Element or nothing
|
|
||||||
*/
|
|
||||||
export function getActiveElement(): HTMLElement | undefined {
|
|
||||||
return document.activeElement instanceof HTMLElement
|
|
||||||
? document.activeElement
|
|
||||||
: undefined
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieve all elements matching the query selector
|
* Retrieve all elements matching the query selector
|
||||||
*
|
*
|
||||||
@ -114,16 +48,73 @@ export function getElements<T extends HTMLElement>(
|
|||||||
return Array.from(node.querySelectorAll<T>(selector))
|
return Array.from(node.querySelectorAll<T>(selector))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve an element matching a query selector or throw a reference error
|
||||||
|
*
|
||||||
|
* Note that this function assumes that the element is present. If unsure if an
|
||||||
|
* element is existent, use the `getOptionalElement` function instead.
|
||||||
|
*
|
||||||
|
* @template T - Element type
|
||||||
|
*
|
||||||
|
* @param selector - Query selector
|
||||||
|
* @param node - Node of reference
|
||||||
|
*
|
||||||
|
* @returns Element
|
||||||
|
*/
|
||||||
|
export function getElement<T extends keyof HTMLElementTagNameMap>(
|
||||||
|
selector: T, node?: ParentNode
|
||||||
|
): HTMLElementTagNameMap[T]
|
||||||
|
|
||||||
|
export function getElement<T extends HTMLElement>(
|
||||||
|
selector: string, node?: ParentNode
|
||||||
|
): T
|
||||||
|
|
||||||
|
export function getElement<T extends HTMLElement>(
|
||||||
|
selector: string, node: ParentNode = document
|
||||||
|
): T {
|
||||||
|
const el = getOptionalElement<T>(selector, node)
|
||||||
|
if (typeof el === "undefined")
|
||||||
|
throw new ReferenceError(
|
||||||
|
`Missing element: expected "${selector}" to be present`
|
||||||
|
)
|
||||||
|
|
||||||
|
/* Return element */
|
||||||
|
return el
|
||||||
|
}
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Replace an element with the given list of nodes
|
* Retrieve an optional element matching the query selector
|
||||||
*
|
*
|
||||||
* @param el - Element
|
* @template T - Element type
|
||||||
* @param nodes - Replacement nodes
|
*
|
||||||
|
* @param selector - Query selector
|
||||||
|
* @param node - Node of reference
|
||||||
|
*
|
||||||
|
* @returns Element or nothing
|
||||||
*/
|
*/
|
||||||
export function replaceElement(
|
export function getOptionalElement<T extends keyof HTMLElementTagNameMap>(
|
||||||
el: HTMLElement, ...nodes: Node[]
|
selector: T, node?: ParentNode
|
||||||
): void {
|
): HTMLElementTagNameMap[T] | undefined
|
||||||
el.replaceWith(...nodes)
|
|
||||||
|
export function getOptionalElement<T extends HTMLElement>(
|
||||||
|
selector: string, node?: ParentNode
|
||||||
|
): T | undefined
|
||||||
|
|
||||||
|
export function getOptionalElement<T extends HTMLElement>(
|
||||||
|
selector: string, node: ParentNode = document
|
||||||
|
): T | undefined {
|
||||||
|
return node.querySelector<T>(selector) || undefined
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve the currently active element
|
||||||
|
*
|
||||||
|
* @returns Element or nothing
|
||||||
|
*/
|
||||||
|
export function getActiveElement(): HTMLElement | undefined {
|
||||||
|
return document.activeElement instanceof HTMLElement
|
||||||
|
? document.activeElement || undefined
|
||||||
|
: undefined
|
||||||
}
|
}
|
||||||
|
@ -25,3 +25,4 @@ export * from "./focus"
|
|||||||
export * from "./offset"
|
export * from "./offset"
|
||||||
export * from "./selection"
|
export * from "./selection"
|
||||||
export * from "./size"
|
export * from "./size"
|
||||||
|
export * from "./visibility"
|
||||||
|
77
src/assets/javascripts/browser/element/offset/_/index.ts
Normal file
77
src/assets/javascripts/browser/element/offset/_/index.ts
Normal file
@ -0,0 +1,77 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016-2021 Martin Donath <martin.donath@squidfunk.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
Observable,
|
||||||
|
fromEvent,
|
||||||
|
map,
|
||||||
|
startWith
|
||||||
|
} from "rxjs"
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Types
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Element offset
|
||||||
|
*/
|
||||||
|
export interface ElementOffset {
|
||||||
|
x: number /* Horizontal offset */
|
||||||
|
y: number /* Vertical offset */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Functions
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve element offset
|
||||||
|
*
|
||||||
|
* @param el - Element
|
||||||
|
*
|
||||||
|
* @returns Element offset
|
||||||
|
*/
|
||||||
|
export function getElementOffset(el: HTMLElement): ElementOffset {
|
||||||
|
return {
|
||||||
|
x: el.offsetLeft,
|
||||||
|
y: el.offsetTop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Watch element offset
|
||||||
|
*
|
||||||
|
* @param el - Element
|
||||||
|
*
|
||||||
|
* @returns Element offset observable
|
||||||
|
*/
|
||||||
|
export function watchElementOffset(
|
||||||
|
el: HTMLElement
|
||||||
|
): Observable<ElementOffset> {
|
||||||
|
return fromEvent(window, "resize")
|
||||||
|
.pipe(
|
||||||
|
map(() => getElementOffset(el)),
|
||||||
|
startWith(getElementOffset(el))
|
||||||
|
)
|
||||||
|
}
|
@ -0,0 +1,71 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016-2021 Martin Donath <martin.donath@squidfunk.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
Observable,
|
||||||
|
fromEvent,
|
||||||
|
map,
|
||||||
|
merge,
|
||||||
|
startWith
|
||||||
|
} from "rxjs"
|
||||||
|
|
||||||
|
import { ElementOffset } from "../_"
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Functions
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve element content offset (= scroll offset)
|
||||||
|
*
|
||||||
|
* @param el - Element
|
||||||
|
*
|
||||||
|
* @returns Element content offset
|
||||||
|
*/
|
||||||
|
export function getElementContentOffset(el: HTMLElement): ElementOffset {
|
||||||
|
return {
|
||||||
|
x: el.scrollLeft,
|
||||||
|
y: el.scrollTop
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Watch element content offset
|
||||||
|
*
|
||||||
|
* @param el - Element
|
||||||
|
*
|
||||||
|
* @returns Element content offset observable
|
||||||
|
*/
|
||||||
|
export function watchElementContentOffset(
|
||||||
|
el: HTMLElement
|
||||||
|
): Observable<ElementOffset> {
|
||||||
|
return merge(
|
||||||
|
fromEvent(el, "scroll"),
|
||||||
|
fromEvent(window, "resize")
|
||||||
|
)
|
||||||
|
.pipe(
|
||||||
|
map(() => getElementContentOffset(el)),
|
||||||
|
startWith(getElementContentOffset(el))
|
||||||
|
)
|
||||||
|
}
|
@ -20,95 +20,5 @@
|
|||||||
* IN THE SOFTWARE.
|
* IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
export * from "./_"
|
||||||
Observable,
|
export * from "./content"
|
||||||
distinctUntilChanged,
|
|
||||||
fromEvent,
|
|
||||||
map,
|
|
||||||
merge,
|
|
||||||
startWith
|
|
||||||
} from "rxjs"
|
|
||||||
|
|
||||||
import {
|
|
||||||
getElementContentSize,
|
|
||||||
getElementSize
|
|
||||||
} from "../size"
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Types
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Element offset
|
|
||||||
*/
|
|
||||||
export interface ElementOffset {
|
|
||||||
x: number /* Horizontal offset */
|
|
||||||
y: number /* Vertical offset */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Functions
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve element offset
|
|
||||||
*
|
|
||||||
* @param el - Element
|
|
||||||
*
|
|
||||||
* @returns Element offset
|
|
||||||
*/
|
|
||||||
export function getElementOffset(el: HTMLElement): ElementOffset {
|
|
||||||
return {
|
|
||||||
x: el.scrollLeft,
|
|
||||||
y: el.scrollTop
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Watch element offset
|
|
||||||
*
|
|
||||||
* @param el - Element
|
|
||||||
*
|
|
||||||
* @returns Element offset observable
|
|
||||||
*/
|
|
||||||
export function watchElementOffset(
|
|
||||||
el: HTMLElement
|
|
||||||
): Observable<ElementOffset> {
|
|
||||||
return merge(
|
|
||||||
fromEvent(el, "scroll"),
|
|
||||||
fromEvent(window, "resize")
|
|
||||||
)
|
|
||||||
.pipe(
|
|
||||||
map(() => getElementOffset(el)),
|
|
||||||
startWith(getElementOffset(el))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Watch element threshold
|
|
||||||
*
|
|
||||||
* This function returns an observable which emits whether the bottom scroll
|
|
||||||
* offset of an elements is within a certain threshold.
|
|
||||||
*
|
|
||||||
* @param el - Element
|
|
||||||
* @param threshold - Threshold
|
|
||||||
*
|
|
||||||
* @returns Element threshold observable
|
|
||||||
*/
|
|
||||||
export function watchElementThreshold(
|
|
||||||
el: HTMLElement, threshold = 16
|
|
||||||
): Observable<boolean> {
|
|
||||||
return watchElementOffset(el)
|
|
||||||
.pipe(
|
|
||||||
map(({ y }) => {
|
|
||||||
const visible = getElementSize(el)
|
|
||||||
const content = getElementContentSize(el)
|
|
||||||
return y >= (
|
|
||||||
content.height - visible.height - threshold
|
|
||||||
)
|
|
||||||
}),
|
|
||||||
distinctUntilChanged()
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
138
src/assets/javascripts/browser/element/size/_/index.ts
Normal file
138
src/assets/javascripts/browser/element/size/_/index.ts
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016-2021 Martin Donath <martin.donath@squidfunk.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
NEVER,
|
||||||
|
Observable,
|
||||||
|
Subject,
|
||||||
|
defer,
|
||||||
|
filter,
|
||||||
|
finalize,
|
||||||
|
map,
|
||||||
|
of,
|
||||||
|
shareReplay,
|
||||||
|
startWith,
|
||||||
|
switchMap,
|
||||||
|
tap
|
||||||
|
} from "rxjs"
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Types
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Element offset
|
||||||
|
*/
|
||||||
|
export interface ElementSize {
|
||||||
|
width: number /* Element width */
|
||||||
|
height: number /* Element height */
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Data
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize observer entry subject
|
||||||
|
*/
|
||||||
|
const entry$ = new Subject<ResizeObserverEntry>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resize observer observable
|
||||||
|
*
|
||||||
|
* This observable will create a `ResizeObserver` on the first subscription
|
||||||
|
* and will automatically terminate it when there are no more subscribers.
|
||||||
|
* It's quite important to centralize observation in a single `ResizeObserver`,
|
||||||
|
* as the performance difference can be quite dramatic, as the link shows.
|
||||||
|
*
|
||||||
|
* @see https://bit.ly/3iIYfEm - Google Groups on performance
|
||||||
|
*/
|
||||||
|
const observer$ = defer(() => of(
|
||||||
|
new ResizeObserver(entries => {
|
||||||
|
for (const entry of entries)
|
||||||
|
entry$.next(entry)
|
||||||
|
})
|
||||||
|
))
|
||||||
|
.pipe(
|
||||||
|
switchMap(observer => NEVER.pipe(startWith(observer))
|
||||||
|
.pipe(
|
||||||
|
finalize(() => observer.disconnect())
|
||||||
|
)
|
||||||
|
),
|
||||||
|
shareReplay(1)
|
||||||
|
)
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Functions
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve element size
|
||||||
|
*
|
||||||
|
* @param el - Element
|
||||||
|
*
|
||||||
|
* @returns Element size
|
||||||
|
*/
|
||||||
|
export function getElementSize(el: HTMLElement): ElementSize {
|
||||||
|
return {
|
||||||
|
width: el.offsetWidth,
|
||||||
|
height: el.offsetHeight
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Watch element size
|
||||||
|
*
|
||||||
|
* This function returns an observable that subscribes to a single internal
|
||||||
|
* instance of `ResizeObserver` upon subscription, and emit resize events until
|
||||||
|
* termination. Note that this function should not be called with the same
|
||||||
|
* element twice, as the first unsubscription will terminate observation.
|
||||||
|
*
|
||||||
|
* Sadly, we can't use the `DOMRect` objects returned by the observer, because
|
||||||
|
* we need the emitted values to be consistent with `getElementSize`, which will
|
||||||
|
* return the used values (rounded) and not actual values (unrounded). Thus, we
|
||||||
|
* use the `offset*` properties. See the linked GitHub issue.
|
||||||
|
*
|
||||||
|
* @see https://bit.ly/3m0k3he - GitHub issue
|
||||||
|
*
|
||||||
|
* @param el - Element
|
||||||
|
*
|
||||||
|
* @returns Element size observable
|
||||||
|
*/
|
||||||
|
export function watchElementSize(
|
||||||
|
el: HTMLElement
|
||||||
|
): Observable<ElementSize> {
|
||||||
|
return observer$
|
||||||
|
.pipe(
|
||||||
|
tap(observer => observer.observe(el)),
|
||||||
|
switchMap(observer => entry$
|
||||||
|
.pipe(
|
||||||
|
filter(({ target }) => target === el),
|
||||||
|
finalize(() => observer.unobserve(el)),
|
||||||
|
map(() => getElementSize(el))
|
||||||
|
)
|
||||||
|
),
|
||||||
|
startWith(getElementSize(el))
|
||||||
|
)
|
||||||
|
}
|
41
src/assets/javascripts/browser/element/size/content/index.ts
Normal file
41
src/assets/javascripts/browser/element/size/content/index.ts
Normal file
@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016-2021 Martin Donath <martin.donath@squidfunk.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import { ElementSize } from "../_"
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Functions
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Retrieve element content size (= scroll width and height)
|
||||||
|
*
|
||||||
|
* @param el - Element
|
||||||
|
*
|
||||||
|
* @returns Element content size
|
||||||
|
*/
|
||||||
|
export function getElementContentSize(el: HTMLElement): ElementSize {
|
||||||
|
return {
|
||||||
|
width: el.scrollWidth,
|
||||||
|
height: el.scrollHeight
|
||||||
|
}
|
||||||
|
}
|
@ -20,133 +20,5 @@
|
|||||||
* IN THE SOFTWARE.
|
* IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
export * from "./_"
|
||||||
NEVER,
|
export * from "./content"
|
||||||
Observable,
|
|
||||||
Subject,
|
|
||||||
defer,
|
|
||||||
filter,
|
|
||||||
finalize,
|
|
||||||
map,
|
|
||||||
of,
|
|
||||||
shareReplay,
|
|
||||||
startWith,
|
|
||||||
switchMap,
|
|
||||||
tap
|
|
||||||
} from "rxjs"
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Types
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Element offset
|
|
||||||
*/
|
|
||||||
export interface ElementSize {
|
|
||||||
width: number /* Element width */
|
|
||||||
height: number /* Element height */
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Data
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resize observer entry subject
|
|
||||||
*/
|
|
||||||
const entry$ = new Subject<ResizeObserverEntry>()
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Resize observer observable
|
|
||||||
*
|
|
||||||
* This observable will create a `ResizeObserver` on the first subscription
|
|
||||||
* and will automatically terminate it when there are no more subscribers.
|
|
||||||
* It's quite important to centralize observation in a single `ResizeObserver`,
|
|
||||||
* as the performance difference can be quite dramatic, as the link shows.
|
|
||||||
*
|
|
||||||
* @see https://bit.ly/3iIYfEm - Google Groups on performance
|
|
||||||
*/
|
|
||||||
const observer$ = defer(() => of(
|
|
||||||
new ResizeObserver(entries => {
|
|
||||||
for (const entry of entries)
|
|
||||||
entry$.next(entry)
|
|
||||||
})
|
|
||||||
))
|
|
||||||
.pipe(
|
|
||||||
switchMap(resize => NEVER.pipe(startWith(resize))
|
|
||||||
.pipe(
|
|
||||||
finalize(() => resize.disconnect())
|
|
||||||
)
|
|
||||||
),
|
|
||||||
shareReplay(1)
|
|
||||||
)
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Functions
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve element size
|
|
||||||
*
|
|
||||||
* @param el - Element
|
|
||||||
*
|
|
||||||
* @returns Element size
|
|
||||||
*/
|
|
||||||
export function getElementSize(el: HTMLElement): ElementSize {
|
|
||||||
return {
|
|
||||||
width: el.offsetWidth,
|
|
||||||
height: el.offsetHeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Retrieve element content size, i.e. including overflowing content
|
|
||||||
*
|
|
||||||
* @param el - Element
|
|
||||||
*
|
|
||||||
* @returns Element size
|
|
||||||
*/
|
|
||||||
export function getElementContentSize(el: HTMLElement): ElementSize {
|
|
||||||
return {
|
|
||||||
width: el.scrollWidth,
|
|
||||||
height: el.scrollHeight
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Watch element size
|
|
||||||
*
|
|
||||||
* This function returns an observable that subscribes to a single internal
|
|
||||||
* instance of `ResizeObserver` upon subscription, and emit resize events until
|
|
||||||
* termination. Note that this function should not be called with the same
|
|
||||||
* element twice, as the first unsubscription will terminate observation.
|
|
||||||
*
|
|
||||||
* Sadly, we can't use the `DOMRect` objects returned by the observer, because
|
|
||||||
* we need the emitted values to be consistent with `getElementSize`, which will
|
|
||||||
* return the used values (rounded) and not actual values (unrounded). Thus, we
|
|
||||||
* use the `offset*` properties. See the linked GitHub issue.
|
|
||||||
*
|
|
||||||
* @see https://bit.ly/3m0k3he - GitHub issue
|
|
||||||
*
|
|
||||||
* @param el - Element
|
|
||||||
*
|
|
||||||
* @returns Element size observable
|
|
||||||
*/
|
|
||||||
export function watchElementSize(
|
|
||||||
el: HTMLElement
|
|
||||||
): Observable<ElementSize> {
|
|
||||||
return observer$
|
|
||||||
.pipe(
|
|
||||||
tap(observer => observer.observe(el)),
|
|
||||||
switchMap(observer => entry$
|
|
||||||
.pipe(
|
|
||||||
filter(({ target }) => target === el),
|
|
||||||
finalize(() => observer.unobserve(el)),
|
|
||||||
map(() => getElementSize(el))
|
|
||||||
)
|
|
||||||
),
|
|
||||||
startWith(getElementSize(el))
|
|
||||||
)
|
|
||||||
}
|
|
||||||
|
131
src/assets/javascripts/browser/element/visibility/index.ts
Normal file
131
src/assets/javascripts/browser/element/visibility/index.ts
Normal file
@ -0,0 +1,131 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (c) 2016-2021 Martin Donath <martin.donath@squidfunk.com>
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to
|
||||||
|
* deal in the Software without restriction, including without limitation the
|
||||||
|
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
|
||||||
|
* sell copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||||
|
* FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
|
||||||
|
* IN THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
|
||||||
|
import {
|
||||||
|
NEVER,
|
||||||
|
Observable,
|
||||||
|
Subject,
|
||||||
|
defer,
|
||||||
|
distinctUntilChanged,
|
||||||
|
filter,
|
||||||
|
finalize,
|
||||||
|
map,
|
||||||
|
of,
|
||||||
|
shareReplay,
|
||||||
|
startWith,
|
||||||
|
switchMap,
|
||||||
|
tap
|
||||||
|
} from "rxjs"
|
||||||
|
|
||||||
|
import {
|
||||||
|
getElementContentSize,
|
||||||
|
getElementSize,
|
||||||
|
watchElementContentOffset
|
||||||
|
} from "~/browser"
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Data
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intersection observer entry subject
|
||||||
|
*/
|
||||||
|
const entry$ = new Subject<IntersectionObserverEntry>()
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Intersection observer observable
|
||||||
|
*
|
||||||
|
* This observable will create an `IntersectionObserver` on first subscription
|
||||||
|
* and will automatically terminate it when there are no more subscribers.
|
||||||
|
*
|
||||||
|
* @see https://bit.ly/3iIYfEm - Google Groups on performance
|
||||||
|
*/
|
||||||
|
const observer$ = defer(() => of(
|
||||||
|
new IntersectionObserver(entries => {
|
||||||
|
for (const entry of entries)
|
||||||
|
entry$.next(entry)
|
||||||
|
}, {
|
||||||
|
threshold: 1
|
||||||
|
})
|
||||||
|
))
|
||||||
|
.pipe(
|
||||||
|
switchMap(observer => NEVER.pipe(startWith(observer))
|
||||||
|
.pipe(
|
||||||
|
finalize(() => observer.disconnect())
|
||||||
|
)
|
||||||
|
),
|
||||||
|
shareReplay(1)
|
||||||
|
)
|
||||||
|
|
||||||
|
/* ----------------------------------------------------------------------------
|
||||||
|
* Functions
|
||||||
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Watch element visibility
|
||||||
|
*
|
||||||
|
* @param el - Element
|
||||||
|
*
|
||||||
|
* @returns Element visibility observable
|
||||||
|
*/
|
||||||
|
export function watchElementVisibility(
|
||||||
|
el: HTMLElement
|
||||||
|
): Observable<boolean> {
|
||||||
|
return observer$
|
||||||
|
.pipe(
|
||||||
|
tap(observer => observer.observe(el)),
|
||||||
|
switchMap(observer => entry$
|
||||||
|
.pipe(
|
||||||
|
filter(({ target }) => target === el),
|
||||||
|
finalize(() => observer.unobserve(el)),
|
||||||
|
map(({ isIntersecting }) => isIntersecting)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Watch element boundary
|
||||||
|
*
|
||||||
|
* This function returns an observable which emits whether the bottom content
|
||||||
|
* boundary (= scroll offset) of an element is within a certain threshold.
|
||||||
|
*
|
||||||
|
* @param el - Element
|
||||||
|
* @param threshold - Threshold
|
||||||
|
*
|
||||||
|
* @returns Element threshold observable
|
||||||
|
*/
|
||||||
|
export function watchElementBoundary(
|
||||||
|
el: HTMLElement, threshold = 16
|
||||||
|
): Observable<boolean> {
|
||||||
|
return watchElementContentOffset(el)
|
||||||
|
.pipe(
|
||||||
|
map(({ y }) => {
|
||||||
|
const visible = getElementSize(el)
|
||||||
|
const content = getElementContentSize(el)
|
||||||
|
return y >= (
|
||||||
|
content.height - visible.height - threshold
|
||||||
|
)
|
||||||
|
}),
|
||||||
|
distinctUntilChanged()
|
||||||
|
)
|
||||||
|
}
|
@ -29,7 +29,7 @@ import {
|
|||||||
startWith
|
startWith
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import { getElement } from "~/browser"
|
import { getOptionalElement } from "~/browser"
|
||||||
import { h } from "~/utilities"
|
import { h } from "~/utilities"
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
@ -86,7 +86,7 @@ export function watchLocationHash(): Observable<string> {
|
|||||||
export function watchLocationTarget(): Observable<HTMLElement> {
|
export function watchLocationTarget(): Observable<HTMLElement> {
|
||||||
return watchLocationHash()
|
return watchLocationHash()
|
||||||
.pipe(
|
.pipe(
|
||||||
map(id => getElement(`[id="${id}"]`)!),
|
map(id => getOptionalElement(`[id="${id}"]`)!),
|
||||||
filter(el => typeof el !== "undefined")
|
filter(el => typeof el !== "undefined")
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -27,7 +27,7 @@ import {
|
|||||||
startWith
|
startWith
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import { getElementOrThrow } from "../element"
|
import { getElement } from "../element"
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
* Types
|
* Types
|
||||||
@ -48,8 +48,8 @@ export type Toggle =
|
|||||||
* Toggle map
|
* Toggle map
|
||||||
*/
|
*/
|
||||||
const toggles: Record<Toggle, HTMLInputElement> = {
|
const toggles: Record<Toggle, HTMLInputElement> = {
|
||||||
drawer: getElementOrThrow("[data-md-toggle=drawer]"),
|
drawer: getElement("[data-md-toggle=drawer]"),
|
||||||
search: getElementOrThrow("[data-md-toggle=search]")
|
search: getElement("[data-md-toggle=search]")
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
|
@ -30,6 +30,7 @@ import {
|
|||||||
|
|
||||||
import { Header } from "~/components"
|
import { Header } from "~/components"
|
||||||
|
|
||||||
|
import { getElementOffset } from "../../element"
|
||||||
import {
|
import {
|
||||||
ViewportOffset,
|
ViewportOffset,
|
||||||
watchViewportOffset
|
watchViewportOffset
|
||||||
@ -102,10 +103,7 @@ export function watchViewportAt(
|
|||||||
/* Compute element offset */
|
/* Compute element offset */
|
||||||
const offset$ = combineLatest([size$, header$])
|
const offset$ = combineLatest([size$, header$])
|
||||||
.pipe(
|
.pipe(
|
||||||
map((): ViewportOffset => ({
|
map(() => getElementOffset(el))
|
||||||
x: el.offsetLeft,
|
|
||||||
y: el.offsetTop
|
|
||||||
}))
|
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Compute relative viewport, return hot observable */
|
/* Compute relative viewport, return hot observable */
|
||||||
|
@ -54,8 +54,8 @@ export interface ViewportOffset {
|
|||||||
*/
|
*/
|
||||||
export function getViewportOffset(): ViewportOffset {
|
export function getViewportOffset(): ViewportOffset {
|
||||||
return {
|
return {
|
||||||
x: Math.max(0, pageXOffset),
|
x: Math.max(0, scrollX),
|
||||||
y: Math.max(0, pageYOffset)
|
y: Math.max(0, scrollY)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,7 +37,7 @@ import {
|
|||||||
import { configuration, feature } from "./_"
|
import { configuration, feature } from "./_"
|
||||||
import {
|
import {
|
||||||
at,
|
at,
|
||||||
getElement,
|
getOptionalElement,
|
||||||
requestJSON,
|
requestJSON,
|
||||||
setToggle,
|
setToggle,
|
||||||
watchDocument,
|
watchDocument,
|
||||||
@ -96,6 +96,7 @@ const keyboard$ = watchKeyboard()
|
|||||||
const viewport$ = watchViewport()
|
const viewport$ = watchViewport()
|
||||||
const tablet$ = watchMedia("(min-width: 960px)")
|
const tablet$ = watchMedia("(min-width: 960px)")
|
||||||
const screen$ = watchMedia("(min-width: 1220px)")
|
const screen$ = watchMedia("(min-width: 1220px)")
|
||||||
|
const hover$ = watchMedia("(hover)")
|
||||||
const print$ = watchPrint()
|
const print$ = watchPrint()
|
||||||
|
|
||||||
/* Retrieve search index, if search is enabled */
|
/* Retrieve search index, if search is enabled */
|
||||||
@ -139,7 +140,7 @@ keyboard$
|
|||||||
/* Go to previous page */
|
/* Go to previous page */
|
||||||
case "p":
|
case "p":
|
||||||
case ",":
|
case ",":
|
||||||
const prev = getElement("[href][rel=prev]")
|
const prev = getOptionalElement("[href][rel=prev]")
|
||||||
if (typeof prev !== "undefined")
|
if (typeof prev !== "undefined")
|
||||||
prev.click()
|
prev.click()
|
||||||
break
|
break
|
||||||
@ -147,7 +148,7 @@ keyboard$
|
|||||||
/* Go to next page */
|
/* Go to next page */
|
||||||
case "n":
|
case "n":
|
||||||
case ".":
|
case ".":
|
||||||
const next = getElement("[href][rel=next]")
|
const next = getOptionalElement("[href][rel=next]")
|
||||||
if (typeof next !== "undefined")
|
if (typeof next !== "undefined")
|
||||||
next.click()
|
next.click()
|
||||||
break
|
break
|
||||||
@ -197,7 +198,7 @@ const content$ = defer(() => merge(
|
|||||||
|
|
||||||
/* Content */
|
/* Content */
|
||||||
...getComponentElements("content")
|
...getComponentElements("content")
|
||||||
.map(el => mountContent(el, { target$, viewport$, print$ })),
|
.map(el => mountContent(el, { target$, viewport$, hover$, print$ })),
|
||||||
|
|
||||||
/* Search highlighting */
|
/* Search highlighting */
|
||||||
...getComponentElements("content")
|
...getComponentElements("content")
|
||||||
@ -250,8 +251,9 @@ window.location$ = location$ /* Location subject */
|
|||||||
window.target$ = target$ /* Location target observable */
|
window.target$ = target$ /* Location target observable */
|
||||||
window.keyboard$ = keyboard$ /* Keyboard observable */
|
window.keyboard$ = keyboard$ /* Keyboard observable */
|
||||||
window.viewport$ = viewport$ /* Viewport observable */
|
window.viewport$ = viewport$ /* Viewport observable */
|
||||||
window.tablet$ = tablet$ /* Tablet observable */
|
window.tablet$ = tablet$ /* Media tablet observable */
|
||||||
window.screen$ = screen$ /* Screen observable */
|
window.screen$ = screen$ /* Media screen observable */
|
||||||
window.print$ = print$ /* Print observable */
|
window.hover$ = hover$ /* Media hover observable */
|
||||||
|
window.print$ = print$ /* Media print observable */
|
||||||
window.alert$ = alert$ /* Alert subject */
|
window.alert$ = alert$ /* Alert subject */
|
||||||
window.component$ = component$ /* Component observable */
|
window.component$ = component$ /* Component observable */
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
* IN THE SOFTWARE.
|
* IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getElementOrThrow, getElements } from "~/browser"
|
import { getElement, getElements } from "~/browser"
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
* Types
|
* Types
|
||||||
@ -114,7 +114,7 @@ interface ComponentTypeMap {
|
|||||||
export function getComponentElement<T extends ComponentType>(
|
export function getComponentElement<T extends ComponentType>(
|
||||||
type: T, node: ParentNode = document
|
type: T, node: ParentNode = document
|
||||||
): ComponentTypeMap[T] {
|
): ComponentTypeMap[T] {
|
||||||
return getElementOrThrow(`[data-md-component=${type}]`, node)
|
return getElement(`[data-md-component=${type}]`, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -53,7 +53,8 @@ export type Content =
|
|||||||
interface MountOptions {
|
interface MountOptions {
|
||||||
target$: Observable<HTMLElement> /* Location target observable */
|
target$: Observable<HTMLElement> /* Location target observable */
|
||||||
viewport$: Observable<Viewport> /* Viewport observable */
|
viewport$: Observable<Viewport> /* Viewport observable */
|
||||||
print$: Observable<boolean> /* Print observable */
|
hover$: Observable<boolean> /* Media hover observable */
|
||||||
|
print$: Observable<boolean> /* Media print observable */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
@ -72,13 +73,13 @@ interface MountOptions {
|
|||||||
* @returns Content component observable
|
* @returns Content component observable
|
||||||
*/
|
*/
|
||||||
export function mountContent(
|
export function mountContent(
|
||||||
el: HTMLElement, { target$, viewport$, print$ }: MountOptions
|
el: HTMLElement, { target$, viewport$, hover$, print$ }: MountOptions
|
||||||
): Observable<Component<Content>> {
|
): Observable<Component<Content>> {
|
||||||
return merge(
|
return merge(
|
||||||
|
|
||||||
/* Code blocks */
|
/* Code blocks */
|
||||||
...getElements("pre > code", el)
|
...getElements("pre > code", el)
|
||||||
.map(child => mountCodeBlock(child, { viewport$, print$ })),
|
.map(child => mountCodeBlock(child, { viewport$, hover$, print$ })),
|
||||||
|
|
||||||
/* Data tables */
|
/* Data tables */
|
||||||
...getElements("table:not([class])", el)
|
...getElements("table:not([class])", el)
|
||||||
|
@ -41,14 +41,17 @@ import {
|
|||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import { feature } from "~/_"
|
import { feature } from "~/_"
|
||||||
import { resetFocusable, setFocusable } from "~/actions"
|
import {
|
||||||
|
resetFocusable,
|
||||||
|
setFocusable
|
||||||
|
} from "~/actions"
|
||||||
import {
|
import {
|
||||||
Viewport,
|
Viewport,
|
||||||
getElement,
|
getElement,
|
||||||
getElementContentSize,
|
getElementContentSize,
|
||||||
getElementOrThrow,
|
|
||||||
getElementSize,
|
getElementSize,
|
||||||
getElements,
|
getElements,
|
||||||
|
getOptionalElement,
|
||||||
watchMedia
|
watchMedia
|
||||||
} from "~/browser"
|
} from "~/browser"
|
||||||
import {
|
import {
|
||||||
@ -174,7 +177,7 @@ export function watchCodeBlock(
|
|||||||
container.insertAdjacentElement("afterend", list)
|
container.insertAdjacentElement("afterend", list)
|
||||||
for (const annotation of annotations) {
|
for (const annotation of annotations) {
|
||||||
const id = parseInt(annotation.getAttribute("data-index")!, 10)
|
const id = parseInt(annotation.getAttribute("data-index")!, 10)
|
||||||
const typeset = getElement(":scope .md-typeset", annotation)!
|
const typeset = getOptionalElement(":scope .md-typeset", annotation)!
|
||||||
items[id - 1].append(...Array.from(typeset.childNodes))
|
items[id - 1].append(...Array.from(typeset.childNodes))
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -182,7 +185,7 @@ export function watchCodeBlock(
|
|||||||
for (const annotation of annotations) {
|
for (const annotation of annotations) {
|
||||||
const id = parseInt(annotation.getAttribute("data-index")!, 10)
|
const id = parseInt(annotation.getAttribute("data-index")!, 10)
|
||||||
const nodes = items[id - 1].childNodes
|
const nodes = items[id - 1].childNodes
|
||||||
getElementOrThrow(":scope .md-typeset", annotation)
|
getElement(":scope .md-typeset", annotation)
|
||||||
.append(...Array.from(nodes))
|
.append(...Array.from(nodes))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -239,7 +242,7 @@ export function mountCodeBlock(
|
|||||||
take(1),
|
take(1),
|
||||||
takeWhile(({ annotations }) => !!annotations?.length),
|
takeWhile(({ annotations }) => !!annotations?.length),
|
||||||
map(({ annotations }) => annotations!
|
map(({ annotations }) => annotations!
|
||||||
.map(annotation => getElementOrThrow(".md-tooltip", annotation))
|
.map(annotation => getElement(".md-tooltip", annotation))
|
||||||
),
|
),
|
||||||
combineLatestWith(viewport$
|
combineLatestWith(viewport$
|
||||||
.pipe(
|
.pipe(
|
||||||
|
@ -54,7 +54,7 @@ export interface Details {
|
|||||||
*/
|
*/
|
||||||
interface WatchOptions {
|
interface WatchOptions {
|
||||||
target$: Observable<HTMLElement> /* Location target observable */
|
target$: Observable<HTMLElement> /* Location target observable */
|
||||||
print$: Observable<boolean> /* Print observable */
|
print$: Observable<boolean> /* Media print observable */
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -62,7 +62,7 @@ interface WatchOptions {
|
|||||||
*/
|
*/
|
||||||
interface MountOptions {
|
interface MountOptions {
|
||||||
target$: Observable<HTMLElement> /* Location target observable */
|
target$: Observable<HTMLElement> /* Location target observable */
|
||||||
print$: Observable<boolean> /* Print observable */
|
print$: Observable<boolean> /* Media print observable */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
|
@ -22,7 +22,6 @@
|
|||||||
|
|
||||||
import { Observable, of } from "rxjs"
|
import { Observable, of } from "rxjs"
|
||||||
|
|
||||||
import { replaceElement } from "~/browser"
|
|
||||||
import { renderTable } from "~/templates"
|
import { renderTable } from "~/templates"
|
||||||
import { h } from "~/utilities"
|
import { h } from "~/utilities"
|
||||||
|
|
||||||
@ -63,8 +62,8 @@ const sentinel = h("table")
|
|||||||
export function mountDataTable(
|
export function mountDataTable(
|
||||||
el: HTMLElement
|
el: HTMLElement
|
||||||
): Observable<Component<DataTable>> {
|
): Observable<Component<DataTable>> {
|
||||||
replaceElement(el, sentinel)
|
el.replaceWith(sentinel)
|
||||||
replaceElement(sentinel, renderTable(el))
|
sentinel.replaceWith(renderTable(el))
|
||||||
|
|
||||||
/* Create and return component */
|
/* Create and return component */
|
||||||
return of({ ref: el })
|
return of({ ref: el })
|
||||||
|
@ -21,7 +21,6 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
NEVER,
|
|
||||||
Observable,
|
Observable,
|
||||||
Subject,
|
Subject,
|
||||||
finalize,
|
finalize,
|
||||||
@ -33,7 +32,7 @@ import {
|
|||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
getElementOrThrow,
|
getElement,
|
||||||
getElements
|
getElements
|
||||||
} from "~/browser"
|
} from "~/browser"
|
||||||
|
|
||||||
@ -64,17 +63,14 @@ export interface ContentTabs {
|
|||||||
export function watchContentTabs(
|
export function watchContentTabs(
|
||||||
el: HTMLElement
|
el: HTMLElement
|
||||||
): Observable<ContentTabs> {
|
): Observable<ContentTabs> {
|
||||||
if (!el.classList.contains("tabbed-alternate"))
|
return merge(...getElements(":scope > input", el)
|
||||||
return NEVER
|
.map(input => fromEvent(input, "change").pipe(mapTo(input.id)))
|
||||||
else
|
)
|
||||||
return merge(...getElements(":scope > input", el)
|
.pipe(
|
||||||
.map(input => fromEvent(input, "change").pipe(mapTo(input.id)))
|
map(id => ({
|
||||||
|
active: getElement<HTMLLabelElement>(`label[for=${id}]`)
|
||||||
|
}))
|
||||||
)
|
)
|
||||||
.pipe(
|
|
||||||
map(id => ({
|
|
||||||
active: getElementOrThrow<HTMLLabelElement>(`label[for=${id}]`)
|
|
||||||
}))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,7 +40,10 @@ import {
|
|||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import { feature } from "~/_"
|
import { feature } from "~/_"
|
||||||
import { resetHeaderState, setHeaderState } from "~/actions"
|
import {
|
||||||
|
resetHeaderState,
|
||||||
|
setHeaderState
|
||||||
|
} from "~/actions"
|
||||||
import {
|
import {
|
||||||
Viewport,
|
Viewport,
|
||||||
watchElementSize,
|
watchElementSize,
|
||||||
|
@ -38,8 +38,8 @@ import {
|
|||||||
} from "~/actions"
|
} from "~/actions"
|
||||||
import {
|
import {
|
||||||
Viewport,
|
Viewport,
|
||||||
getElement,
|
|
||||||
getElementSize,
|
getElementSize,
|
||||||
|
getOptionalElement,
|
||||||
watchViewportAt
|
watchViewportAt
|
||||||
} from "~/browser"
|
} from "~/browser"
|
||||||
|
|
||||||
@ -131,7 +131,7 @@ export function mountHeaderTitle(
|
|||||||
})
|
})
|
||||||
|
|
||||||
/* Obtain headline, if any */
|
/* Obtain headline, if any */
|
||||||
const headline = getElement<HTMLHeadingElement>("article h1")
|
const headline = getOptionalElement<HTMLHeadingElement>("article h1")
|
||||||
if (typeof headline === "undefined")
|
if (typeof headline === "undefined")
|
||||||
return NEVER
|
return NEVER
|
||||||
|
|
||||||
|
@ -29,7 +29,10 @@ import {
|
|||||||
switchMap
|
switchMap
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import { Viewport, watchElementSize } from "~/browser"
|
import {
|
||||||
|
Viewport,
|
||||||
|
watchElementSize
|
||||||
|
} from "~/browser"
|
||||||
|
|
||||||
import { Header } from "../header"
|
import { Header } from "../header"
|
||||||
|
|
||||||
|
@ -53,10 +53,19 @@ import {
|
|||||||
getComponentElement,
|
getComponentElement,
|
||||||
getComponentElements
|
getComponentElements
|
||||||
} from "../../_"
|
} from "../../_"
|
||||||
import { SearchQuery, mountSearchQuery } from "../query"
|
import {
|
||||||
|
SearchQuery,
|
||||||
|
mountSearchQuery
|
||||||
|
} from "../query"
|
||||||
import { mountSearchResult } from "../result"
|
import { mountSearchResult } from "../result"
|
||||||
import { SearchShare, mountSearchShare } from "../share"
|
import {
|
||||||
import { SearchSuggest, mountSearchSuggest } from "../suggest"
|
SearchShare,
|
||||||
|
mountSearchShare
|
||||||
|
} from "../share"
|
||||||
|
import {
|
||||||
|
SearchSuggest,
|
||||||
|
mountSearchSuggest
|
||||||
|
} from "../suggest"
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
* Types
|
* Types
|
||||||
|
@ -46,8 +46,8 @@ import {
|
|||||||
setSearchResultMeta
|
setSearchResultMeta
|
||||||
} from "~/actions"
|
} from "~/actions"
|
||||||
import {
|
import {
|
||||||
getElementOrThrow,
|
getElement,
|
||||||
watchElementThreshold
|
watchElementBoundary
|
||||||
} from "~/browser"
|
} from "~/browser"
|
||||||
import {
|
import {
|
||||||
SearchResult,
|
SearchResult,
|
||||||
@ -91,14 +91,14 @@ export function mountSearchResult(
|
|||||||
el: HTMLElement, { rx$ }: SearchWorker, { query$ }: MountOptions
|
el: HTMLElement, { rx$ }: SearchWorker, { query$ }: MountOptions
|
||||||
): Observable<Component<SearchResult>> {
|
): Observable<Component<SearchResult>> {
|
||||||
const internal$ = new Subject<SearchResult>()
|
const internal$ = new Subject<SearchResult>()
|
||||||
const boundary$ = watchElementThreshold(el.parentElement!)
|
const boundary$ = watchElementBoundary(el.parentElement!)
|
||||||
.pipe(
|
.pipe(
|
||||||
filter(Boolean)
|
filter(Boolean)
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Retrieve nested components */
|
/* Retrieve nested components */
|
||||||
const meta = getElementOrThrow(":scope > :first-child", el)
|
const meta = getElement(":scope > :first-child", el)
|
||||||
const list = getElementOrThrow(":scope > :last-child", el)
|
const list = getElement(":scope > :last-child", el)
|
||||||
|
|
||||||
/* Wait until search is ready */
|
/* Wait until search is ready */
|
||||||
const ready$ = rx$
|
const ready$ = rx$
|
||||||
|
@ -98,9 +98,10 @@ interface MountOptions {
|
|||||||
export function watchSidebar(
|
export function watchSidebar(
|
||||||
el: HTMLElement, { viewport$, main$ }: WatchOptions
|
el: HTMLElement, { viewport$, main$ }: WatchOptions
|
||||||
): Observable<Sidebar> {
|
): Observable<Sidebar> {
|
||||||
|
const parent = el.parentElement!
|
||||||
const adjust =
|
const adjust =
|
||||||
el.parentElement!.offsetTop -
|
parent.offsetTop -
|
||||||
el.parentElement!.parentElement!.offsetTop
|
parent.parentElement!.offsetTop
|
||||||
|
|
||||||
/* Compute the sidebar's available height and if it should be locked */
|
/* Compute the sidebar's available height and if it should be locked */
|
||||||
return combineLatest([main$, viewport$])
|
return combineLatest([main$, viewport$])
|
||||||
|
@ -34,11 +34,17 @@ import {
|
|||||||
tap
|
tap
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import { setSourceFacts, setSourceState } from "~/actions"
|
import {
|
||||||
|
setSourceFacts,
|
||||||
|
setSourceState
|
||||||
|
} from "~/actions"
|
||||||
import { renderSourceFacts } from "~/templates"
|
import { renderSourceFacts } from "~/templates"
|
||||||
|
|
||||||
import { Component } from "../../_"
|
import { Component } from "../../_"
|
||||||
import { SourceFacts, fetchSourceFacts } from "../facts"
|
import {
|
||||||
|
SourceFacts,
|
||||||
|
fetchSourceFacts
|
||||||
|
} from "../facts"
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
* Types
|
* Types
|
||||||
|
@ -34,7 +34,10 @@ import {
|
|||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import { feature } from "~/_"
|
import { feature } from "~/_"
|
||||||
import { resetTabsState, setTabsState } from "~/actions"
|
import {
|
||||||
|
resetTabsState,
|
||||||
|
setTabsState
|
||||||
|
} from "~/actions"
|
||||||
import {
|
import {
|
||||||
Viewport,
|
Viewport,
|
||||||
watchElementSize,
|
watchElementSize,
|
||||||
|
@ -48,9 +48,9 @@ import {
|
|||||||
} from "~/actions"
|
} from "~/actions"
|
||||||
import {
|
import {
|
||||||
Viewport,
|
Viewport,
|
||||||
getElement,
|
|
||||||
getElements,
|
getElements,
|
||||||
getLocation,
|
getLocation,
|
||||||
|
getOptionalElement,
|
||||||
watchElementSize
|
watchElementSize
|
||||||
} from "~/browser"
|
} from "~/browser"
|
||||||
|
|
||||||
@ -122,7 +122,7 @@ export function watchTableOfContents(
|
|||||||
const anchors = getElements<HTMLAnchorElement>("[href^=\\#]", el)
|
const anchors = getElements<HTMLAnchorElement>("[href^=\\#]", el)
|
||||||
for (const anchor of anchors) {
|
for (const anchor of anchors) {
|
||||||
const id = decodeURIComponent(anchor.hash.substring(1))
|
const id = decodeURIComponent(anchor.hash.substring(1))
|
||||||
const target = getElement(`[id="${id}"]`)
|
const target = getOptionalElement(`[id="${id}"]`)
|
||||||
if (typeof target !== "undefined")
|
if (typeof target !== "undefined")
|
||||||
table.set(anchor, target)
|
table.set(anchor, target)
|
||||||
}
|
}
|
||||||
|
@ -43,7 +43,10 @@ import {
|
|||||||
setBackToTopState,
|
setBackToTopState,
|
||||||
setFocusable
|
setFocusable
|
||||||
} from "~/actions"
|
} from "~/actions"
|
||||||
import { Viewport, setElementFocus } from "~/browser"
|
import {
|
||||||
|
Viewport,
|
||||||
|
setElementFocus
|
||||||
|
} from "~/browser"
|
||||||
|
|
||||||
import { Component } from "../_"
|
import { Component } from "../_"
|
||||||
import { Header } from "../header"
|
import { Header } from "../header"
|
||||||
|
@ -25,7 +25,7 @@ import { Observable, Subject } from "rxjs"
|
|||||||
|
|
||||||
import { translation } from "~/_"
|
import { translation } from "~/_"
|
||||||
import {
|
import {
|
||||||
getElementOrThrow,
|
getElement,
|
||||||
getElements
|
getElements
|
||||||
} from "~/browser"
|
} from "~/browser"
|
||||||
|
|
||||||
@ -85,7 +85,7 @@ export function setupClipboardJS(
|
|||||||
new ClipboardJS("[data-clipboard-target], [data-clipboard-text]", {
|
new ClipboardJS("[data-clipboard-target], [data-clipboard-text]", {
|
||||||
text: el => (
|
text: el => (
|
||||||
el.getAttribute("data-clipboard-text")! ||
|
el.getAttribute("data-clipboard-text")! ||
|
||||||
extract(getElementOrThrow(
|
extract(getElement(
|
||||||
el.getAttribute("data-clipboard-target")!
|
el.getAttribute("data-clipboard-target")!
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
|
@ -47,9 +47,8 @@ import { configuration, feature } from "~/_"
|
|||||||
import {
|
import {
|
||||||
Viewport,
|
Viewport,
|
||||||
ViewportOffset,
|
ViewportOffset,
|
||||||
getElement,
|
|
||||||
getElements,
|
getElements,
|
||||||
replaceElement,
|
getOptionalElement,
|
||||||
request,
|
request,
|
||||||
requestXML,
|
requestXML,
|
||||||
setLocation,
|
setLocation,
|
||||||
@ -166,7 +165,7 @@ export function setupInstantLoading(
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* Hack: ensure absolute favicon link to omit 404s when switching */
|
/* Hack: ensure absolute favicon link to omit 404s when switching */
|
||||||
const favicon = getElement<HTMLLinkElement>("link[rel=icon]")
|
const favicon = getOptionalElement<HTMLLinkElement>("link[rel=icon]")
|
||||||
if (typeof favicon !== "undefined")
|
if (typeof favicon !== "undefined")
|
||||||
favicon.href = favicon.href
|
favicon.href = favicon.href
|
||||||
|
|
||||||
@ -286,13 +285,13 @@ export function setupInstantLoading(
|
|||||||
? ["[data-md-component=tabs]"]
|
? ["[data-md-component=tabs]"]
|
||||||
: []
|
: []
|
||||||
]) {
|
]) {
|
||||||
const source = getElement(selector)
|
const source = getOptionalElement(selector)
|
||||||
const target = getElement(selector, replacement)
|
const target = getOptionalElement(selector, replacement)
|
||||||
if (
|
if (
|
||||||
typeof source !== "undefined" &&
|
typeof source !== "undefined" &&
|
||||||
typeof target !== "undefined"
|
typeof target !== "undefined"
|
||||||
) {
|
) {
|
||||||
replaceElement(source, target)
|
source.replaceWith(target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@ -308,7 +307,7 @@ export function setupInstantLoading(
|
|||||||
if (el.src) {
|
if (el.src) {
|
||||||
for (const name of el.getAttributeNames())
|
for (const name of el.getAttributeNames())
|
||||||
script.setAttribute(name, el.getAttribute(name)!)
|
script.setAttribute(name, el.getAttribute(name)!)
|
||||||
replaceElement(el, script)
|
el.replaceWith(script)
|
||||||
|
|
||||||
/* Complete when script is loaded */
|
/* Complete when script is loaded */
|
||||||
return new Observable(observer => {
|
return new Observable(observer => {
|
||||||
@ -318,7 +317,7 @@ export function setupInstantLoading(
|
|||||||
/* Complete immediately */
|
/* Complete immediately */
|
||||||
} else {
|
} else {
|
||||||
script.textContent = el.textContent
|
script.textContent = el.textContent
|
||||||
replaceElement(el, script)
|
el.replaceWith(script)
|
||||||
return EMPTY
|
return EMPTY
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
@ -24,7 +24,7 @@ import { combineLatest, map } from "rxjs"
|
|||||||
|
|
||||||
import { configuration } from "~/_"
|
import { configuration } from "~/_"
|
||||||
import {
|
import {
|
||||||
getElementOrThrow,
|
getElement,
|
||||||
requestJSON
|
requestJSON
|
||||||
} from "~/browser"
|
} from "~/browser"
|
||||||
import { getComponentElements } from "~/components"
|
import { getComponentElements } from "~/components"
|
||||||
@ -60,7 +60,7 @@ export function setupVersionSelector(): void {
|
|||||||
/* Render version selector and warning */
|
/* Render version selector and warning */
|
||||||
combineLatest([versions$, current$])
|
combineLatest([versions$, current$])
|
||||||
.subscribe(([versions, current]) => {
|
.subscribe(([versions, current]) => {
|
||||||
const topic = getElementOrThrow(".md-header__topic")
|
const topic = getElement(".md-header__topic")
|
||||||
topic.appendChild(renderVersionSelector(versions, current))
|
topic.appendChild(renderVersionSelector(versions, current))
|
||||||
|
|
||||||
/* Check if version state was already determined */
|
/* Check if version state was already determined */
|
||||||
|
@ -43,7 +43,7 @@ import { getElements } from "~/browser"
|
|||||||
*/
|
*/
|
||||||
interface PatchOptions {
|
interface PatchOptions {
|
||||||
document$: Observable<Document> /* Document observable */
|
document$: Observable<Document> /* Document observable */
|
||||||
tablet$: Observable<boolean> /* Tablet breakpoint observable */
|
tablet$: Observable<boolean> /* Media tablet observable */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
|
@ -32,8 +32,14 @@ import {
|
|||||||
withLatestFrom
|
withLatestFrom
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import { resetScrollLock, setScrollLock } from "~/actions"
|
import {
|
||||||
import { Viewport, watchToggle } from "~/browser"
|
resetScrollLock,
|
||||||
|
setScrollLock
|
||||||
|
} from "~/actions"
|
||||||
|
import {
|
||||||
|
Viewport,
|
||||||
|
watchToggle
|
||||||
|
} from "~/browser"
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
* Helper types
|
* Helper types
|
||||||
@ -44,7 +50,7 @@ import { Viewport, watchToggle } from "~/browser"
|
|||||||
*/
|
*/
|
||||||
interface PatchOptions {
|
interface PatchOptions {
|
||||||
viewport$: Observable<Viewport> /* Viewport observable */
|
viewport$: Observable<Viewport> /* Viewport observable */
|
||||||
tablet$: Observable<boolean> /* Tablet breakpoint observable */
|
tablet$: Observable<boolean> /* Media tablet observable */
|
||||||
}
|
}
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
|
@ -27,7 +27,7 @@ import { h } from "~/utilities"
|
|||||||
* ------------------------------------------------------------------------- */
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Render a 'copy-to-clipboard' button
|
* Render a a code annotation
|
||||||
*
|
*
|
||||||
* @param id - Unique identifier
|
* @param id - Unique identifier
|
||||||
* @param content - Annotation content
|
* @param content - Annotation content
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
* IN THE SOFTWARE.
|
* IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { getElementOrThrow, getElements } from "~/browser"
|
import { getElement, getElements } from "~/browser"
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
/* ----------------------------------------------------------------------------
|
||||||
* Types
|
* Types
|
||||||
@ -84,7 +84,7 @@ interface ComponentTypeMap {
|
|||||||
export function getComponentElement<T extends ComponentType>(
|
export function getComponentElement<T extends ComponentType>(
|
||||||
type: T, node: ParentNode = document
|
type: T, node: ParentNode = document
|
||||||
): ComponentTypeMap[T] {
|
): ComponentTypeMap[T] {
|
||||||
return getElementOrThrow(`[data-mdx-component=${type}]`, node)
|
return getElement(`[data-mdx-component=${type}]`, node)
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -47,8 +47,8 @@ import {
|
|||||||
setSearchResultMeta
|
setSearchResultMeta
|
||||||
} from "~/actions"
|
} from "~/actions"
|
||||||
import {
|
import {
|
||||||
getElementOrThrow,
|
getElement,
|
||||||
watchElementThreshold
|
watchElementBoundary
|
||||||
} from "~/browser"
|
} from "~/browser"
|
||||||
|
|
||||||
import { Icon, renderIconSearchResult } from "_/templates"
|
import { Icon, renderIconSearchResult } from "_/templates"
|
||||||
@ -147,13 +147,13 @@ export function mountIconSearchResult(
|
|||||||
el: HTMLElement, { index$, query$ }: MountOptions
|
el: HTMLElement, { index$, query$ }: MountOptions
|
||||||
): Observable<Component<IconSearchResult, HTMLElement>> {
|
): Observable<Component<IconSearchResult, HTMLElement>> {
|
||||||
const internal$ = new Subject<IconSearchResult>()
|
const internal$ = new Subject<IconSearchResult>()
|
||||||
const boundary$ = watchElementThreshold(el)
|
const boundary$ = watchElementBoundary(el)
|
||||||
.pipe(
|
.pipe(
|
||||||
filter(Boolean)
|
filter(Boolean)
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Update search result metadata */
|
/* Update search result metadata */
|
||||||
const meta = getElementOrThrow(":scope > :first-child", el)
|
const meta = getElement(":scope > :first-child", el)
|
||||||
internal$
|
internal$
|
||||||
.pipe(
|
.pipe(
|
||||||
observeOn(animationFrameScheduler),
|
observeOn(animationFrameScheduler),
|
||||||
@ -167,7 +167,7 @@ export function mountIconSearchResult(
|
|||||||
})
|
})
|
||||||
|
|
||||||
/* Update icon search result list */
|
/* Update icon search result list */
|
||||||
const list = getElementOrThrow(":scope > :last-child", el)
|
const list = getElement(":scope > :last-child", el)
|
||||||
internal$
|
internal$
|
||||||
.pipe(
|
.pipe(
|
||||||
observeOn(animationFrameScheduler),
|
observeOn(animationFrameScheduler),
|
||||||
|
@ -22,7 +22,7 @@
|
|||||||
|
|
||||||
import { Observable, map } from "rxjs"
|
import { Observable, map } from "rxjs"
|
||||||
|
|
||||||
import { getElementOrThrow, requestJSON } from "~/browser"
|
import { getElement, requestJSON } from "~/browser"
|
||||||
|
|
||||||
import { renderPrivateSponsor, renderPublicSponsor } from "_/templates"
|
import { renderPrivateSponsor, renderPublicSponsor } from "_/templates"
|
||||||
|
|
||||||
@ -121,7 +121,7 @@ export function mountSponsorship(
|
|||||||
el.removeAttribute("hidden")
|
el.removeAttribute("hidden")
|
||||||
|
|
||||||
/* Render public sponsors with avatar and links */
|
/* Render public sponsors with avatar and links */
|
||||||
const list = getElementOrThrow(":scope > :first-child", el)
|
const list = getElement(":scope > :first-child", el)
|
||||||
for (const sponsor of sponsorship.sponsors)
|
for (const sponsor of sponsorship.sponsors)
|
||||||
if (sponsor.type === "public")
|
if (sponsor.type === "public")
|
||||||
list.appendChild(renderPublicSponsor(sponsor.user))
|
list.appendChild(renderPublicSponsor(sponsor.user))
|
||||||
|
@ -182,6 +182,7 @@ export function transformScript(
|
|||||||
map: Buffer.from(data, "base64")
|
map: Buffer.from(data, "base64")
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
|
catchError(() => NEVER),
|
||||||
switchMap(({ js, map }) => {
|
switchMap(({ js, map }) => {
|
||||||
const file = digest(options.to, js)
|
const file = digest(options.to, js)
|
||||||
return concat(
|
return concat(
|
||||||
|
7
typings/_/index.d.ts
vendored
7
typings/_/index.d.ts
vendored
@ -106,9 +106,10 @@ declare global {
|
|||||||
var target$: Observable<HTMLElement> /* Location target observable */
|
var target$: Observable<HTMLElement> /* Location target observable */
|
||||||
var keyboard$: Observable<Keyboard> /* Keyboard observable */
|
var keyboard$: Observable<Keyboard> /* Keyboard observable */
|
||||||
var viewport$: Observable<Viewport> /* Viewport obsevable */
|
var viewport$: Observable<Viewport> /* Viewport obsevable */
|
||||||
var tablet$: Observable<boolean> /* Tablet breakpoint observable */
|
var tablet$: Observable<boolean> /* Media tablet observable */
|
||||||
var screen$: Observable<boolean> /* Screen breakpoint observable */
|
var screen$: Observable<boolean> /* Media screen observable */
|
||||||
var print$: Observable<boolean> /* Print observable */
|
var hover$: Observable<boolean> /* Media hover observable */
|
||||||
|
var print$: Observable<boolean> /* Media print observable */
|
||||||
var alert$: Subject<string> /* Alert subject */
|
var alert$: Subject<string> /* Alert subject */
|
||||||
var component$: Observable<Component>/* Component observable */
|
var component$: Observable<Component>/* Component observable */
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user