mirror of
https://github.com/squidfunk/mkdocs-material.git
synced 2024-11-30 18:24:35 +01:00
Fixed observable completion semantics
This commit is contained in:
parent
abe475e151
commit
c30c3d196e
29
material/assets/javascripts/bundle.054bf2ee.min.js
vendored
Normal file
29
material/assets/javascripts/bundle.054bf2ee.min.js
vendored
Normal file
File diff suppressed because one or more lines are too long
7
material/assets/javascripts/bundle.054bf2ee.min.js.map
Normal file
7
material/assets/javascripts/bundle.054bf2ee.min.js.map
Normal file
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
@ -213,7 +213,7 @@
|
|||||||
</script>
|
</script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
{% block scripts %}
|
{% block scripts %}
|
||||||
<script src="{{ 'assets/javascripts/bundle.7c769d4b.min.js' | url }}"></script>
|
<script src="{{ 'assets/javascripts/bundle.054bf2ee.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 %}
|
||||||
|
18
material/overrides/assets/javascripts/bundle.a08d04cf.min.js
vendored
Normal file
18
material/overrides/assets/javascripts/bundle.a08d04cf.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
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.afb943e6.min.js' | url }}"></script>
|
<script src="{{ 'overrides/assets/javascripts/bundle.a08d04cf.min.js' | url }}"></script>
|
||||||
{% endblock %}
|
{% endblock %}
|
||||||
|
@ -1,78 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Functions
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set focusable property
|
|
||||||
*
|
|
||||||
* @param el - Element
|
|
||||||
* @param value - Tabindex value
|
|
||||||
*/
|
|
||||||
export function setFocusable(
|
|
||||||
el: HTMLElement, value = 0
|
|
||||||
): void {
|
|
||||||
el.setAttribute("tabindex", value.toString())
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset focusable property
|
|
||||||
*
|
|
||||||
* @param el - Element
|
|
||||||
*/
|
|
||||||
export function resetFocusable(
|
|
||||||
el: HTMLElement
|
|
||||||
): void {
|
|
||||||
el.removeAttribute("tabindex")
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set scroll lock
|
|
||||||
*
|
|
||||||
* @param el - Scrollable element
|
|
||||||
* @param value - Vertical offset
|
|
||||||
*/
|
|
||||||
export function setScrollLock(
|
|
||||||
el: HTMLElement, value: number
|
|
||||||
): void {
|
|
||||||
el.setAttribute("data-md-state", "lock")
|
|
||||||
el.style.top = `-${value}px`
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset scroll lock
|
|
||||||
*
|
|
||||||
* @param el - Scrollable element
|
|
||||||
*/
|
|
||||||
export function resetScrollLock(
|
|
||||||
el: HTMLElement
|
|
||||||
): void {
|
|
||||||
const value = -1 * parseInt(el.style.top, 10)
|
|
||||||
el.removeAttribute("data-md-state")
|
|
||||||
el.style.top = ""
|
|
||||||
if (value)
|
|
||||||
window.scrollTo(0, value)
|
|
||||||
}
|
|
@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Functions
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set anchor state
|
|
||||||
*
|
|
||||||
* @param el - Anchor element
|
|
||||||
* @param state - Anchor state
|
|
||||||
*/
|
|
||||||
export function setAnchorState(
|
|
||||||
el: HTMLElement, state: "blur"
|
|
||||||
): void {
|
|
||||||
el.setAttribute("data-md-state", state)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset anchor state
|
|
||||||
*
|
|
||||||
* @param el - Anchor element
|
|
||||||
*/
|
|
||||||
export function resetAnchorState(
|
|
||||||
el: HTMLElement
|
|
||||||
): void {
|
|
||||||
el.removeAttribute("data-md-state")
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set anchor active
|
|
||||||
*
|
|
||||||
* @param el - Anchor element
|
|
||||||
* @param value - Whether the anchor is active
|
|
||||||
*/
|
|
||||||
export function setAnchorActive(
|
|
||||||
el: HTMLElement, value: boolean
|
|
||||||
): void {
|
|
||||||
el.classList.toggle("md-nav__link--active", value)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset anchor active
|
|
||||||
*
|
|
||||||
* @param el - Anchor element
|
|
||||||
*/
|
|
||||||
export function resetAnchorActive(
|
|
||||||
el: HTMLElement
|
|
||||||
): void {
|
|
||||||
el.classList.remove("md-nav__link--active")
|
|
||||||
}
|
|
@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Functions
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set dialog message
|
|
||||||
*
|
|
||||||
* @param el - Dialog element
|
|
||||||
* @param value - Dialog message
|
|
||||||
*/
|
|
||||||
export function setDialogMessage(
|
|
||||||
el: HTMLElement, value: string
|
|
||||||
): void {
|
|
||||||
el.firstElementChild!.innerHTML = value
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set dialog state
|
|
||||||
*
|
|
||||||
* @param el - Dialog element
|
|
||||||
* @param state - Dialog state
|
|
||||||
*/
|
|
||||||
export function setDialogState(
|
|
||||||
el: HTMLElement, state: "open"
|
|
||||||
): void {
|
|
||||||
el.setAttribute("data-md-state", state)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset dialog state
|
|
||||||
*
|
|
||||||
* @param el - Dialog element
|
|
||||||
*/
|
|
||||||
export function resetDialogState(
|
|
||||||
el: HTMLElement
|
|
||||||
): void {
|
|
||||||
el.removeAttribute("data-md-state")
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Functions
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set header state
|
|
||||||
*
|
|
||||||
* @param el - Header element
|
|
||||||
* @param state - Header state
|
|
||||||
*/
|
|
||||||
export function setHeaderState(
|
|
||||||
el: HTMLElement, state: "shadow" | "hidden"
|
|
||||||
): void {
|
|
||||||
el.setAttribute("data-md-state", state)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset header state
|
|
||||||
*
|
|
||||||
* @param el - Header element
|
|
||||||
*/
|
|
||||||
export function resetHeaderState(
|
|
||||||
el: HTMLElement
|
|
||||||
): void {
|
|
||||||
el.removeAttribute("data-md-state")
|
|
||||||
}
|
|
@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from "./_"
|
|
||||||
export * from "./title"
|
|
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Functions
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set header title state
|
|
||||||
*
|
|
||||||
* @param el - Header title element
|
|
||||||
* @param state - Header title state
|
|
||||||
*/
|
|
||||||
export function setHeaderTitleState(
|
|
||||||
el: HTMLElement, state: "active"
|
|
||||||
): void {
|
|
||||||
el.setAttribute("data-md-state", state)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset header title state
|
|
||||||
*
|
|
||||||
* @param el - Header title element
|
|
||||||
*/
|
|
||||||
export function resetHeaderTitleState(
|
|
||||||
el: HTMLElement
|
|
||||||
): void {
|
|
||||||
el.removeAttribute("data-md-state")
|
|
||||||
}
|
|
@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from "./_"
|
|
||||||
export * from "./anchor"
|
|
||||||
export * from "./dialog"
|
|
||||||
export * from "./header"
|
|
||||||
export * from "./search"
|
|
||||||
export * from "./sidebar"
|
|
||||||
export * from "./source"
|
|
||||||
export * from "./tabs"
|
|
||||||
export * from "./top"
|
|
@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
export * from "./query"
|
|
||||||
export * from "./result"
|
|
@ -1,50 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 { translation } from "~/_"
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Functions
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set search query placeholder
|
|
||||||
*
|
|
||||||
* @param el - Search query element
|
|
||||||
* @param value - Placeholder
|
|
||||||
*/
|
|
||||||
export function setSearchQueryPlaceholder(
|
|
||||||
el: HTMLInputElement, value: string
|
|
||||||
): void {
|
|
||||||
el.placeholder = value
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset search query placeholder
|
|
||||||
*
|
|
||||||
* @param el - Search query element
|
|
||||||
*/
|
|
||||||
export function resetSearchQueryPlaceholder(
|
|
||||||
el: HTMLInputElement
|
|
||||||
): void {
|
|
||||||
el.placeholder = translation("search.placeholder")
|
|
||||||
}
|
|
@ -1,91 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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 { translation } from "~/_"
|
|
||||||
import { round } from "~/utilities"
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Functions
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set number of search results
|
|
||||||
*
|
|
||||||
* @param el - Search result metadata element
|
|
||||||
* @param value - Number of results
|
|
||||||
*/
|
|
||||||
export function setSearchResultMeta(
|
|
||||||
el: HTMLElement, value: number
|
|
||||||
): void {
|
|
||||||
switch (value) {
|
|
||||||
|
|
||||||
/* No results */
|
|
||||||
case 0:
|
|
||||||
el.textContent = translation("search.result.none")
|
|
||||||
break
|
|
||||||
|
|
||||||
/* One result */
|
|
||||||
case 1:
|
|
||||||
el.textContent = translation("search.result.one")
|
|
||||||
break
|
|
||||||
|
|
||||||
/* Multiple result */
|
|
||||||
default:
|
|
||||||
el.textContent = translation("search.result.other", round(value))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset number of search results
|
|
||||||
*
|
|
||||||
* @param el - Search result metadata element
|
|
||||||
*/
|
|
||||||
export function resetSearchResultMeta(
|
|
||||||
el: HTMLElement
|
|
||||||
): void {
|
|
||||||
el.textContent = translation("search.result.placeholder")
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Add an element to the search result list
|
|
||||||
*
|
|
||||||
* @param el - Search result list element
|
|
||||||
* @param child - Search result element
|
|
||||||
*/
|
|
||||||
export function addToSearchResultList(
|
|
||||||
el: HTMLElement, child: Element
|
|
||||||
): void {
|
|
||||||
el.appendChild(child)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset search result list
|
|
||||||
*
|
|
||||||
* @param el - Search result list element
|
|
||||||
*/
|
|
||||||
export function resetSearchResultList(
|
|
||||||
el: HTMLElement
|
|
||||||
): void {
|
|
||||||
el.innerHTML = ""
|
|
||||||
}
|
|
@ -1,88 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Functions
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set sidebar offset
|
|
||||||
*
|
|
||||||
* @param el - Sidebar element
|
|
||||||
* @param value - Sidebar offset
|
|
||||||
*/
|
|
||||||
export function setSidebarOffset(
|
|
||||||
el: HTMLElement, value: number
|
|
||||||
): void {
|
|
||||||
el.style.top = `${value}px`
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset sidebar offset
|
|
||||||
*
|
|
||||||
* @param el - Sidebar element
|
|
||||||
*/
|
|
||||||
export function resetSidebarOffset(
|
|
||||||
el: HTMLElement
|
|
||||||
): void {
|
|
||||||
el.style.top = ""
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set sidebar height
|
|
||||||
*
|
|
||||||
* This function doesn't set the height of the actual sidebar, but of its first
|
|
||||||
* child – the `.md-sidebar__scrollwrap` element in order to mitigiate jittery
|
|
||||||
* sidebars when the footer is scrolled into view. At some point we switched
|
|
||||||
* from `absolute` / `fixed` positioning to `sticky` positioning, significantly
|
|
||||||
* reducing jitter in some browsers (respectively Firefox and Safari) when
|
|
||||||
* scrolling from the top. However, top-aligned sticky positioning means that
|
|
||||||
* the sidebar snaps to the bottom when the end of the container is reached.
|
|
||||||
* This is what leads to the mentioned jitter, as the sidebar's height may be
|
|
||||||
* updated too slowly.
|
|
||||||
*
|
|
||||||
* This behaviour can be mitigiated by setting the height of the sidebar to `0`
|
|
||||||
* while preserving the padding, and the height on its first element.
|
|
||||||
*
|
|
||||||
* @param el - Sidebar element
|
|
||||||
* @param value - Sidebar height
|
|
||||||
*/
|
|
||||||
export function setSidebarHeight(
|
|
||||||
el: HTMLElement, value: number
|
|
||||||
): void {
|
|
||||||
const scrollwrap = el.firstElementChild as HTMLElement
|
|
||||||
scrollwrap.style.height = `${value - 2 * scrollwrap.offsetTop}px`
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset sidebar height
|
|
||||||
*
|
|
||||||
* @param el - Sidebar element
|
|
||||||
*/
|
|
||||||
export function resetSidebarHeight(
|
|
||||||
el: HTMLElement
|
|
||||||
): void {
|
|
||||||
const scrollwrap = el.firstElementChild as HTMLElement
|
|
||||||
scrollwrap.style.height = ""
|
|
||||||
}
|
|
@ -1,49 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Functions
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set repository facts
|
|
||||||
*
|
|
||||||
* @param el - Repository element
|
|
||||||
* @param child - Repository facts element
|
|
||||||
*/
|
|
||||||
export function setSourceFacts(
|
|
||||||
el: HTMLElement, child: Element
|
|
||||||
): void {
|
|
||||||
el.lastElementChild!.appendChild(child)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set repository state
|
|
||||||
*
|
|
||||||
* @param el - Repository element
|
|
||||||
* @param state - Repository state
|
|
||||||
*/
|
|
||||||
export function setSourceState(
|
|
||||||
el: HTMLElement, state: "done"
|
|
||||||
): void {
|
|
||||||
el.lastElementChild!.setAttribute("data-md-state", state)
|
|
||||||
}
|
|
@ -1,48 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Functions
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set tabs state
|
|
||||||
*
|
|
||||||
* @param el - Tabs element
|
|
||||||
* @param state - Tabs state
|
|
||||||
*/
|
|
||||||
export function setTabsState(
|
|
||||||
el: HTMLElement, state: "hidden"
|
|
||||||
): void {
|
|
||||||
el.setAttribute("data-md-state", state)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset tabs state
|
|
||||||
*
|
|
||||||
* @param el - Tabs element
|
|
||||||
*/
|
|
||||||
export function resetTabsState(
|
|
||||||
el: HTMLElement
|
|
||||||
): void {
|
|
||||||
el.removeAttribute("data-md-state")
|
|
||||||
}
|
|
@ -1,73 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Functions
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set back-to-top state
|
|
||||||
*
|
|
||||||
* @param el - Back-to-top element
|
|
||||||
* @param state - Back-to-top state
|
|
||||||
*/
|
|
||||||
export function setBackToTopState(
|
|
||||||
el: HTMLElement, state: "hidden"
|
|
||||||
): void {
|
|
||||||
el.setAttribute("data-md-state", state)
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset back-to-top state
|
|
||||||
*
|
|
||||||
* @param el - Back-to-top element
|
|
||||||
*/
|
|
||||||
export function resetBackToTopState(
|
|
||||||
el: HTMLElement
|
|
||||||
): void {
|
|
||||||
el.removeAttribute("data-md-state")
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set back-to-top offset
|
|
||||||
*
|
|
||||||
* @param el - Back-to-top element
|
|
||||||
* @param value - Back-to-top offset
|
|
||||||
*/
|
|
||||||
export function setBackToTopOffset(
|
|
||||||
el: HTMLElement, value: number
|
|
||||||
): void {
|
|
||||||
el.style.top = `${value}px`
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Reset back-to-top offset
|
|
||||||
*
|
|
||||||
* @param el - Back-to-top element
|
|
||||||
*/
|
|
||||||
export function resetBackToTopOffset(
|
|
||||||
el: HTMLElement
|
|
||||||
): void {
|
|
||||||
el.style.top = ""
|
|
||||||
}
|
|
@ -34,23 +34,6 @@ import { getActiveElement } from "../_"
|
|||||||
* Functions
|
* Functions
|
||||||
* ------------------------------------------------------------------------- */
|
* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/**
|
|
||||||
* Set element focus
|
|
||||||
*
|
|
||||||
* @param el - Element
|
|
||||||
* @param value - Whether the element should be focused
|
|
||||||
*/
|
|
||||||
export function setElementFocus(
|
|
||||||
el: HTMLElement, value = true
|
|
||||||
): void {
|
|
||||||
if (value)
|
|
||||||
el.focus()
|
|
||||||
else
|
|
||||||
el.blur()
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Watch element focus
|
* Watch element focus
|
||||||
*
|
*
|
||||||
|
@ -23,6 +23,5 @@
|
|||||||
export * from "./_"
|
export * from "./_"
|
||||||
export * from "./focus"
|
export * from "./focus"
|
||||||
export * from "./offset"
|
export * from "./offset"
|
||||||
export * from "./selection"
|
|
||||||
export * from "./size"
|
export * from "./size"
|
||||||
export * from "./visibility"
|
export * from "./visibility"
|
||||||
|
@ -1,39 +0,0 @@
|
|||||||
/*
|
|
||||||
* 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.
|
|
||||||
*/
|
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------------
|
|
||||||
* Functions
|
|
||||||
* ------------------------------------------------------------------------- */
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Set element text selection
|
|
||||||
*
|
|
||||||
* @param el - Element
|
|
||||||
*/
|
|
||||||
export function setElementSelection(
|
|
||||||
el: HTMLElement
|
|
||||||
): void {
|
|
||||||
if (el instanceof HTMLInputElement)
|
|
||||||
el.select()
|
|
||||||
else
|
|
||||||
throw new Error("Not implemented")
|
|
||||||
}
|
|
@ -32,7 +32,6 @@ import {
|
|||||||
merge,
|
merge,
|
||||||
of,
|
of,
|
||||||
shareReplay,
|
shareReplay,
|
||||||
startWith,
|
|
||||||
switchMap,
|
switchMap,
|
||||||
tap
|
tap
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
@ -113,7 +112,7 @@ export function watchElementVisibility(
|
|||||||
* @param el - Element
|
* @param el - Element
|
||||||
* @param threshold - Threshold
|
* @param threshold - Threshold
|
||||||
*
|
*
|
||||||
* @returns Element threshold observable
|
* @returns Element boundary observable
|
||||||
*/
|
*/
|
||||||
export function watchElementBoundary(
|
export function watchElementBoundary(
|
||||||
el: HTMLElement, threshold = 16
|
el: HTMLElement, threshold = 16
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
NEVER,
|
EMPTY,
|
||||||
Observable,
|
Observable,
|
||||||
fromEvent,
|
fromEvent,
|
||||||
fromEventPattern,
|
fromEventPattern,
|
||||||
@ -86,6 +86,6 @@ export function at<T>(
|
|||||||
): Observable<T> {
|
): Observable<T> {
|
||||||
return query$
|
return query$
|
||||||
.pipe(
|
.pipe(
|
||||||
switchMap(active => active ? factory() : NEVER)
|
switchMap(active => active ? factory() : EMPTY)
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -59,17 +59,6 @@ export function getViewportOffset(): ViewportOffset {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Set viewport offset
|
|
||||||
*
|
|
||||||
* @param offset - Viewport offset
|
|
||||||
*/
|
|
||||||
export function setViewportOffset(
|
|
||||||
{ x, y }: Partial<ViewportOffset>
|
|
||||||
): void {
|
|
||||||
window.scrollTo(x || 0, y || 0)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ------------------------------------------------------------------------- */
|
/* ------------------------------------------------------------------------- */
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
import "focus-visible"
|
import "focus-visible"
|
||||||
import {
|
import {
|
||||||
|
EMPTY,
|
||||||
NEVER,
|
NEVER,
|
||||||
Subject,
|
Subject,
|
||||||
defer,
|
defer,
|
||||||
@ -198,13 +199,13 @@ const content$ = defer(() => merge(
|
|||||||
|
|
||||||
/* Content */
|
/* Content */
|
||||||
...getComponentElements("content")
|
...getComponentElements("content")
|
||||||
.map(el => mountContent(el, { target$, viewport$, hover$, print$ })),
|
.map(el => mountContent(el, { target$, hover$, print$ })),
|
||||||
|
|
||||||
/* Search highlighting */
|
/* Search highlighting */
|
||||||
...getComponentElements("content")
|
...getComponentElements("content")
|
||||||
.map(el => feature("search.highlight")
|
.map(el => feature("search.highlight")
|
||||||
? mountSearchHiglight(el, { index$, location$ })
|
? mountSearchHiglight(el, { index$, location$ })
|
||||||
: NEVER
|
: EMPTY
|
||||||
),
|
),
|
||||||
|
|
||||||
/* Header title */
|
/* Header title */
|
||||||
|
@ -36,6 +36,7 @@ import {
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
ElementOffset,
|
ElementOffset,
|
||||||
|
getElement,
|
||||||
watchElementContentOffset,
|
watchElementContentOffset,
|
||||||
watchElementFocus,
|
watchElementFocus,
|
||||||
watchElementOffset
|
watchElementOffset
|
||||||
@ -122,7 +123,7 @@ export function mountAnnotation(
|
|||||||
})
|
})
|
||||||
|
|
||||||
/* Blur open annotation on click (= close) */
|
/* Blur open annotation on click (= close) */
|
||||||
const index = el.lastElementChild!
|
const index = getElement(":scope > :last-child")
|
||||||
const blur$ = fromEvent(index, "mousedown", { once: true })
|
const blur$ = fromEvent(index, "mousedown", { once: true })
|
||||||
push$
|
push$
|
||||||
.pipe(
|
.pipe(
|
||||||
|
@ -120,36 +120,36 @@ export function mountAnnotationList(
|
|||||||
|
|
||||||
/* Create and return component */
|
/* Create and return component */
|
||||||
return defer(() => {
|
return defer(() => {
|
||||||
const push$ = new Subject<Annotation>()
|
const done$ = new Subject<void>()
|
||||||
|
|
||||||
/* Handle print mode - see https://bit.ly/3rgPdpt */
|
/* Handle print mode - see https://bit.ly/3rgPdpt */
|
||||||
print$
|
print$
|
||||||
.pipe(
|
.pipe(
|
||||||
startWith(false),
|
startWith(false),
|
||||||
takeUntil(push$.pipe(takeLast(1)))
|
takeUntil(done$.pipe(takeLast(1)))
|
||||||
)
|
)
|
||||||
.subscribe(active => {
|
.subscribe(active => {
|
||||||
el.hidden = !active
|
el.hidden = !active
|
||||||
|
|
||||||
/* Move annotation contents back into list */
|
/* Move annotation contents back into list */
|
||||||
for (const [id, annotation] of annotations) {
|
for (const [id, annotation] of annotations) {
|
||||||
const tooltip = getElement(".md-typeset", annotation)
|
const inner = getElement(".md-typeset", annotation)
|
||||||
const child = getElement(`li:nth-child(${id})`, el)
|
const child = getElement(`li:nth-child(${id})`, el)
|
||||||
if (!active)
|
if (!active)
|
||||||
swap(child, tooltip)
|
swap(child, inner)
|
||||||
else
|
else
|
||||||
swap(tooltip, child)
|
swap(inner, child)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/* Create and return component */
|
/* Create and return component */
|
||||||
return merge(
|
return merge(...[...annotations]
|
||||||
...[...annotations].map(([, annotation]) => (
|
.map(([, annotation]) => (
|
||||||
mountAnnotation(annotation, container)
|
mountAnnotation(annotation, container)
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
.pipe(
|
.pipe(
|
||||||
finalize(() => push$.complete()),
|
finalize(() => done$.complete()),
|
||||||
share()
|
share()
|
||||||
)
|
)
|
||||||
})
|
})
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
import {
|
import {
|
||||||
Observable,
|
Observable,
|
||||||
Subject,
|
Subject,
|
||||||
|
defer,
|
||||||
filter,
|
filter,
|
||||||
finalize,
|
finalize,
|
||||||
map,
|
map,
|
||||||
@ -41,7 +42,7 @@ import { Component } from "../../_"
|
|||||||
* Details
|
* Details
|
||||||
*/
|
*/
|
||||||
export interface Details {
|
export interface Details {
|
||||||
action: "open" | "close" /* Action */
|
action: "open" | "close" /* Details state */
|
||||||
scroll?: boolean /* Scroll into view */
|
scroll?: boolean /* Scroll into view */
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -117,21 +118,23 @@ export function watchDetails(
|
|||||||
export function mountDetails(
|
export function mountDetails(
|
||||||
el: HTMLDetailsElement, options: MountOptions
|
el: HTMLDetailsElement, options: MountOptions
|
||||||
): Observable<Component<Details>> {
|
): Observable<Component<Details>> {
|
||||||
const internal$ = new Subject<Details>()
|
return defer(() => {
|
||||||
internal$.subscribe(({ action, scroll }) => {
|
const push$ = new Subject<Details>()
|
||||||
if (action === "open")
|
push$.subscribe(({ action, scroll }) => {
|
||||||
el.setAttribute("open", "")
|
if (action === "open")
|
||||||
else
|
el.setAttribute("open", "")
|
||||||
el.removeAttribute("open")
|
else
|
||||||
if (scroll)
|
el.removeAttribute("open")
|
||||||
el.scrollIntoView()
|
if (scroll)
|
||||||
})
|
el.scrollIntoView()
|
||||||
|
})
|
||||||
|
|
||||||
/* Create and return component */
|
/* Create and return component */
|
||||||
return watchDetails(el, options)
|
return watchDetails(el, options)
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(state => internal$.next(state)),
|
tap(state => push$.next(state)),
|
||||||
finalize(() => internal$.complete()),
|
finalize(() => push$.complete()),
|
||||||
map(state => ({ ref: el, ...state }))
|
map(state => ({ ref: el, ...state }))
|
||||||
)
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
import {
|
import {
|
||||||
Observable,
|
Observable,
|
||||||
Subject,
|
Subject,
|
||||||
|
defer,
|
||||||
finalize,
|
finalize,
|
||||||
fromEvent,
|
fromEvent,
|
||||||
map,
|
map,
|
||||||
@ -33,6 +34,7 @@ import {
|
|||||||
|
|
||||||
import {
|
import {
|
||||||
getElement,
|
getElement,
|
||||||
|
getElementOffset,
|
||||||
getElements
|
getElements
|
||||||
} from "~/browser"
|
} from "~/browser"
|
||||||
|
|
||||||
@ -64,7 +66,11 @@ export function watchContentTabs(
|
|||||||
el: HTMLElement
|
el: HTMLElement
|
||||||
): Observable<ContentTabs> {
|
): Observable<ContentTabs> {
|
||||||
return merge(...getElements(":scope > input", el)
|
return merge(...getElements(":scope > input", el)
|
||||||
.map(input => fromEvent(input, "change").pipe(mapTo(input.id)))
|
.map(input => fromEvent(input, "change")
|
||||||
|
.pipe(
|
||||||
|
mapTo(input.id)
|
||||||
|
)
|
||||||
|
)
|
||||||
)
|
)
|
||||||
.pipe(
|
.pipe(
|
||||||
map(id => ({
|
map(id => ({
|
||||||
@ -76,6 +82,11 @@ export function watchContentTabs(
|
|||||||
/**
|
/**
|
||||||
* Mount content tabs
|
* Mount content tabs
|
||||||
*
|
*
|
||||||
|
* This function scrolls the active tab into view. While this functionality is
|
||||||
|
* provided by browsers as part of `scrollInfoView`, browsers will always also
|
||||||
|
* scroll the vertical axis, which we do not want. Thus, we decided to provide
|
||||||
|
* this functionality ourselves.
|
||||||
|
*
|
||||||
* @param el - Content tabs element
|
* @param el - Content tabs element
|
||||||
*
|
*
|
||||||
* @returns Content tabs component observable
|
* @returns Content tabs component observable
|
||||||
@ -83,25 +94,23 @@ export function watchContentTabs(
|
|||||||
export function mountContentTabs(
|
export function mountContentTabs(
|
||||||
el: HTMLElement
|
el: HTMLElement
|
||||||
): Observable<Component<ContentTabs>> {
|
): Observable<Component<ContentTabs>> {
|
||||||
const internal$ = new Subject<ContentTabs>()
|
const container = getElement(".tabbed-labels", el)
|
||||||
internal$.subscribe(({ active }) => {
|
return defer(() => {
|
||||||
// TODO: Hack, scrollIntoView is too buggy
|
const push$ = new Subject<ContentTabs>()
|
||||||
const container = active.parentElement!
|
push$.subscribe(({ active }) => {
|
||||||
if (
|
const { x } = getElementOffset(active)
|
||||||
active.offsetLeft + active.offsetWidth > container.scrollLeft + container.offsetWidth ||
|
|
||||||
active.offsetLeft < container.scrollLeft
|
|
||||||
)
|
|
||||||
container.scrollTo({
|
container.scrollTo({
|
||||||
behavior: "smooth",
|
behavior: "smooth",
|
||||||
left: active.offsetLeft
|
left: x
|
||||||
})
|
})
|
||||||
})
|
})
|
||||||
|
|
||||||
/* Create and return component */
|
/* Create and return component */
|
||||||
return watchContentTabs(el)
|
return watchContentTabs(el)
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(state => internal$.next(state)),
|
tap(state => push$.next(state)),
|
||||||
finalize(() => internal$.complete()),
|
finalize(() => push$.complete()),
|
||||||
map(state => ({ ref: el, ...state }))
|
map(state => ({ ref: el, ...state }))
|
||||||
)
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -23,22 +23,17 @@
|
|||||||
import {
|
import {
|
||||||
Observable,
|
Observable,
|
||||||
Subject,
|
Subject,
|
||||||
animationFrameScheduler,
|
defer,
|
||||||
delay,
|
delay,
|
||||||
finalize,
|
finalize,
|
||||||
map,
|
map,
|
||||||
merge,
|
merge,
|
||||||
observeOn,
|
|
||||||
of,
|
of,
|
||||||
switchMap,
|
switchMap,
|
||||||
tap
|
tap
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import {
|
import { getElement } from "~/browser"
|
||||||
resetDialogState,
|
|
||||||
setDialogMessage,
|
|
||||||
setDialogState
|
|
||||||
} from "~/actions"
|
|
||||||
|
|
||||||
import { Component } from "../_"
|
import { Component } from "../_"
|
||||||
|
|
||||||
@ -103,7 +98,7 @@ export function watchDialog(
|
|||||||
/**
|
/**
|
||||||
* Mount dialog
|
* Mount dialog
|
||||||
*
|
*
|
||||||
* This function reveals the dialog in the right cornerwhen a new alert is
|
* This function reveals the dialog in the right corner when a new alert is
|
||||||
* emitted through the subject that is passed as part of the options.
|
* emitted through the subject that is passed as part of the options.
|
||||||
*
|
*
|
||||||
* @param el - Dialog element
|
* @param el - Dialog element
|
||||||
@ -114,24 +109,23 @@ export function watchDialog(
|
|||||||
export function mountDialog(
|
export function mountDialog(
|
||||||
el: HTMLElement, options: MountOptions
|
el: HTMLElement, options: MountOptions
|
||||||
): Observable<Component<Dialog>> {
|
): Observable<Component<Dialog>> {
|
||||||
const internal$ = new Subject<Dialog>()
|
const inner = getElement(".md-typeset", el)
|
||||||
internal$
|
return defer(() => {
|
||||||
.pipe(
|
const push$ = new Subject<Dialog>()
|
||||||
observeOn(animationFrameScheduler)
|
push$.subscribe(({ message, open }) => {
|
||||||
)
|
inner.textContent = message
|
||||||
.subscribe(({ message, open }) => {
|
if (open)
|
||||||
setDialogMessage(el, message)
|
el.setAttribute("data-md-state", "open")
|
||||||
if (open)
|
else
|
||||||
setDialogState(el, "open")
|
el.removeAttribute("data-md-state")
|
||||||
else
|
})
|
||||||
resetDialogState(el)
|
|
||||||
})
|
|
||||||
|
|
||||||
/* Create and return component */
|
/* Create and return component */
|
||||||
return watchDialog(el, options)
|
return watchDialog(el, options)
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(state => internal$.next(state)),
|
tap(state => push$.next(state)),
|
||||||
finalize(() => internal$.complete()),
|
finalize(() => push$.complete()),
|
||||||
map(state => ({ ref: el, ...state }))
|
map(state => ({ ref: el, ...state }))
|
||||||
)
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
import {
|
import {
|
||||||
Observable,
|
Observable,
|
||||||
Subject,
|
Subject,
|
||||||
animationFrameScheduler,
|
|
||||||
bufferCount,
|
bufferCount,
|
||||||
combineLatest,
|
combineLatest,
|
||||||
combineLatestWith,
|
combineLatestWith,
|
||||||
@ -32,18 +31,15 @@ import {
|
|||||||
distinctUntilKeyChanged,
|
distinctUntilKeyChanged,
|
||||||
filter,
|
filter,
|
||||||
map,
|
map,
|
||||||
observeOn,
|
|
||||||
of,
|
of,
|
||||||
shareReplay,
|
shareReplay,
|
||||||
startWith,
|
startWith,
|
||||||
switchMap
|
switchMap,
|
||||||
|
takeLast,
|
||||||
|
takeUntil
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import { feature } from "~/_"
|
import { feature } from "~/_"
|
||||||
import {
|
|
||||||
resetHeaderState,
|
|
||||||
setHeaderState
|
|
||||||
} from "~/actions"
|
|
||||||
import {
|
import {
|
||||||
Viewport,
|
Viewport,
|
||||||
watchElementSize,
|
watchElementSize,
|
||||||
@ -184,24 +180,28 @@ export function watchHeader(
|
|||||||
export function mountHeader(
|
export function mountHeader(
|
||||||
el: HTMLElement, { header$, main$ }: MountOptions
|
el: HTMLElement, { header$, main$ }: MountOptions
|
||||||
): Observable<Component<Header>> {
|
): Observable<Component<Header>> {
|
||||||
const internal$ = new Subject<Main>()
|
return defer(() => {
|
||||||
internal$
|
const push$ = new Subject<Main>()
|
||||||
.pipe(
|
push$
|
||||||
distinctUntilKeyChanged("active"),
|
.pipe(
|
||||||
combineLatestWith(header$),
|
distinctUntilKeyChanged("active"),
|
||||||
observeOn(animationFrameScheduler)
|
combineLatestWith(header$)
|
||||||
)
|
)
|
||||||
.subscribe(([{ active }, { hidden }]) => {
|
.subscribe(([{ active }, { hidden }]) => {
|
||||||
if (active)
|
if (active)
|
||||||
setHeaderState(el, hidden ? "hidden" : "shadow")
|
el.setAttribute("data-md-state", hidden ? "hidden" : "shadow")
|
||||||
else
|
else
|
||||||
resetHeaderState(el)
|
el.removeAttribute("data-md-state")
|
||||||
})
|
})
|
||||||
|
|
||||||
/* Connect to long-living subject and return component */
|
/* Link to main area */
|
||||||
main$.subscribe(main => internal$.next(main))
|
main$.subscribe(push$)
|
||||||
return header$
|
|
||||||
.pipe(
|
/* Create and return component */
|
||||||
map(state => ({ ref: el, ...state }))
|
return header$
|
||||||
)
|
.pipe(
|
||||||
|
takeUntil(push$.pipe(takeLast(1))),
|
||||||
|
map(state => ({ ref: el, ...state }))
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -21,21 +21,16 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
NEVER,
|
EMPTY,
|
||||||
Observable,
|
Observable,
|
||||||
Subject,
|
Subject,
|
||||||
animationFrameScheduler,
|
defer,
|
||||||
distinctUntilKeyChanged,
|
distinctUntilKeyChanged,
|
||||||
finalize,
|
finalize,
|
||||||
map,
|
map,
|
||||||
observeOn,
|
|
||||||
tap
|
tap
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import {
|
|
||||||
resetHeaderTitleState,
|
|
||||||
setHeaderTitleState
|
|
||||||
} from "~/actions"
|
|
||||||
import {
|
import {
|
||||||
Viewport,
|
Viewport,
|
||||||
getElementSize,
|
getElementSize,
|
||||||
@ -118,28 +113,26 @@ export function watchHeaderTitle(
|
|||||||
export function mountHeaderTitle(
|
export function mountHeaderTitle(
|
||||||
el: HTMLElement, options: MountOptions
|
el: HTMLElement, options: MountOptions
|
||||||
): Observable<Component<HeaderTitle>> {
|
): Observable<Component<HeaderTitle>> {
|
||||||
const internal$ = new Subject<HeaderTitle>()
|
return defer(() => {
|
||||||
internal$
|
const push$ = new Subject<HeaderTitle>()
|
||||||
.pipe(
|
push$.subscribe(({ active }) => {
|
||||||
observeOn(animationFrameScheduler)
|
if (active)
|
||||||
)
|
el.setAttribute("data-md-state", "active")
|
||||||
.subscribe(({ active }) => {
|
else
|
||||||
if (active)
|
el.removeAttribute("data-md-state")
|
||||||
setHeaderTitleState(el, "active")
|
})
|
||||||
else
|
|
||||||
resetHeaderTitleState(el)
|
|
||||||
})
|
|
||||||
|
|
||||||
/* Obtain headline, if any */
|
/* Obtain headline, if any */
|
||||||
const headline = getOptionalElement<HTMLHeadingElement>("article h1")
|
const heading = getOptionalElement<HTMLHeadingElement>("article h1")
|
||||||
if (typeof headline === "undefined")
|
if (typeof heading === "undefined")
|
||||||
return NEVER
|
return EMPTY
|
||||||
|
|
||||||
/* Create and return component */
|
/* Create and return component */
|
||||||
return watchHeaderTitle(headline, options)
|
return watchHeaderTitle(heading, options)
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(state => internal$.next(state)),
|
tap(state => push$.next(state)),
|
||||||
finalize(() => internal$.complete()),
|
finalize(() => push$.complete()),
|
||||||
map(state => ({ ref: el, ...state }))
|
map(state => ({ ref: el, ...state }))
|
||||||
)
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -23,6 +23,7 @@
|
|||||||
import {
|
import {
|
||||||
Observable,
|
Observable,
|
||||||
Subject,
|
Subject,
|
||||||
|
defer,
|
||||||
finalize,
|
finalize,
|
||||||
fromEvent,
|
fromEvent,
|
||||||
map,
|
map,
|
||||||
@ -74,9 +75,9 @@ export function watchPalette(
|
|||||||
inputs: HTMLInputElement[]
|
inputs: HTMLInputElement[]
|
||||||
): Observable<Palette> {
|
): Observable<Palette> {
|
||||||
const current = __md_get<Palette>("__palette") || {
|
const current = __md_get<Palette>("__palette") || {
|
||||||
index: inputs.findIndex(input => (
|
index: inputs.findIndex(input => matchMedia(
|
||||||
matchMedia(input.getAttribute("data-md-color-media")!).matches
|
input.getAttribute("data-md-color-media")!
|
||||||
))
|
).matches)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Emit changes in color palette */
|
/* Emit changes in color palette */
|
||||||
@ -99,11 +100,6 @@ export function watchPalette(
|
|||||||
shareReplay(1)
|
shareReplay(1)
|
||||||
)
|
)
|
||||||
|
|
||||||
/* Persist preference in local storage */
|
|
||||||
palette$.subscribe(palette => {
|
|
||||||
__md_set("__palette", palette)
|
|
||||||
})
|
|
||||||
|
|
||||||
/* Return palette */
|
/* Return palette */
|
||||||
return palette$
|
return palette$
|
||||||
}
|
}
|
||||||
@ -118,28 +114,33 @@ export function watchPalette(
|
|||||||
export function mountPalette(
|
export function mountPalette(
|
||||||
el: HTMLElement
|
el: HTMLElement
|
||||||
): Observable<Component<Palette>> {
|
): Observable<Component<Palette>> {
|
||||||
const internal$ = new Subject<Palette>()
|
return defer(() => {
|
||||||
|
const push$ = new Subject<Palette>()
|
||||||
|
push$.subscribe(palette => {
|
||||||
|
|
||||||
/* Set color palette */
|
/* Set color palette */
|
||||||
internal$.subscribe(palette => {
|
for (const [key, value] of Object.entries(palette.color))
|
||||||
for (const [key, value] of Object.entries(palette.color))
|
if (typeof value === "string")
|
||||||
if (typeof value === "string")
|
document.body.setAttribute(`data-md-color-${key}`, value)
|
||||||
document.body.setAttribute(`data-md-color-${key}`, value)
|
|
||||||
|
|
||||||
/* Toggle visibility */
|
/* Toggle visibility */
|
||||||
for (let index = 0; index < inputs.length; index++) {
|
for (let index = 0; index < inputs.length; index++) {
|
||||||
const label = inputs[index].nextElementSibling
|
const label = inputs[index].nextElementSibling
|
||||||
if (label instanceof HTMLElement)
|
if (label instanceof HTMLElement)
|
||||||
label.hidden = palette.index !== index
|
label.hidden = palette.index !== index
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Persist preference in local storage */
|
||||||
|
__md_set("__palette", palette)
|
||||||
|
})
|
||||||
|
|
||||||
|
/* Create and return component */
|
||||||
|
const inputs = getElements<HTMLInputElement>("input", el)
|
||||||
|
return watchPalette(inputs)
|
||||||
|
.pipe(
|
||||||
|
tap(state => push$.next(state)),
|
||||||
|
finalize(() => push$.complete()),
|
||||||
|
map(state => ({ ref: el, ...state }))
|
||||||
|
)
|
||||||
})
|
})
|
||||||
|
|
||||||
/* Create and return component */
|
|
||||||
const inputs = getElements<HTMLInputElement>("input", el)
|
|
||||||
return watchPalette(inputs)
|
|
||||||
.pipe(
|
|
||||||
tap(state => internal$.next(state)),
|
|
||||||
finalize(() => internal$.complete()),
|
|
||||||
map(state => ({ ref: el, ...state }))
|
|
||||||
)
|
|
||||||
}
|
}
|
||||||
|
@ -36,8 +36,6 @@ import {
|
|||||||
Keyboard,
|
Keyboard,
|
||||||
getActiveElement,
|
getActiveElement,
|
||||||
getElements,
|
getElements,
|
||||||
setElementFocus,
|
|
||||||
setElementSelection,
|
|
||||||
setToggle
|
setToggle
|
||||||
} from "~/browser"
|
} from "~/browser"
|
||||||
import {
|
import {
|
||||||
@ -166,14 +164,14 @@ export function mountSearch(
|
|||||||
case "Escape":
|
case "Escape":
|
||||||
case "Tab":
|
case "Tab":
|
||||||
setToggle("search", false)
|
setToggle("search", false)
|
||||||
setElementFocus(query, false)
|
query.blur()
|
||||||
break
|
break
|
||||||
|
|
||||||
/* Vertical arrows: select previous or next search result */
|
/* Vertical arrows: select previous or next search result */
|
||||||
case "ArrowUp":
|
case "ArrowUp":
|
||||||
case "ArrowDown":
|
case "ArrowDown":
|
||||||
if (typeof active === "undefined") {
|
if (typeof active === "undefined") {
|
||||||
setElementFocus(query)
|
query.focus()
|
||||||
} else {
|
} else {
|
||||||
const els = [query, ...getElements(
|
const els = [query, ...getElements(
|
||||||
":not(details) > [href], summary, details[open] [href]",
|
":not(details) > [href], summary, details[open] [href]",
|
||||||
@ -184,7 +182,7 @@ export function mountSearch(
|
|||||||
key.type === "ArrowUp" ? -1 : +1
|
key.type === "ArrowUp" ? -1 : +1
|
||||||
)
|
)
|
||||||
) % els.length)
|
) % els.length)
|
||||||
setElementFocus(els[i])
|
els[i].focus()
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Prevent scrolling of page */
|
/* Prevent scrolling of page */
|
||||||
@ -194,7 +192,7 @@ export function mountSearch(
|
|||||||
/* All other keys: hand to search query */
|
/* All other keys: hand to search query */
|
||||||
default:
|
default:
|
||||||
if (query !== getActiveElement())
|
if (query !== getActiveElement())
|
||||||
setElementFocus(query)
|
query.focus()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -210,8 +208,10 @@ export function mountSearch(
|
|||||||
case "f":
|
case "f":
|
||||||
case "s":
|
case "s":
|
||||||
case "/":
|
case "/":
|
||||||
setElementFocus(query)
|
query.focus()
|
||||||
setElementSelection(query)
|
query.select()
|
||||||
|
|
||||||
|
/* Prevent scrolling of page */
|
||||||
key.claim()
|
key.claim()
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
|
@ -40,13 +40,9 @@ import {
|
|||||||
tap
|
tap
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import {
|
import { translation } from "~/_"
|
||||||
resetSearchQueryPlaceholder,
|
|
||||||
setSearchQueryPlaceholder
|
|
||||||
} from "~/actions"
|
|
||||||
import {
|
import {
|
||||||
getLocation,
|
getLocation,
|
||||||
setElementFocus,
|
|
||||||
setToggle,
|
setToggle,
|
||||||
watchElementFocus
|
watchElementFocus
|
||||||
} from "~/browser"
|
} from "~/browser"
|
||||||
@ -143,10 +139,10 @@ export function watchSearchQuery(
|
|||||||
export function mountSearchQuery(
|
export function mountSearchQuery(
|
||||||
el: HTMLInputElement, { tx$, rx$ }: SearchWorker
|
el: HTMLInputElement, { tx$, rx$ }: SearchWorker
|
||||||
): Observable<Component<SearchQuery, HTMLInputElement>> {
|
): Observable<Component<SearchQuery, HTMLInputElement>> {
|
||||||
const internal$ = new Subject<SearchQuery>()
|
const push$ = new Subject<SearchQuery>()
|
||||||
|
|
||||||
/* Handle value changes */
|
/* Handle value changes */
|
||||||
internal$
|
push$
|
||||||
.pipe(
|
.pipe(
|
||||||
distinctUntilKeyChanged("value"),
|
distinctUntilKeyChanged("value"),
|
||||||
map(({ value }): SearchQueryMessage => ({
|
map(({ value }): SearchQueryMessage => ({
|
||||||
@ -157,31 +153,31 @@ export function mountSearchQuery(
|
|||||||
.subscribe(tx$.next.bind(tx$))
|
.subscribe(tx$.next.bind(tx$))
|
||||||
|
|
||||||
/* Handle focus changes */
|
/* Handle focus changes */
|
||||||
internal$
|
push$
|
||||||
.pipe(
|
.pipe(
|
||||||
distinctUntilKeyChanged("focus")
|
distinctUntilKeyChanged("focus")
|
||||||
)
|
)
|
||||||
.subscribe(({ focus }) => {
|
.subscribe(({ focus }) => {
|
||||||
if (focus) {
|
if (focus) {
|
||||||
setToggle("search", focus)
|
setToggle("search", focus)
|
||||||
setSearchQueryPlaceholder(el, "")
|
el.placeholder = ""
|
||||||
} else {
|
} else {
|
||||||
resetSearchQueryPlaceholder(el)
|
el.placeholder = translation("search.placeholder")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/* Handle reset */
|
/* Handle reset */
|
||||||
fromEvent(el.form!, "reset")
|
fromEvent(el.form!, "reset")
|
||||||
.pipe(
|
.pipe(
|
||||||
takeUntil(internal$.pipe(takeLast(1)))
|
takeUntil(push$.pipe(takeLast(1)))
|
||||||
)
|
)
|
||||||
.subscribe(() => setElementFocus(el))
|
.subscribe(() => el.focus())
|
||||||
|
|
||||||
/* Create and return component */
|
/* Create and return component */
|
||||||
return watchSearchQuery(el, { tx$, rx$ })
|
return watchSearchQuery(el, { tx$, rx$ })
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(state => internal$.next(state)),
|
tap(state => push$.next(state)),
|
||||||
finalize(() => internal$.complete()),
|
finalize(() => push$.complete()),
|
||||||
map(state => ({ ref: el, ...state }))
|
map(state => ({ ref: el, ...state }))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -39,12 +39,7 @@ import {
|
|||||||
zipWith
|
zipWith
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import {
|
import { translation } from "~/_"
|
||||||
addToSearchResultList,
|
|
||||||
resetSearchResultList,
|
|
||||||
resetSearchResultMeta,
|
|
||||||
setSearchResultMeta
|
|
||||||
} from "~/actions"
|
|
||||||
import {
|
import {
|
||||||
getElement,
|
getElement,
|
||||||
watchElementBoundary
|
watchElementBoundary
|
||||||
@ -56,6 +51,7 @@ import {
|
|||||||
isSearchResultMessage
|
isSearchResultMessage
|
||||||
} from "~/integrations"
|
} from "~/integrations"
|
||||||
import { renderSearchResultItem } from "~/templates"
|
import { renderSearchResultItem } from "~/templates"
|
||||||
|
import { round } from "~/utilities"
|
||||||
|
|
||||||
import { Component } from "../../_"
|
import { Component } from "../../_"
|
||||||
import { SearchQuery } from "../query"
|
import { SearchQuery } from "../query"
|
||||||
@ -90,7 +86,7 @@ interface MountOptions {
|
|||||||
export function mountSearchResult(
|
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 push$ = new Subject<SearchResult>()
|
||||||
const boundary$ = watchElementBoundary(el.parentElement!)
|
const boundary$ = watchElementBoundary(el.parentElement!)
|
||||||
.pipe(
|
.pipe(
|
||||||
filter(Boolean)
|
filter(Boolean)
|
||||||
@ -108,24 +104,43 @@ export function mountSearchResult(
|
|||||||
)
|
)
|
||||||
|
|
||||||
/* Update search result metadata */
|
/* Update search result metadata */
|
||||||
internal$
|
push$
|
||||||
.pipe(
|
.pipe(
|
||||||
observeOn(animationFrameScheduler),
|
observeOn(animationFrameScheduler),
|
||||||
withLatestFrom(query$),
|
withLatestFrom(query$),
|
||||||
skipUntil(ready$)
|
skipUntil(ready$)
|
||||||
)
|
)
|
||||||
.subscribe(([{ items }, { value }]) => {
|
.subscribe(([{ items }, { value }]) => {
|
||||||
if (value)
|
if (value) {
|
||||||
setSearchResultMeta(meta, items.length)
|
switch (items.length) {
|
||||||
else
|
|
||||||
resetSearchResultMeta(meta)
|
/* No results */
|
||||||
|
case 0:
|
||||||
|
meta.textContent = translation("search.result.none")
|
||||||
|
break
|
||||||
|
|
||||||
|
/* One result */
|
||||||
|
case 1:
|
||||||
|
meta.textContent = translation("search.result.one")
|
||||||
|
break
|
||||||
|
|
||||||
|
/* Multiple result */
|
||||||
|
default:
|
||||||
|
meta.textContent = translation(
|
||||||
|
"search.result.other",
|
||||||
|
round(items.length)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
meta.textContent = translation("search.result.placeholder")
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/* Update search result list */
|
/* Update search result list */
|
||||||
internal$
|
push$
|
||||||
.pipe(
|
.pipe(
|
||||||
observeOn(animationFrameScheduler),
|
observeOn(animationFrameScheduler),
|
||||||
tap(() => resetSearchResultList(list)),
|
tap(() => list.innerHTML = ""),
|
||||||
switchMap(({ items }) => merge(
|
switchMap(({ items }) => merge(
|
||||||
of(...items.slice(0, 10)),
|
of(...items.slice(0, 10)),
|
||||||
of(...items.slice(10))
|
of(...items.slice(10))
|
||||||
@ -136,9 +151,9 @@ export function mountSearchResult(
|
|||||||
)
|
)
|
||||||
))
|
))
|
||||||
)
|
)
|
||||||
.subscribe(result => {
|
.subscribe(result => list.appendChild(
|
||||||
addToSearchResultList(list, renderSearchResultItem(result))
|
renderSearchResultItem(result)
|
||||||
})
|
))
|
||||||
|
|
||||||
/* Filter search result message */
|
/* Filter search result message */
|
||||||
const result$ = rx$
|
const result$ = rx$
|
||||||
@ -150,8 +165,8 @@ export function mountSearchResult(
|
|||||||
/* Create and return component */
|
/* Create and return component */
|
||||||
return result$
|
return result$
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(state => internal$.next(state)),
|
tap(state => push$.next(state)),
|
||||||
finalize(() => internal$.complete()),
|
finalize(() => push$.complete()),
|
||||||
map(state => ({ ref: el, ...state }))
|
map(state => ({ ref: el, ...state }))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -101,8 +101,8 @@ export function watchSearchShare(
|
|||||||
export function mountSearchShare(
|
export function mountSearchShare(
|
||||||
el: HTMLAnchorElement, options: MountOptions
|
el: HTMLAnchorElement, options: MountOptions
|
||||||
): Observable<Component<SearchShare>> {
|
): Observable<Component<SearchShare>> {
|
||||||
const internal$ = new Subject<SearchShare>()
|
const push$ = new Subject<SearchShare>()
|
||||||
internal$.subscribe(({ url }) => {
|
push$.subscribe(({ url }) => {
|
||||||
el.setAttribute("data-clipboard-text", el.href)
|
el.setAttribute("data-clipboard-text", el.href)
|
||||||
el.href = `${url}`
|
el.href = `${url}`
|
||||||
})
|
})
|
||||||
@ -114,8 +114,8 @@ export function mountSearchShare(
|
|||||||
/* Create and return component */
|
/* Create and return component */
|
||||||
return watchSearchShare(el, options)
|
return watchSearchShare(el, options)
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(state => internal$.next(state)),
|
tap(state => push$.next(state)),
|
||||||
finalize(() => internal$.complete()),
|
finalize(() => push$.complete()),
|
||||||
map(state => ({ ref: el, ...state }))
|
map(state => ({ ref: el, ...state }))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -83,7 +83,7 @@ interface MountOptions {
|
|||||||
export function mountSearchSuggest(
|
export function mountSearchSuggest(
|
||||||
el: HTMLElement, { rx$ }: SearchWorker, { keyboard$ }: MountOptions
|
el: HTMLElement, { rx$ }: SearchWorker, { keyboard$ }: MountOptions
|
||||||
): Observable<Component<SearchSuggest>> {
|
): Observable<Component<SearchSuggest>> {
|
||||||
const internal$ = new Subject<SearchResult>()
|
const push$ = new Subject<SearchResult>()
|
||||||
|
|
||||||
/* Retrieve query component and track all changes */
|
/* Retrieve query component and track all changes */
|
||||||
const query = getComponentElement("search-query")
|
const query = getComponentElement("search-query")
|
||||||
@ -98,7 +98,7 @@ export function mountSearchSuggest(
|
|||||||
)
|
)
|
||||||
|
|
||||||
/* Update search suggestions */
|
/* Update search suggestions */
|
||||||
internal$
|
push$
|
||||||
.pipe(
|
.pipe(
|
||||||
combineLatestWith(query$),
|
combineLatestWith(query$),
|
||||||
map(([{ suggestions }, value]) => {
|
map(([{ suggestions }, value]) => {
|
||||||
@ -147,8 +147,8 @@ export function mountSearchSuggest(
|
|||||||
/* Create and return component */
|
/* Create and return component */
|
||||||
return result$
|
return result$
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(state => internal$.next(state)),
|
tap(state => push$.next(state)),
|
||||||
finalize(() => internal$.complete()),
|
finalize(() => push$.complete()),
|
||||||
map(() => ({ ref: el }))
|
map(() => ({ ref: el }))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -24,22 +24,21 @@ import {
|
|||||||
Observable,
|
Observable,
|
||||||
Subject,
|
Subject,
|
||||||
animationFrameScheduler,
|
animationFrameScheduler,
|
||||||
|
auditTime,
|
||||||
combineLatest,
|
combineLatest,
|
||||||
|
defer,
|
||||||
distinctUntilChanged,
|
distinctUntilChanged,
|
||||||
finalize,
|
finalize,
|
||||||
map,
|
map,
|
||||||
observeOn,
|
|
||||||
tap,
|
tap,
|
||||||
withLatestFrom
|
withLatestFrom
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import {
|
import {
|
||||||
resetSidebarHeight,
|
Viewport,
|
||||||
resetSidebarOffset,
|
getElement,
|
||||||
setSidebarHeight,
|
getElementOffset
|
||||||
setSidebarOffset
|
} from "~/browser"
|
||||||
} from "~/actions"
|
|
||||||
import { Viewport } from "~/browser"
|
|
||||||
|
|
||||||
import { Component } from "../_"
|
import { Component } from "../_"
|
||||||
import { Header } from "../header"
|
import { Header } from "../header"
|
||||||
@ -125,6 +124,19 @@ export function watchSidebar(
|
|||||||
/**
|
/**
|
||||||
* Mount sidebar
|
* Mount sidebar
|
||||||
*
|
*
|
||||||
|
* This function doesn't set the height of the actual sidebar, but of its first
|
||||||
|
* child – the `.md-sidebar__scrollwrap` element in order to mitigiate jittery
|
||||||
|
* sidebars when the footer is scrolled into view. At some point we switched
|
||||||
|
* from `absolute` / `fixed` positioning to `sticky` positioning, significantly
|
||||||
|
* reducing jitter in some browsers (respectively Firefox and Safari) when
|
||||||
|
* scrolling from the top. However, top-aligned sticky positioning means that
|
||||||
|
* the sidebar snaps to the bottom when the end of the container is reached.
|
||||||
|
* This is what leads to the mentioned jitter, as the sidebar's height may be
|
||||||
|
* updated too slowly.
|
||||||
|
*
|
||||||
|
* This behaviour can be mitigiated by setting the height of the sidebar to `0`
|
||||||
|
* while preserving the padding, and the height on its first element.
|
||||||
|
*
|
||||||
* @param el - Sidebar element
|
* @param el - Sidebar element
|
||||||
* @param options - Options
|
* @param options - Options
|
||||||
*
|
*
|
||||||
@ -133,32 +145,36 @@ export function watchSidebar(
|
|||||||
export function mountSidebar(
|
export function mountSidebar(
|
||||||
el: HTMLElement, { header$, ...options }: MountOptions
|
el: HTMLElement, { header$, ...options }: MountOptions
|
||||||
): Observable<Component<Sidebar>> {
|
): Observable<Component<Sidebar>> {
|
||||||
const internal$ = new Subject<Sidebar>()
|
const inner = getElement(".md-sidebar__scrollwrap", el)
|
||||||
internal$
|
const { y } = getElementOffset(inner)
|
||||||
.pipe(
|
return defer(() => {
|
||||||
observeOn(animationFrameScheduler),
|
const push$ = new Subject<Sidebar>()
|
||||||
withLatestFrom(header$)
|
push$
|
||||||
)
|
.pipe(
|
||||||
.subscribe({
|
auditTime(0, animationFrameScheduler),
|
||||||
|
withLatestFrom(header$)
|
||||||
|
)
|
||||||
|
.subscribe({
|
||||||
|
|
||||||
/* Update height and offset */
|
/* Handle emission */
|
||||||
next([{ height }, { height: offset }]) {
|
next([{ height }, { height: offset }]) {
|
||||||
setSidebarHeight(el, height)
|
inner.style.height = `${height - 2 * y}px`
|
||||||
setSidebarOffset(el, offset)
|
el.style.top = `${offset}px`
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Reset on complete */
|
/* Handle complete */
|
||||||
complete() {
|
complete() {
|
||||||
resetSidebarOffset(el)
|
inner.style.height = ""
|
||||||
resetSidebarHeight(el)
|
el.style.top = ""
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/* Create and return component */
|
/* Create and return component */
|
||||||
return watchSidebar(el, options)
|
return watchSidebar(el, options)
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(state => internal$.next(state)),
|
tap(state => push$.next(state)),
|
||||||
finalize(() => internal$.complete()),
|
finalize(() => push$.complete()),
|
||||||
map(state => ({ ref: el, ...state }))
|
map(state => ({ ref: el, ...state }))
|
||||||
)
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
|
|
||||||
import {
|
import {
|
||||||
NEVER,
|
EMPTY,
|
||||||
Observable,
|
Observable,
|
||||||
Subject,
|
Subject,
|
||||||
catchError,
|
catchError,
|
||||||
@ -34,10 +34,7 @@ import {
|
|||||||
tap
|
tap
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import {
|
import { getElement } from "~/browser"
|
||||||
setSourceFacts,
|
|
||||||
setSourceState
|
|
||||||
} from "~/actions"
|
|
||||||
import { renderSourceFacts } from "~/templates"
|
import { renderSourceFacts } from "~/templates"
|
||||||
|
|
||||||
import { Component } from "../../_"
|
import { Component } from "../../_"
|
||||||
@ -94,7 +91,7 @@ export function watchSource(
|
|||||||
)
|
)
|
||||||
})
|
})
|
||||||
.pipe(
|
.pipe(
|
||||||
catchError(() => NEVER),
|
catchError(() => EMPTY),
|
||||||
filter(facts => Object.keys(facts).length > 0),
|
filter(facts => Object.keys(facts).length > 0),
|
||||||
map(facts => ({ facts })),
|
map(facts => ({ facts })),
|
||||||
shareReplay(1)
|
shareReplay(1)
|
||||||
@ -111,17 +108,20 @@ export function watchSource(
|
|||||||
export function mountSource(
|
export function mountSource(
|
||||||
el: HTMLAnchorElement
|
el: HTMLAnchorElement
|
||||||
): Observable<Component<Source>> {
|
): Observable<Component<Source>> {
|
||||||
const internal$ = new Subject<Source>()
|
const inner = getElement(":scope > :last-child", el)
|
||||||
internal$.subscribe(({ facts }) => {
|
return defer(() => {
|
||||||
setSourceFacts(el, renderSourceFacts(facts))
|
const push$ = new Subject<Source>()
|
||||||
setSourceState(el, "done")
|
push$.subscribe(({ facts }) => {
|
||||||
})
|
inner.appendChild(renderSourceFacts(facts))
|
||||||
|
inner.setAttribute("data-md-state", "done")
|
||||||
|
})
|
||||||
|
|
||||||
/* Create and return component */
|
/* Create and return component */
|
||||||
return watchSource(el)
|
return watchSource(el)
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(state => internal$.next(state)),
|
tap(state => push$.next(state)),
|
||||||
finalize(() => internal$.complete()),
|
finalize(() => push$.complete()),
|
||||||
map(state => ({ ref: el, ...state }))
|
map(state => ({ ref: el, ...state }))
|
||||||
)
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -20,7 +20,7 @@
|
|||||||
* IN THE SOFTWARE.
|
* IN THE SOFTWARE.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
import { NEVER, Observable } from "rxjs"
|
import { EMPTY, Observable } from "rxjs"
|
||||||
|
|
||||||
import { fetchSourceFactsFromGitHub } from "../github"
|
import { fetchSourceFactsFromGitHub } from "../github"
|
||||||
import { fetchSourceFactsFromGitLab } from "../gitlab"
|
import { fetchSourceFactsFromGitLab } from "../gitlab"
|
||||||
@ -83,6 +83,6 @@ export function fetchSourceFacts(
|
|||||||
|
|
||||||
/* Everything else */
|
/* Everything else */
|
||||||
default:
|
default:
|
||||||
return NEVER
|
return EMPTY
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -50,7 +50,7 @@ interface Release {
|
|||||||
/**
|
/**
|
||||||
* Fetch GitHub repository facts
|
* Fetch GitHub repository facts
|
||||||
*
|
*
|
||||||
* @param user - GitHub user
|
* @param user - GitHub user or organization
|
||||||
* @param repo - GitHub repository
|
* @param repo - GitHub repository
|
||||||
*
|
*
|
||||||
* @returns Repository facts observable
|
* @returns Repository facts observable
|
||||||
|
@ -23,21 +23,16 @@
|
|||||||
import {
|
import {
|
||||||
Observable,
|
Observable,
|
||||||
Subject,
|
Subject,
|
||||||
animationFrameScheduler,
|
defer,
|
||||||
distinctUntilKeyChanged,
|
distinctUntilKeyChanged,
|
||||||
finalize,
|
finalize,
|
||||||
map,
|
map,
|
||||||
observeOn,
|
|
||||||
of,
|
of,
|
||||||
switchMap,
|
switchMap,
|
||||||
tap
|
tap
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import { feature } from "~/_"
|
import { feature } from "~/_"
|
||||||
import {
|
|
||||||
resetTabsState,
|
|
||||||
setTabsState
|
|
||||||
} from "~/actions"
|
|
||||||
import {
|
import {
|
||||||
Viewport,
|
Viewport,
|
||||||
watchElementSize,
|
watchElementSize,
|
||||||
@ -119,36 +114,34 @@ export function watchTabs(
|
|||||||
export function mountTabs(
|
export function mountTabs(
|
||||||
el: HTMLElement, options: MountOptions
|
el: HTMLElement, options: MountOptions
|
||||||
): Observable<Component<Tabs>> {
|
): Observable<Component<Tabs>> {
|
||||||
const internal$ = new Subject<Tabs>()
|
return defer(() => {
|
||||||
internal$
|
const push$ = new Subject<Tabs>()
|
||||||
.pipe(
|
push$.subscribe({
|
||||||
observeOn(animationFrameScheduler)
|
|
||||||
)
|
/* Handle emission */
|
||||||
.subscribe({
|
next({ hidden }) {
|
||||||
|
if (hidden)
|
||||||
/* Update state */
|
el.setAttribute("data-md-state", "hidden")
|
||||||
next({ hidden }) {
|
else
|
||||||
if (hidden)
|
el.removeAttribute("data-md-state")
|
||||||
setTabsState(el, "hidden")
|
},
|
||||||
else
|
|
||||||
resetTabsState(el)
|
/* Handle complete */
|
||||||
},
|
complete() {
|
||||||
|
el.removeAttribute("data-md-state")
|
||||||
/* Reset on complete */
|
}
|
||||||
complete() {
|
})
|
||||||
resetTabsState(el)
|
|
||||||
}
|
/* Create and return component */
|
||||||
})
|
return (
|
||||||
|
feature("navigation.tabs.sticky")
|
||||||
/* Create and return component */
|
? of({ hidden: false })
|
||||||
return (
|
: watchTabs(el, options)
|
||||||
feature("navigation.tabs.sticky")
|
|
||||||
? of({ hidden: false })
|
|
||||||
: watchTabs(el, options)
|
|
||||||
)
|
|
||||||
.pipe(
|
|
||||||
tap(state => internal$.next(state)),
|
|
||||||
finalize(() => internal$.complete()),
|
|
||||||
map(state => ({ ref: el, ...state }))
|
|
||||||
)
|
)
|
||||||
|
.pipe(
|
||||||
|
tap(state => push$.next(state)),
|
||||||
|
finalize(() => push$.complete()),
|
||||||
|
map(state => ({ ref: el, ...state }))
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,6 @@
|
|||||||
import {
|
import {
|
||||||
Observable,
|
Observable,
|
||||||
Subject,
|
Subject,
|
||||||
animationFrameScheduler,
|
|
||||||
bufferCount,
|
bufferCount,
|
||||||
combineLatest,
|
combineLatest,
|
||||||
defer,
|
defer,
|
||||||
@ -31,7 +30,6 @@ import {
|
|||||||
distinctUntilKeyChanged,
|
distinctUntilKeyChanged,
|
||||||
finalize,
|
finalize,
|
||||||
map,
|
map,
|
||||||
observeOn,
|
|
||||||
of,
|
of,
|
||||||
scan,
|
scan,
|
||||||
startWith,
|
startWith,
|
||||||
@ -40,12 +38,6 @@ import {
|
|||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import { feature } from "~/_"
|
import { feature } from "~/_"
|
||||||
import {
|
|
||||||
resetAnchorActive,
|
|
||||||
resetAnchorState,
|
|
||||||
setAnchorActive,
|
|
||||||
setAnchorState
|
|
||||||
} from "~/actions"
|
|
||||||
import {
|
import {
|
||||||
Viewport,
|
Viewport,
|
||||||
getElements,
|
getElements,
|
||||||
@ -253,52 +245,55 @@ export function watchTableOfContents(
|
|||||||
export function mountTableOfContents(
|
export function mountTableOfContents(
|
||||||
el: HTMLElement, options: MountOptions
|
el: HTMLElement, options: MountOptions
|
||||||
): Observable<Component<TableOfContents>> {
|
): Observable<Component<TableOfContents>> {
|
||||||
const internal$ = new Subject<TableOfContents>()
|
return defer(() => {
|
||||||
internal$
|
const push$ = new Subject<TableOfContents>()
|
||||||
.pipe(
|
push$.subscribe(({ prev, next }) => {
|
||||||
observeOn(animationFrameScheduler),
|
|
||||||
)
|
|
||||||
.subscribe(({ prev, next }) => {
|
|
||||||
|
|
||||||
/* Look forward */
|
/* Look forward */
|
||||||
for (const [anchor] of next) {
|
for (const [anchor] of next) {
|
||||||
resetAnchorActive(anchor)
|
anchor.removeAttribute("data-md-state")
|
||||||
resetAnchorState(anchor)
|
anchor.classList.remove(
|
||||||
}
|
"md-nav__link--active"
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/* Look backward */
|
/* Look backward */
|
||||||
for (const [index, [anchor]] of prev.entries()) {
|
for (const [index, [anchor]] of prev.entries()) {
|
||||||
setAnchorActive(anchor, index === prev.length - 1)
|
anchor.setAttribute("data-md-state", "blur")
|
||||||
setAnchorState(anchor, "blur")
|
anchor.classList.toggle(
|
||||||
}
|
"md-nav__link--active",
|
||||||
|
index === prev.length - 1
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
/* Set up anchor tracking, if enabled */
|
/* Set up anchor tracking, if enabled */
|
||||||
if (feature("navigation.tracking")) {
|
if (feature("navigation.tracking")) {
|
||||||
const url = getLocation()
|
const url = getLocation()
|
||||||
|
|
||||||
/* Set hash fragment to active anchor */
|
/* Set hash fragment to active anchor */
|
||||||
const anchor = prev[prev.length - 1]
|
const anchor = prev[prev.length - 1]
|
||||||
if (anchor && anchor.length) {
|
if (anchor && anchor.length) {
|
||||||
const [active] = anchor
|
const [active] = anchor
|
||||||
const { hash } = new URL(active.href)
|
const { hash } = new URL(active.href)
|
||||||
if (url.hash !== hash) {
|
if (url.hash !== hash) {
|
||||||
url.hash = hash
|
url.hash = hash
|
||||||
history.replaceState({}, "", `${url}`)
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Reset anchor when at the top */
|
|
||||||
} else {
|
|
||||||
url.hash = ""
|
|
||||||
history.replaceState({}, "", `${url}`)
|
history.replaceState({}, "", `${url}`)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
})
|
|
||||||
|
|
||||||
/* Create and return component */
|
/* Reset anchor when at the top */
|
||||||
return watchTableOfContents(el, options)
|
} else {
|
||||||
.pipe(
|
url.hash = ""
|
||||||
tap(state => internal$.next(state)),
|
history.replaceState({}, "", `${url}`)
|
||||||
finalize(() => internal$.complete()),
|
}
|
||||||
map(state => ({ ref: el, ...state }))
|
}
|
||||||
)
|
})
|
||||||
|
|
||||||
|
/* Create and return component */
|
||||||
|
return watchTableOfContents(el, options)
|
||||||
|
.pipe(
|
||||||
|
tap(state => push$.next(state)),
|
||||||
|
finalize(() => push$.complete()),
|
||||||
|
map(state => ({ ref: el, ...state }))
|
||||||
|
)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
@ -23,30 +23,17 @@
|
|||||||
import {
|
import {
|
||||||
Observable,
|
Observable,
|
||||||
Subject,
|
Subject,
|
||||||
animationFrameScheduler,
|
|
||||||
bufferCount,
|
bufferCount,
|
||||||
combineLatest,
|
combineLatest,
|
||||||
distinctUntilChanged,
|
distinctUntilChanged,
|
||||||
distinctUntilKeyChanged,
|
distinctUntilKeyChanged,
|
||||||
finalize,
|
finalize,
|
||||||
map,
|
map,
|
||||||
observeOn,
|
|
||||||
tap,
|
tap,
|
||||||
withLatestFrom
|
withLatestFrom
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import {
|
import { Viewport } from "~/browser"
|
||||||
resetBackToTopOffset,
|
|
||||||
resetBackToTopState,
|
|
||||||
resetFocusable,
|
|
||||||
setBackToTopOffset,
|
|
||||||
setBackToTopState,
|
|
||||||
setFocusable
|
|
||||||
} from "~/actions"
|
|
||||||
import {
|
|
||||||
Viewport,
|
|
||||||
setElementFocus
|
|
||||||
} from "~/browser"
|
|
||||||
|
|
||||||
import { Component } from "../_"
|
import { Component } from "../_"
|
||||||
import { Header } from "../header"
|
import { Header } from "../header"
|
||||||
@ -141,10 +128,9 @@ export function watchBackToTop(
|
|||||||
export function mountBackToTop(
|
export function mountBackToTop(
|
||||||
el: HTMLElement, { viewport$, header$, main$ }: MountOptions
|
el: HTMLElement, { viewport$, header$, main$ }: MountOptions
|
||||||
): Observable<Component<BackToTop>> {
|
): Observable<Component<BackToTop>> {
|
||||||
const internal$ = new Subject<BackToTop>()
|
const push$ = new Subject<BackToTop>()
|
||||||
internal$
|
push$
|
||||||
.pipe(
|
.pipe(
|
||||||
observeOn(animationFrameScheduler),
|
|
||||||
withLatestFrom(header$
|
withLatestFrom(header$
|
||||||
.pipe(
|
.pipe(
|
||||||
distinctUntilKeyChanged("height")
|
distinctUntilKeyChanged("height")
|
||||||
@ -153,32 +139,33 @@ export function mountBackToTop(
|
|||||||
)
|
)
|
||||||
.subscribe({
|
.subscribe({
|
||||||
|
|
||||||
/* Update state */
|
/* Handle emission */
|
||||||
next([{ hidden }, { height }]) {
|
next([{ hidden }, { height }]) {
|
||||||
setBackToTopOffset(el, height + 16)
|
el.style.top = `${height + 16}px`
|
||||||
if (hidden) {
|
if (hidden) {
|
||||||
setBackToTopState(el, "hidden")
|
el.setAttribute("data-md-state", "hidden")
|
||||||
setElementFocus(el, false)
|
el.setAttribute("tabindex", "-1")
|
||||||
setFocusable(el, -1)
|
el.blur()
|
||||||
} else {
|
} else {
|
||||||
resetBackToTopState(el)
|
el.style.top = ""
|
||||||
resetFocusable(el)
|
el.removeAttribute("data-md-state")
|
||||||
|
el.removeAttribute("tabindex")
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
||||||
/* Reset on complete */
|
/* Handle complete */
|
||||||
complete() {
|
complete() {
|
||||||
resetBackToTopOffset(el)
|
el.style.top = ""
|
||||||
resetBackToTopState(el)
|
el.removeAttribute("data-md-state")
|
||||||
resetFocusable(el)
|
el.removeAttribute("tabindex")
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/* Create and return component */
|
/* Create and return component */
|
||||||
return watchBackToTop(el, { viewport$, header$, main$ })
|
return watchBackToTop(el, { viewport$, header$, main$ })
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(state => internal$.next(state)),
|
tap(state => push$.next(state)),
|
||||||
finalize(() => internal$.complete()),
|
finalize(() => push$.complete()),
|
||||||
map(state => ({ ref: el, ...state }))
|
map(state => ({ ref: el, ...state }))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -52,8 +52,7 @@ import {
|
|||||||
request,
|
request,
|
||||||
requestXML,
|
requestXML,
|
||||||
setLocation,
|
setLocation,
|
||||||
setLocationHash,
|
setLocationHash
|
||||||
setViewportOffset
|
|
||||||
} from "~/browser"
|
} from "~/browser"
|
||||||
import { getComponentElement } from "~/components"
|
import { getComponentElement } from "~/components"
|
||||||
import { h } from "~/utilities"
|
import { h } from "~/utilities"
|
||||||
@ -329,11 +328,11 @@ export function setupInstantLoading(
|
|||||||
.pipe(
|
.pipe(
|
||||||
sample(document$),
|
sample(document$),
|
||||||
)
|
)
|
||||||
.subscribe(({ url, offset }) => {
|
.subscribe(({ url, offset = { y: 0 } }) => {
|
||||||
if (url.hash && !offset) {
|
if (url.hash && !offset) {
|
||||||
setLocationHash(url.hash)
|
setLocationHash(url.hash)
|
||||||
} else {
|
} else {
|
||||||
setViewportOffset(offset || { y: 0 })
|
window.scrollTo(0, offset.y)
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
@ -355,7 +354,7 @@ export function setupInstantLoading(
|
|||||||
filter(([a, b]) => a.url.pathname === b.url.pathname),
|
filter(([a, b]) => a.url.pathname === b.url.pathname),
|
||||||
map(([, state]) => state)
|
map(([, state]) => state)
|
||||||
)
|
)
|
||||||
.subscribe(({ offset }) => {
|
.subscribe(({ offset = { y: 0 } }) => {
|
||||||
setViewportOffset(offset || { y: 0 })
|
window.scrollTo(0, offset.y)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -32,10 +32,6 @@ import {
|
|||||||
withLatestFrom
|
withLatestFrom
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import {
|
|
||||||
resetScrollLock,
|
|
||||||
setScrollLock
|
|
||||||
} from "~/actions"
|
|
||||||
import {
|
import {
|
||||||
Viewport,
|
Viewport,
|
||||||
watchToggle
|
watchToggle
|
||||||
@ -82,9 +78,15 @@ export function patchScrolllock(
|
|||||||
withLatestFrom(viewport$)
|
withLatestFrom(viewport$)
|
||||||
)
|
)
|
||||||
.subscribe(([active, { offset: { y }}]) => {
|
.subscribe(([active, { offset: { y }}]) => {
|
||||||
if (active)
|
if (active) {
|
||||||
setScrollLock(document.body, y)
|
document.body.setAttribute("data-md-state", "lock")
|
||||||
else
|
document.body.style.top = `-${y}px`
|
||||||
resetScrollLock(document.body)
|
} else {
|
||||||
|
const value = -1 * parseInt(document.body.style.top, 10)
|
||||||
|
document.body.removeAttribute("data-md-state")
|
||||||
|
document.body.style.top = ""
|
||||||
|
if (value)
|
||||||
|
window.scrollTo(0, value)
|
||||||
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
@ -70,21 +70,3 @@ export function round(value: number): string {
|
|||||||
return value.toString()
|
return value.toString()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Simple hash function
|
|
||||||
*
|
|
||||||
* @see https://bit.ly/2wsVjJ4 - Original source
|
|
||||||
*
|
|
||||||
* @param value - Value to be hashed
|
|
||||||
*
|
|
||||||
* @returns Hash as 32bit integer
|
|
||||||
*/
|
|
||||||
export function hash(value: string): number {
|
|
||||||
let h = 0
|
|
||||||
for (let i = 0, len = value.length; i < len; i++) {
|
|
||||||
h = ((h << 5) - h) + value.charCodeAt(i)
|
|
||||||
h |= 0 // Convert to 32bit integer
|
|
||||||
}
|
|
||||||
return h
|
|
||||||
}
|
|
||||||
|
@ -40,16 +40,12 @@ import {
|
|||||||
zipWith
|
zipWith
|
||||||
} from "rxjs"
|
} from "rxjs"
|
||||||
|
|
||||||
import {
|
import { translation } from "~/_"
|
||||||
addToSearchResultList,
|
|
||||||
resetSearchResultList,
|
|
||||||
resetSearchResultMeta,
|
|
||||||
setSearchResultMeta
|
|
||||||
} from "~/actions"
|
|
||||||
import {
|
import {
|
||||||
getElement,
|
getElement,
|
||||||
watchElementBoundary
|
watchElementBoundary
|
||||||
} from "~/browser"
|
} from "~/browser"
|
||||||
|
import { round } from "~/utilities"
|
||||||
|
|
||||||
import { Icon, renderIconSearchResult } from "_/templates"
|
import { Icon, renderIconSearchResult } from "_/templates"
|
||||||
|
|
||||||
@ -146,7 +142,7 @@ export function watchIconSearchResult(
|
|||||||
export function mountIconSearchResult(
|
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 push$ = new Subject<IconSearchResult>()
|
||||||
const boundary$ = watchElementBoundary(el)
|
const boundary$ = watchElementBoundary(el)
|
||||||
.pipe(
|
.pipe(
|
||||||
filter(Boolean)
|
filter(Boolean)
|
||||||
@ -154,24 +150,43 @@ export function mountIconSearchResult(
|
|||||||
|
|
||||||
/* Update search result metadata */
|
/* Update search result metadata */
|
||||||
const meta = getElement(":scope > :first-child", el)
|
const meta = getElement(":scope > :first-child", el)
|
||||||
internal$
|
push$
|
||||||
.pipe(
|
.pipe(
|
||||||
observeOn(animationFrameScheduler),
|
observeOn(animationFrameScheduler),
|
||||||
withLatestFrom(query$)
|
withLatestFrom(query$)
|
||||||
)
|
)
|
||||||
.subscribe(([{ data }, { value }]) => {
|
.subscribe(([{ data }, { value }]) => {
|
||||||
if (value)
|
if (value) {
|
||||||
setSearchResultMeta(meta, data.length)
|
switch (data.length) {
|
||||||
else
|
|
||||||
resetSearchResultMeta(meta)
|
/* No results */
|
||||||
|
case 0:
|
||||||
|
meta.textContent = translation("search.result.none")
|
||||||
|
break
|
||||||
|
|
||||||
|
/* One result */
|
||||||
|
case 1:
|
||||||
|
meta.textContent = translation("search.result.one")
|
||||||
|
break
|
||||||
|
|
||||||
|
/* Multiple result */
|
||||||
|
default:
|
||||||
|
meta.textContent = translation(
|
||||||
|
"search.result.other",
|
||||||
|
round(data.length)
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
meta.textContent = translation("search.result.placeholder")
|
||||||
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
/* Update icon search result list */
|
/* Update icon search result list */
|
||||||
const list = getElement(":scope > :last-child", el)
|
const list = getElement(":scope > :last-child", el)
|
||||||
internal$
|
push$
|
||||||
.pipe(
|
.pipe(
|
||||||
observeOn(animationFrameScheduler),
|
observeOn(animationFrameScheduler),
|
||||||
tap(() => resetSearchResultList(list)),
|
tap(() => list.innerHTML = ""),
|
||||||
switchMap(({ data }) => merge(
|
switchMap(({ data }) => merge(
|
||||||
of(...data.slice(0, 10)),
|
of(...data.slice(0, 10)),
|
||||||
of(...data.slice(10))
|
of(...data.slice(10))
|
||||||
@ -183,15 +198,15 @@ export function mountIconSearchResult(
|
|||||||
)),
|
)),
|
||||||
withLatestFrom(query$)
|
withLatestFrom(query$)
|
||||||
)
|
)
|
||||||
.subscribe(([result, { value }]) => {
|
.subscribe(([result, { value }]) => list.appendChild(
|
||||||
addToSearchResultList(list, renderIconSearchResult(result, value))
|
renderIconSearchResult(result, value)
|
||||||
})
|
))
|
||||||
|
|
||||||
/* Create and return component */
|
/* Create and return component */
|
||||||
return watchIconSearchResult(el, { query$, index$ })
|
return watchIconSearchResult(el, { query$, index$ })
|
||||||
.pipe(
|
.pipe(
|
||||||
tap(state => internal$.next(state)),
|
tap(state => push$.next(state)),
|
||||||
finalize(() => internal$.complete()),
|
finalize(() => push$.complete()),
|
||||||
map(state => ({ ref: el, ...state }))
|
map(state => ({ ref: el, ...state }))
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
@ -25,7 +25,7 @@ import { build as esbuild } from "esbuild"
|
|||||||
import * as path from "path"
|
import * as path from "path"
|
||||||
import postcss from "postcss"
|
import postcss from "postcss"
|
||||||
import {
|
import {
|
||||||
NEVER,
|
EMPTY,
|
||||||
Observable,
|
Observable,
|
||||||
catchError,
|
catchError,
|
||||||
concat,
|
concat,
|
||||||
@ -132,7 +132,7 @@ export function transformStyle(
|
|||||||
),
|
),
|
||||||
catchError(err => {
|
catchError(err => {
|
||||||
console.log(err.formatted || err.message)
|
console.log(err.formatted || err.message)
|
||||||
return NEVER
|
return EMPTY
|
||||||
}),
|
}),
|
||||||
switchMap(({ css, map }) => {
|
switchMap(({ css, map }) => {
|
||||||
const file = digest(options.to, css)
|
const file = digest(options.to, css)
|
||||||
@ -182,7 +182,7 @@ export function transformScript(
|
|||||||
map: Buffer.from(data, "base64")
|
map: Buffer.from(data, "base64")
|
||||||
})
|
})
|
||||||
}),
|
}),
|
||||||
catchError(() => NEVER),
|
catchError(() => EMPTY),
|
||||||
switchMap(({ js, map }) => {
|
switchMap(({ js, map }) => {
|
||||||
const file = digest(options.to, js)
|
const file = digest(options.to, js)
|
||||||
return concat(
|
return concat(
|
||||||
|
Loading…
Reference in New Issue
Block a user