diff options
Diffstat (limited to 'src')
350 files changed, 0 insertions, 34530 deletions
diff --git a/src/.gitignore b/src/.gitignore deleted file mode 100644 index 3119f231..00000000 --- a/src/.gitignore +++ /dev/null @@ -1,2 +0,0 @@ -logs/ -test/
\ No newline at end of file diff --git a/src/__init__.py b/src/__init__.py deleted file mode 100644 index f875ee63..00000000 --- a/src/__init__.py +++ /dev/null @@ -1,21 +0,0 @@ -# Copyright (c) 2016-2023 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. - -__version__ = "$md-version$" diff --git a/src/extensions/__init__.py b/src/extensions/__init__.py deleted file mode 100644 index d1899378..00000000 --- a/src/extensions/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2016-2023 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. diff --git a/src/extensions/emoji.py b/src/extensions/emoji.py deleted file mode 100644 index c8c955cc..00000000 --- a/src/extensions/emoji.py +++ /dev/null @@ -1,98 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from __future__ import annotations - -import codecs -import functools -import material -import os - -from glob import iglob -from inspect import getfile -from markdown import Markdown -from pymdownx import emoji, twemoji_db -from xml.etree.ElementTree import Element - -# ----------------------------------------------------------------------------- -# Functions -# ----------------------------------------------------------------------------- - -# Create twemoji index -def twemoji(options: object, md: Markdown): - paths = options.get("custom_icons", [])[:] - return _load_twemoji_index(tuple(paths)) - -# Create emoji or icon -def to_svg( - index: str, shortname: str, alias: str, uc: str | None, alt: str, - title: str, category: str, options: object, md: Markdown -): - if not uc: - icons = md.inlinePatterns["emoji"].emoji_index["emoji"] - - # Create and return element to host icon - el = Element("span", { "class": options.get("classes", index) }) - el.text = md.htmlStash.store(_load(icons[shortname]["path"])) - return el - - # Delegate to `pymdownx.emoji` extension - return emoji.to_svg( - index, shortname, alias, uc, alt, title, category, options, md - ) - -# ----------------------------------------------------------------------------- -# Helper functions -# ----------------------------------------------------------------------------- - -# Load icon -@functools.lru_cache(maxsize = None) -def _load(file: str): - with codecs.open(file, encoding = "utf-8") as f: - return f.read() - -# Load twemoji index and add icons -@functools.lru_cache(maxsize = None) -def _load_twemoji_index(paths): - index = { - "name": "twemoji", - "emoji": twemoji_db.emoji, - "aliases": twemoji_db.aliases - } - - # Compute path to theme root and traverse all icon directories - root = os.path.dirname(getfile(material)) - root = os.path.join(root, "templates", ".icons") - for path in [*paths, root]: - base = os.path.normpath(path) - - # Index icons provided by the theme and via custom icons - glob = os.path.join(base, "**", "*.svg") - glob = iglob(os.path.normpath(glob), recursive = True) - for file in glob: - icon = file[len(base) + 1:-4].replace(os.path.sep, "-") - - # Add icon to index - name = f":{icon}:" - if not any(name in index[key] for key in ["emoji", "aliases"]): - index["emoji"][name] = { "name": name, "path": file } - - # Return index - return index diff --git a/src/hydrorollcore/__init__.py b/src/infini/__init__.py index 9c88b4f9..9c88b4f9 100644 --- a/src/hydrorollcore/__init__.py +++ b/src/infini/__init__.py diff --git a/src/hydrorollcore/cli.py b/src/infini/cli.py index e372b4b4..e372b4b4 100644 --- a/src/hydrorollcore/cli.py +++ b/src/infini/cli.py diff --git a/src/hydrorollcore/consts/__init__.py b/src/infini/consts/__init__.py index e69de29b..e69de29b 100644 --- a/src/hydrorollcore/consts/__init__.py +++ b/src/infini/consts/__init__.py diff --git a/src/hydrorollcore/consts/templates.py b/src/infini/consts/templates.py index e2edc2d6..e2edc2d6 100644 --- a/src/hydrorollcore/consts/templates.py +++ b/src/infini/consts/templates.py diff --git a/src/hydrorollcore/event.py b/src/infini/event.py index 9ce34bd9..9ce34bd9 100644 --- a/src/hydrorollcore/event.py +++ b/src/infini/event.py diff --git a/src/hydrorollcore/exceptions.py b/src/infini/exceptions.py index 62c88fa1..62c88fa1 100644 --- a/src/hydrorollcore/exceptions.py +++ b/src/infini/exceptions.py diff --git a/src/hydrorollcore/logging.py b/src/infini/logging.py index a1458ef4..a1458ef4 100644 --- a/src/hydrorollcore/logging.py +++ b/src/infini/logging.py diff --git a/src/hydrorollcore/manager.py b/src/infini/manager.py index 42e79563..42e79563 100644 --- a/src/hydrorollcore/manager.py +++ b/src/infini/manager.py diff --git a/src/hydrorollcore/rule.py b/src/infini/rule.py index a1f04151..a1f04151 100644 --- a/src/hydrorollcore/rule.py +++ b/src/infini/rule.py diff --git a/src/hydrorollcore/settings.py b/src/infini/settings.py index 51c64dd2..51c64dd2 100644 --- a/src/hydrorollcore/settings.py +++ b/src/infini/settings.py diff --git a/src/hydrorollcore/typing.py b/src/infini/typing.py index 333a763b..333a763b 100644 --- a/src/hydrorollcore/typing.py +++ b/src/infini/typing.py diff --git a/src/overrides/assets/javascripts/components/_/index.ts b/src/overrides/assets/javascripts/components/_/index.ts deleted file mode 100644 index 3cb4c18e..00000000 --- a/src/overrides/assets/javascripts/components/_/index.ts +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { getElement, getElements } from "~/browser" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Component type - */ -export type ComponentType = - | "iconsearch" /* Icon search */ - | "iconsearch-query" /* Icon search input */ - | "iconsearch-result" /* Icon search results */ - | "sponsorship" /* Sponsorship */ - | "sponsorship-count" /* Sponsorship count */ - | "sponsorship-total" /* Sponsorship total */ - -/** - * Component - * - * @template T - Component type - * @template U - Reference type - */ -export type Component< - T extends {} = {}, - U extends HTMLElement = HTMLElement -> = - T & { - ref: U /* Component reference */ - } - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Component type map - */ -interface ComponentTypeMap { - "iconsearch": HTMLElement /* Icon search */ - "iconsearch-query": HTMLInputElement /* Icon search input */ - "iconsearch-result": HTMLElement /* Icon search results */ - "sponsorship": HTMLElement /* Sponsorship */ - "sponsorship-count": HTMLElement /* Sponsorship count */ - "sponsorship-total": HTMLElement /* Sponsorship total */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Retrieve the element for a given component or throw a reference error - * - * @template T - Component type - * - * @param type - Component type - * @param node - Node of reference - * - * @returns Element - */ -export function getComponentElement<T extends ComponentType>( - type: T, node: ParentNode = document -): ComponentTypeMap[T] { - return getElement(`[data-mdx-component=${type}]`, node) -} - -/** - * Retrieve all elements for a given component - * - * @template T - Component type - * - * @param type - Component type - * @param node - Node of reference - * - * @returns Elements - */ -export function getComponentElements<T extends ComponentType>( - type: T, node: ParentNode = document -): ComponentTypeMap[T][] { - return getElements(`[data-mdx-component=${type}]`, node) -} diff --git a/src/overrides/assets/javascripts/components/iconsearch/_/index.ts b/src/overrides/assets/javascripts/components/iconsearch/_/index.ts deleted file mode 100644 index f509a6f9..00000000 --- a/src/overrides/assets/javascripts/components/iconsearch/_/index.ts +++ /dev/null @@ -1,94 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { Observable, merge } from "rxjs" - -import { configuration } from "~/_" -import { requestJSON } from "~/browser" - -import { Component, getComponentElement } from "../../_" -import { - IconSearchQuery, - mountIconSearchQuery -} from "../query" -import { - IconSearchResult, - mountIconSearchResult -} from "../result" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Icon category - */ -export interface IconCategory { - base: string /* Category base URL */ - data: Record<string, string> /* Category data */ -} - -/** - * Icon search index - */ -export interface IconSearchIndex { - icons: IconCategory /* Icons */ - emojis: IconCategory /* Emojis */ -} - -/* ------------------------------------------------------------------------- */ - -/** - * Icon search - */ -export type IconSearch = - | IconSearchQuery - | IconSearchResult - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Mount icon search - * - * @param el - Icon search element - * - * @returns Icon search component observable - */ -export function mountIconSearch( - el: HTMLElement -): Observable<Component<IconSearch>> { - const config = configuration() - const index$ = requestJSON<IconSearchIndex>( - new URL("assets/javascripts/iconsearch_index.json", config.base) - ) - - /* Retrieve query and result components */ - const query = getComponentElement("iconsearch-query", el) - const result = getComponentElement("iconsearch-result", el) - - /* Create and return component */ - const query$ = mountIconSearchQuery(query) - const result$ = mountIconSearchResult(result, { index$, query$ }) - return merge(query$, result$) -} diff --git a/src/overrides/assets/javascripts/components/iconsearch/index.ts b/src/overrides/assets/javascripts/components/iconsearch/index.ts deleted file mode 100644 index 9d856774..00000000 --- a/src/overrides/assets/javascripts/components/iconsearch/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./query" -export * from "./result" diff --git a/src/overrides/assets/javascripts/components/iconsearch/query/index.ts b/src/overrides/assets/javascripts/components/iconsearch/query/index.ts deleted file mode 100644 index 03a3daad..00000000 --- a/src/overrides/assets/javascripts/components/iconsearch/query/index.ts +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - combineLatest, - delay, - distinctUntilChanged, - filter, - fromEvent, - map, - merge, - startWith, - withLatestFrom -} from "rxjs" - -import { watchElementFocus } from "~/browser" - -import { Component } from "../../_" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Icon search query - */ -export interface IconSearchQuery { - value: string /* Query value */ - focus: boolean /* Query focus */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Mount icon search query - * - * @param el - Icon search query element - * - * @returns Icon search query component observable - */ -export function mountIconSearchQuery( - el: HTMLInputElement -): Observable<Component<IconSearchQuery, HTMLInputElement>> { - - /* Intercept focus and input events */ - const focus$ = watchElementFocus(el) - const value$ = merge( - fromEvent(el, "keyup"), - fromEvent(el, "focus").pipe(delay(1)) - ) - .pipe( - map(() => el.value), - startWith(el.value), - distinctUntilChanged(), - ) - - /* Log search on blur */ - focus$ - .pipe( - filter(active => !active), - withLatestFrom(value$) - ) - .subscribe(([, value]) => { - const path = document.location.pathname - if (typeof ga === "function" && value.length) - ga("send", "pageview", `${path}?q=[icon]+${value}`) - }) - - /* Combine into single observable */ - return combineLatest([value$, focus$]) - .pipe( - map(([value, focus]) => ({ ref: el, value, focus })), - ) -} diff --git a/src/overrides/assets/javascripts/components/iconsearch/result/index.ts b/src/overrides/assets/javascripts/components/iconsearch/result/index.ts deleted file mode 100644 index 2b9d97fb..00000000 --- a/src/overrides/assets/javascripts/components/iconsearch/result/index.ts +++ /dev/null @@ -1,237 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { filter as search } from "fuzzaldrin-plus" -import { - Observable, - Subject, - bufferCount, - combineLatest, - distinctUntilKeyChanged, - filter, - finalize, - map, - merge, - of, - switchMap, - tap, - withLatestFrom, - zipWith -} from "rxjs" - -import { - getElement, - watchElementBoundary -} from "~/browser" -import { round } from "~/utilities" - -import { Icon, renderIconSearchResult } from "_/templates" - -import { Component } from "../../_" -import { IconSearchIndex } from "../_" -import { IconSearchQuery } from "../query" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Icon search result - */ -export interface IconSearchResult { - data: Icon[] /* Search result data */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Watch options - */ -interface WatchOptions { - index$: Observable<IconSearchIndex> /* Search index observable */ - query$: Observable<IconSearchQuery> /* Search query observable */ -} - -/** - * Mount options - */ -interface MountOptions { - index$: Observable<IconSearchIndex> /* Search index observable */ - query$: Observable<IconSearchQuery> /* Search query observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch icon search result - * - * @param el - Icon search result element - * @param options - Options - * - * @returns Icon search result observable - */ -export function watchIconSearchResult( - el: HTMLElement, { index$, query$ }: WatchOptions -): Observable<IconSearchResult> { - switch (el.getAttribute("data-mdx-mode")) { - - case "file": - return combineLatest([ - query$.pipe(distinctUntilKeyChanged("value")), - index$ - .pipe( - map(({ icons }) => Object.values(icons.data) - .map(icon => icon.replace(/\.svg$/, "")) - ) - ) - ]) - .pipe( - map(([{ value }, data]) => search(data, value)), - switchMap(files => index$.pipe( - map(({ icons }) => ({ - data: files.map<Icon>(shortcode => { - return { - shortcode, - url: [ - icons.base, - shortcode, - ".svg" - ].join("") - } - }) - })) - )) - ) - - default: - return combineLatest([ - query$.pipe(distinctUntilKeyChanged("value")), - index$ - .pipe( - map(({ icons, emojis }) => [ - ...Object.keys(icons.data), - ...Object.keys(emojis.data) - ]) - ) - ]) - .pipe( - map(([{ value }, data]) => search(data, value)), - switchMap(shortcodes => index$.pipe( - map(({ icons, emojis }) => ({ - data: shortcodes.map<Icon>(shortcode => { - const category = - shortcode in icons.data - ? icons - : emojis - return { - shortcode, - url: [ - category.base, - category.data[shortcode] - ].join("") - } - }) - })) - )) - ) - } -} - -/** - * Mount icon search result - * - * @param el - Icon search result element - * @param options - Options - * - * @returns Icon search result component observable - */ -export function mountIconSearchResult( - el: HTMLElement, { index$, query$ }: MountOptions -): Observable<Component<IconSearchResult, HTMLElement>> { - const push$ = new Subject<IconSearchResult>() - const boundary$ = watchElementBoundary(el) - .pipe( - filter(Boolean) - ) - - /* Update search result metadata */ - const meta = getElement(":scope > :first-child", el) - push$ - .pipe( - withLatestFrom(query$) - ) - .subscribe(([{ data }, { value }]) => { - if (value) { - switch (data.length) { - - /* No results */ - case 0: - meta.textContent = "No matches" - break - - /* One result */ - case 1: - meta.textContent = "1 match" - break - - /* Multiple result */ - default: - meta.textContent = `${round(data.length)} matches` - } - } else { - meta.textContent = "Type to start searching" - } - }) - - /* Update icon search result list */ - const file = el.getAttribute("data-mdx-mode") === "file" - const list = getElement(":scope > :last-child", el) - push$ - .pipe( - tap(() => list.innerHTML = ""), - switchMap(({ data }) => merge( - of(...data.slice(0, 10)), - of(...data.slice(10)) - .pipe( - bufferCount(10), - zipWith(boundary$), - switchMap(([chunk]) => chunk) - ) - )), - withLatestFrom(query$) - ) - .subscribe(([result, { value }]) => list.appendChild( - renderIconSearchResult(result, value, file) - )) - - /* Create and return component */ - return watchIconSearchResult(el, { query$, index$ }) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })) - ) -} diff --git a/src/overrides/assets/javascripts/components/index.ts b/src/overrides/assets/javascripts/components/index.ts deleted file mode 100644 index ec6c9dce..00000000 --- a/src/overrides/assets/javascripts/components/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./iconsearch" -export * from "./sponsorship" diff --git a/src/overrides/assets/javascripts/components/sponsorship/index.ts b/src/overrides/assets/javascripts/components/sponsorship/index.ts deleted file mode 100644 index 711f423a..00000000 --- a/src/overrides/assets/javascripts/components/sponsorship/index.ts +++ /dev/null @@ -1,149 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { Observable, map } from "rxjs" - -import { getElement, requestJSON } from "~/browser" - -import { renderPrivateSponsor, renderPublicSponsor } from "_/templates" - -import { Component, getComponentElement } from "../_" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Sponsor type - */ -export type SponsorType = - | "user" /* Sponsor is a user */ - | "organization" /* Sponsor is an organization */ - -/** - * Sponsor visibility - */ -export type SponsorVisibility = - | "public" /* Sponsor is a user */ - | "private" /* Sponsor is an organization */ - -/* ------------------------------------------------------------------------- */ - -/** - * Sponsor user - */ -export interface SponsorUser { - type: SponsorType /* Sponsor type */ - name: string /* Sponsor login name */ - image: string /* Sponsor image URL */ - url: string /* Sponsor URL */ -} - -/* ------------------------------------------------------------------------- */ - -/** - * Public sponsor - */ -export interface PublicSponsor { - type: "public" /* Sponsor visibility */ - user: SponsorUser /* Sponsor user */ -} - -/** - * Private sponsor - */ -export interface PrivateSponsor { - type: "private" /* Sponsor visibility */ -} - -/* ------------------------------------------------------------------------- */ - -/** - * Sponsor - */ -export type Sponsor = - | PublicSponsor - | PrivateSponsor - -/* ------------------------------------------------------------------------- */ - -/** - * Sponsorship - */ -export interface Sponsorship { - sponsors: Sponsor[] /* Sponsors */ - total: number /* Total amount */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Mount sponsorship - * - * @param el - Sponsorship element - * - * @returns Sponsorship component observable - */ -export function mountSponsorship( - el: HTMLElement -): Observable<Component<Sponsorship>> { - const sponsorship$ = requestJSON<Sponsorship>( - "https://3if8u9o552.execute-api.us-east-1.amazonaws.com/_/" - ) - - /* Retrieve adjacent components */ - const count = getComponentElement("sponsorship-count") - const total = getComponentElement("sponsorship-total") - - /* Render sponsorship */ - sponsorship$.subscribe(sponsorship => { - el.removeAttribute("hidden") - - /* Render public sponsors with avatar and links */ - const list = getElement(":scope > :first-child", el) - for (const sponsor of sponsorship.sponsors) - if (sponsor.type === "public") - list.appendChild(renderPublicSponsor(sponsor.user)) - - /* Render combined private sponsors */ - list.appendChild(renderPrivateSponsor( - sponsorship.sponsors.filter(({ type }) => ( - type === "private" - )).length - )) - - /* Render sponsorship count and total */ - count.innerText = `${sponsorship.sponsors.length}` - total.innerText = `$ ${sponsorship.total - .toString() - .replace(/\B(?=(\d{3})+(?!\d))/g, ",") - } a month` - }) - - // /* Create and return component */ - return sponsorship$ - .pipe( - map(state => ({ ref: el, ...state })) - ) -} diff --git a/src/overrides/assets/javascripts/custom.ts b/src/overrides/assets/javascripts/custom.ts deleted file mode 100644 index 7c3c3847..00000000 --- a/src/overrides/assets/javascripts/custom.ts +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { merge, switchMap } from "rxjs" - -import { - getComponentElements, - mountIconSearch, - mountSponsorship -} from "./components" -import { setupAnalytics } from "./integrations" - -/* ---------------------------------------------------------------------------- - * Application - * ------------------------------------------------------------------------- */ - -/* Set up extra analytics events */ -setupAnalytics() - -/* Set up extra component observables */ -const component$ = document$ - .pipe( - switchMap(() => merge( - - /* Icon search */ - ...getComponentElements("iconsearch") - .map(el => mountIconSearch(el)), - - /* Sponsorship */ - ...getComponentElements("sponsorship") - .map(el => mountSponsorship(el)) - )) - ) - -/* Subscribe to all components */ -component$.subscribe() diff --git a/src/overrides/assets/javascripts/integrations/analytics/index.ts b/src/overrides/assets/javascripts/integrations/analytics/index.ts deleted file mode 100644 index 658add2a..00000000 --- a/src/overrides/assets/javascripts/integrations/analytics/index.ts +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { fromEvent } from "rxjs" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Set up extra analytics events - */ -export function setupAnalytics(): void { - const { origin } = new URL(location.href) - fromEvent(document.body, "click") - .subscribe(ev => { - if (ev.target instanceof HTMLElement) { - const el = ev.target.closest("a") - if (el && el.origin !== origin) - ga("send", "event", "outbound", "click", el.href) - } - }) -} diff --git a/src/overrides/assets/javascripts/integrations/index.ts b/src/overrides/assets/javascripts/integrations/index.ts deleted file mode 100644 index 9179f2a2..00000000 --- a/src/overrides/assets/javascripts/integrations/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./analytics" diff --git a/src/overrides/assets/javascripts/templates/iconsearch/index.tsx b/src/overrides/assets/javascripts/templates/iconsearch/index.tsx deleted file mode 100644 index 13cafa6d..00000000 --- a/src/overrides/assets/javascripts/templates/iconsearch/index.tsx +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { wrap } from "fuzzaldrin-plus" - -import { translation } from "~/_" -import { h } from "~/utilities" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Icon - */ -export interface Icon { - shortcode: string /* Icon shortcode */ - url: string /* Icon URL */ -} - -/* ---------------------------------------------------------------------------- - * Helper functions - * ------------------------------------------------------------------------- */ - -/** - * Highlight an icon search result - * - * @param icon - Icon - * @param query - Search query - * - * @returns Highlighted result - */ -function highlight(icon: Icon, query: string): string { - return wrap(icon.shortcode, query, { - wrap: { - tagOpen: "<b>", - tagClose: "</b>" - } - }) -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Render an icon search result - * - * @param icon - Icon - * @param query - Search query - * @param file - Render as file - * - * @returns Element - */ -export function renderIconSearchResult( - icon: Icon, query: string, file?: boolean -): HTMLElement { - return ( - <li class="mdx-iconsearch-result__item"> - <span class="twemoji"> - <img src={icon.url} /> - </span> - <button - class="md-clipboard--inline" - title={translation("clipboard.copy")} - data-clipboard-text={file ? icon.shortcode : `:${icon.shortcode}:`} - > - <code>{ - file - ? highlight(icon, query) - : `:${highlight(icon, query)}:` - }</code> - </button> - </li> - ) -} diff --git a/src/overrides/assets/javascripts/templates/index.ts b/src/overrides/assets/javascripts/templates/index.ts deleted file mode 100644 index 02376b3d..00000000 --- a/src/overrides/assets/javascripts/templates/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./iconsearch" -export * from "./sponsorship" diff --git a/src/overrides/assets/javascripts/templates/sponsorship/index.tsx b/src/overrides/assets/javascripts/templates/sponsorship/index.tsx deleted file mode 100644 index 7891c2e0..00000000 --- a/src/overrides/assets/javascripts/templates/sponsorship/index.tsx +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { h } from "~/utilities" - -import { SponsorUser } from "_/components" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Render public sponsor - * - * @param user - Sponsor user - * - * @returns Element - */ -export function renderPublicSponsor( - user: SponsorUser -): HTMLElement { - const title = `@${user.name}` - return ( - <a href={user.url} title={title} class="mdx-sponsorship__item"> - <img src={user.image} /> - </a> - ) -} - -/** - * Render private sponsor - * - * @param count - Number of private sponsors - * - * @returns Element - */ -export function renderPrivateSponsor( - count: number -): HTMLElement { - return ( - <a - href="https://github.com/sponsors/squidfunk?metadata_origin=docs" - class="mdx-sponsorship__item mdx-sponsorship__item--private" - > - +{count} - </a> - ) -} diff --git a/src/overrides/assets/stylesheets/custom.scss b/src/overrides/assets/stylesheets/custom.scss deleted file mode 100644 index 8235e7d0..00000000 --- a/src/overrides/assets/stylesheets/custom.scss +++ /dev/null @@ -1,44 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Dependencies -// ---------------------------------------------------------------------------- - -@import "material-color"; -@import "material-shadows"; - -// ---------------------------------------------------------------------------- -// Local imports -// ---------------------------------------------------------------------------- - -@import "utilities/break"; -@import "utilities/convert"; - -@import "config"; - -@import "custom/typeset"; - -@import "custom/layout/banner"; -@import "custom/layout/hero"; -@import "custom/layout/iconsearch"; -@import "custom/layout/sponsorship"; diff --git a/src/overrides/assets/stylesheets/custom/_typeset.scss b/src/overrides/assets/stylesheets/custom/_typeset.scss deleted file mode 100644 index bef30073..00000000 --- a/src/overrides/assets/stylesheets/custom/_typeset.scss +++ /dev/null @@ -1,294 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Keyframes -// ---------------------------------------------------------------------------- - -// Pumping heart animation -@keyframes heart { - 0%, - 40%, - 80%, - 100% { - transform: scale(1); - } - - 20%, - 60% { - transform: scale(1.15); - } -} - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Twitter icon - .twitter { - color: #00acee; - } - - // Mastodon icon - it's not the exact brand color, because that doesn't work - // well on dark backgrounds, so we lightened it up a bit. - .mastodon { - color: #897ff8; - } - - // Insiders video - .mdx-video { - width: auto; - - // Insiders video container - &__inner { - position: relative; - width: 100%; - height: 0; - padding-bottom: 56.138%; - } - - // Insiders video iframe - iframe { - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - overflow: hidden; - border: none; - } - } - - // Pumping heart - .mdx-heart { - animation: heart 1000ms infinite; - } - - // Insiders color (for links, etc.) // remove - .mdx-insiders { - color: $clr-pink-500; - } - - // BETA ##################################################################### - - // Badge - .mdx-badge { - font-size: 0.85em; - - // Badge with heart - &--heart { - --md-typeset-a-color: hsla(#{hex2hsl($clr-pink-500)}, 1); - --md-accent-fg-color: hsla(#{hex2hsl($clr-pink-a200)}, 1); - --md-accent-fg-color--transparent: hsla(#{hex2hsl($clr-pink-500)}, 0.1); - - // Animate icon - .twemoji { - animation: heart 1000ms infinite; - } - } - - // Badge moved to the right - &--right { - float: right; - margin-left: 0.35em; - } - - // Badge icon - &__icon { - padding: px2rem(4px); - background: var(--md-accent-fg-color--transparent); - border-start-start-radius: px2rem(2px); - border-end-start-radius: px2rem(2px); - - // If icon is alone, round corners - &:last-child { - border-radius: px2rem(2px); - } - } - - // Badge text - &__text { - padding: px2rem(4px) px2rem(6px); - border-start-end-radius: px2rem(2px); - border-end-end-radius: px2rem(2px); - box-shadow: 0 0 0 1px inset var(--md-accent-fg-color--transparent); - } - } - - // BETA ##################################################################### - - // Switch buttons - .mdx-switch button { - cursor: pointer; - transition: opacity 250ms; - - // Button on focus/hover - &:is(:focus, :hover) { - opacity: 0.75; - } - - // Code block - > code { - display: block; - color: var(--md-primary-bg-color); - background-color: var(--md-primary-fg-color); - } - } - - // Two-column layout - .mdx-columns { - - // Column - ol, - ul { - columns: 2; - - // [mobile portrait -]: Reset columns on mobile - @include break-to-device(mobile portrait) { - columns: initial; - } - } - - // Column item - li { - break-inside: avoid; - } - } - - // Language list - .mdx-flags { - margin: 2em auto; - - // Language list - ol { - list-style: none; - - // Language list item - li { - margin-bottom: 1em; - } - } - - // Language item - &__item { - display: flex; - gap: px2rem(12px); - } - - // Language content - &__content { - display: flex; - flex: 1; - flex-direction: column; - - // Language name - span { - display: inline-flex; - align-items: baseline; - justify-content: space-between; - } - - // Language link - > span:nth-child(2) { - font-size: 80%; - } - - // Language code - code { - float: right; - } - } - } - - // Social card - .mdx-social { - position: relative; - height: min(#{px2rem(540px)}, 80vw); - - // Social card image on hover - &:hover .mdx-social__image { - background-color: rgba(228, 228, 228, 0.05); - } - - // Social card layer - &__layer { - position: absolute; - margin-top: px2rem(80px); - transition: 250ms cubic-bezier(0.7, 0, 0.3, 1); - transform-style: preserve-3d; - - // Social card layer on hover - &:hover { - - // Social card label - .mdx-social__label { - opacity: 1; - } - - // Social card image - .mdx-social__image { - background-color: rgba(127, 127, 127, 0.99); - } - - // Hide top layers - ~ .mdx-social__layer { - opacity: 0; - } - } - } - - // Social card image - &__image { - box-shadow: - px2rem(-5px) px2rem(5px) px2rem(10px) - rgba(0, 0, 0, 0.05); - transition: all 250ms; - transform: rotate(-40deg) skew(15deg, 15deg) scale(0.7); - - // Actual image - img { - display: block; - } - } - - // Social card label - &__label { - position: absolute; - display: block; - padding: px2rem(4px) px2rem(8px); - color: var(--md-default-bg-color); - background-color: var(--md-default-fg-color--light); - opacity: 0; - transition: all 250ms; - } - - // Transform on hover - @for $i from 6 through 0 { - &:hover .mdx-social__layer:nth-child(#{$i}) { - transform: translateY(#{($i - 3) * -10}px); - } - } - } -} diff --git a/src/overrides/assets/stylesheets/custom/layout/_banner.scss b/src/overrides/assets/stylesheets/custom/layout/_banner.scss deleted file mode 100644 index b67d7fff..00000000 --- a/src/overrides/assets/stylesheets/custom/layout/_banner.scss +++ /dev/null @@ -1,66 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Banner for announcements and warnings -.md-banner { - color: var(--md-footer-fg-color--lighter); - - // Don't wrap name of blog article - strong { - color: var(--md-footer-fg-color); - white-space: nowrap; - } - - a { - color: var(--md-footer-fg-color); - - &:focus, - &:hover { - color: currentcolor; - - .twemoji { - background-color: var(--md-footer-fg-color); - box-shadow: none; - } - } - } - - .twemoji { - display: inline-block; - width: px2rem(24px); - height: px2rem(24px); - padding: px2rem(5px); - vertical-align: bottom; - border-radius: 100%; - box-shadow: 0 0 0 px2rem(1px) currentcolor inset; - transition: all 250ms; - - svg { - display: block; - max-height: initial; - } - } -} diff --git a/src/overrides/assets/stylesheets/custom/layout/_hero.scss b/src/overrides/assets/stylesheets/custom/layout/_hero.scss deleted file mode 100644 index 428cd37e..00000000 --- a/src/overrides/assets/stylesheets/custom/layout/_hero.scss +++ /dev/null @@ -1,123 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Landing page container -.mdx-container { - padding-top: px2rem(20px); - background: - url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1123 258'><path d='M1124,2c0,0 0,256 0,256l-1125,0l0,-48c0,0 16,5 55,5c116,0 197,-92 325,-92c121,0 114,46 254,46c140,0 214,-167 572,-166Z' style='fill: hsla(0, 0%, 100%, 1)' /></svg>") no-repeat bottom, - linear-gradient( - to bottom, - var(--md-primary-fg-color), - hsla(280, 67%, 55%, 1) 99%, - var(--md-default-bg-color) 99% - ); - - // Adjust background for slate theme - [data-md-color-scheme="slate"] & { - background: - url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 1123 258'><path d='M1124,2c0,0 0,256 0,256l-1125,0l0,-48c0,0 16,5 55,5c116,0 197,-92 325,-92c121,0 114,46 254,46c140,0 214,-167 572,-166Z' style='fill: hsla(230, 15%, 14%, 1)' /></svg>") no-repeat bottom, - linear-gradient( - to bottom, - var(--md-primary-fg-color), - hsla(230, 15%, 25%, 1) 99%, - var(--md-default-bg-color) 99% - ); - } -} - -// Landing page hero -.mdx-hero { - margin: 0 px2rem(16px); - color: var(--md-primary-bg-color); - - // Hero headline - h1 { - margin-bottom: px2rem(20px); - font-weight: 700; - color: currentcolor; - - // [mobile portrait -]: Larger hero headline - @include break-to-device(mobile portrait) { - font-size: px2rem(28px); - } - } - - // Hero content - &__content { - padding-bottom: px2rem(120px); - } - - // [tablet landscape +]: Columnar display - @include break-from-device(tablet landscape) { - display: flex; - align-items: stretch; - - // Adjust spacing and set dimensions - &__content { - max-width: px2rem(380px); - padding-bottom: 14vw; - margin-top: px2rem(70px); - } - - // Hero image - &__image { - order: 1; - width: px2rem(760px); - transform: translateX(#{px2rem(80px)}); - } - } - - // [screen +]: Columnar display and adjusted spacing - @include break-from-device(screen) { - - // Hero image - &__image { - transform: translateX(#{px2rem(160px)}); - } - } - - // Button - .md-button { - margin-top: px2rem(10px); - margin-right: px2rem(10px); - color: var(--md-primary-bg-color); - - // Button on focus/hover - &:is(:focus, :hover) { - color: var(--md-accent-bg-color); - background-color: var(--md-accent-fg-color); - border-color: var(--md-accent-fg-color); - } - - // Primary button - &--primary { - color: hsla(280, 37%, 48%, 1); - background-color: var(--md-primary-bg-color); - border-color: var(--md-primary-bg-color); - } - } -} diff --git a/src/overrides/assets/stylesheets/custom/layout/_iconsearch.scss b/src/overrides/assets/stylesheets/custom/layout/_iconsearch.scss deleted file mode 100644 index 651c4135..00000000 --- a/src/overrides/assets/stylesheets/custom/layout/_iconsearch.scss +++ /dev/null @@ -1,136 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Icon search - .mdx-iconsearch { - position: relative; - background-color: var(--md-default-bg-color); - border-radius: px2rem(2px); - box-shadow: var(--md-shadow-z1); - transition: box-shadow 125ms; - - // Icon search on focus/hover - &:is(:focus-within, :hover) { - box-shadow: var(--md-shadow-z2); - } - - // Icon search input - .md-input { - background: var(--md-default-bg-color); - box-shadow: none; - - // Slate theme, i.e. dark mode - [data-md-color-scheme="slate"] & { - background: var(--md-code-bg-color); - } - } - } - - // Icon search result - .mdx-iconsearch-result { - max-height: 50vh; - overflow-y: auto; - // Hack: promote to own layer to reduce jitter - backface-visibility: hidden; - touch-action: pan-y; - scrollbar-width: thin; - scrollbar-color: var(--md-default-fg-color--lighter) transparent; - - // Icon search result inside tooltip - .md-tooltip & { - max-height: px2rem(205px); - } - - // Webkit scrollbar - &::-webkit-scrollbar { - width: px2rem(4px); - height: px2rem(4px); - } - - // Webkit scrollbar thumb - &::-webkit-scrollbar-thumb { - background-color: var(--md-default-fg-color--lighter); - - // Webkit scrollbar thumb on hover - &:hover { - background-color: var(--md-accent-fg-color); - } - } - - // Icon search result metadata - &__meta { - position: absolute; - top: px2rem(8px); - right: px2rem(12px); - font-size: px2rem(12.8px); - color: var(--md-default-fg-color--lighter); - } - - // Icon search result list - &__list { - padding: 0; - margin: 0; - // Hack: necessary because of increased specificity due to the PostCSS - // plugin which prefixes this with `[dir=...]` selectors. - margin-inline-start: 0; - list-style: none; - } - - // Icon search result item - &__item { - padding: px2rem(4px) px2rem(12px); - margin: 0; - // Hack: necessary because of increased specificity due to the PostCSS - // plugin which prefixes this with `[dir=...]` selectors. - margin-inline-start: 0; - border-bottom: px2rem(1px) solid var(--md-default-fg-color--lightest); - - // Omit border on last child - &:last-child { - border-bottom: none; - } - - // Item content - > * { - margin-right: px2rem(12px); - } - - // Set icon dimensions to fit - img { - width: px2rem(18px); - height: px2rem(18px); - - // Slate theme, i.e. dark mode - [data-md-color-scheme="slate"] &[src*="squidfunk"] { - filter: invert(1); /* stylelint-disable-line */ - } - } - } - } -} diff --git a/src/overrides/assets/stylesheets/custom/layout/_sponsorship.scss b/src/overrides/assets/stylesheets/custom/layout/_sponsorship.scss deleted file mode 100644 index e2b16570..00000000 --- a/src/overrides/assets/stylesheets/custom/layout/_sponsorship.scss +++ /dev/null @@ -1,128 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Premium sponsors - .mdx-premium { - - // Paragraphs - p { - margin: 2em 0; - text-align: center; - } - - // Premium sponsor image - img { - height: px2rem(65px); - } - - // Premium sponsor list - p:last-child { - display: flex; - flex-wrap: wrap; - justify-content: center; - - // Premium sponsor link - > a { - display: block; - flex-shrink: 0; - } - } - } - - // Sponsorship - .mdx-sponsorship { - - // Sponsorship list - &__list { - margin: 2em 0; - - // Clearfix, because we can't use overflow: auto - &::after { - display: block; - clear: both; - content: ""; - } - } - - // Sponsorship item - &__item { - display: block; - float: inline-start; - width: px2rem(32px); - height: px2rem(32px); - margin: px2rem(4px); - overflow: hidden; - border-radius: 100%; - transition: - color 125ms, - transform 125ms; - transform: scale(1); - - // Sponsor item on focus/hover - &:is(:focus, :hover) { - transform: scale(1.1); - - // Sponsor avatar - img { - filter: grayscale(0%); - } - } - - // Private sponsor - &--private { - font-size: px2rem(12px); - font-weight: 700; - line-height: px2rem(32px); - color: var(--md-default-fg-color--lighter); - text-align: center; - background: var(--md-default-fg-color--lightest); - } - - // Sponsor avatar - img { - display: block; - width: 100%; - height: auto; - filter: grayscale(100%) opacity(75%); - transition: filter 125ms; - } - } - } - - // Sponsorship button - .mdx-sponsorship-button { - font-weight: 400; - } - - // Sponsorship count and total - .mdx-sponsorship-count, - .mdx-sponsorship-total { - font-weight: 700; - } -} diff --git a/src/overrides/home.html b/src/overrides/home.html deleted file mode 100644 index 3f54ca82..00000000 --- a/src/overrides/home.html +++ /dev/null @@ -1,106 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -{% extends "main.html" %} - -<!-- Render hero under tabs --> -{% block tabs %} - {{ super() }} - - <!-- Additional styles for landing page --> - <style> - - /* Application header should be static for the landing page */ - .md-header { - position: initial; - } - - /* Remove spacing, as we cannot hide it completely */ - .md-main__inner { - margin: 0; - } - - /* Hide main content for now */ - .md-content { - display: none; - } - - /* Hide table of contents */ - @media screen and (min-width: 60em) { - .md-sidebar--secondary { - display: none; - } - } - - /* Hide navigation */ - @media screen and (min-width: 76.25em) { - .md-sidebar--primary { - display: none; - } - } - </style> - - <!-- Hero for landing page --> - <section class="mdx-container"> - <div class="md-grid md-typeset"> - <div class="mdx-hero"> - - <!-- Hero image --> - <div class="mdx-hero__image"> - <img - src="assets/images/illustration.png" - alt="" - width="1659" - height="1200" - draggable="false" - > - </div> - - <!-- Hero content --> - <div class="mdx-hero__content"> - <h1>Technical documentation that just works</h1> - <p>{{ config.site_description }}. Set up in 5 minutes.</p> - <a - href="{{ page.next_page.url | url }}" - title="{{ page.next_page.title | e }}" - class="md-button md-button--primary" - > - Quick start - </a> - <a - href="{{ 'insiders/' | url }}" - title="Material for MkDocs Insiders" - class="md-button" - > - Get Insiders - </a> - </div> - </div> - </div> - </section> -{% endblock %} - -<!-- Content --> -{% block content %}{% endblock %} - -<!-- Application footer --> -{% block footer %}{% endblock %} diff --git a/src/overrides/hooks/shortcodes.py b/src/overrides/hooks/shortcodes.py deleted file mode 100644 index 5b02e3cf..00000000 --- a/src/overrides/hooks/shortcodes.py +++ /dev/null @@ -1,283 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from __future__ import annotations - -import posixpath -import re - -from mkdocs.config.defaults import MkDocsConfig -from mkdocs.structure.files import File, Files -from mkdocs.structure.pages import Page -from re import Match - -# ----------------------------------------------------------------------------- -# Hooks -# ----------------------------------------------------------------------------- - -# @todo -def on_page_markdown( - markdown: str, *, page: Page, config: MkDocsConfig, files: Files -): - - # Replace callback - def replace(match: Match): - type, args = match.groups() - args = args.strip() - if type == "version": - if args.startswith("insiders-"): - return _badge_for_version_insiders(args, page, files) - else: - return _badge_for_version(args, page, files) - elif type == "sponsors": return _badge_for_sponsors(page, files) - elif type == "flag": return flag(args, page, files) - elif type == "option": return option(args) - elif type == "setting": return setting(args) - elif type == "feature": return _badge_for_feature(args, page, files) - elif type == "plugin": return _badge_for_plugin(args, page, files) - elif type == "extension": return _badge_for_extension(args, page, files) - elif type == "utility": return _badge_for_utility(args, page, files) - elif type == "example": return _badge_for_example(args, page, files) - elif type == "default": - if args == "none": return _badge_for_default_none(page, files) - elif args == "computed": return _badge_for_default_computed(page, files) - else: return _badge_for_default(args, page, files) - - # Otherwise, raise an error - raise RuntimeError(f"Unknown shortcode: {type}") - - # Find and replace all external asset URLs in current page - return re.sub( - r"<!-- md:(\w+)(.*?) -->", - replace, markdown, flags = re.I | re.M - ) - -# ----------------------------------------------------------------------------- -# Helper functions -# ----------------------------------------------------------------------------- - -# Create a flag of a specific type -def flag(args: str, page: Page, files: Files): - type, *_ = args.split(" ", 1) - if type == "experimental": return _badge_for_experimental(page, files) - elif type == "required": return _badge_for_required(page, files) - elif type == "customization": return _badge_for_customization(page, files) - elif type == "metadata": return _badge_for_metadata(page, files) - elif type == "multiple": return _badge_for_multiple(page, files) - raise RuntimeError(f"Unknown type: {type}") - -# Create a linkable option -def option(type: str): - _, *_, name = re.split(r"[.:]", type) - return f"[`{name}`](#+{type}){{ #+{type} }}\n\n" - -# Create a linkable setting - @todo append them to the bottom of the page -def setting(type: str): - _, *_, name = re.split(r"[.*]", type) - return f"`{name}` {{ #{type} }}\n\n[{type}]: #{type}\n\n" - -# ----------------------------------------------------------------------------- - -# Resolve path of file relative to given page - the posixpath always includes -# one additional level of `..` which we need to remove -def _resolve_path(path: str, page: Page, files: Files): - path, anchor, *_ = f"{path}#".split("#") - path = _resolve(files.get_file_from_path(path), page) - return "#".join([path, anchor]) if anchor else path - -# Resolve path of file relative to given page - the posixpath always includes -# one additional level of `..` which we need to remove -def _resolve(file: File, page: Page): - path = posixpath.relpath(file.src_uri, page.file.src_uri) - return posixpath.sep.join(path.split(posixpath.sep)[1:]) - -# ----------------------------------------------------------------------------- - -# Create badge -def _badge(icon: str, text: str = "", type: str = ""): - classes = f"mdx-badge mdx-badge--{type}" if type else "mdx-badge" - return "".join([ - f"<span class=\"{classes}\">", - *([f"<span class=\"mdx-badge__icon\">{icon}</span>"] if icon else []), - *([f"<span class=\"mdx-badge__text\">{text}</span>"] if text else []), - f"</span>", - ]) - -# Create sponsors badge -def _badge_for_sponsors(page: Page, files: Files): - icon = "material-heart" - href = _resolve_path("insiders/index.md", page, files) - return _badge( - icon = f"[:{icon}:]({href} 'Sponsors only')", - type = "heart" - ) - -# Create badge for version -def _badge_for_version(text: str, page: Page, files: Files): - spec = text - path = f"changelog/index.md#{spec}" - - # Return badge - icon = "material-tag-outline" - href = _resolve_path("conventions.md#version", page, files) - return _badge( - icon = f"[:{icon}:]({href} 'Minimum version')", - text = f"[{text}]({_resolve_path(path, page, files)})" if spec else "" - ) - -# Create badge for version of Insiders -def _badge_for_version_insiders(text: str, page: Page, files: Files): - spec = text.replace("insiders-", "") - path = f"insiders/changelog/index.md#{spec}" - - # Return badge - icon = "material-tag-heart-outline" - href = _resolve_path("conventions.md#version-insiders", page, files) - return _badge( - icon = f"[:{icon}:]({href} 'Minimum version')", - text = f"[{text}]({_resolve_path(path, page, files)})" if spec else "" - ) - -# Create badge for feature -def _badge_for_feature(text: str, page: Page, files: Files): - icon = "material-toggle-switch" - href = _resolve_path("conventions.md#feature", page, files) - return _badge( - icon = f"[:{icon}:]({href} 'Optional feature')", - text = text - ) - -# Create badge for plugin -def _badge_for_plugin(text: str, page: Page, files: Files): - icon = "material-floppy" - href = _resolve_path("conventions.md#plugin", page, files) - return _badge( - icon = f"[:{icon}:]({href} 'Plugin')", - text = text - ) - -# Create badge for extension -def _badge_for_extension(text: str, page: Page, files: Files): - icon = "material-language-markdown" - href = _resolve_path("conventions.md#extension", page, files) - return _badge( - icon = f"[:{icon}:]({href} 'Markdown extension')", - text = text - ) - -# Create badge for utility -def _badge_for_utility(text: str, page: Page, files: Files): - icon = "material-package-variant" - href = _resolve_path("conventions.md#utility", page, files) - return _badge( - icon = f"[:{icon}:]({href} 'Third-party utility')", - text = text - ) - -# Create badge for example -def _badge_for_example(text: str, page: Page, files: Files): - return "\n".join([ - _badge_for_example_download(text, page, files), - _badge_for_example_view(text, page, files) - ]) - -# Create badge for example view -def _badge_for_example_view(text: str, page: Page, files: Files): - icon = "material-folder-eye" - href = f"https://mkdocs-material.github.io/examples/{text}/" - return _badge( - icon = f"[:{icon}:]({href} 'View example')", - type = "right" - ) - -# Create badge for example download -def _badge_for_example_download(text: str, page: Page, files: Files): - icon = "material-folder-download" - href = f"https://mkdocs-material.github.io/examples/{text}.zip" - return _badge( - icon = f"[:{icon}:]({href} 'Download example')", - text = f"[`.zip`]({href})", - type = "right" - ) - -# Create badge for default value -def _badge_for_default(text: str, page: Page, files: Files): - icon = "material-water" - href = _resolve_path("conventions.md#default", page, files) - return _badge( - icon = f"[:{icon}:]({href} 'Default value')", - text = text - ) - -# Create badge for empty default value -def _badge_for_default_none(page: Page, files: Files): - icon = "material-water-outline" - href = _resolve_path("conventions.md#default", page, files) - return _badge( - icon = f"[:{icon}:]({href} 'Default value is empty')" - ) - -# Create badge for computed default value -def _badge_for_default_computed(page: Page, files: Files): - icon = "material-water-check" - href = _resolve_path("conventions.md#default", page, files) - return _badge( - icon = f"[:{icon}:]({href} 'Default value is computed')" - ) - -# Create badge for metadata property flag -def _badge_for_metadata(page: Page, files: Files): - icon = "material-list-box-outline" - href = _resolve_path("conventions.md#metadata", page, files) - return _badge( - icon = f"[:{icon}:]({href} 'Metadata property')" - ) - -# Create badge for required value flag -def _badge_for_required(page: Page, files: Files): - icon = "material-alert" - href = _resolve_path("conventions.md#required", page, files) - return _badge( - icon = f"[:{icon}:]({href} 'Required value')" - ) - -# Create badge for customization flag -def _badge_for_customization(page: Page, files: Files): - icon = "material-brush-variant" - href = _resolve_path("conventions.md#customization", page, files) - return _badge( - icon = f"[:{icon}:]({href} 'Customization')" - ) - -# Create badge for multiple instance flag -def _badge_for_multiple(page: Page, files: Files): - icon = "material-inbox-multiple" - href = _resolve_path("conventions.md#multiple-instances", page, files) - return _badge( - icon = f"[:{icon}:]({href} 'Multiple instances')" - ) - -# Create badge for experimental flag -def _badge_for_experimental(page: Page, files: Files): - icon = "material-flask-outline" - href = _resolve_path("conventions.md#experimental", page, files) - return _badge( - icon = f"[:{icon}:]({href} 'Experimental')" - ) diff --git a/src/overrides/hooks/translations.html b/src/overrides/hooks/translations.html deleted file mode 100644 index ab41c77d..00000000 --- a/src/overrides/hooks/translations.html +++ /dev/null @@ -1,54 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Render translation language --> -{% macro render_language(language) %} - <div class="mdx-flags__item" markdown> - :flag_{{ language.flag }}:{ .lg .middle } - <span class="mdx-flags__content"> - <span> - <strong>{{ language.name }}</strong> - <code>{{ language.code }}</code> - </span> - {% if language.miss %} - <span> - <a href="{{ language.link }}"> - {{ language.miss | length }} translations missing - </a> - </span> - {% else %} - <small>Complete</small> - {% endif %} - </span> - </div> -{% endmacro %} - -<!-- Render translations --> -{% macro render(translations, start = 1) %} - <div class="mdx-columns mdx-flags" markdown> - <ol markdown> - {% for language in translations %} - <li markdown>{{ render_language(language) }}</li> - {% endfor %} - </ol> - </div> -{% endmacro %} diff --git a/src/overrides/hooks/translations.py b/src/overrides/hooks/translations.py deleted file mode 100644 index 661fd18e..00000000 --- a/src/overrides/hooks/translations.py +++ /dev/null @@ -1,193 +0,0 @@ -# Copyright (c) 2016-2023 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 os -import re - -from glob import iglob -from mkdocs.config.defaults import MkDocsConfig -from mkdocs.structure.pages import Page -from urllib.parse import urlencode, urlparse - -# ----------------------------------------------------------------------------- -# Hooks -# ----------------------------------------------------------------------------- - -# Determine missing translations and render language overview in the setup -# guide, including links to provide missing translations. -def on_page_markdown(markdown: str, *, page: Page, config: MkDocsConfig, files): - issue_url = "https://github.com/squidfunk/mkdocs-material/issues/new" - if page.file.src_uri != "setup/changing-the-language.md": - return - - # Collect all existing languages - names: dict[str, str] = {} - known: dict[str, dict[str, str]] = {} - for path in iglob("src/templates/partials/languages/*.html"): - with open(path, "r", encoding = "utf-8") as f: - data = f.read() - - # Extract language code and name - name, = re.findall(r"<!-- Translations: (.+) -->", data) - code, _ = os.path.splitext(os.path.basename(path)) - - # Map names and available translations - names[code] = name - known[code] = dict(re.findall( - r"^ \"([^\"]+)\": \"([^\"]*)\"(?:,|$)?", data, - re.MULTILINE - )) - - # Remove technical stuff - for key in [ - "direction", - "search.config.pipeline", - "search.config.lang", - "search.config.separator" - ]: - if key in known[code]: - del known[code][key] - - # Traverse all languages and compute missing translations - languages = [] - reference = set(known["en"]) - for code, name in names.items(): - miss = reference - set(known[code]) - - # Check each translations - translations: list[str] = [] - for key, value in known["en"].items(): - if key in known[code]: - translations.append( - f" \"{key}\": \"{known[code][key]}\"" - ) - else: - translations.append( - f" \"{key}\": \"{value} ⬅️\"" - ) - - # Assemble GitHub issue URL - link = urlparse(issue_url) - link = link._replace(query = urlencode({ - "template": "04-add-translations.yml", - "title": f"Update {name} translations", - "translations": "\n".join([ - "{% macro t(key) %}{{ {", - ",\n".join(translations), - "}[key] }}{% endmacro %}" - ]), - "country-flag": f":flag_{countries[code]}:" - })) - - # Add translation - languages.append({ - "flag": countries[code], - "code": code, - "name": name, - "link": link.geturl(), - "miss": miss - }) - - # Load template and render translations - env = config.theme.get_env() - template = env.get_template( "hooks/translations.html") - translations = template.module.render( - sorted(languages, key = lambda language: language["name"]) - ) - - # Replace translation marker - return markdown.replace( - "<!-- hooks/translations.py -->", "\n".join( - [line.lstrip() for line in translations.split("\n") - ] - )) - -# ----------------------------------------------------------------------------- -# Data -# ----------------------------------------------------------------------------- - -# Map ISO 639-1 (languages) to ISO 3166 (countries) -countries = dict({ - "af": "za", - "ar": "ae", - "be": "by", - "bg": "bg", - "bn": "bd", - "ca": "es", - "cs": "cz", - "da": "dk", - "de": "de", - "el": "gr", - "en": "us", - "eo": "eu", - "es": "es", - "et": "ee", - "eu": "es", - "fa": "ir", - "fi": "fi", - "fr": "fr", - "gl": "es", - "he": "il", - "hi": "in", - "hr": "hr", - "hu": "hu", - "hy": "am", - "id": "id", - "is": "is", - "it": "it", - "ja": "jp", - "ka": "ge", - "kn": "in", - "ko": "kr", - "ku-IQ": "iq", - "lb": "lu", - "lt": "lt", - "lv": "lv", - "mk": "mk", - "mn": "mn", - "ms": "my", - "my": "mm", - "nb": "no", - "nl": "nl", - "nn": "no", - "pl": "pl", - "pt-BR": "br", - "pt": "pt", - "ro": "ro", - "ru": "ru", - "sa": "in", - "sh": "rs", - "si": "lk", - "sk": "sk", - "sl": "si", - "sr": "rs", - "sv": "se", - "te": "in", - "th": "th", - "tl": "ph", - "tr": "tr", - "uk": "ua", - "ur": "pk", - "uz": "uz", - "vi": "vn", - "zh": "cn", - "zh-Hant": "cn", - "zh-TW": "tw" -}) diff --git a/src/overrides/main.html b/src/overrides/main.html deleted file mode 100644 index 39b68b5a..00000000 --- a/src/overrides/main.html +++ /dev/null @@ -1,59 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -{% extends "base.html" %} - -<!-- Custom front matter --> -{% block extrahead %} - - <!-- Extra style sheets (can't be set in mkdocs.yml due to content hash) --> - <link - rel="stylesheet" - href="{{ 'assets/stylesheets/custom.css' | url }}" - /> -{% endblock %} - -<!-- Announcement bar --> -{% block announce %} - For updates follow <strong>@squidfunk</strong> on - <a rel="me" href="https://fosstodon.org/@squidfunk"> - <span class="twemoji mastodon"> - {% include ".icons/fontawesome/brands/mastodon.svg" %} - </span> - <strong>Fosstodon</strong> - </a> - and - <a href="https://twitter.com/squidfunk"> - <span class="twemoji twitter"> - {% include ".icons/fontawesome/brands/twitter.svg" %} - </span> - <strong>Twitter</strong> - </a> -{% endblock %} - -<!-- Theme-related JavaScript --> -{% block scripts %} - {{ super() }} - - <!-- Extra JavaScript (can't be set in mkdocs.yml due to content hash) --> - <script src="{{ 'assets/javascripts/custom.js' | url }}"></script> -{% endblock %} diff --git a/src/plugins/__init__.py b/src/plugins/__init__.py deleted file mode 100644 index d1899378..00000000 --- a/src/plugins/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2016-2023 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. diff --git a/src/plugins/blog/__init__.py b/src/plugins/blog/__init__.py deleted file mode 100644 index d1899378..00000000 --- a/src/plugins/blog/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2016-2023 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. diff --git a/src/plugins/blog/author.py b/src/plugins/blog/author.py deleted file mode 100644 index 1dcfc2de..00000000 --- a/src/plugins/blog/author.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from mkdocs.config.base import Config -from mkdocs.config.config_options import DictOfItems, SubConfig, Type - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Author -class Author(Config): - name = Type(str) - description = Type(str) - avatar = Type(str) - -# ----------------------------------------------------------------------------- - -# Authors -class Authors(Config): - authors = DictOfItems(SubConfig(Author), default = {}) diff --git a/src/plugins/blog/config.py b/src/plugins/blog/config.py deleted file mode 100644 index c7a85095..00000000 --- a/src/plugins/blog/config.py +++ /dev/null @@ -1,88 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from functools import partial -from markdown.extensions.toc import slugify -from mkdocs.config.config_options import Choice, Deprecated, Optional, Type -from mkdocs.config.base import Config - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Blog plugin configuration -class BlogConfig(Config): - enabled = Type(bool, default = True) - - # Settings for blog - blog_dir = Type(str, default = "blog") - blog_toc = Type(bool, default = False) - - # Settings for posts - post_dir = Type(str, default = "{blog}/posts") - post_date_format = Type(str, default = "long") - post_url_date_format = Type(str, default = "yyyy/MM/dd") - post_url_format = Type(str, default = "{date}/{slug}") - post_url_max_categories = Type(int, default = 1) - post_slugify = Type((type(slugify), partial), default = slugify) - post_slugify_separator = Type(str, default = "-") - post_excerpt = Choice(["optional", "required"], default = "optional") - post_excerpt_max_authors = Type(int, default = 1) - post_excerpt_max_categories = Type(int, default = 5) - post_excerpt_separator = Type(str, default = "<!-- more -->") - post_readtime = Type(bool, default = True) - post_readtime_words_per_minute = Type(int, default = 265) - - # Settings for archive - archive = Type(bool, default = True) - archive_name = Type(str, default = "blog.archive") - archive_date_format = Type(str, default = "yyyy") - archive_url_date_format = Type(str, default = "yyyy") - archive_url_format = Type(str, default = "archive/{date}") - archive_toc = Optional(Type(bool)) - - # Settings for categories - categories = Type(bool, default = True) - categories_name = Type(str, default = "blog.categories") - categories_url_format = Type(str, default = "category/{slug}") - categories_slugify = Type((type(slugify), partial), default = slugify) - categories_slugify_separator = Type(str, default = "-") - categories_allowed = Type(list, default = []) - categories_toc = Optional(Type(bool)) - - # Settings for pagination - pagination = Type(bool, default = True) - pagination_per_page = Type(int, default = 10) - pagination_url_format = Type(str, default = "page/{page}") - pagination_format = Type(str, default = "~2~") - pagination_if_single_page = Type(bool, default = False) - pagination_keep_content = Type(bool, default = False) - - # Settings for authors - authors = Type(bool, default = True) - authors_file = Type(str, default = "{blog}/.authors.yml") - - # Settings for drafts - draft = Type(bool, default = False) - draft_on_serve = Type(bool, default = True) - draft_if_future_date = Type(bool, default = False) - - # Deprecated settings - pagination_template = Deprecated(moved_to = "pagination_format") diff --git a/src/plugins/blog/plugin.py b/src/plugins/blog/plugin.py deleted file mode 100644 index 375b8cfe..00000000 --- a/src/plugins/blog/plugin.py +++ /dev/null @@ -1,884 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from __future__ import annotations - -import logging -import os -import posixpath -import yaml - -from babel.dates import format_date -from datetime import datetime -from mkdocs.config.defaults import MkDocsConfig -from mkdocs.exceptions import PluginError -from mkdocs.plugins import BasePlugin, event_priority -from mkdocs.structure import StructureItem -from mkdocs.structure.files import File, Files, InclusionLevel -from mkdocs.structure.nav import Navigation, Section -from mkdocs.structure.pages import Page -from mkdocs.utils import copy_file, get_relative_url -from paginate import Page as Pagination -from shutil import rmtree -from tempfile import mkdtemp -from yaml import SafeLoader - -from .author import Authors -from .config import BlogConfig -from .readtime import readtime -from .structure import Archive, Category, Excerpt, Post, View -from .templates import url_filter - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Blog plugin -class BlogPlugin(BasePlugin[BlogConfig]): - supports_multiple_instances = True - - # Initialize plugin - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - # Initialize incremental builds - self.is_serve = False - self.is_dirty = False - - # Initialize temporary directory - self.temp_dir = mkdtemp() - - # Determine whether we're serving the site - def on_startup(self, *, command, dirty): - self.is_serve = command == "serve" - self.is_dirty = dirty - - # Initialize authors and set defaults - def on_config(self, config): - if not self.config.enabled: - return - - # Initialize entrypoint - self.blog: View - - # Initialize and resolve authors, if enabled - if self.config.authors: - self.authors = self._resolve_authors(config) - - # Initialize table of contents settings - if not isinstance(self.config.archive_toc, bool): - self.config.archive_toc = self.config.blog_toc - if not isinstance(self.config.categories_toc, bool): - self.config.categories_toc = self.config.blog_toc - - # By default, drafts are rendered when the documentation is served, - # but not when it is built, for a better user experience - if self.is_serve and self.config.draft_on_serve: - self.config.draft = True - - # Resolve and load posts and generate views (run later) - we want to allow - # other plugins to add generated posts or views, so we run this plugin as - # late as possible. We also need to remove the posts from the navigation - # before navigation is constructed, as the entrypoint should be considered - # to be the active page for each post. The URLs of posts are computed before - # Markdown processing, so that when linking to and from posts, behavior is - # exactly the same as with regular documentation pages. We create all pages - # related to posts as part of this plugin, so we control the entire process. - @event_priority(-50) - def on_files(self, files, *, config): - if not self.config.enabled: - return - - # Resolve path to entrypoint and site directory - root = posixpath.normpath(self.config.blog_dir) - site = config.site_dir - - # Compute path to posts directory - path = self.config.post_dir.format(blog = root) - path = posixpath.normpath(path) - - # Adjust destination paths for media files - for file in files.media_files(): - if not file.src_uri.startswith(path): - continue - - # We need to adjust destination paths for assets to remove the - # purely functional posts directory prefix when building - file.dest_uri = file.dest_uri.replace(path, root) - file.abs_dest_path = os.path.join(site, file.dest_path) - file.url = file.url.replace(path, root) - - # Resolve entrypoint and posts sorted by descending date - if the posts - # directory or entrypoint do not exist, they are automatically created - self.blog = self._resolve(files, config) - self.blog.posts = sorted( - self._resolve_posts(files, config), - key = lambda post: post.config.date.created, - reverse = True - ) - - # Generate views for archive - if self.config.archive: - views = self._generate_archive(config, files) - self.blog.views.extend(views) - - # Generate views for categories - if self.config.categories: - views = self._generate_categories(config, files) - self.blog.views.extend(views) - - # Generate pages for views - if self.config.pagination: - for view in self._resolve_views(self.blog): - for page in self._generate_pages(view, config, files): - page.file.inclusion = InclusionLevel.EXCLUDED - view.pages.append(page) - - # Ensure that entrypoint is always included in navigation - self.blog.file.inclusion = InclusionLevel.INCLUDED - - # Attach posts and views to navigation (run later) - again, we allow other - # plugins to alter the navigation before we start to attach posts and views - # generated by this plugin at the correct locations in the navigation. Also, - # we make sure to correct links to the parent and siblings of each page. - @event_priority(-50) - def on_nav(self, nav, *, config, files): - if not self.config.enabled: - return - - # If we're not building a standalone blog, the entrypoint will always - # have a parent when it is included in the navigation. The parent is - # essential to correctly resolve the location where the archive and - # category views are attached. If the entrypoint doesn't have a parent, - # we know that the author did not include it in the navigation, so we - # explicitly mark it as not included. - if not self.blog.parent and self.config.blog_dir != ".": - self.blog.file.inclusion = InclusionLevel.NOT_IN_NAV - - # Attach posts to entrypoint without adding them to the navigation, so - # that the entrypoint is considered to be the active page for each post - self._attach(self.blog, [None, *reversed(self.blog.posts), None]) - for post in self.blog.posts: - post.file.inclusion = InclusionLevel.NOT_IN_NAV - - # Revert temporary exclusion of views from navigation - for view in self._resolve_views(self.blog): - for page in view.pages: - page.file.inclusion = self.blog.file.inclusion - - # Attach views for archive - if self.config.archive: - title = self._translate(self.config.archive_name, config) - views = [_ for _ in self.blog.views if isinstance(_, Archive)] - - # Attach and link views for archive - if self.blog.file.inclusion.is_in_nav(): - self._attach_to(self.blog, Section(title, views), nav) - - # Attach views for categories - if self.config.categories: - title = self._translate(self.config.categories_name, config) - views = [_ for _ in self.blog.views if isinstance(_, Category)] - - # Attach and link views for categories, if any - if self.blog.file.inclusion.is_in_nav() and views: - self._attach_to(self.blog, Section(title, views), nav) - - # Attach pages for views - if self.config.pagination: - for view in self._resolve_views(self.blog): - for at in range(1, len(view.pages)): - self._attach_at(view.parent, view, view.pages[at]) - - # Prepare post for rendering (run later) - allow other plugins to alter - # the contents or metadata of a post before it is rendered and make sure - # that the post includes a separator, which is essential for rendering - # excerpts that should be included in views - @event_priority(-50) - def on_page_markdown(self, markdown, *, page, config, files): - if not self.config.enabled: - return - - # Skip if page is not a post managed by this instance - this plugin has - # support for multiple instances, which is why this check is necessary - if page not in self.blog.posts: - if not self.config.pagination: - return - - # We set the contents of the view to its title if pagination should - # not keep the content of the original view on paginated views - if not self.config.pagination_keep_content: - view = self._resolve_original(page) - if view in self._resolve_views(self.blog): - - # If the current view is paginated, use the rendered title - # of the original view in case the author set the title in - # the page's contents, or it would be overridden with the - # one set in mkdocs.yml, leading to inconsistent headings - assert isinstance(view, View) - if view != page: - name = view._title_from_render or view.title - return f"# {name}" - - # Nothing more to be done for views - return - - # Extract and assign authors to post, if enabled - if self.config.authors: - for name in page.config.authors: - if name not in self.authors: - raise PluginError(f"Couldn't find author '{name}'") - - # Append to list of authors - page.authors.append(self.authors[name]) - - # Extract settings for excerpts - separator = self.config.post_excerpt_separator - max_authors = self.config.post_excerpt_max_authors - max_categories = self.config.post_excerpt_max_categories - - # Ensure presence of separator and throw, if its absent and required - - # we append the separator to the end of the contents of the post, if it - # is not already present, so we can remove footnotes or other content - # from the excerpt without affecting the content of the excerpt - if separator not in page.markdown: - path = page.file.src_path - if self.config.post_excerpt == "required": - raise PluginError( - f"Couldn't find '{separator}' separator in '{path}'" - ) - else: - page.markdown += f"\n\n{separator}" - - # Create excerpt for post and inherit authors and categories - excerpts - # can contain a subset of the authors and categories of the post - page.excerpt = Excerpt(page, config, files) - page.excerpt.authors = page.authors[:max_authors] - page.excerpt.categories = page.categories[:max_categories] - - # Process posts - def on_page_content(self, html, *, page, config, files): - if not self.config.enabled: - return - - # Skip if page is not a post managed by this instance - this plugin has - # support for multiple instances, which is why this check is necessary - if page not in self.blog.posts: - return - - # Compute readtime of post, if enabled and not explicitly set - if self.config.post_readtime: - words_per_minute = self.config.post_readtime_words_per_minute - if not page.config.readtime: - page.config.readtime = readtime(html, words_per_minute) - - # Register template filters for plugin - def on_env(self, env, *, config, files): - if not self.config.enabled: - return - - # Filter for formatting dates related to posts - def date_filter(date: datetime): - return self._format_date_for_post(date, config) - - # Register custom template filters - env.filters["date"] = date_filter - env.filters["url"] = url_filter - - # Prepare view for rendering (run latest) - views are rendered last, as we - # need to mutate the navigation to account for pagination. The main problem - # is that we need to replace the view in the navigation, because otherwise - # the view would not be considered active. - @event_priority(-100) - def on_page_context(self, context, *, page, config, nav): - if not self.config.enabled: - return - - # Skip if page is not a view managed by this instance - this plugin has - # support for multiple instances, which is why this check is necessary - view = self._resolve_original(page) - if view not in self._resolve_views(self.blog): - return - - # If the current view is paginated, replace and rewire it - the current - # view temporarily becomes the main view, and is reset after rendering - assert isinstance(view, View) - if view != page: - prev = view.pages[view.pages.index(page) - 1] - - # Replace previous page with current page - items = self._resolve_siblings(view, nav) - items[items.index(prev)] = page - - # Render excerpts and prepare pagination - posts, pagination = self._render(page) - - # Render pagination links - def pager(args: object): - return pagination.pager( - format = self.config.pagination_format, - show_if_single_page = self.config.pagination_if_single_page, - **args - ) - - # Assign posts and pagination to context - context["posts"] = posts - context["pagination"] = pager if pagination else None - - # After rendering a paginated view, replace the URL of the paginated view - # with the URL of the original view - since we need to replace the original - # view with a paginated view in `on_page_context` for correct resolution of - # the active state, we must fix the paginated view URLs after rendering - def on_post_page(self, output, *, page, config): - if not self.config.enabled: - return - - # Skip if page is not a view managed by this instance - this plugin has - # support for multiple instances, which is why this check is necessary - view = self._resolve_original(page) - if view not in self._resolve_views(self.blog): - return - - # If the current view is paginated, replace the URL of the paginated - # view with the URL of the original view - see https://t.ly/Yeh-P - assert isinstance(view, View) - if view != page: - page.file.url = view.file.url - - # Remove temporary directory on shutdown - def on_shutdown(self): - rmtree(self.temp_dir) - - # ------------------------------------------------------------------------- - - # Check if the given post is excluded - def _is_excluded(self, post: Post): - if self.config.draft: - return False - - # If a post was not explicitly marked or unmarked as draft, and the - # date should be taken into account, we automatically mark it as draft - # if the publishing date is in the future. This, of course, is opt-in - # and must be explicitly enabled by the author. - if not isinstance(post.config.draft, bool): - if self.config.draft_if_future_date: - return post.config.date.created > datetime.now() - - # Post might be a draft - return bool(post.config.draft) - - # ------------------------------------------------------------------------- - - # Resolve entrypoint - the entrypoint of the blog must have been created - # if it did not exist before, and hosts all posts sorted by descending date - def _resolve(self, files: Files, config: MkDocsConfig): - path = os.path.join(self.config.blog_dir, "index.md") - path = os.path.normpath(path) - - # Create entrypoint, if it does not exist - note that the entrypoint is - # created in the docs directory, not in the temporary directory - docs = os.path.relpath(config.docs_dir) - name = os.path.join(docs, path) - if not os.path.isfile(name): - file = self._path_to_file(path, config, temp = False) - files.append(file) - - # Create file in docs directory - self._save_to_file(file.abs_src_path, "# Blog\n\n") - - # Create and return entrypoint - file = files.get_file_from_path(path) - return View(None, file, config) - - # Resolve post - the caller must make sure that the given file points to an - # actual post (and not a page), or behavior might be unpredictable - def _resolve_post(self, file: File, config: MkDocsConfig): - post = Post(file, config) - - # Compute path and create a temporary file for path resolution - path = self._format_path_for_post(post, config) - temp = self._path_to_file(path, config, temp = False) - - # Replace destination file system path and URL - file.dest_uri = temp.dest_uri - file.abs_dest_path = temp.abs_dest_path - file.url = temp.url - - # Replace canonical URL and return post - post._set_canonical_url(config.site_url) - return post - - # Resolve posts from directory - traverse all documentation pages and filter - # and yield those that are located in the posts directory - def _resolve_posts(self, files: Files, config: MkDocsConfig): - path = self.config.post_dir.format(blog = self.config.blog_dir) - path = os.path.normpath(path) - - # Create posts directory, if it does not exist - docs = os.path.relpath(config.docs_dir) - name = os.path.join(docs, path) - if not os.path.isdir(name): - os.makedirs(name, exist_ok = True) - - # Filter posts from pages - for file in files.documentation_pages(): - if not file.src_path.startswith(path): - continue - - # Temporarily remove post from navigation - file.inclusion = InclusionLevel.EXCLUDED - - # Resolve post - in order to determine whether a post should be - # excluded, we must load it and analyze its metadata. All posts - # marked as drafts are excluded, except for when the author has - # configured drafts to be included in the navigation. - post = self._resolve_post(file, config) - if not self._is_excluded(post): - yield post - - # Resolve authors - check if there's an authors file at the configured - # location, and if one was found, load and validate it - def _resolve_authors(self, config: MkDocsConfig): - path = self.config.authors_file.format(blog = self.config.blog_dir) - path = os.path.normpath(path) - - # Resolve path relative to docs directory - docs = os.path.relpath(config.docs_dir) - file = os.path.join(docs, path) - - # If the authors file does not exist, return here - config: Authors = Authors() - if not os.path.isfile(file): - return config.authors - - # Open file and parse as YAML - with open(file, encoding = "utf-8") as f: - config.config_file_path = os.path.abspath(file) - try: - config.load_dict(yaml.load(f, SafeLoader) or {}) - - # The authors file could not be loaded because of a syntax error, - # which we display to the author with a nice error message - except Exception as e: - raise PluginError( - f"Error reading authors file '{path}' in '{docs}':\n" - f"{e}" - ) - - # Validate authors and throw if errors occurred - errors, warnings = config.validate() - if not config.authors and warnings: - log.warning( - f"Action required: the format of the authors file changed.\n" - f"All authors must now be located under the 'authors' key.\n" - f"Please adjust '{file}' to match:\n" - f"\n" - f"authors:\n" - f" squidfunk:\n" - f" avatar: https://avatars.githubusercontent.com/u/932156\n" - f" description: Creator\n" - f" name: Martin Donath\n" - f"\n" - ) - for _, w in warnings: - log.warning(w) - for _, e in errors: - raise PluginError( - f"Error reading authors file '{path}' in '{docs}':\n" - f"{e}" - ) - - # Return authors - return config.authors - - # Resolve views of the given view in pre-order - def _resolve_views(self, view: View): - yield view - - # Resolve views recursively - for page in view.views: - for next in self._resolve_views(page): - assert isinstance(next, View) - yield next - - # Resolve siblings of a navigation item - def _resolve_siblings(self, item: StructureItem, nav: Navigation): - if isinstance(item.parent, Section): - return item.parent.children - else: - return nav.items - - # Resolve original page or view (e.g. for paginated views) - def _resolve_original(self, page: Page): - if isinstance(page, View): - return page.pages[0] - else: - return page - - # ------------------------------------------------------------------------- - - # Generate views for archive - analyze posts and generate the necessary - # views, taking the date format provided by the author into account - def _generate_archive(self, config: MkDocsConfig, files: Files): - for post in self.blog.posts: - date = post.config.date.created - - # Compute name and path of archive view - name = self._format_date_for_archive(date, config) - path = self._format_path_for_archive(post, config) - - # Create file for view, if it does not exist - file = files.get_file_from_path(path) - if not file or self.temp_dir not in file.abs_src_path: - file = self._path_to_file(path, config) - files.append(file) - - # Create file in temporary directory - self._save_to_file(file.abs_src_path, f"# {name}") - - # Create and yield view - we don't explicitly set the title of - # the view, so authors can override them in the page's content - if not isinstance(file.page, Archive): - yield Archive(None, file, config) - - # Assign post to archive - assert isinstance(file.page, Archive) - file.page.posts.append(post) - - # Generate views for categories - analyze posts and generate the necessary - # views, taking the allowed categories as set by the author into account - def _generate_categories(self, config: MkDocsConfig, files: Files): - for post in self.blog.posts: - for name in post.config.categories: - path = self._format_path_for_category(name) - - # Ensure category is in non-empty allow list - categories = self.config.categories_allowed or [name] - if name not in categories: - docs = os.path.relpath(config.docs_dir) - path = os.path.relpath(post.file.abs_src_path, docs) - raise PluginError( - f"Error reading categories of post '{path}' in " - f"'{docs}': category '{name}' not in allow list" - ) - - # Create file for view, if it does not exist - file = files.get_file_from_path(path) - if not file or self.temp_dir not in file.abs_src_path: - file = self._path_to_file(path, config) - files.append(file) - - # Create file in temporary directory - self._save_to_file(file.abs_src_path, f"# {name}") - - # Create and yield view - we don't explicitly set the title of - # the view, so authors can override them in the page's content - if not isinstance(file.page, Category): - yield Category(None, file, config) - - # Assign post to category and vice versa - assert isinstance(file.page, Category) - file.page.posts.append(post) - post.categories.append(file.page) - - # Generate pages for pagination - analyze view and generate the necessary - # pages, creating a chain of views for simple rendering and replacement - def _generate_pages(self, view: View, config: MkDocsConfig, files: Files): - yield view - - # Compute pagination boundaries and create pages - pages are internally - # handled as copies of a view, as they map to the same source location - step = self.config.pagination_per_page - for at in range(step, len(view.posts), step): - path = self._format_path_for_pagination(view, 1 + at // step) - - # Create file for view, if it does not exist - file = files.get_file_from_path(path) - if not file or self.temp_dir not in file.abs_src_path: - file = self._path_to_file(path, config) - files.append(file) - - # Copy file to temporary directory - copy_file(view.file.abs_src_path, file.abs_src_path) - - # Create view and attach to previous page - if not isinstance(file.page, View): - yield View(None, file, config) - - # Assign pages and posts to view - assert isinstance(file.page, View) - file.page.pages = view.pages - file.page.posts = view.posts - - # ------------------------------------------------------------------------- - - # Attach a list of pages to each other and to the given parent item without - # explicitly adding them to the navigation, which can be done by the caller - def _attach(self, parent: StructureItem, pages: list[Page]): - for tail, page, head in zip(pages, pages[1:], pages[2:]): - - # Link page to parent and siblings - page.parent = parent - page.previous_page = tail - page.next_page = head - - # If the page is a view, we know that we generated it and need to - # link its siblings back to the view - if isinstance(page, View): - view = self._resolve_original(page) - if tail: tail.next_page = view - if head: head.previous_page = view - - # Attach a page to the given parent and link it to the previous and next - # page of the given host - this is exclusively used for paginated views - def _attach_at(self, parent: StructureItem, host: Page, page: Page): - self._attach(parent, [host.previous_page, page, host.next_page]) - - # Attach a section as a sibling to the given view, make sure its pages are - # part of the navigation, and ensure all pages are linked correctly - def _attach_to(self, view: View, section: Section, nav: Navigation): - section.parent = view.parent - - # Resolve siblings, which are the children of the parent section, or - # the top-level list of navigation items if the view is at the root of - # the project, and append the given section to it. It's currently not - # possible to chose the position of a section. - items = self._resolve_siblings(view, nav) - items.append(section) - - # Find last sibling that is a page, skipping sections, as we need to - # append the given section after all other pages - tail = next(item for item in reversed(items) if isinstance(item, Page)) - head = tail.next_page - - # Attach section to navigation and pages to each other - nav.pages.extend(section.children) - self._attach(section, [tail, *section.children, head]) - - # ------------------------------------------------------------------------- - - # Render excerpts and pagination for the given view - def _render(self, view: View): - posts, pagination = view.posts, None - - # Create pagination, if enabled - if self.config.pagination: - at = view.pages.index(view) - - # Compute pagination boundaries - step = self.config.pagination_per_page - p, q = at * step, at * step + step - - # Extract posts in pagination boundaries - posts = view.posts[p:q] - pagination = self._render_pagination(view, (p, q)) - - # Render excerpts for selected posts - posts = [ - self._render_post(post.excerpt, view) - for post in posts if post.excerpt - ] - - # Return posts and pagination - return posts, pagination - - # Render excerpt in the context of the given view - def _render_post(self, excerpt: Excerpt, view: View): - excerpt.render(view, self.config.post_excerpt_separator) - - # Determine whether to add posts to the table of contents of the view - - # note that those settings can be changed individually for each type of - # view, which is why we need to check the type of view and the table of - # contents setting for that type of view - toc = self.config.blog_toc - if isinstance(view, Archive): - toc = self.config.archive_toc - if isinstance(view, Category): - toc = self.config.categories_toc - - # Attach top-level table of contents item to view if it should be added - # and both, the view and excerpt contain table of contents items - if toc and excerpt.toc.items and view.toc.items: - view.toc.items[0].children.append(excerpt.toc.items[0]) - - # Return excerpt - return excerpt - - # Create pagination for the given view and range - def _render_pagination(self, view: View, range: tuple[int, int]): - p, q = range - - # Create URL from the given page to another page - def url_maker(n: int): - return get_relative_url(view.pages[n - 1].url, view.url) - - # Return pagination - return Pagination( - view.posts, page = q // (q - p), - items_per_page = q - p, - url_maker = url_maker - ) - - # ------------------------------------------------------------------------- - - # Format path for post - def _format_path_for_post(self, post: Post, config: MkDocsConfig): - categories = post.config.categories[:self.config.post_url_max_categories] - categories = [self._slugify_category(name) for name in categories] - - # Replace placeholders in format string - date = post.config.date.created - path = self.config.post_url_format.format( - categories = "/".join(categories), - date = self._format_date_for_post_url(date, config), - file = post.file.name, - slug = post.config.slug or self._slugify_post(post) - ) - - # Normalize path and strip slashes at the beginning and end - path = posixpath.normpath(path.strip("/")) - return posixpath.join(self.config.blog_dir, f"{path}.md") - - # Format path for archive - def _format_path_for_archive(self, post: Post, config: MkDocsConfig): - date = post.config.date.created - path = self.config.archive_url_format.format( - date = self._format_date_for_archive_url(date, config) - ) - - # Normalize path and strip slashes at the beginning and end - path = posixpath.normpath(path.strip("/")) - return posixpath.join(self.config.blog_dir, f"{path}.md") - - # Format path for category - def _format_path_for_category(self, name: str): - path = self.config.categories_url_format.format( - slug = self._slugify_category(name) - ) - - # Normalize path and strip slashes at the beginning and end - path = posixpath.normpath(path.strip("/")) - return posixpath.join(self.config.blog_dir, f"{path}.md") - - # Format path for pagination - def _format_path_for_pagination(self, view: View, page: int): - path = self.config.pagination_url_format.format( - page = page - ) - - # Compute base path for pagination - if the given view is an index file, - # we need to pop the file name from the base so it's not part of the URL - # and we need to append `index` to the path, so the paginated view is - # also an index page - see https://t.ly/71MKF - base, _ = posixpath.splitext(view.file.src_uri) - if view.is_index: - base = posixpath.dirname(base) - path = posixpath.join(path, "index") - - # Normalize path and strip slashes at the beginning and end - path = posixpath.normpath(path.strip("/")) - return posixpath.join(base, f"{path}.md") - - # ------------------------------------------------------------------------- - - # Format date - def _format_date(self, date: datetime, format: str, config: MkDocsConfig): - locale = config.theme["language"] - return format_date(date, format = format, locale = locale) - - # Format date for post - def _format_date_for_post(self, date: datetime, config: MkDocsConfig): - format = self.config.post_date_format - return self._format_date(date, format, config) - - # Format date for post URL - def _format_date_for_post_url(self, date: datetime, config: MkDocsConfig): - format = self.config.post_url_date_format - return self._format_date(date, format, config) - - # Format date for archive - def _format_date_for_archive(self, date: datetime, config: MkDocsConfig): - format = self.config.archive_date_format - return self._format_date(date, format, config) - - # Format date for archive URL - def _format_date_for_archive_url(self, date: datetime, config: MkDocsConfig): - format = self.config.archive_url_date_format - return self._format_date(date, format, config) - - # ------------------------------------------------------------------------- - - # Slugify post title - def _slugify_post(self, post: Post): - separator = self.config.post_slugify_separator - return self.config.post_slugify(post.title, separator) - - # Slugify category - def _slugify_category(self, name: str): - separator = self.config.categories_slugify_separator - return self.config.categories_slugify(name, separator) - - # ------------------------------------------------------------------------- - - # Create a file for the given path, which must point to a valid source file, - # either inside the temporary directory or the docs directory - def _path_to_file(self, path: str, config: MkDocsConfig, *, temp = True): - assert path.endswith(".md") - file = File( - path, - config.docs_dir if not temp else self.temp_dir, - config.site_dir, - config.use_directory_urls - ) - - # Hack: mark file as generated, so other plugins don't think it's part - # of the file system. This is more or less a new quasi-standard that - # still needs to be adopted by MkDocs, and was introduced by the - # git-revision-date-localized-plugin - see https://bit.ly/3ZUmdBx - if temp: - file.generated_by = "material/blog" - - # Return file - return file - - # Create a file with the given content on disk - def _save_to_file(self, path: str, content: str): - os.makedirs(os.path.dirname(path), exist_ok = True) - with open(path, "w", encoding = "utf-8") as f: - f.write(content) - - # ------------------------------------------------------------------------- - - # Translate the placeholder referenced by the given key - def _translate(self, key: str, config: MkDocsConfig) -> str: - env = config.theme.get_env() - template = env.get_template( - "partials/language.html", globals = { "config": config } - ) - - # Translate placeholder - return template.module.t(key) - -# ----------------------------------------------------------------------------- -# Data -# ----------------------------------------------------------------------------- - -# Set up logging -log = logging.getLogger("mkdocs.material.blog") diff --git a/src/plugins/blog/readtime/__init__.py b/src/plugins/blog/readtime/__init__.py deleted file mode 100644 index a0c149b9..00000000 --- a/src/plugins/blog/readtime/__init__.py +++ /dev/null @@ -1,51 +0,0 @@ -# Copyright (c) 2016-2023 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 re - -from math import ceil - -from .parser import ReadtimeParser - -# ----------------------------------------------------------------------------- -# Functions -# ----------------------------------------------------------------------------- - -# Compute readtime - we first used the original readtime library, but the list -# of dependencies it brings with it increased the size of the Docker image by -# 20 MB (packed), which is an increase of 50%. For this reason, we adapt the -# original readtime algorithm to our needs - see https://t.ly/fPZ7L -def readtime(html: str, words_per_minute: int): - parser = ReadtimeParser() - parser.feed(html) - parser.close() - - # Extract words from text and compute readtime in seconds - words = len(re.split(r"\W+", "".join(parser.text))) - seconds = ceil(words / words_per_minute * 60) - - # Account for additional images - delta = 12 - for _ in range(parser.images): - seconds += delta - if delta > 3: delta -= 1 - - # Return readtime in minutes - return ceil(seconds / 60) diff --git a/src/plugins/blog/readtime/parser.py b/src/plugins/blog/readtime/parser.py deleted file mode 100644 index b91a7b30..00000000 --- a/src/plugins/blog/readtime/parser.py +++ /dev/null @@ -1,45 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from html.parser import HTMLParser - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Readtime parser -class ReadtimeParser(HTMLParser): - - # Initialize parser - def __init__(self): - super().__init__(convert_charrefs = True) - - # Keep track of text and images - self.text = [] - self.images = 0 - - # Collect images - def handle_starttag(self, tag, attrs): - if tag == "img": - self.images += 1 - - # Collect text - def handle_data(self, data): - self.text.append(data) diff --git a/src/plugins/blog/structure/__init__.py b/src/plugins/blog/structure/__init__.py deleted file mode 100644 index 2fc541fe..00000000 --- a/src/plugins/blog/structure/__init__.py +++ /dev/null @@ -1,292 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from __future__ import annotations - -import logging -import os -import yaml - -from copy import copy -from markdown import Markdown -from material.plugins.blog.author import Author -from mkdocs.config.defaults import MkDocsConfig -from mkdocs.exceptions import PluginError -from mkdocs.structure.files import File, Files -from mkdocs.structure.nav import Section -from mkdocs.structure.pages import Page, _RelativePathTreeprocessor -from mkdocs.structure.toc import get_toc -from mkdocs.utils.meta import YAML_RE -from re import Match -from yaml import SafeLoader - -from .config import PostConfig -from .markdown import ExcerptTreeprocessor - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Post -class Post(Page): - - # Initialize post - posts are never listed in the navigation, which is why - # they will never include a title that was manually set, so we can omit it - def __init__(self, file: File, config: MkDocsConfig): - super().__init__(None, file, config) - - # Resolve path relative to docs directory - docs = os.path.relpath(config.docs_dir) - path = os.path.relpath(file.abs_src_path, docs) - - # Read contents and metadata immediately - with open(file.abs_src_path, encoding = "utf-8") as f: - self.markdown = f.read() - - # Sadly, MkDocs swallows any exceptions that occur during parsing. - # As we want to provide the best possible authoring experience, we - # need to catch errors early and display them nicely. We decided to - # drop support for MkDocs' MultiMarkdown syntax, because it is not - # correctly implemented anyway. When using MultiMarkdown syntax, all - # date formats are returned as strings and list are not properly - # supported. Thus, we just use the relevants parts of `get_data`. - match: Match = YAML_RE.match(self.markdown) - if not match: - raise PluginError( - f"Error reading metadata of post '{path}' in '{docs}':\n" - f"Expected metadata to be defined but found nothing" - ) - - # Extract metadata and parse as YAML - try: - self.meta = yaml.load(match.group(1), SafeLoader) or {} - self.markdown = self.markdown[match.end():].lstrip("\n") - - # The post's metadata could not be parsed because of a syntax error, - # which we display to the user with a nice error message - except Exception as e: - raise PluginError( - f"Error reading metadata of post '{path}' in '{docs}':\n" - f"{e}" - ) - - # Initialize post configuration, but remove all keys that this plugin - # doesn't care about, or they will be reported as invalid configuration - self.config: PostConfig = PostConfig(file.abs_src_path) - self.config.load_dict({ - key: self.meta[key] for key in ( - set(self.meta.keys()) & - set(self.config.keys()) - ) - }) - - # Validate configuration and throw if errors occurred - errors, warnings = self.config.validate() - for _, w in warnings: - log.warning(w) - for k, e in errors: - raise PluginError( - f"Error reading metadata '{k}' of post '{path}' in '{docs}':\n" - f"{e}" - ) - - # Excerpts are subsets of posts that are used in pages like archive and - # category views. They are not rendered as standalone pages, but are - # rendered in the context of a view. Each post has a dedicated excerpt - # instance which is reused when rendering views. - self.excerpt: Excerpt = None - - # Initialize authors and actegories - self.authors: list[Author] = [] - self.categories: list[Category] = [] - - # Ensure template is set or use default - self.meta.setdefault("template", "blog-post.html") - - # Ensure template hides navigation - self.meta["hide"] = self.meta.get("hide", []) - if "navigation" not in self.meta["hide"]: - self.meta["hide"].append("navigation") - - # The contents and metadata were already read in the constructor (and not - # in `read_source` as for pages), so this function must be set to a no-op - def read_source(self, config: MkDocsConfig): - pass - -# ----------------------------------------------------------------------------- - -# Excerpt -class Excerpt(Page): - - # Initialize an excerpt for the given post - we create the Markdown parser - # when intitializing the excerpt in order to improve rendering performance - # for excerpts, as they are reused across several different views, because - # posts might be referenced from multiple different locations - def __init__(self, post: Post, config: MkDocsConfig, files: Files): - self.file = copy(post.file) - self.post = post - - # Set canonical URL, or we can't print excerpts when debugging the - # blog plugin, as the `abs_url` property would be missing - self._set_canonical_url(config.site_url) - - # Initialize configuration and metadata - self.config = post.config - self.meta = post.meta - - # Initialize authors and categories - note that views usually contain - # subsets of those lists, which is why we need to manage them here - self.authors: list[Author] = [] - self.categories: list[Category] = [] - - # Initialize parser - note that we need to patch the configuration, - # more specifically the table of contents extension - config = _patch(config) - self.md = Markdown( - extensions = config.markdown_extensions, - extension_configs = config.mdx_configs, - ) - - # Register excerpt tree processor - this processor resolves anchors to - # posts from within views, so they point to the correct location - self.md.treeprocessors.register( - ExcerptTreeprocessor(post), - "excerpt", - 0 - ) - - # Register relative path tree processor - this processor resolves links - # to other pages and assets, and is used by MkDocs itself - self.md.treeprocessors.register( - _RelativePathTreeprocessor(self.file, files, config), - "relpath", - 1 - ) - - # Render an excerpt of the post on the given page - note that this is not - # thread-safe because excerpts are shared across views, as it cuts down on - # the cost of initialization. However, if in the future, we decide to render - # posts and views concurrently, we must change this behavior. - def render(self, page: Page, separator: str): - self.file.url = page.url - - # Retrieve excerpt tree processor and set page as base - at = self.md.treeprocessors.get_index_for_name("excerpt") - processor: ExcerptTreeprocessor = self.md.treeprocessors[at] - processor.base = page - - # Ensure that the excerpt includes a title in its content, since the - # title is linked to the post when rendering - see https://t.ly/5Gg2F - self.markdown = self.post.markdown - if not self.post._title_from_render: - self.markdown = "\n\n".join([f"# {self.post.title}", self.markdown]) - - # Convert Markdown to HTML and extract excerpt - self.content = self.md.convert(self.markdown) - self.content, *_ = self.content.split(separator, 1) - - # Extract table of contents and reset post URL - if we wouldn't reset - # the excerpt URL, linking to the excerpt from the view would not work - self.toc = get_toc(getattr(self.md, "toc_tokens", [])) - self.file.url = self.post.url - -# ----------------------------------------------------------------------------- - -# View -class View(Page): - - # Initialize view - def __init__(self, title: str | None, file: File, config: MkDocsConfig): - super().__init__(title, file, config) - self.parent: View | Section - - # Initialize posts and views - self.posts: list[Post] = [] - self.views: list[View] = [] - - # Initialize pages for pagination - self.pages: list[View] = [] - - # Set necessary metadata - def read_source(self, config: MkDocsConfig): - super().read_source(config) - - # Ensure template is set or use default - self.meta.setdefault("template", "blog.html") - -# ----------------------------------------------------------------------------- - -# Archive view -class Archive(View): - pass - -# ----------------------------------------------------------------------------- - -# Category view -class Category(View): - pass - -# ----------------------------------------------------------------------------- -# Helper functions -# ----------------------------------------------------------------------------- - -# Patch configuration -def _patch(config: MkDocsConfig): - config = copy(config) - - # Copy parts of configuration that needs to be patched - config.validation = copy(config.validation) - config.validation.links = copy(config.validation.links) - config.markdown_extensions = copy(config.markdown_extensions) - config.mdx_configs = copy(config.mdx_configs) - - # Make sure that the author did not add another instance of the table of - # contents extension to the configuration, as this leads to weird behavior - if "markdown.extensions.toc" in config.markdown_extensions: - config.markdown_extensions.remove("markdown.extensions.toc") - - # In order to render excerpts for posts, we need to make sure that the - # table of contents extension is appropriately configured - config.mdx_configs["toc"] = { - **config.mdx_configs.get("toc", {}), - **{ - "anchorlink": True, # Render headline as clickable - "baselevel": 2, # Render h1 as h2 and so forth - "permalink": False, # Remove permalinks - "toc_depth": 2 # Remove everything below h2 - } - } - - # Additionally, we disable link validation when rendering excerpts, because - # invalid links have already been reported when rendering the page - links = config.validation.links - links.not_found = logging.DEBUG - links.absolute_links = logging.DEBUG - links.unrecognized_links = logging.DEBUG - - # Return patched configuration - return config - -# ----------------------------------------------------------------------------- -# Data -# ----------------------------------------------------------------------------- - -# Set up logging -log = logging.getLogger("mkdocs.material.blog") diff --git a/src/plugins/blog/structure/config.py b/src/plugins/blog/structure/config.py deleted file mode 100644 index 129491b9..00000000 --- a/src/plugins/blog/structure/config.py +++ /dev/null @@ -1,37 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from mkdocs.config.base import Config -from mkdocs.config.config_options import ListOfItems, Optional, Type - -from .options import PostDate - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Post configuration -class PostConfig(Config): - authors = ListOfItems(Type(str), default = []) - categories = ListOfItems(Type(str), default = []) - date = PostDate() - draft = Optional(Type(bool)) - readtime = Optional(Type(int)) - slug = Optional(Type(str)) diff --git a/src/plugins/blog/structure/markdown.py b/src/plugins/blog/structure/markdown.py deleted file mode 100644 index 64ade554..00000000 --- a/src/plugins/blog/structure/markdown.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from markdown.treeprocessors import Treeprocessor -from mkdocs.structure.pages import Page -from mkdocs.utils import get_relative_url -from xml.etree.ElementTree import Element - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Excerpt tree processor -class ExcerptTreeprocessor(Treeprocessor): - - # Initialize excerpt tree processor - def __init__(self, page: Page, base: Page = None): - self.page = page - self.base = base - - # Transform HTML after Markdown processing - def run(self, root: Element): - main = True - - # We're only interested in anchors, which is why we continue when the - # link does not start with an anchor tag - for el in root.iter("a"): - anchor = el.get("href") - if not anchor.startswith("#"): - continue - - # The main headline should link to the post page, not to a specific - # anchor, which is why we remove the anchor in that case - path = get_relative_url(self.page.url, self.base.url) - if main: - el.set("href", path) - else: - el.set("href", path + anchor) - - # Main headline has been seen - main = False diff --git a/src/plugins/blog/structure/options.py b/src/plugins/blog/structure/options.py deleted file mode 100644 index 281dec9f..00000000 --- a/src/plugins/blog/structure/options.py +++ /dev/null @@ -1,87 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from datetime import date, datetime, time -from mkdocs.config.base import BaseConfigOption, Config, ValidationError -from typing import Dict - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Date dictionary -class DateDict(Dict[str, datetime]): - - # Initialize date dictionary - def __init__(self, data: dict): - super().__init__(data) - - # Ensure presence of `date.created` - self.created: datetime = data["created"] - - # Allow attribute access - def __getattr__(self, name: str): - if name in self: - return self[name] - -# ----------------------------------------------------------------------------- - -# Post date option -class PostDate(BaseConfigOption[DateDict]): - - # Initialize post dates - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - # Normalize the supported types for post dates to datetime - def pre_validation(self, config: Config, key_name: str): - - # If the date points to a scalar value, convert it to a dictionary, - # since we want to allow the user to specify custom and arbitrary date - # values for posts. Currently, only the `created` date is mandatory, - # because it's needed to sort posts for views. - if not isinstance(config[key_name], dict): - config[key_name] = { "created": config[key_name] } - - # Convert all date values to datetime - for key, value in config[key_name].items(): - if isinstance(value, date): - config[key_name][key] = datetime.combine(value, time()) - - # Initialize date dictionary - config[key_name] = DateDict(config[key_name]) - - # Ensure each date value is of type datetime - def run_validation(self, value: DateDict): - for key in value: - if not isinstance(value[key], datetime): - raise ValidationError( - f"Expected type: {date} or {datetime} " - f"but received: {type(value[key])}" - ) - - # Ensure presence of `date.created` - if not value.created: - raise ValidationError( - "Expected 'created' date when using dictionary syntax" - ) - - # Return date dictionary - return value diff --git a/src/plugins/blog/templates/__init__.py b/src/plugins/blog/templates/__init__.py deleted file mode 100644 index 9f7d794b..00000000 --- a/src/plugins/blog/templates/__init__.py +++ /dev/null @@ -1,42 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from jinja2 import pass_context -from jinja2.runtime import Context -from material.plugins.blog.structure import View -from mkdocs.utils.templates import url_filter as _url_filter - -# ----------------------------------------------------------------------------- -# Functions -# ----------------------------------------------------------------------------- - -# Filter for normalizing URLs with support for paginated views -@pass_context -def url_filter(context: Context, url: str): - page = context["page"] - - # If the current page is a view, check if the URL links to the page - # itself, and replace it with the URL of the main view - if isinstance(page, View): - if page.url == url: - url = page.pages[0].url - - # Forward to original template filter - return _url_filter(context, url) diff --git a/src/plugins/group/__init__.py b/src/plugins/group/__init__.py deleted file mode 100644 index d1899378..00000000 --- a/src/plugins/group/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2016-2023 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. diff --git a/src/plugins/group/config.py b/src/plugins/group/config.py deleted file mode 100644 index fb19222a..00000000 --- a/src/plugins/group/config.py +++ /dev/null @@ -1,33 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from __future__ import annotations - -from mkdocs.config.config_options import Type -from mkdocs.config.base import Config - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Group plugin configuration -class GroupConfig(Config): - enabled = Type(bool, default = False) - plugins = Type(list | dict) diff --git a/src/plugins/group/plugin.py b/src/plugins/group/plugin.py deleted file mode 100644 index 4ab13dbf..00000000 --- a/src/plugins/group/plugin.py +++ /dev/null @@ -1,151 +0,0 @@ -# Copyright (c) 2016-2023 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 logging - -from collections.abc import Callable -from mkdocs.config.config_options import Plugins -from mkdocs.config.defaults import MkDocsConfig -from mkdocs.exceptions import PluginError -from mkdocs.plugins import BasePlugin, event_priority - -from .config import GroupConfig - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Group plugin -class GroupPlugin(BasePlugin[GroupConfig]): - supports_multiple_instances = True - - # Determine whether we're serving the site - def on_startup(self, *, command, dirty): - self.is_serve = command == "serve" - self.is_dirty = dirty - - # If the group is enabled, conditionally load plugins - at first, this might - # sound easier than it actually is, as we need to jump through some hoops to - # ensure correct ordering among plugins. We're effectively initializing the - # plugins that are part of the group after all MkDocs finished initializing - # all other plugins, so we need to patch the order of the methods. Moreover, - # we must use MkDocs existing plugin collection, or we might have collisions - # with other plugins that are not part of the group. As so often, this is a - # little hacky, but has huge potential making plugin configuration easier. - # There's one little caveat: the `__init__` and `on_startup` methods of the - # plugins that are part of the group are called after all other plugins, so - # the `event_priority` decorator for `on_startup` events and is effectively - # useless. However, the `on_startup` event is only intended to set up the - # plugin and doesn't receive anything else than the invoked command and - # whether we're running a dirty build, so there should be no problems. - @event_priority(150) - def on_config(self, config): - if not self.config.enabled: - return - - # Retrieve plugin collection from configuration - option: Plugins = dict(config._schema)["plugins"] - assert isinstance(option, Plugins) - - # Load all plugins in group - self.plugins: dict[str, BasePlugin] = {} - try: - for name, plugin in self._load(option): - self.plugins[name] = plugin - - # The plugin could not be loaded, likely because it's not installed or - # misconfigured, so we raise a plugin error for a nicer error message - except Exception as e: - raise PluginError(str(e)) - - # Patch order of plugin methods - for events in option.plugins.events.values(): - self._patch(events, config) - - # Invoke `on_startup` event for plugins in group - command = "serve" if self.is_serve else "build" - for method in option.plugins.events["startup"]: - plugin = self._get_plugin(method) - - # Ensure that we have a method bound to a plugin (and not a hook) - if plugin and plugin in self.plugins.values(): - method(command = command, dirty = self.is_dirty) - - # ------------------------------------------------------------------------- - - # Retrieve plugin instance for bound method or nothing - def _get_plugin(self, method: Callable): - return getattr(method, "__self__", None) - - # Retrieve priority of plugin method - def _get_priority(self, method: Callable): - return getattr(method, "mkdocs_priority", 0) - - # Retrieve position of plugin - def _get_position(self, plugin: BasePlugin, config: MkDocsConfig) -> int: - for at, (_, candidate) in enumerate(config.plugins.items()): - if plugin == candidate: - return at - - # ------------------------------------------------------------------------- - - # Load plugins that are part of the group - def _load(self, option: Plugins): - for name, data in option._parse_configs(self.config.plugins): - yield option.load_plugin_with_namespace(name, data) - - # ------------------------------------------------------------------------- - - # Patch order of plugin methods - all other plugin methods are already in - # the right order, so we only need to check those that are part of the group - # and bubble them up into the right location. Some plugin methods may define - # priorities, so we need to make sure to order correctly within those. - def _patch(self, methods: list[Callable], config: MkDocsConfig): - position = self._get_position(self, config) - for at in reversed(range(1, len(methods))): - tail = methods[at - 1] - head = methods[at] - - # Skip if the plugin is not part of the group - plugin = self._get_plugin(head) - if not plugin or plugin not in self.plugins.values(): - continue - - # Skip if the previous method has a higher priority than the current - # one, because we know we can't swap them anyway - if self._get_priority(tail) > self._get_priority(head): - continue - - # Ensure that we have a method bound to a plugin (and not a hook) - plugin = self._get_plugin(tail) - if not plugin: - continue - - # Both methods have the same priority, so we check if the ordering - # of both methods is violated, and if it is, swap them - if (position < self._get_position(plugin, config)): - methods[at], methods[at - 1] = tail, head - -# ----------------------------------------------------------------------------- -# Data -# ----------------------------------------------------------------------------- - -# Set up logging -log = logging.getLogger("mkdocs.material.group") diff --git a/src/plugins/info/__init__.py b/src/plugins/info/__init__.py deleted file mode 100644 index d1899378..00000000 --- a/src/plugins/info/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2016-2023 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. diff --git a/src/plugins/info/config.py b/src/plugins/info/config.py deleted file mode 100644 index cbd64d4c..00000000 --- a/src/plugins/info/config.py +++ /dev/null @@ -1,35 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from mkdocs.config.config_options import Type -from mkdocs.config.base import Config - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Info plugin configuration -class InfoConfig(Config): - enabled = Type(bool, default = True) - enabled_on_serve = Type(bool, default = False) - - # Settings for archive - archive = Type(bool, default = True) - archive_stop_on_violation = Type(bool, default = True) diff --git a/src/plugins/info/plugin.py b/src/plugins/info/plugin.py deleted file mode 100644 index 7c6fdc17..00000000 --- a/src/plugins/info/plugin.py +++ /dev/null @@ -1,245 +0,0 @@ -# Copyright (c) 2016-2023 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 json -import logging -import os -import platform -import requests -import sys - -from colorama import Fore, Style -from importlib.metadata import distributions, version -from io import BytesIO -from markdown.extensions.toc import slugify -from mkdocs.plugins import BasePlugin, event_priority -from mkdocs.structure.files import get_files -from mkdocs.utils import get_theme_dir -from zipfile import ZipFile, ZIP_DEFLATED - -from .config import InfoConfig - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Info plugin -class InfoPlugin(BasePlugin[InfoConfig]): - - # Initialize plugin - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - # Initialize incremental builds - self.is_serve = False - - # Determine whether we're serving the site - def on_startup(self, *, command, dirty): - self.is_serve = command == "serve" - - # Create a self-contained example (run earliest) - determine all files that - # are visible to MkDocs and are used to build the site, create an archive - # that contains all of them, and print a summary of the archive contents. - # The user must attach this archive to the bug report. - @event_priority(100) - def on_config(self, config): - if not self.config.enabled: - return - - # By default, the plugin is disabled when the documentation is served, - # but not when it is built. This should nicely align with the expected - # user experience when creating reproductions. - if not self.config.enabled_on_serve and self.is_serve: - return - - # Resolve latest version - url = "https://github.com/squidfunk/mkdocs-material/releases/latest" - res = requests.get(url, allow_redirects = False) - - # Check if we're running the latest version - _, current = res.headers.get("location").rsplit("/", 1) - present = version("mkdocs-material") - if not present.startswith(current): - log.error("Please upgrade to the latest version.") - self._help_on_versions_and_exit(present, current) - - # Exit if archive creation is disabled - if not self.config.archive: - sys.exit(1) - - # Print message that we're creating a bug report - log.info("Started archive creation for bug report") - - # Check that there are no overrides in place - we need to use a little - # hack to detect whether the custom_dir setting was used without parsing - # mkdocs.yml again - we check at which position the directory provided - # by the theme resides, and if it's not the first one, abort. - if config.theme.dirs.index(get_theme_dir(config.theme.name)): - log.error("Please remove 'custom_dir' setting.") - self._help_on_customizations_and_exit() - - # Check that there are no hooks in place - hooks can alter the behavior - # of MkDocs in unpredictable ways, which is why they must be considered - # being customizations. Thus, we can't offer support for debugging and - # must abort here. - if config.hooks: - log.error("Please remove 'hooks' setting.") - self._help_on_customizations_and_exit() - - # Create in-memory archive and prompt user to enter a short descriptive - # name for the archive, which is also used as the directory name. Note - # that the name is slugified for better readability and stripped of any - # file extension that the user might have entered. - archive = BytesIO() - example = input("\nPlease name your bug report (2-4 words): ") - example, _ = os.path.splitext(example) - example = "-".join([present, slugify(example, "-")]) - - # Create self-contained example from project - files: list[str] = [] - with ZipFile(archive, "a", ZIP_DEFLATED, False) as f: - for path in ["mkdocs.yml", "requirements.txt"]: - if os.path.isfile(path): - f.write(path, os.path.join(example, path)) - - # Append all files visible to MkDocs - for file in get_files(config): - path = os.path.relpath(file.abs_src_path, os.path.curdir) - f.write(path, os.path.join(example, path)) - - # Add information on installed packages - f.writestr( - os.path.join(example, "requirements.lock.txt"), - "\n".join(sorted([ - "==".join([package.name, package.version]) - for package in distributions() - ])) - ) - - # Add information on platform - f.writestr( - os.path.join(example, "platform.json"), - json.dumps( - { - "system": platform.platform(), - "python": platform.python_version() - }, - default = str, - indent = 2 - ) - ) - - # Retrieve list of processed files - for a in f.filelist: - files.append("".join([ - Fore.LIGHTBLACK_EX, a.filename, " ", - _size(a.compress_size) - ])) - - # Finally, write archive to disk - buffer = archive.getbuffer() - with open(f"{example}.zip", "wb") as f: - f.write(archive.getvalue()) - - # Print summary - log.info("Archive successfully created:") - print(Style.NORMAL) - - # Print archive file names - files.sort() - for file in files: - print(f" {file}") - - # Print archive name - print(Style.RESET_ALL) - print("".join([ - " ", f.name, " ", - _size(buffer.nbytes, 10) - ])) - - # Print warning when file size is excessively large - print(Style.RESET_ALL) - if buffer.nbytes > 1000000: - log.warning("Archive exceeds recommended maximum size of 1 MB") - - # Aaaaaand done - sys.exit(1) - - # ------------------------------------------------------------------------- - - # Print help on versions and exit - def _help_on_versions_and_exit(self, have, need): - print(Fore.RED) - print(" When reporting issues, please first upgrade to the latest") - print(" version of Material for MkDocs, as the problem might already") - print(" be fixed in the latest version. This helps reduce duplicate") - print(" efforts and saves us maintainers time.") - print(Style.NORMAL) - print(f" Please update from {have} to {need}.") - print(Style.RESET_ALL) - print(f" pip install --upgrade --force-reinstall mkdocs-material") - print(Style.NORMAL) - - # Exit, unless explicitly told not to - if self.config.archive_stop_on_violation: - sys.exit(1) - - # Print help on customizations and exit - def _help_on_customizations_and_exit(self): - print(Fore.RED) - print(" When reporting issues, you must remove all customizations") - print(" and check if the problem persists. If not, the problem is") - print(" caused by your overrides. Please understand that we can't") - print(" help you debug your customizations. Please remove:") - print(Style.NORMAL) - print(" - theme.custom_dir") - print(" - hooks") - print(Fore.YELLOW) - print(" Additionally, please remove all third-party JavaScript or") - print(" CSS not explicitly mentioned in our documentation:") - print(Style.NORMAL) - print(" - extra_css") - print(" - extra_javascript") - print(Style.RESET_ALL) - - # Exit, unless explicitly told not to - if self.config.archive_stop_on_violation: - sys.exit(1) - -# ----------------------------------------------------------------------------- -# Helper functions -# ----------------------------------------------------------------------------- - -# Print human-readable size -def _size(value, factor = 1): - color = Fore.GREEN - if value > 100000 * factor: color = Fore.RED - elif value > 25000 * factor: color = Fore.YELLOW - for unit in ["B", "kB", "MB", "GB", "TB", "PB", "EB", "ZB"]: - if abs(value) < 1000.0: - return f"{color}{value:3.1f} {unit}" - value /= 1000.0 - -# ----------------------------------------------------------------------------- -# Data -# ----------------------------------------------------------------------------- - -# Set up logging -log = logging.getLogger("mkdocs.material.info") diff --git a/src/plugins/offline/__init__.py b/src/plugins/offline/__init__.py deleted file mode 100644 index d1899378..00000000 --- a/src/plugins/offline/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2016-2023 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. diff --git a/src/plugins/offline/config.py b/src/plugins/offline/config.py deleted file mode 100644 index 49f51a94..00000000 --- a/src/plugins/offline/config.py +++ /dev/null @@ -1,30 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from mkdocs.config.config_options import Type -from mkdocs.config.base import Config - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Offline plugin configuration -class OfflineConfig(Config): - enabled = Type(bool, default = True) diff --git a/src/plugins/offline/plugin.py b/src/plugins/offline/plugin.py deleted file mode 100644 index abcb2598..00000000 --- a/src/plugins/offline/plugin.py +++ /dev/null @@ -1,69 +0,0 @@ -# Copyright (c) 2016-2023 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 os - -from mkdocs.plugins import BasePlugin, event_priority - -from .config import OfflineConfig - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Offline plugin -class OfflinePlugin(BasePlugin[OfflineConfig]): - - # Set configuration for offline build - def on_config(self, config): - if not self.config.enabled: - return - - # Ensure correct resolution of links when viewing the site from the - # file system by disabling directory URLs - config.use_directory_urls = False - - # Append iframe-worker to polyfills/shims - config.extra["polyfills"] = config.extra.get("polyfills", []) - if not any("iframe-worker" in url for url in config.extra["polyfills"]): - script = "https://unpkg.com/iframe-worker/shim" - config.extra["polyfills"].append(script) - - # Add support for offline search (run latest) - the search index is copied - # and inlined into a script, so that it can be used without a server - @event_priority(-100) - def on_post_build(self, *, config): - if not self.config.enabled: - return - - # Ensure presence of search index - path = os.path.join(config.site_dir, "search") - file = os.path.join(path, "search_index.json") - if not os.path.isfile(file): - return - - # Obtain search index contents - with open(file, encoding = "utf-8") as f: - data = f.read() - - # Inline search index contents into script - file = os.path.join(path, "search_index.js") - with open(file, "w", encoding = "utf-8") as f: - f.write(f"var __index = {data}") diff --git a/src/plugins/search/__init__.py b/src/plugins/search/__init__.py deleted file mode 100644 index d1899378..00000000 --- a/src/plugins/search/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2016-2023 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. diff --git a/src/plugins/search/config.py b/src/plugins/search/config.py deleted file mode 100644 index e150fbb3..00000000 --- a/src/plugins/search/config.py +++ /dev/null @@ -1,58 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from mkdocs.config.config_options import ( - Choice, - Deprecated, - Optional, - ListOfItems, - Type -) -from mkdocs.config.base import Config -from mkdocs.contrib.search import LangOption - -# ----------------------------------------------------------------------------- -# Options -# ----------------------------------------------------------------------------- - -# Options for search pipeline -pipeline = ("stemmer", "stopWordFilter", "trimmer") - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Search plugin configuration -class SearchConfig(Config): - enabled = Type(bool, default = True) - - # Settings for search - lang = Optional(LangOption()) - separator = Optional(Type(str)) - pipeline = ListOfItems(Choice(pipeline), default = []) - - # Settings for text segmentation (Chinese) - jieba_dict = Optional(Type(str)) - jieba_dict_user = Optional(Type(str)) - - # Unsupported settings, originally implemented in MkDocs - indexing = Deprecated(message = "Unsupported option") - prebuild_index = Deprecated(message = "Unsupported option") - min_search_length = Deprecated(message = "Unsupported option") diff --git a/src/plugins/search/plugin.py b/src/plugins/search/plugin.py deleted file mode 100644 index 5c254e3f..00000000 --- a/src/plugins/search/plugin.py +++ /dev/null @@ -1,580 +0,0 @@ -# Copyright (c) 2016-2023 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 json -import logging -import os -import regex as re - -from html import escape -from html.parser import HTMLParser -from mkdocs import utils -from mkdocs.plugins import BasePlugin - -from .config import SearchConfig - -try: - import jieba -except ImportError: - jieba = None - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Search plugin -class SearchPlugin(BasePlugin[SearchConfig]): - - # Initialize plugin - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - # Initialize incremental builds - self.is_dirtyreload = False - - # Initialize search index cache - self.search_index_prev = None - - # Determine whether we're serving the site - def on_startup(self, *, command, dirty): - self.is_dirty = dirty - - # Initialize plugin - def on_config(self, config): - if not self.config.enabled: - return - - # Retrieve default value for language - if not self.config.lang: - self.config.lang = [self._translate( - config, "search.config.lang" - )] - - # Retrieve default value for separator - if not self.config.separator: - self.config.separator = self._translate( - config, "search.config.separator" - ) - - # Retrieve default value for pipeline - if not self.config.pipeline: - self.config.pipeline = list(filter(len, re.split( - r"\s*,\s*", self._translate(config, "search.config.pipeline") - ))) - - # Initialize search index - self.search_index = SearchIndex(**self.config) - - # Set jieba dictionary, if given - if self.config.jieba_dict: - path = os.path.normpath(self.config.jieba_dict) - if os.path.isfile(path): - jieba.set_dictionary(path) - log.debug(f"Loading jieba dictionary: {path}") - else: - log.warning( - f"Configuration error for 'search.jieba_dict': " - f"'{self.config.jieba_dict}' does not exist." - ) - - # Set jieba user dictionary, if given - if self.config.jieba_dict_user: - path = os.path.normpath(self.config.jieba_dict_user) - if os.path.isfile(path): - jieba.load_userdict(path) - log.debug(f"Loading jieba user dictionary: {path}") - else: - log.warning( - f"Configuration error for 'search.jieba_dict_user': " - f"'{self.config.jieba_dict_user}' does not exist." - ) - - # Add page to search index - def on_page_context(self, context, *, page, config, nav): - if not self.config.enabled: - return - - # Index page - self.search_index.add_entry_from_context(page) - page.content = re.sub( - r"\s?data-search-\w+=\"[^\"]+\"", - "", - page.content - ) - - # Generate search index - def on_post_build(self, *, config): - if not self.config.enabled: - return - - # Write search index - base = os.path.join(config.site_dir, "search") - path = os.path.join(base, "search_index.json") - - # Generate and write search index to file - data = self.search_index.generate_search_index(self.search_index_prev) - utils.write_file(data.encode("utf-8"), path) - - # Persist search index for repeated invocation - if self.is_dirty: - self.search_index_prev = self.search_index - - # Determine whether we're running under dirty reload - def on_serve(self, server, *, config, builder): - self.is_dirtyreload = self.is_dirty - - # ------------------------------------------------------------------------- - - # Translate the given placeholder value - def _translate(self, config, value): - env = config.theme.get_env() - - # Load language template and return translation for placeholder - language = "partials/language.html" - template = env.get_template(language, None, { "config": config }) - return template.module.t(value) - -# ----------------------------------------------------------------------------- - -# Search index with support for additional fields -class SearchIndex: - - # Initialize search index - def __init__(self, **config): - self.config = config - self.entries = [] - - # Add page to search index - def add_entry_from_context(self, page): - search = page.meta.get("search", {}) - if search.get("exclude"): - return - - # Divide page content into sections - parser = Parser() - parser.feed(page.content) - parser.close() - - # Add sections to index - for section in parser.data: - if not section.is_excluded(): - self.create_entry_for_section(section, page.toc, page.url, page) - - # Override: graceful indexing and additional fields - def create_entry_for_section(self, section, toc, url, page): - item = self._find_toc_by_id(toc, section.id) - if item: - url = url + item.url - elif section.id: - url = url + "#" + section.id - - # Set page title as section title if none was given, which happens when - # the first headline in a Markdown document is not a h1 headline. Also, - # if a page title was set via front matter, use that even though a h1 - # might be given or the page name was specified in nav in mkdocs.yml - if not section.title: - section.title = [str(page.meta.get("title", page.title))] - - # Compute title and text - title = "".join(section.title).strip() - text = "".join(section.text).strip() - - # Segment Chinese characters if jieba is available - if jieba: - title = self._segment_chinese(title) - text = self._segment_chinese(text) - - # Create entry for section - entry = { - "location": url, - "title": title, - "text": text - } - - # Set document tags - tags = page.meta.get("tags") - if isinstance(tags, list): - entry["tags"] = [] - for name in tags: - if name and isinstance(name, (str, int, float, bool)): - entry["tags"].append(name) - - # Set document boost - search = page.meta.get("search", {}) - if "boost" in search: - entry["boost"] = search["boost"] - - # Add entry to index - self.entries.append(entry) - - # Generate search index - def generate_search_index(self, prev): - config = { - key: self.config[key] - for key in ["lang", "separator", "pipeline"] - } - - # Hack: if we're running under dirty reload, the search index will only - # include the entries for the current page. However, MkDocs > 1.4 allows - # us to persist plugin state across rebuilds, which is exactly what we - # do by passing the previously built index to this method. Thus, we just - # remove the previous entries for the current page, and append the new - # entries to the end of the index, as order doesn't matter. - if prev and self.entries: - path = self.entries[0]["location"] - - # Since we're sure that we're running under dirty reload, the list - # of entries will only contain sections for a single page. Thus, we - # use the first entry to remove all entries from the previous run - # that belong to the current page. The rationale behind this is that - # authors might add or remove section headers, so we need to make - # sure that sections are synchronized correctly. - entries = [ - entry for entry in prev.entries - if not entry["location"].startswith(path) - ] - - # Merge previous with current entries - self.entries = entries + self.entries - - # Otherwise just set previous entries - if prev and not self.entries: - self.entries = prev.entries - - # Return search index as JSON - data = { "config": config, "docs": self.entries } - return json.dumps( - data, - separators = (",", ":"), - default = str - ) - - # ------------------------------------------------------------------------- - - # Retrieve item for anchor - def _find_toc_by_id(self, toc, id): - for toc_item in toc: - if toc_item.id == id: - return toc_item - - # Recurse into children of item - toc_item = self._find_toc_by_id(toc_item.children, id) - if toc_item is not None: - return toc_item - - # No item found - return None - - # Find and segment Chinese characters in string - def _segment_chinese(self, data): - expr = re.compile(r"(\p{IsHan}+)", re.UNICODE) - - # Replace callback - def replace(match): - value = match.group(0) - - # Replace occurrence in original string with segmented version and - # surround with zero-width whitespace for efficient indexing - return "".join([ - "\u200b", - "\u200b".join(jieba.cut(value.encode("utf-8"))), - "\u200b", - ]) - - # Return string with segmented occurrences - return expr.sub(replace, data).strip("\u200b") - -# ----------------------------------------------------------------------------- - -# HTML element -class Element: - """ - An element with attributes, essentially a small wrapper object for the - parser to access attributes in other callbacks than handle_starttag. - """ - - # Initialize HTML element - def __init__(self, tag, attrs = {}): - self.tag = tag - self.attrs = attrs - - # String representation - def __repr__(self): - return self.tag - - # Support comparison (compare by tag only) - def __eq__(self, other): - if other is Element: - return self.tag == other.tag - else: - return self.tag == other - - # Support set operations - def __hash__(self): - return hash(self.tag) - - # Check whether the element should be excluded - def is_excluded(self): - return "data-search-exclude" in self.attrs - -# ----------------------------------------------------------------------------- - -# HTML section -class Section: - """ - A block of text with markup, preceded by a title (with markup), i.e., a - headline with a certain level (h1-h6). Internally used by the parser. - """ - - # Initialize HTML section - def __init__(self, el, depth = 0): - self.el = el - self.depth = depth - - # Initialize section data - self.text = [] - self.title = [] - self.id = None - - # String representation - def __repr__(self): - if self.id: - return "#".join([self.el.tag, self.id]) - else: - return self.el.tag - - # Check whether the section should be excluded - def is_excluded(self): - return self.el.is_excluded() - -# ----------------------------------------------------------------------------- - -# HTML parser -class Parser(HTMLParser): - """ - This parser divides the given string of HTML into a list of sections, each - of which are preceded by a h1-h6 level heading. A white- and blacklist of - tags dictates which tags should be preserved as part of the index, and - which should be ignored in their entirety. - """ - - # Initialize HTML parser - def __init__(self, *args, **kwargs): - super().__init__(*args, **kwargs) - - # Tags to skip - self.skip = set([ - "object", # Objects - "script", # Scripts - "style" # Styles - ]) - - # Tags to keep - self.keep = set([ - "p", # Paragraphs - "code", "pre", # Code blocks - "li", "ol", "ul", # Lists - "sub", "sup" # Sub- and superscripts - ]) - - # Current context and section - self.context = [] - self.section = None - - # All parsed sections - self.data = [] - - # Called at the start of every HTML tag - def handle_starttag(self, tag, attrs): - attrs = dict(attrs) - - # Ignore self-closing tags - el = Element(tag, attrs) - if not tag in void: - self.context.append(el) - else: - return - - # Handle heading - if tag in ([f"h{x}" for x in range(1, 7)]): - depth = len(self.context) - if "id" in attrs: - - # Ensure top-level section - if tag != "h1" and not self.data: - self.section = Section(Element("hx"), depth) - self.data.append(self.section) - - # Set identifier, if not first section - self.section = Section(el, depth) - if self.data: - self.section.id = attrs["id"] - - # Append section to list - self.data.append(self.section) - - # Handle preface - ensure top-level section - if not self.section: - self.section = Section(Element("hx")) - self.data.append(self.section) - - # Handle special cases to skip - for key, value in attrs.items(): - - # Skip block if explicitly excluded from search - if key == "data-search-exclude": - self.skip.add(el) - return - - # Skip line numbers - see https://bit.ly/3GvubZx - if key == "class" and value == "linenodiv": - self.skip.add(el) - return - - # Render opening tag if kept - if not self.skip.intersection(self.context): - if tag in self.keep: - - # Check whether we're inside the section title - data = self.section.text - if self.section.el in self.context: - data = self.section.title - - # Append to section title or text - data.append(f"<{tag}>") - - # Called at the end of every HTML tag - def handle_endtag(self, tag): - if not self.context or self.context[-1] != tag: - return - - # Check whether we're exiting the current context, which happens when - # a headline is nested in another element. In that case, we close the - # current section, continuing to append data to the previous section, - # which could also be a nested section – see https://bit.ly/3IxxIJZ - if self.section.depth > len(self.context): - for section in reversed(self.data): - if section.depth <= len(self.context): - - # Set depth to infinity in order to denote that the current - # section is exited and must never be considered again. - self.section.depth = float("inf") - self.section = section - break - - # Remove element from skip list - el = self.context.pop() - if el in self.skip: - if el.tag not in ["script", "style", "object"]: - self.skip.remove(el) - return - - # Render closing tag if kept - if not self.skip.intersection(self.context): - if tag in self.keep: - - # Check whether we're inside the section title - data = self.section.text - if self.section.el in self.context: - data = self.section.title - - # Search for corresponding opening tag - index = data.index(f"<{tag}>") - for i in range(index + 1, len(data)): - if not data[i].isspace(): - index = len(data) - break - - # Remove element if empty (or only whitespace) - if len(data) > index: - while len(data) > index: - data.pop() - - # Append to section title or text - else: - data.append(f"</{tag}>") - - # Called for the text contents of each tag - def handle_data(self, data): - if self.skip.intersection(self.context): - return - - # Collapse whitespace in non-pre contexts - if not "pre" in self.context: - if not data.isspace(): - data = data.replace("\n", " ") - else: - data = " " - - # Handle preface - ensure top-level section - if not self.section: - self.section = Section(Element("hx")) - self.data.append(self.section) - - # Handle section headline - if self.section.el in self.context: - permalink = False - for el in self.context: - if el.tag == "a" and el.attrs.get("class") == "headerlink": - permalink = True - - # Ignore permalinks - if not permalink: - self.section.title.append( - escape(data, quote = False) - ) - - # Collapse adjacent whitespace - elif data.isspace(): - if not self.section.text or not self.section.text[-1].isspace(): - self.section.text.append(data) - elif "pre" in self.context: - self.section.text.append(data) - - # Handle everything else - else: - self.section.text.append( - escape(data, quote = False) - ) - -# ----------------------------------------------------------------------------- -# Data -# ----------------------------------------------------------------------------- - -# Set up logging -log = logging.getLogger("mkdocs.material.search") - -# Tags that are self-closing -void = set([ - "area", # Image map areas - "base", # Document base - "br", # Line breaks - "col", # Table columns - "embed", # External content - "hr", # Horizontal rules - "img", # Images - "input", # Input fields - "link", # Links - "meta", # Metadata - "param", # External parameters - "source", # Image source sets - "track", # Text track - "wbr" # Line break opportunities -]) diff --git a/src/plugins/social/__init__.py b/src/plugins/social/__init__.py deleted file mode 100644 index d1899378..00000000 --- a/src/plugins/social/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2016-2023 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. diff --git a/src/plugins/social/config.py b/src/plugins/social/config.py deleted file mode 100644 index 2d87c25e..00000000 --- a/src/plugins/social/config.py +++ /dev/null @@ -1,48 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from mkdocs.config.base import Config -from mkdocs.config.config_options import Deprecated, Type - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Social plugin configuration -class SocialConfig(Config): - enabled = Type(bool, default = True) - cache_dir = Type(str, default = ".cache/plugin/social") - - # Settings for social cards - cards = Type(bool, default = True) - cards_dir = Type(str, default = "assets/images/social") - cards_layout_options = Type(dict, default = {}) - - # Deprecated settings - cards_color = Deprecated( - option_type = Type(dict, default = {}), - message = - "Deprecated, use 'cards_layout_options.background_color' " - "and 'cards_layout_options.color' with 'default' layout" - ) - cards_font = Deprecated( - option_type = Type(str), - message = "Deprecated, use 'cards_layout_options.font_family'" - ) diff --git a/src/plugins/social/plugin.py b/src/plugins/social/plugin.py deleted file mode 100644 index 3cdfa3ce..00000000 --- a/src/plugins/social/plugin.py +++ /dev/null @@ -1,516 +0,0 @@ -# Copyright (c) 2016-2023 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. - -# ----------------------------------------------------------------------------- -# Disclaimer -# ----------------------------------------------------------------------------- -# Please note: this version of the social plugin is not actively development -# anymore. Instead, Material for MkDocs Insiders ships a complete rewrite of -# the plugin which is much more powerful and addresses all shortcomings of -# this implementation. Additionally, the new social plugin allows to create -# entirely custom social cards. You can probably imagine, that this was a lot -# of work to pull off. If you run into problems, or want to have additional -# functionality, please consider sponsoring the project. You can then use the -# new version of the plugin immediately. -# ----------------------------------------------------------------------------- - -import concurrent.futures -import functools -import logging -import os -import posixpath -import re -import requests -import sys - -from collections import defaultdict -from hashlib import md5 -from io import BytesIO -from mkdocs.commands.build import DuplicateFilter -from mkdocs.exceptions import PluginError -from mkdocs.plugins import BasePlugin -from shutil import copyfile -from tempfile import TemporaryFile -from zipfile import ZipFile -try: - from cairosvg import svg2png - from PIL import Image, ImageDraw, ImageFont -except ImportError: - pass - -from .config import SocialConfig - - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Social plugin -class SocialPlugin(BasePlugin[SocialConfig]): - - def __init__(self): - self._executor = concurrent.futures.ThreadPoolExecutor(4) - - # Retrieve configuration - def on_config(self, config): - self.color = colors.get("indigo") - self.config.cards = self.config.enabled - if not self.config.cards: - return - - # Check dependencies - if "Image" not in globals(): - raise PluginError( - "Required dependencies of \"social\" plugin not found. " - "Install with: pip install \"mkdocs-material[imaging]\"" - ) - - # Move color options - if self.config.cards_color: - - # Move background color to new option - value = self.config.cards_color.get("fill") - if value: - self.config.cards_layout_options["background_color"] = value - - # Move color to new option - value = self.config.cards_color.get("text") - if value: - self.config.cards_layout_options["color"] = value - - # Move font family to new option - if self.config.cards_font: - value = self.config.cards_font - self.config.cards_layout_options["font_family"] = value - - # Check if site URL is defined - if not config.site_url: - log.warning( - "The \"site_url\" option is not set. The cards are generated, " - "but not linked, so they won't be visible on social media." - ) - - # Ensure presence of cache directory - self.cache = self.config.cache_dir - if not os.path.isdir(self.cache): - os.makedirs(self.cache) - - # Retrieve palette from theme configuration - theme = config.theme - if "palette" in theme: - palette = theme["palette"] - - # Use first palette, if multiple are defined - if isinstance(palette, list): - palette = palette[0] - - # Set colors according to palette - if "primary" in palette and palette["primary"]: - primary = palette["primary"].replace(" ", "-") - self.color = colors.get(primary, self.color) - - # Retrieve color overrides - options = self.config.cards_layout_options - self.color = { - "fill": options.get("background_color", self.color["fill"]), - "text": options.get("color", self.color["text"]) - } - - # Retrieve logo and font - self._resized_logo_promise = self._executor.submit(self._load_resized_logo, config) - self.font = self._load_font(config) - - self._image_promises = [] - - # Create social cards - def on_page_markdown(self, markdown, page, config, files): - if not self.config.cards: - return - - # Resolve image directory - directory = self.config.cards_dir - file, _ = os.path.splitext(page.file.src_path) - - # Resolve path of image - path = "{}.png".format(os.path.join( - config.site_dir, - directory, - file - )) - - # Resolve path of image directory - directory = os.path.dirname(path) - if not os.path.isdir(directory): - os.makedirs(directory) - - # Compute site name - site_name = config.site_name - - # Compute page title and description - title = page.meta.get("title", page.title) - description = config.site_description or "" - if "description" in page.meta: - description = page.meta["description"] - - # Check type of meta title - see https://t.ly/m1Us - if not isinstance(title, str): - log.error( - f"Page meta title of page '{page.file.src_uri}' must be a " - f"string, but is of type \"{type(title)}\"." - ) - sys.exit(1) - - # Check type of meta description - see https://t.ly/m1Us - if not isinstance(description, str): - log.error( - f"Page meta description of '{page.file.src_uri}' must be a " - f"string, but is of type \"{type(description)}\"." - ) - sys.exit(1) - - # Generate social card if not in cache - hash = md5("".join([ - site_name, - str(title), - description - ]).encode("utf-8")) - file = os.path.join(self.cache, f"{hash.hexdigest()}.png") - self._image_promises.append(self._executor.submit( - self._cache_image, - cache_path = file, dest_path = path, - render_function = lambda: self._render_card(site_name, title, description) - )) - - # Inject meta tags into page - meta = page.meta.get("meta", []) - page.meta["meta"] = meta + self._generate_meta(page, config) - - def on_post_build(self, config): - if not self.config.cards: - return - - # Check for exceptions - for promise in self._image_promises: - promise.result() - - # ------------------------------------------------------------------------- - - # Render image to cache (if not present), then copy from cache to site - def _cache_image(self, cache_path, dest_path, render_function): - if not os.path.isfile(cache_path): - image = render_function() - image.save(cache_path) - - # Copy file from cache - copyfile(cache_path, dest_path) - - @functools.lru_cache(maxsize=None) - def _get_font(self, kind, size): - return ImageFont.truetype(self.font[kind], size) - - # Render social card - def _render_card(self, site_name, title, description): - # Render background and logo - image = self._render_card_background((1200, 630), self.color["fill"]) - image.alpha_composite( - self._resized_logo_promise.result(), - (1200 - 228, 64 - 4) - ) - - # Render site name - font = self._get_font("Bold", 36) - image.alpha_composite( - self._render_text((826, 48), font, site_name, 1, 20), - (64 + 4, 64) - ) - - # Render page title - font = self._get_font("Bold", 92) - image.alpha_composite( - self._render_text((826, 328), font, title, 3, 30), - (64, 160) - ) - - # Render page description - font = self._get_font("Regular", 28) - image.alpha_composite( - self._render_text((826, 80), font, description, 2, 14), - (64 + 4, 512) - ) - - # Return social card image - return image - - # Render social card background - def _render_card_background(self, size, fill): - return Image.new(mode = "RGBA", size = size, color = fill) - - @functools.lru_cache(maxsize=None) - def _tmp_context(self): - image = Image.new(mode = "RGBA", size = (50, 50)) - return ImageDraw.Draw(image) - - @functools.lru_cache(maxsize=None) - def _text_bounding_box(self, text, font): - return self._tmp_context().textbbox((0, 0), text, font = font) - - # Render social card text - def _render_text(self, size, font, text, lmax, spacing = 0): - width = size[0] - lines, words = [], [] - - # Remove remnant HTML tags - text = re.sub(r"(<[^>]+>)", "", text) - - # Retrieve y-offset of textbox to correct for spacing - yoffset = 0 - - # Create drawing context and split text into lines - for word in text.split(" "): - combine = " ".join(words + [word]) - textbox = self._text_bounding_box(combine, font = font) - yoffset = textbox[1] - if not words or textbox[2] <= width: - words.append(word) - else: - lines.append(words) - words = [word] - - # Join words for each line and create image - lines.append(words) - lines = [" ".join(line) for line in lines] - image = Image.new(mode = "RGBA", size = size) - - # Create drawing context and split text into lines - context = ImageDraw.Draw(image) - context.text( - (0, spacing / 2 - yoffset), "\n".join(lines[:lmax]), - font = font, fill = self.color["text"], spacing = spacing - yoffset - ) - - # Return text image - return image - - # ------------------------------------------------------------------------- - - # Generate meta tags - def _generate_meta(self, page, config): - directory = self.config.cards_dir - file, _ = os.path.splitext(page.file.src_uri) - - # Compute page title - title = page.meta.get("title", page.title) - if not page.is_homepage: - title = f"{title} - {config.site_name}" - - # Compute page description - description = config.site_description - if "description" in page.meta: - description = page.meta["description"] - - # Resolve image URL - url = "{}.png".format(posixpath.join( - config.site_url or ".", - directory, - file - )) - - # Ensure forward slashes - url = url.replace(os.path.sep, "/") - - # Return meta tags - return [ - - # Meta tags for Open Graph - { "property": "og:type", "content": "website" }, - { "property": "og:title", "content": title }, - { "property": "og:description", "content": description }, - { "property": "og:image", "content": url }, - { "property": "og:image:type", "content": "image/png" }, - { "property": "og:image:width", "content": "1200" }, - { "property": "og:image:height", "content": "630" }, - { "property": "og:url", "content": page.canonical_url }, - - # Meta tags for Twitter - { "name": "twitter:card", "content": "summary_large_image" }, - # { "name": "twitter:site", "content": user }, - # { "name": "twitter:creator", "content": user }, - { "name": "twitter:title", "content": title }, - { "name": "twitter:description", "content": description }, - { "name": "twitter:image", "content": url } - ] - - def _load_resized_logo(self, config, width = 144): - logo = self._load_logo(config) - height = int(width * logo.height / logo.width) - return logo.resize((width, height)) - - # Retrieve logo image or icon - def _load_logo(self, config): - theme = config.theme - - # Handle images (precedence over icons) - if "logo" in theme: - _, extension = os.path.splitext(theme["logo"]) - - path = os.path.join(config.docs_dir, theme["logo"]) - - # Allow users to put the logo inside their custom_dir (theme["logo"] case) - if theme.custom_dir: - custom_dir_logo = os.path.join(theme.custom_dir, theme["logo"]) - if os.path.exists(custom_dir_logo): - path = custom_dir_logo - - # Load SVG and convert to PNG - if extension == ".svg": - return self._load_logo_svg(path) - - # Load PNG, JPEG, etc. - return Image.open(path).convert("RGBA") - - # Handle icons - icon = theme["icon"] or {} - if "logo" in icon and icon["logo"]: - logo = icon["logo"] - else: - logo = "material/library" - - # Resolve path of package - base = os.path.abspath(os.path.join( - os.path.dirname(__file__), - "../.." - )) - - path = f"{base}/templates/.icons/{logo}.svg" - - # Allow users to put the logo inside their custom_dir (theme["icon"]["logo"] case) - if theme.custom_dir: - custom_dir_logo = os.path.join(theme.custom_dir, ".icons", f"{logo}.svg") - if os.path.exists(custom_dir_logo): - path = custom_dir_logo - - # Load icon data and fill with color - return self._load_logo_svg(path, self.color["text"]) - - # Load SVG file and convert to PNG - def _load_logo_svg(self, path, fill = None): - file = BytesIO() - data = open(path).read() - - # Fill with color, if given - if fill: - data = data.replace("<svg", f"<svg fill=\"{fill}\"") - - # Convert to PNG and return image - svg2png(bytestring = data, write_to = file, scale = 10) - return Image.open(file) - - # Retrieve font - def _load_font(self, config): - name = self.config.cards_layout_options.get("font_family") - if not name: - - # Retrieve from theme (default: Roboto) - theme = config.theme - if isinstance(theme["font"], dict) and "text" in theme["font"]: - name = theme["font"]["text"] - else: - name = "Roboto" - - # Google fonts can return varients like OpenSans_Condensed-Regular.ttf so - # we only use the font requested e.g. OpenSans-Regular.ttf - font_filename_base = name.replace(' ', '') - filename_regex = re.escape(font_filename_base)+r"-(\w+)\.[ot]tf$" - - font = {} - # Check for cached files - note these may be in subfolders - for currentpath, folders, files in os.walk(self.cache): - for file in files: - # Map available font weights to file paths - fname = os.path.join(currentpath, file) - match = re.search(filename_regex, fname) - if match: - font[match.group(1)] = fname - - # If none found, fetch from Google and try again - if len(font) == 0: - self._load_font_from_google(name) - for currentpath, folders, files in os.walk(self.cache): - for file in files: - # Map available font weights to file paths - fname = os.path.join(currentpath, file) - match = re.search(filename_regex, fname) - if match: - font[match.group(1)] = fname - - # Return available font weights with fallback - return defaultdict(lambda: font["Regular"], font) - - # Retrieve font from Google Fonts - def _load_font_from_google(self, name): - url = "https://fonts.google.com/download?family={}" - res = requests.get(url.format(name.replace(" ", "+")), stream = True) - - # Write archive to temporary file - tmp = TemporaryFile() - for chunk in res.iter_content(chunk_size = 32768): - tmp.write(chunk) - - # Unzip fonts from temporary file - zip = ZipFile(tmp) - files = [file for file in zip.namelist() if file.endswith(".ttf") or file.endswith(".otf")] - zip.extractall(self.cache, files) - - # Close and delete temporary file - tmp.close() - return files - -# ----------------------------------------------------------------------------- -# Data -# ----------------------------------------------------------------------------- - -# Set up logging -log = logging.getLogger("mkdocs") -log.addFilter(DuplicateFilter()) - -# Color palette -colors = dict({ - "red": { "fill": "#ef5552", "text": "#ffffff" }, - "pink": { "fill": "#e92063", "text": "#ffffff" }, - "purple": { "fill": "#ab47bd", "text": "#ffffff" }, - "deep-purple": { "fill": "#7e56c2", "text": "#ffffff" }, - "indigo": { "fill": "#4051b5", "text": "#ffffff" }, - "blue": { "fill": "#2094f3", "text": "#ffffff" }, - "light-blue": { "fill": "#02a6f2", "text": "#ffffff" }, - "cyan": { "fill": "#00bdd6", "text": "#ffffff" }, - "teal": { "fill": "#009485", "text": "#ffffff" }, - "green": { "fill": "#4cae4f", "text": "#ffffff" }, - "light-green": { "fill": "#8bc34b", "text": "#ffffff" }, - "lime": { "fill": "#cbdc38", "text": "#000000" }, - "yellow": { "fill": "#ffec3d", "text": "#000000" }, - "amber": { "fill": "#ffc105", "text": "#000000" }, - "orange": { "fill": "#ffa724", "text": "#000000" }, - "deep-orange": { "fill": "#ff6e42", "text": "#ffffff" }, - "brown": { "fill": "#795649", "text": "#ffffff" }, - "grey": { "fill": "#757575", "text": "#ffffff" }, - "blue-grey": { "fill": "#546d78", "text": "#ffffff" }, - "black": { "fill": "#000000", "text": "#ffffff" }, - "white": { "fill": "#ffffff", "text": "#000000" } -}) diff --git a/src/plugins/tags/__init__.py b/src/plugins/tags/__init__.py deleted file mode 100644 index 19994c95..00000000 --- a/src/plugins/tags/__init__.py +++ /dev/null @@ -1,27 +0,0 @@ -# Copyright (c) 2016-2023 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 -# ----------------------------------------------------------------------------- - -# Casefold a string for comparison when sorting -def casefold(tag: str): - return tag.casefold() diff --git a/src/plugins/tags/config.py b/src/plugins/tags/config.py deleted file mode 100644 index f2d95084..00000000 --- a/src/plugins/tags/config.py +++ /dev/null @@ -1,38 +0,0 @@ -# Copyright (c) 2016-2023 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. - -from functools import partial -from markdown.extensions.toc import slugify -from mkdocs.config.config_options import Optional, Type -from mkdocs.config.base import Config - -from . import casefold - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Tags plugin configuration -class TagsConfig(Config): - enabled = Type(bool, default = True) - - # Settings for tags - tags = Type(bool, default = True) - tags_file = Optional(Type(str)) diff --git a/src/plugins/tags/plugin.py b/src/plugins/tags/plugin.py deleted file mode 100644 index e5ce6bde..00000000 --- a/src/plugins/tags/plugin.py +++ /dev/null @@ -1,182 +0,0 @@ -# Copyright (c) 2016-2023 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 logging -import sys - -from collections import defaultdict -from markdown.extensions.toc import slugify -from mkdocs import utils -from mkdocs.plugins import BasePlugin - -# deprecated, but kept for downward compatibility. Use 'material.plugins.tags' -# as an import source instead. This import is removed in the next major version. -from . import casefold -from .config import TagsConfig - -# ----------------------------------------------------------------------------- -# Classes -# ----------------------------------------------------------------------------- - -# Tags plugin -class TagsPlugin(BasePlugin[TagsConfig]): - supports_multiple_instances = True - - # Initialize plugin - def on_config(self, config): - if not self.config.enabled: - return - - # Skip if tags should not be built - if not self.config.tags: - return - - # Initialize tags - self.tags = defaultdict(list) - self.tags_file = None - - # Retrieve tags mapping from configuration - self.tags_map = config.extra.get("tags") - - # Use override of slugify function - toc = { "slugify": slugify, "separator": "-" } - if "toc" in config.mdx_configs: - toc = { **toc, **config.mdx_configs["toc"] } - - # Partially apply slugify function - self.slugify = lambda value: ( - toc["slugify"](str(value), toc["separator"]) - ) - - # Hack: 2nd pass for tags index page(s) - def on_nav(self, nav, config, files): - if not self.config.enabled: - return - - # Skip if tags should not be built - if not self.config.tags: - return - - # Resolve tags index page - file = self.config.tags_file - if file: - self.tags_file = self._get_tags_file(files, file) - - # Build and render tags index page - def on_page_markdown(self, markdown, page, config, files): - if not self.config.enabled: - return - - # Skip if tags should not be built - if not self.config.tags: - return - - # Skip, if page is excluded - if page.file.inclusion.is_excluded(): - return - - # Render tags index page - if page.file == self.tags_file: - return self._render_tag_index(markdown) - - # Add page to tags index - for tag in page.meta.get("tags", []): - self.tags[tag].append(page) - - # Inject tags into page (after search and before minification) - def on_page_context(self, context, page, config, nav): - if not self.config.enabled: - return - - # Skip if tags should not be built - if not self.config.tags: - return - - # Provide tags for page - if "tags" in page.meta: - context["tags"] = [ - self._render_tag(tag) - for tag in page.meta["tags"] - ] - - # ------------------------------------------------------------------------- - - # Obtain tags file - def _get_tags_file(self, files, path): - file = files.get_file_from_path(path) - if not file: - log.error(f"Tags file '{path}' does not exist.") - sys.exit(1) - - # Add tags file to files - files.append(file) - return file - - # Render tags index - def _render_tag_index(self, markdown): - if not "[TAGS]" in markdown: - markdown += "\n[TAGS]" - - # Replace placeholder in Markdown with rendered tags index - return markdown.replace("[TAGS]", "\n".join([ - self._render_tag_links(*args) - for args in sorted(self.tags.items()) - ])) - - # Render the given tag and links to all pages with occurrences - def _render_tag_links(self, tag, pages): - classes = ["md-tag"] - if isinstance(self.tags_map, dict): - classes.append("md-tag-icon") - type = self.tags_map.get(tag) - if type: - classes.append(f"md-tag--{type}") - - # Render section for tag and a link to each page - classes = " ".join(classes) - content = [f"## <span class=\"{classes}\">{tag}</span>", ""] - for page in pages: - url = utils.get_relative_url( - page.file.src_uri, - self.tags_file.src_uri - ) - - # Render link to page - title = page.meta.get("title", page.title) - content.append(f"- [{title}]({url})") - - # Return rendered tag links - return "\n".join(content) - - # Render the given tag, linking to the tags index (if enabled) - def _render_tag(self, tag): - type = self.tags_map.get(tag) if self.tags_map else None - if not self.tags_file or not self.slugify: - return dict(name = tag, type = type) - else: - url = f"{self.tags_file.url}#{self.slugify(tag)}" - return dict(name = tag, type = type, url = url) - -# ----------------------------------------------------------------------------- -# Data -# ----------------------------------------------------------------------------- - -# Set up logging -log = logging.getLogger("mkdocs.material.tags") diff --git a/src/templates/.icons/logo.afdesign b/src/templates/.icons/logo.afdesign Binary files differdeleted file mode 100644 index 07f57d0a..00000000 --- a/src/templates/.icons/logo.afdesign +++ /dev/null diff --git a/src/templates/.icons/logo.svg b/src/templates/.icons/logo.svg deleted file mode 100644 index 763eb2c2..00000000 --- a/src/templates/.icons/logo.svg +++ /dev/null @@ -1,6 +0,0 @@ -<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 89 89"> - <path d="M3.136,17.387l0,42.932l42.932,21.467l-42.932,-64.399Z" /> - <path d="M21.91,8l42.933,64.398l-18.775,9.388l-42.932,-64.399l18.774,-9.387Z" style="fill-opacity: 0.5" /> - <path d="M67.535,17.387l-27.262,18.156l21.878,32.818l5.384,2.691l0,-53.665Z" /> - <path d="M67.535,17.387l0,53.666l18.774,-9.388l0,-53.665l-18.774,9.387Z" style="fill-opacity: 0.25" /> -</svg> diff --git a/src/templates/404.html b/src/templates/404.html deleted file mode 100644 index e87e7783..00000000 --- a/src/templates/404.html +++ /dev/null @@ -1,28 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -{% extends "main.html" %} - -<!-- Content --> -{% block content %} - <h1>404 - Not found</h1> -{% endblock %} diff --git a/src/templates/__init__.py b/src/templates/__init__.py deleted file mode 100644 index d1899378..00000000 --- a/src/templates/__init__.py +++ /dev/null @@ -1,19 +0,0 @@ -# Copyright (c) 2016-2023 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. diff --git a/src/templates/assets/images/favicon.png b/src/templates/assets/images/favicon.png Binary files differdeleted file mode 100644 index 1cf13b9f..00000000 --- a/src/templates/assets/images/favicon.png +++ /dev/null diff --git a/src/templates/assets/javascripts/_/index.ts b/src/templates/assets/javascripts/_/index.ts deleted file mode 100644 index be0f4a42..00000000 --- a/src/templates/assets/javascripts/_/index.ts +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { getElement, getLocation } from "~/browser" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Feature flag - */ -export type Flag = - | "announce.dismiss" /* Dismissable announcement bar */ - | "content.code.annotate" /* Code annotations */ - | "content.code.copy" /* Code copy button */ - | "content.lazy" /* Lazy content elements */ - | "content.tabs.link" /* Link content tabs */ - | "header.autohide" /* Hide header */ - | "navigation.expand" /* Automatic expansion */ - | "navigation.indexes" /* Section pages */ - | "navigation.instant" /* Instant navigation */ - | "navigation.instant.progress" /* Instant navigation progress */ - | "navigation.sections" /* Section navigation */ - | "navigation.tabs" /* Tabs navigation */ - | "navigation.tabs.sticky" /* Tabs navigation (sticky) */ - | "navigation.top" /* Back-to-top button */ - | "navigation.tracking" /* Anchor tracking */ - | "search.highlight" /* Search highlighting */ - | "search.share" /* Search sharing */ - | "search.suggest" /* Search suggestions */ - | "toc.follow" /* Following table of contents */ - | "toc.integrate" /* Integrated table of contents */ - -/* ------------------------------------------------------------------------- */ - -/** - * Translation - */ -export type Translation = - | "clipboard.copy" /* Copy to clipboard */ - | "clipboard.copied" /* Copied to clipboard */ - | "search.result.placeholder" /* Type to start searching */ - | "search.result.none" /* No matching documents */ - | "search.result.one" /* 1 matching document */ - | "search.result.other" /* # matching documents */ - | "search.result.more.one" /* 1 more on this page */ - | "search.result.more.other" /* # more on this page */ - | "search.result.term.missing" /* Missing */ - | "select.version" /* Version selector */ - -/** - * Translations - */ -export type Translations = - Record<Translation, string> - -/* ------------------------------------------------------------------------- */ - -/** - * Versioning - */ -export interface Versioning { - provider: "mike" /* Version provider */ - default?: string | string[] /* Default version */ -} - -/** - * Configuration - */ -export interface Config { - base: string /* Base URL */ - features: Flag[] /* Feature flags */ - translations: Translations /* Translations */ - search: string /* Search worker URL */ - tags?: Record<string, string> /* Tags mapping */ - version?: Versioning /* Versioning */ -} - -/* ---------------------------------------------------------------------------- - * Data - * ------------------------------------------------------------------------- */ - -/** - * Retrieve global configuration and make base URL absolute - */ -const script = getElement("#__config") -const config: Config = JSON.parse(script.textContent!) -config.base = `${new URL(config.base, getLocation())}` - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Retrieve global configuration - * - * @returns Global configuration - */ -export function configuration(): Config { - return config -} - -/** - * Check whether a feature flag is enabled - * - * @param flag - Feature flag - * - * @returns Test result - */ -export function feature(flag: Flag): boolean { - return config.features.includes(flag) -} - -/** - * Retrieve the translation for the given key - * - * @param key - Key to be translated - * @param value - Positional value, if any - * - * @returns Translation - */ -export function translation( - key: Translation, value?: string | number -): string { - return typeof value !== "undefined" - ? config.translations[key].replace("#", value.toString()) - : config.translations[key] -} diff --git a/src/templates/assets/javascripts/browser/document/index.ts b/src/templates/assets/javascripts/browser/document/index.ts deleted file mode 100644 index 354c9b5c..00000000 --- a/src/templates/assets/javascripts/browser/document/index.ts +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { - ReplaySubject, - Subject, - fromEvent -} from "rxjs" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch document - * - * Documents are implemented as subjects, so all downstream observables are - * automatically updated when a new document is emitted. - * - * @returns Document subject - */ -export function watchDocument(): Subject<Document> { - const document$ = new ReplaySubject<Document>(1) - fromEvent(document, "DOMContentLoaded", { once: true }) - .subscribe(() => document$.next(document)) - - /* Return document */ - return document$ -} diff --git a/src/templates/assets/javascripts/browser/element/_/.eslintrc b/src/templates/assets/javascripts/browser/element/_/.eslintrc deleted file mode 100644 index 16973760..00000000 --- a/src/templates/assets/javascripts/browser/element/_/.eslintrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "rules": { - "jsdoc/require-jsdoc": "off", - "jsdoc/require-returns-check": "off" - } -} diff --git a/src/templates/assets/javascripts/browser/element/_/index.ts b/src/templates/assets/javascripts/browser/element/_/index.ts deleted file mode 100644 index b7beb462..00000000 --- a/src/templates/assets/javascripts/browser/element/_/index.ts +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 - * ------------------------------------------------------------------------- */ - -/** - * Retrieve all elements matching the query selector - * - * @template T - Element type - * - * @param selector - Query selector - * @param node - Node of reference - * - * @returns Elements - */ -export function getElements<T extends keyof HTMLElementTagNameMap>( - selector: T, node?: ParentNode -): HTMLElementTagNameMap[T][] - -export function getElements<T extends HTMLElement>( - selector: string, node?: ParentNode -): T[] - -export function getElements<T extends HTMLElement>( - selector: string, node: ParentNode = document -): T[] { - return Array.from(node.querySelectorAll<T>(selector)) -} - -/** - * Retrieve an element matching a query selector or throw a reference error - * - * Note that this function assumes that the element is present. If unsure if an - * element is existent, use the `getOptionalElement` function instead. - * - * @template T - Element type - * - * @param selector - Query selector - * @param node - Node of reference - * - * @returns Element - */ -export function getElement<T extends keyof HTMLElementTagNameMap>( - selector: T, node?: ParentNode -): HTMLElementTagNameMap[T] - -export function getElement<T extends HTMLElement>( - selector: string, node?: ParentNode -): T - -export function getElement<T extends HTMLElement>( - selector: string, node: ParentNode = document -): T { - const el = getOptionalElement<T>(selector, node) - if (typeof el === "undefined") - throw new ReferenceError( - `Missing element: expected "${selector}" to be present` - ) - - /* Return element */ - return el -} - -/* ------------------------------------------------------------------------- */ - -/** - * Retrieve an optional element matching the query selector - * - * @template T - Element type - * - * @param selector - Query selector - * @param node - Node of reference - * - * @returns Element or nothing - */ -export function getOptionalElement<T extends keyof HTMLElementTagNameMap>( - selector: T, node?: ParentNode -): HTMLElementTagNameMap[T] | undefined - -export function getOptionalElement<T extends HTMLElement>( - selector: string, node?: ParentNode -): T | undefined - -export function getOptionalElement<T extends HTMLElement>( - selector: string, node: ParentNode = document -): T | undefined { - return node.querySelector<T>(selector) || undefined -} - -/** - * Retrieve the currently active element - * - * @returns Element or nothing - */ -export function getActiveElement(): HTMLElement | undefined { - return document.activeElement instanceof HTMLElement - ? document.activeElement || undefined - : undefined -} diff --git a/src/templates/assets/javascripts/browser/element/focus/index.ts b/src/templates/assets/javascripts/browser/element/focus/index.ts deleted file mode 100644 index f31fe276..00000000 --- a/src/templates/assets/javascripts/browser/element/focus/index.ts +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - debounceTime, - distinctUntilChanged, - fromEvent, - map, - merge, - shareReplay, - startWith -} from "rxjs" - -import { getActiveElement } from "../_" - -/* ---------------------------------------------------------------------------- - * Data - * ------------------------------------------------------------------------- */ - -/** - * Focus observable - * - * Previously, this observer used `focus` and `blur` events to determine whether - * an element is focused, but this doesn't work if there are focusable elements - * within the elements itself. A better solutions are `focusin` and `focusout` - * events, which bubble up the tree and allow for more fine-grained control. - * - * `debounceTime` is necessary, because when a focus change happens inside an - * element, the observable would first emit `false` and then `true` again. - */ -const observer$ = merge( - fromEvent(document.body, "focusin"), - fromEvent(document.body, "focusout") -) - .pipe( - debounceTime(1), - startWith(undefined), - map(() => getActiveElement() || document.body), - shareReplay(1) - ) - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch element focus - * - * @param el - Element - * - * @returns Element focus observable - */ -export function watchElementFocus( - el: HTMLElement -): Observable<boolean> { - return observer$ - .pipe( - map(active => el.contains(active)), - distinctUntilChanged() - ) -} diff --git a/src/templates/assets/javascripts/browser/element/index.ts b/src/templates/assets/javascripts/browser/element/index.ts deleted file mode 100644 index 50ce84b2..00000000 --- a/src/templates/assets/javascripts/browser/element/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./focus" -export * from "./offset" -export * from "./size" -export * from "./visibility" diff --git a/src/templates/assets/javascripts/browser/element/offset/_/index.ts b/src/templates/assets/javascripts/browser/element/offset/_/index.ts deleted file mode 100644 index 6dd229d5..00000000 --- a/src/templates/assets/javascripts/browser/element/offset/_/index.ts +++ /dev/null @@ -1,86 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - animationFrameScheduler, - auditTime, - fromEvent, - map, - merge, - startWith -} from "rxjs" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Element offset - */ -export interface ElementOffset { - x: number /* Horizontal offset */ - y: number /* Vertical offset */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Retrieve element offset - * - * @param el - Element - * - * @returns Element offset - */ -export function getElementOffset( - el: HTMLElement -): ElementOffset { - return { - x: el.offsetLeft, - y: el.offsetTop - } -} - -/* ------------------------------------------------------------------------- */ - -/** - * Watch element offset - * - * @param el - Element - * - * @returns Element offset observable - */ -export function watchElementOffset( - el: HTMLElement -): Observable<ElementOffset> { - return merge( - fromEvent(window, "load"), - fromEvent(window, "resize") - ) - .pipe( - auditTime(0, animationFrameScheduler), - map(() => getElementOffset(el)), - startWith(getElementOffset(el)) - ) -} diff --git a/src/templates/assets/javascripts/browser/element/offset/content/index.ts b/src/templates/assets/javascripts/browser/element/offset/content/index.ts deleted file mode 100644 index 557301a6..00000000 --- a/src/templates/assets/javascripts/browser/element/offset/content/index.ts +++ /dev/null @@ -1,76 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - animationFrameScheduler, - auditTime, - fromEvent, - map, - merge, - startWith -} from "rxjs" - -import { ElementOffset } from "../_" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Retrieve element content offset (= scroll offset) - * - * @param el - Element - * - * @returns Element content offset - */ -export function getElementContentOffset( - el: HTMLElement -): ElementOffset { - return { - x: el.scrollLeft, - y: el.scrollTop - } -} - -/* ------------------------------------------------------------------------- */ - -/** - * Watch element content offset - * - * @param el - Element - * - * @returns Element content offset observable - */ -export function watchElementContentOffset( - el: HTMLElement -): Observable<ElementOffset> { - return merge( - fromEvent(el, "scroll"), - fromEvent(window, "resize") - ) - .pipe( - auditTime(0, animationFrameScheduler), - map(() => getElementContentOffset(el)), - startWith(getElementContentOffset(el)) - ) -} diff --git a/src/templates/assets/javascripts/browser/element/offset/index.ts b/src/templates/assets/javascripts/browser/element/offset/index.ts deleted file mode 100644 index 602ff2cf..00000000 --- a/src/templates/assets/javascripts/browser/element/offset/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./content" diff --git a/src/templates/assets/javascripts/browser/element/size/_/index.ts b/src/templates/assets/javascripts/browser/element/size/_/index.ts deleted file mode 100644 index 35a5e68b..00000000 --- a/src/templates/assets/javascripts/browser/element/size/_/index.ts +++ /dev/null @@ -1,151 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - NEVER, - Observable, - Subject, - defer, - filter, - finalize, - map, - merge, - of, - shareReplay, - startWith, - switchMap, - tap -} from "rxjs" - -import { watchScript } from "../../../script" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Element offset - */ -export interface ElementSize { - width: number /* Element width */ - height: number /* Element height */ -} - -/* ---------------------------------------------------------------------------- - * Data - * ------------------------------------------------------------------------- */ - -/** - * Resize observer entry subject - */ -const entry$ = new Subject<ResizeObserverEntry>() - -/** - * Resize observer observable - * - * This observable will create a `ResizeObserver` on the first subscription - * and will automatically terminate it when there are no more subscribers. - * It's quite important to centralize observation in a single `ResizeObserver`, - * as the performance difference can be quite dramatic, as the link shows. - * - * If the browser doesn't have a `ResizeObserver` implementation available, a - * polyfill is automatically downloaded from unpkg.com. This is also compatible - * with the built-in privacy plugin, which will download the polyfill and put - * it alongside the built site for self-hosting. - * - * @see https://bit.ly/3iIYfEm - Google Groups on performance - */ -const observer$ = defer(() => ( - typeof ResizeObserver === "undefined" - ? watchScript("https://unpkg.com/resize-observer-polyfill") - : of(undefined) -)) - .pipe( - map(() => new ResizeObserver(entries => { - for (const entry of entries) - entry$.next(entry) - })), - switchMap(observer => merge(NEVER, of(observer)) - .pipe( - finalize(() => observer.disconnect()) - ) - ), - shareReplay(1) - ) - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Retrieve element size - * - * @param el - Element - * - * @returns Element size - */ -export function getElementSize( - el: HTMLElement -): ElementSize { - return { - width: el.offsetWidth, - height: el.offsetHeight - } -} - -/* ------------------------------------------------------------------------- */ - -/** - * Watch element size - * - * This function returns an observable that subscribes to a single internal - * instance of `ResizeObserver` upon subscription, and emit resize events until - * termination. Note that this function should not be called with the same - * element twice, as the first unsubscription will terminate observation. - * - * Sadly, we can't use the `DOMRect` objects returned by the observer, because - * we need the emitted values to be consistent with `getElementSize`, which will - * return the used values (rounded) and not actual values (unrounded). Thus, we - * use the `offset*` properties. See the linked GitHub issue. - * - * @see https://bit.ly/3m0k3he - GitHub issue - * - * @param el - Element - * - * @returns Element size observable - */ -export function watchElementSize( - el: HTMLElement -): Observable<ElementSize> { - return observer$ - .pipe( - tap(observer => observer.observe(el)), - switchMap(observer => entry$ - .pipe( - filter(({ target }) => target === el), - finalize(() => observer.unobserve(el)), - map(() => getElementSize(el)) - ) - ), - startWith(getElementSize(el)) - ) -} diff --git a/src/templates/assets/javascripts/browser/element/size/content/index.ts b/src/templates/assets/javascripts/browser/element/size/content/index.ts deleted file mode 100644 index 5ed388cf..00000000 --- a/src/templates/assets/javascripts/browser/element/size/content/index.ts +++ /dev/null @@ -1,67 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { ElementSize } from "../_" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Retrieve element content size (= scroll width and height) - * - * @param el - Element - * - * @returns Element content size - */ -export function getElementContentSize( - el: HTMLElement -): ElementSize { - return { - width: el.scrollWidth, - height: el.scrollHeight - } -} - -/** - * Retrieve the overflowing container of an element, if any - * - * @param el - Element - * - * @returns Overflowing container or nothing - */ -export function getElementContainer( - el: HTMLElement -): HTMLElement | undefined { - let parent = el.parentElement - while (parent) - if ( - el.scrollWidth <= parent.scrollWidth && - el.scrollHeight <= parent.scrollHeight - ) - parent = (el = parent).parentElement - else - break - - /* Return overflowing container */ - return parent ? el : undefined -} diff --git a/src/templates/assets/javascripts/browser/element/size/index.ts b/src/templates/assets/javascripts/browser/element/size/index.ts deleted file mode 100644 index 602ff2cf..00000000 --- a/src/templates/assets/javascripts/browser/element/size/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./content" diff --git a/src/templates/assets/javascripts/browser/element/visibility/index.ts b/src/templates/assets/javascripts/browser/element/visibility/index.ts deleted file mode 100644 index 1ffe0b8d..00000000 --- a/src/templates/assets/javascripts/browser/element/visibility/index.ts +++ /dev/null @@ -1,131 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - NEVER, - Observable, - Subject, - defer, - distinctUntilChanged, - filter, - finalize, - map, - merge, - of, - shareReplay, - switchMap, - tap -} from "rxjs" - -import { - getElementContentSize, - getElementSize, - watchElementContentOffset -} from "~/browser" - -/* ---------------------------------------------------------------------------- - * Data - * ------------------------------------------------------------------------- */ - -/** - * Intersection observer entry subject - */ -const entry$ = new Subject<IntersectionObserverEntry>() - -/** - * Intersection observer observable - * - * This observable will create an `IntersectionObserver` on first subscription - * and will automatically terminate it when there are no more subscribers. - * - * @see https://bit.ly/3iIYfEm - Google Groups on performance - */ -const observer$ = defer(() => of( - new IntersectionObserver(entries => { - for (const entry of entries) - entry$.next(entry) - }, { - threshold: 0 - }) -)) - .pipe( - switchMap(observer => merge(NEVER, of(observer)) - .pipe( - finalize(() => observer.disconnect()) - ) - ), - shareReplay(1) - ) - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch element visibility - * - * @param el - Element - * - * @returns Element visibility observable - */ -export function watchElementVisibility( - el: HTMLElement -): Observable<boolean> { - return observer$ - .pipe( - tap(observer => observer.observe(el)), - switchMap(observer => entry$ - .pipe( - filter(({ target }) => target === el), - finalize(() => observer.unobserve(el)), - map(({ isIntersecting }) => isIntersecting) - ) - ) - ) -} - -/** - * Watch element boundary - * - * This function returns an observable which emits whether the bottom content - * boundary (= scroll offset) of an element is within a certain threshold. - * - * @param el - Element - * @param threshold - Threshold - * - * @returns Element boundary observable - */ -export function watchElementBoundary( - el: HTMLElement, threshold = 16 -): Observable<boolean> { - return watchElementContentOffset(el) - .pipe( - map(({ y }) => { - const visible = getElementSize(el) - const content = getElementContentSize(el) - return y >= ( - content.height - visible.height - threshold - ) - }), - distinctUntilChanged() - ) -} diff --git a/src/templates/assets/javascripts/browser/index.ts b/src/templates/assets/javascripts/browser/index.ts deleted file mode 100644 index f1ee2bae..00000000 --- a/src/templates/assets/javascripts/browser/index.ts +++ /dev/null @@ -1,32 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./document" -export * from "./element" -export * from "./keyboard" -export * from "./location" -export * from "./media" -export * from "./request" -export * from "./script" -export * from "./toggle" -export * from "./viewport" -export * from "./worker" diff --git a/src/templates/assets/javascripts/browser/keyboard/index.ts b/src/templates/assets/javascripts/browser/keyboard/index.ts deleted file mode 100644 index 783f2cda..00000000 --- a/src/templates/assets/javascripts/browser/keyboard/index.ts +++ /dev/null @@ -1,148 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { - EMPTY, - Observable, - filter, - fromEvent, - map, - merge, - share, - startWith, - switchMap -} from "rxjs" - -import { getActiveElement } from "../element" -import { getToggle } from "../toggle" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Keyboard mode - */ -export type KeyboardMode = - | "global" /* Global */ - | "search" /* Search is open */ - -/* ------------------------------------------------------------------------- */ - -/** - * Keyboard - */ -export interface Keyboard { - mode: KeyboardMode /* Keyboard mode */ - type: string /* Key type */ - claim(): void /* Key claim */ -} - -/* ---------------------------------------------------------------------------- - * Helper functions - * ------------------------------------------------------------------------- */ - -/** - * Check whether an element may receive keyboard input - * - * @param el - Element - * @param type - Key type - * - * @returns Test result - */ -function isSusceptibleToKeyboard( - el: HTMLElement, type: string -): boolean { - switch (el.constructor) { - - /* Input elements */ - case HTMLInputElement: - /* @ts-expect-error - omit unnecessary type cast */ - if (el.type === "radio") - return /^Arrow/.test(type) - else - return true - - /* Select element and textarea */ - case HTMLSelectElement: - case HTMLTextAreaElement: - return true - - /* Everything else */ - default: - return el.isContentEditable - } -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch composition events - * - * @returns Composition observable - */ -export function watchComposition(): Observable<boolean> { - return merge( - fromEvent(window, "compositionstart").pipe(map(() => true)), - fromEvent(window, "compositionend").pipe(map(() => false)) - ) - .pipe( - startWith(false) - ) -} - -/** - * Watch keyboard - * - * @returns Keyboard observable - */ -export function watchKeyboard(): Observable<Keyboard> { - const keyboard$ = fromEvent<KeyboardEvent>(window, "keydown") - .pipe( - filter(ev => !(ev.metaKey || ev.ctrlKey)), - map(ev => ({ - mode: getToggle("search") ? "search" : "global", - type: ev.key, - claim() { - ev.preventDefault() - ev.stopPropagation() - } - } as Keyboard)), - filter(({ mode, type }) => { - if (mode === "global") { - const active = getActiveElement() - if (typeof active !== "undefined") - return !isSusceptibleToKeyboard(active, type) - } - return true - }), - share() - ) - - /* Don't emit during composition events - see https://bit.ly/3te3Wl8 */ - return watchComposition() - .pipe( - switchMap(active => !active ? keyboard$ : EMPTY) - ) -} diff --git a/src/templates/assets/javascripts/browser/location/_/index.ts b/src/templates/assets/javascripts/browser/location/_/index.ts deleted file mode 100644 index 2672fa74..00000000 --- a/src/templates/assets/javascripts/browser/location/_/index.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { Subject } from "rxjs" - -import { feature } from "~/_" -import { h } from "~/utilities" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Retrieve location - * - * This function returns a `URL` object (and not `Location`) to normalize the - * typings across the application. Furthermore, locations need to be tracked - * without setting them and `Location` is a singleton which represents the - * current location. - * - * @returns URL - */ -export function getLocation(): URL { - return new URL(location.href) -} - -/** - * Set location - * - * If instant navigation is enabled, this function creates a temporary anchor - * element, sets the `href` attribute, appends it to the body, clicks it, and - * then removes it again. The event will bubble up the DOM and trigger be - * intercepted by the instant loading business logic. - * - * Note that we must append and remove the anchor element, or the event will - * not bubble up the DOM, making it impossible to intercept it. - * - * @param url - URL to navigate to - * @param navigate - Force navigation - */ -export function setLocation( - url: URL | HTMLLinkElement, navigate = false -): void { - if (feature("navigation.instant") && !navigate) { - const el = h("a", { href: url.href }) - document.body.appendChild(el) - el.click() - el.remove() - - // If we're not using instant navigation, and the page should not be reloaded - // just instruct the browser to navigate to the given URL - } else { - location.href = url.href - } -} - -/* ------------------------------------------------------------------------- */ - -/** - * Watch location - * - * @returns Location subject - */ -export function watchLocation(): Subject<URL> { - return new Subject<URL>() -} diff --git a/src/templates/assets/javascripts/browser/location/hash/index.ts b/src/templates/assets/javascripts/browser/location/hash/index.ts deleted file mode 100644 index 5d3a134a..00000000 --- a/src/templates/assets/javascripts/browser/location/hash/index.ts +++ /dev/null @@ -1,104 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - filter, - fromEvent, - map, - merge, - shareReplay, - startWith -} from "rxjs" - -import { getOptionalElement } from "~/browser" -import { h } from "~/utilities" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Retrieve location hash - * - * @returns Location hash - */ -export function getLocationHash(): string { - return location.hash.slice(1) -} - -/** - * Set location hash - * - * Setting a new fragment identifier via `location.hash` will have no effect - * if the value doesn't change. When a new fragment identifier is set, we want - * the browser to target the respective element at all times, which is why we - * use this dirty little trick. - * - * @param hash - Location hash - */ -export function setLocationHash(hash: string): void { - const el = h("a", { href: hash }) - el.addEventListener("click", ev => ev.stopPropagation()) - el.click() -} - -/* ------------------------------------------------------------------------- */ - -/** - * Watch location hash - * - * @param location$ - Location observable - * - * @returns Location hash observable - */ -export function watchLocationHash( - location$: Observable<URL> -): Observable<string> { - return merge( - fromEvent<HashChangeEvent>(window, "hashchange"), - location$ - ) - .pipe( - map(getLocationHash), - startWith(getLocationHash()), - filter(hash => hash.length > 0), - shareReplay(1) - ) -} - -/** - * Watch location target - * - * @param location$ - Location observable - * - * @returns Location target observable - */ -export function watchLocationTarget( - location$: Observable<URL> -): Observable<HTMLElement> { - return watchLocationHash(location$) - .pipe( - map(id => getOptionalElement(`[id="${id}"]`)!), - filter(el => typeof el !== "undefined") - ) -} diff --git a/src/templates/assets/javascripts/browser/location/index.ts b/src/templates/assets/javascripts/browser/location/index.ts deleted file mode 100644 index d77a5444..00000000 --- a/src/templates/assets/javascripts/browser/location/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./hash" diff --git a/src/templates/assets/javascripts/browser/media/index.ts b/src/templates/assets/javascripts/browser/media/index.ts deleted file mode 100644 index dd7400d4..00000000 --- a/src/templates/assets/javascripts/browser/media/index.ts +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { - EMPTY, - Observable, - fromEvent, - fromEventPattern, - map, - merge, - startWith, - switchMap -} from "rxjs" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch media query - * - * Note that although `MediaQueryList.addListener` is deprecated we have to - * use it, because it's the only way to ensure proper downward compatibility. - * - * @see https://bit.ly/3dUBH2m - GitHub issue - * - * @param query - Media query - * - * @returns Media observable - */ -export function watchMedia(query: string): Observable<boolean> { - const media = matchMedia(query) - return fromEventPattern<boolean>(next => ( - media.addListener(() => next(media.matches)) - )) - .pipe( - startWith(media.matches) - ) -} - -/** - * Watch print mode - * - * @returns Print observable - */ -export function watchPrint(): Observable<boolean> { - const media = matchMedia("print") - return merge( - fromEvent(window, "beforeprint").pipe(map(() => true)), - fromEvent(window, "afterprint").pipe(map(() => false)) - ) - .pipe( - startWith(media.matches) - ) -} - -/* ------------------------------------------------------------------------- */ - -/** - * Toggle an observable with a media observable - * - * @template T - Data type - * - * @param query$ - Media observable - * @param factory - Observable factory - * - * @returns Toggled observable - */ -export function at<T>( - query$: Observable<boolean>, factory: () => Observable<T> -): Observable<T> { - return query$ - .pipe( - switchMap(active => active ? factory() : EMPTY) - ) -} diff --git a/src/templates/assets/javascripts/browser/request/index.ts b/src/templates/assets/javascripts/browser/request/index.ts deleted file mode 100644 index 74a56a64..00000000 --- a/src/templates/assets/javascripts/browser/request/index.ts +++ /dev/null @@ -1,141 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - map, - shareReplay, - switchMap -} from "rxjs" - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Options - */ -interface Options { - progress$?: Subject<number> // Progress subject -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Fetch the given URL - * - * If the request fails (e.g. when dispatched from `file://` locations), the - * observable will complete without emitting a value. - * - * @param url - Request URL - * @param options - Options - * - * @returns Response observable - */ -export function request( - url: URL | string, options?: Options -): Observable<Blob> { - return new Observable<Blob>(observer => { - const req = new XMLHttpRequest() - req.open("GET", `${url}`) - req.responseType = "blob" - - // Handle response - req.addEventListener("load", () => { - if (req.status >= 200 && req.status < 300) { - observer.next(req.response) - observer.complete() - } else { - observer.error(new Error(req.statusText)) - } - }) - - // Handle network errors - req.addEventListener("error", () => { - observer.error(new Error("Network Error")) - }) - - // Handle aborted requests - req.addEventListener("abort", () => { - observer.error(new Error("Request aborted")) - }) - - // Handle download progress - if (typeof options?.progress$ !== "undefined") { - req.addEventListener("progress", event => { - options.progress$!.next((event.loaded / event.total) * 100) - }) - - // Immediately set progress to 5% to indicate that we're loading - options.progress$.next(5) - } - - // Send request - req.send() - }) -} - -/* ------------------------------------------------------------------------- */ - -/** - * Fetch JSON from the given URL - * - * @template T - Data type - * - * @param url - Request URL - * @param options - Options - * - * @returns Data observable - */ -export function requestJSON<T>( - url: URL | string, options?: Options -): Observable<T> { - return request(url, options) - .pipe( - switchMap(res => res.text()), - map(body => JSON.parse(body) as T), - shareReplay(1) - ) -} - -/** - * Fetch XML from the given URL - * - * @param url - Request URL - * @param options - Options - * - * @returns Data observable - */ -export function requestXML( - url: URL | string, options?: Options -): Observable<Document> { - const dom = new DOMParser() - return request(url, options) - .pipe( - switchMap(res => res.text()), - map(res => dom.parseFromString(res, "text/xml")), - shareReplay(1) - ) -} diff --git a/src/templates/assets/javascripts/browser/script/index.ts b/src/templates/assets/javascripts/browser/script/index.ts deleted file mode 100644 index ef5c89e6..00000000 --- a/src/templates/assets/javascripts/browser/script/index.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - defer, - finalize, - fromEvent, - map, - merge, - switchMap, - take, - throwError -} from "rxjs" - -import { h } from "~/utilities" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Create and load a `script` element - * - * This function returns an observable that will emit when the script was - * successfully loaded, or throw an error if it wasn't. - * - * @param src - Script URL - * - * @returns Script observable - */ -export function watchScript(src: string): Observable<void> { - const script = h("script", { src }) - return defer(() => { - document.head.appendChild(script) - return merge( - fromEvent(script, "load"), - fromEvent(script, "error") - .pipe( - switchMap(() => ( - throwError(() => new ReferenceError(`Invalid script: ${src}`)) - )) - ) - ) - .pipe( - map(() => undefined), - finalize(() => document.head.removeChild(script)), - take(1) - ) - }) -} diff --git a/src/templates/assets/javascripts/browser/toggle/index.ts b/src/templates/assets/javascripts/browser/toggle/index.ts deleted file mode 100644 index 0be4b29d..00000000 --- a/src/templates/assets/javascripts/browser/toggle/index.ts +++ /dev/null @@ -1,102 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - fromEvent, - map, - startWith -} from "rxjs" - -import { getElement } from "../element" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Toggle - */ -export type Toggle = - | "drawer" /* Toggle for drawer */ - | "search" /* Toggle for search */ - -/* ---------------------------------------------------------------------------- - * Data - * ------------------------------------------------------------------------- */ - -/** - * Toggle map - */ -const toggles: Record<Toggle, HTMLInputElement> = { - drawer: getElement("[data-md-toggle=drawer]"), - search: getElement("[data-md-toggle=search]") -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Retrieve the value of a toggle - * - * @param name - Toggle - * - * @returns Toggle value - */ -export function getToggle(name: Toggle): boolean { - return toggles[name].checked -} - -/** - * Set toggle - * - * Simulating a click event seems to be the most cross-browser compatible way - * of changing the value while also emitting a `change` event. Before, Material - * used `CustomEvent` to programmatically change the value of a toggle, but this - * is a much simpler and cleaner solution which doesn't require a polyfill. - * - * @param name - Toggle - * @param value - Toggle value - */ -export function setToggle(name: Toggle, value: boolean): void { - if (toggles[name].checked !== value) - toggles[name].click() -} - -/* ------------------------------------------------------------------------- */ - -/** - * Watch toggle - * - * @param name - Toggle - * - * @returns Toggle value observable - */ -export function watchToggle(name: Toggle): Observable<boolean> { - const el = toggles[name] - return fromEvent(el, "change") - .pipe( - map(() => el.checked), - startWith(el.checked) - ) -} diff --git a/src/templates/assets/javascripts/browser/viewport/_/index.ts b/src/templates/assets/javascripts/browser/viewport/_/index.ts deleted file mode 100644 index 09c45f32..00000000 --- a/src/templates/assets/javascripts/browser/viewport/_/index.ts +++ /dev/null @@ -1,69 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - combineLatest, - map, - shareReplay -} from "rxjs" - -import { - ViewportOffset, - watchViewportOffset -} from "../offset" -import { - ViewportSize, - watchViewportSize -} from "../size" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Viewport - */ -export interface Viewport { - offset: ViewportOffset /* Viewport offset */ - size: ViewportSize /* Viewport size */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch viewport - * - * @returns Viewport observable - */ -export function watchViewport(): Observable<Viewport> { - return combineLatest([ - watchViewportOffset(), - watchViewportSize() - ]) - .pipe( - map(([offset, size]) => ({ offset, size })), - shareReplay(1) - ) -} diff --git a/src/templates/assets/javascripts/browser/viewport/at/index.ts b/src/templates/assets/javascripts/browser/viewport/at/index.ts deleted file mode 100644 index 8769cf3b..00000000 --- a/src/templates/assets/javascripts/browser/viewport/at/index.ts +++ /dev/null @@ -1,84 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - combineLatest, - distinctUntilKeyChanged, - map -} from "rxjs" - -import { Header } from "~/components" - -import { getElementOffset } from "../../element" -import { Viewport } from "../_" - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Watch options - */ -interface WatchOptions { - viewport$: Observable<Viewport> /* Viewport observable */ - header$: Observable<Header> /* Header observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch viewport relative to element - * - * @param el - Element - * @param options - Options - * - * @returns Viewport observable - */ -export function watchViewportAt( - el: HTMLElement, { viewport$, header$ }: WatchOptions -): Observable<Viewport> { - const size$ = viewport$ - .pipe( - distinctUntilKeyChanged("size") - ) - - /* Compute element offset */ - const offset$ = combineLatest([size$, header$]) - .pipe( - map(() => getElementOffset(el)) - ) - - /* Compute relative viewport, return hot observable */ - return combineLatest([header$, viewport$, offset$]) - .pipe( - map(([{ height }, { offset, size }, { x, y }]) => ({ - offset: { - x: offset.x - x, - y: offset.y - y + height - }, - size - })) - ) -} diff --git a/src/templates/assets/javascripts/browser/viewport/index.ts b/src/templates/assets/javascripts/browser/viewport/index.ts deleted file mode 100644 index b3d135e9..00000000 --- a/src/templates/assets/javascripts/browser/viewport/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./at" -export * from "./offset" -export * from "./size" diff --git a/src/templates/assets/javascripts/browser/viewport/offset/index.ts b/src/templates/assets/javascripts/browser/viewport/offset/index.ts deleted file mode 100644 index 63d37dd2..00000000 --- a/src/templates/assets/javascripts/browser/viewport/offset/index.ts +++ /dev/null @@ -1,78 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - fromEvent, - map, - merge, - startWith -} from "rxjs" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Viewport offset - */ -export interface ViewportOffset { - x: number /* Horizontal offset */ - y: number /* Vertical offset */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Retrieve viewport offset - * - * On iOS Safari, viewport offset can be negative due to overflow scrolling. - * As this may induce strange behaviors downstream, we'll just limit it to 0. - * - * @returns Viewport offset - */ -export function getViewportOffset(): ViewportOffset { - return { - x: Math.max(0, scrollX), - y: Math.max(0, scrollY) - } -} - -/* ------------------------------------------------------------------------- */ - -/** - * Watch viewport offset - * - * @returns Viewport offset observable - */ -export function watchViewportOffset(): Observable<ViewportOffset> { - return merge( - fromEvent(window, "scroll", { passive: true }), - fromEvent(window, "resize", { passive: true }) - ) - .pipe( - map(getViewportOffset), - startWith(getViewportOffset()) - ) -} diff --git a/src/templates/assets/javascripts/browser/viewport/size/index.ts b/src/templates/assets/javascripts/browser/viewport/size/index.ts deleted file mode 100644 index 06694888..00000000 --- a/src/templates/assets/javascripts/browser/viewport/size/index.ts +++ /dev/null @@ -1,71 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - fromEvent, - map, - startWith -} from "rxjs" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Viewport size - */ -export interface ViewportSize { - width: number /* Viewport width */ - height: number /* Viewport height */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Retrieve viewport size - * - * @returns Viewport size - */ -export function getViewportSize(): ViewportSize { - return { - width: innerWidth, - height: innerHeight - } -} - -/* ------------------------------------------------------------------------- */ - -/** - * Watch viewport size - * - * @returns Viewport size observable - */ -export function watchViewportSize(): Observable<ViewportSize> { - return fromEvent(window, "resize", { passive: true }) - .pipe( - map(getViewportSize), - startWith(getViewportSize()) - ) -} diff --git a/src/templates/assets/javascripts/browser/worker/index.ts b/src/templates/assets/javascripts/browser/worker/index.ts deleted file mode 100644 index 12e4e63b..00000000 --- a/src/templates/assets/javascripts/browser/worker/index.ts +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - endWith, - fromEvent, - ignoreElements, - mergeWith, - share, - takeUntil -} from "rxjs" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Worker message - */ -export interface WorkerMessage { - type: unknown /* Message type */ - data?: unknown /* Message data */ -} - -/* ---------------------------------------------------------------------------- - * Helper functions - * ------------------------------------------------------------------------- */ - -/** - * Create an observable for receiving from a web worker - * - * @template T - Data type - * - * @param worker - Web worker - * - * @returns Message observable - */ -function recv<T>(worker: Worker): Observable<T> { - return fromEvent<MessageEvent<T>, T>(worker, "message", ev => ev.data) -} - -/** - * Create a subject for sending to a web worker - * - * @template T - Data type - * - * @param worker - Web worker - * - * @returns Message subject - */ -function send<T>(worker: Worker): Subject<T> { - const send$ = new Subject<T>() - send$.subscribe(data => worker.postMessage(data)) - - /* Return message subject */ - return send$ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Create a bidirectional communication channel to a web worker - * - * @template T - Data type - * - * @param url - Worker URL - * @param worker - Worker - * - * @returns Worker subject - */ -export function watchWorker<T extends WorkerMessage>( - url: string, worker = new Worker(url) -): Subject<T> { - const recv$ = recv<T>(worker) - const send$ = send<T>(worker) - - /* Create worker subject and forward messages */ - const worker$ = new Subject<T>() - worker$.subscribe(send$) - - /* Return worker subject */ - const done$ = send$.pipe(ignoreElements(), endWith(true)) - return worker$ - .pipe( - ignoreElements(), - mergeWith(recv$.pipe(takeUntil(done$))), - share() - ) as Subject<T> -} diff --git a/src/templates/assets/javascripts/bundle.ts b/src/templates/assets/javascripts/bundle.ts deleted file mode 100644 index 141789c9..00000000 --- a/src/templates/assets/javascripts/bundle.ts +++ /dev/null @@ -1,316 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "focus-visible" - -import { - EMPTY, - NEVER, - Observable, - Subject, - defer, - delay, - filter, - map, - merge, - mergeWith, - shareReplay, - switchMap -} from "rxjs" - -import { configuration, feature } from "./_" -import { - at, - getActiveElement, - getOptionalElement, - requestJSON, - setLocation, - setToggle, - watchDocument, - watchKeyboard, - watchLocation, - watchLocationTarget, - watchMedia, - watchPrint, - watchScript, - watchViewport -} from "./browser" -import { - getComponentElement, - getComponentElements, - mountAnnounce, - mountBackToTop, - mountConsent, - mountContent, - mountDialog, - mountHeader, - mountHeaderTitle, - mountPalette, - mountProgress, - mountSearch, - mountSearchHiglight, - mountSidebar, - mountSource, - mountTableOfContents, - mountTabs, - watchHeader, - watchMain -} from "./components" -import { - SearchIndex, - setupClipboardJS, - setupInstantNavigation, - setupVersionSelector -} from "./integrations" -import { - patchIndeterminate, - patchScrollfix, - patchScrolllock -} from "./patches" -import "./polyfills" - -/* ---------------------------------------------------------------------------- - * Functions - @todo refactor - * ------------------------------------------------------------------------- */ - -/** - * Fetch search index - * - * @returns Search index observable - */ -function fetchSearchIndex(): Observable<SearchIndex> { - if (location.protocol === "file:") { - return watchScript( - `${new URL("search/search_index.js", config.base)}` - ) - .pipe( - // @ts-ignore - @todo fix typings - map(() => __index), - shareReplay(1) - ) - } else { - return requestJSON<SearchIndex>( - new URL("search/search_index.json", config.base) - ) - } -} - -/* ---------------------------------------------------------------------------- - * Application - * ------------------------------------------------------------------------- */ - -/* Yay, JavaScript is available */ -document.documentElement.classList.remove("no-js") -document.documentElement.classList.add("js") - -/* Set up navigation observables and subjects */ -const document$ = watchDocument() -const location$ = watchLocation() -const target$ = watchLocationTarget(location$) -const keyboard$ = watchKeyboard() - -/* Set up media observables */ -const viewport$ = watchViewport() -const tablet$ = watchMedia("(min-width: 960px)") -const screen$ = watchMedia("(min-width: 1220px)") -const print$ = watchPrint() - -/* Retrieve search index, if search is enabled */ -const config = configuration() -const index$ = document.forms.namedItem("search") - ? fetchSearchIndex() - : NEVER - -/* Set up Clipboard.js integration */ -const alert$ = new Subject<string>() -setupClipboardJS({ alert$ }) - -/* Set up progress indicator */ -const progress$ = new Subject<number>() - -/* Set up instant navigation, if enabled */ -if (feature("navigation.instant")) - setupInstantNavigation({ location$, viewport$, progress$ }) - .subscribe(document$) - -/* Set up version selector */ -if (config.version?.provider === "mike") - setupVersionSelector({ document$ }) - -/* Always close drawer and search on navigation */ -merge(location$, target$) - .pipe( - delay(125) - ) - .subscribe(() => { - setToggle("drawer", false) - setToggle("search", false) - }) - -/* Set up global keyboard handlers */ -keyboard$ - .pipe( - filter(({ mode }) => mode === "global") - ) - .subscribe(key => { - switch (key.type) { - - /* Go to previous page */ - case "p": - case ",": - const prev = getOptionalElement<HTMLLinkElement>("link[rel=prev]") - if (typeof prev !== "undefined") - setLocation(prev) - break - - /* Go to next page */ - case "n": - case ".": - const next = getOptionalElement<HTMLLinkElement>("link[rel=next]") - if (typeof next !== "undefined") - setLocation(next) - break - - /* Expand navigation, see https://bit.ly/3ZjG5io */ - case "Enter": - const active = getActiveElement() - if (active instanceof HTMLLabelElement) - active.click() - } - }) - -/* Set up patches */ -patchIndeterminate({ document$, tablet$ }) -patchScrollfix({ document$ }) -patchScrolllock({ viewport$, tablet$ }) - -/* Set up header and main area observable */ -const header$ = watchHeader(getComponentElement("header"), { viewport$ }) -const main$ = document$ - .pipe( - map(() => getComponentElement("main")), - switchMap(el => watchMain(el, { viewport$, header$ })), - shareReplay(1) - ) - -/* Set up control component observables */ -const control$ = merge( - - /* Consent */ - ...getComponentElements("consent") - .map(el => mountConsent(el, { target$ })), - - /* Dialog */ - ...getComponentElements("dialog") - .map(el => mountDialog(el, { alert$ })), - - /* Header */ - ...getComponentElements("header") - .map(el => mountHeader(el, { viewport$, header$, main$ })), - - /* Color palette */ - ...getComponentElements("palette") - .map(el => mountPalette(el)), - - /* Progress bar */ - ...getComponentElements("progress") - .map(el => mountProgress(el, { progress$ })), - - /* Search */ - ...getComponentElements("search") - .map(el => mountSearch(el, { index$, keyboard$ })), - - /* Repository information */ - ...getComponentElements("source") - .map(el => mountSource(el)) -) - -/* Set up content component observables */ -const content$ = defer(() => merge( - - /* Announcement bar */ - ...getComponentElements("announce") - .map(el => mountAnnounce(el)), - - /* Content */ - ...getComponentElements("content") - .map(el => mountContent(el, { viewport$, target$, print$ })), - - /* Search highlighting */ - ...getComponentElements("content") - .map(el => feature("search.highlight") - ? mountSearchHiglight(el, { index$, location$ }) - : EMPTY - ), - - /* Header title */ - ...getComponentElements("header-title") - .map(el => mountHeaderTitle(el, { viewport$, header$ })), - - /* Sidebar */ - ...getComponentElements("sidebar") - .map(el => el.getAttribute("data-md-type") === "navigation" - ? at(screen$, () => mountSidebar(el, { viewport$, header$, main$ })) - : at(tablet$, () => mountSidebar(el, { viewport$, header$, main$ })) - ), - - /* Navigation tabs */ - ...getComponentElements("tabs") - .map(el => mountTabs(el, { viewport$, header$ })), - - /* Table of contents */ - ...getComponentElements("toc") - .map(el => mountTableOfContents(el, { - viewport$, header$, main$, target$ - })), - - /* Back-to-top button */ - ...getComponentElements("top") - .map(el => mountBackToTop(el, { viewport$, header$, main$, target$ })) -)) - -/* Set up component observables */ -const component$ = document$ - .pipe( - switchMap(() => content$), - mergeWith(control$), - shareReplay(1) - ) - -/* Subscribe to all components */ -component$.subscribe() - -/* ---------------------------------------------------------------------------- - * Exports - * ------------------------------------------------------------------------- */ - -window.document$ = document$ /* Document observable */ -window.location$ = location$ /* Location subject */ -window.target$ = target$ /* Location target observable */ -window.keyboard$ = keyboard$ /* Keyboard observable */ -window.viewport$ = viewport$ /* Viewport observable */ -window.tablet$ = tablet$ /* Media tablet observable */ -window.screen$ = screen$ /* Media screen observable */ -window.print$ = print$ /* Media print observable */ -window.alert$ = alert$ /* Alert subject */ -window.progress$ = progress$ /* Progress indicator subject */ -window.component$ = component$ /* Component observable */ diff --git a/src/templates/assets/javascripts/components/_/index.ts b/src/templates/assets/javascripts/components/_/index.ts deleted file mode 100644 index 61c471d9..00000000 --- a/src/templates/assets/javascripts/components/_/index.ts +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { getElement, getElements } from "~/browser" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Component type - */ -export type ComponentType = - | "announce" /* Announcement bar */ - | "container" /* Container */ - | "consent" /* Consent */ - | "content" /* Content */ - | "dialog" /* Dialog */ - | "header" /* Header */ - | "header-title" /* Header title */ - | "header-topic" /* Header topic */ - | "main" /* Main area */ - | "outdated" /* Version warning */ - | "palette" /* Color palette */ - | "progress" /* Progress indicator */ - | "search" /* Search */ - | "search-query" /* Search input */ - | "search-result" /* Search results */ - | "search-share" /* Search sharing */ - | "search-suggest" /* Search suggestions */ - | "sidebar" /* Sidebar */ - | "skip" /* Skip link */ - | "source" /* Repository information */ - | "tabs" /* Navigation tabs */ - | "toc" /* Table of contents */ - | "top" /* Back-to-top button */ - -/** - * Component - * - * @template T - Component type - * @template U - Reference type - */ -export type Component< - T extends {} = {}, - U extends HTMLElement = HTMLElement -> = - T & { - ref: U /* Component reference */ - } - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Component type map - */ -interface ComponentTypeMap { - "announce": HTMLElement /* Announcement bar */ - "container": HTMLElement /* Container */ - "consent": HTMLElement /* Consent */ - "content": HTMLElement /* Content */ - "dialog": HTMLElement /* Dialog */ - "header": HTMLElement /* Header */ - "header-title": HTMLElement /* Header title */ - "header-topic": HTMLElement /* Header topic */ - "main": HTMLElement /* Main area */ - "outdated": HTMLElement /* Version warning */ - "palette": HTMLElement /* Color palette */ - "progress": HTMLElement /* Progress indicator */ - "search": HTMLElement /* Search */ - "search-query": HTMLInputElement /* Search input */ - "search-result": HTMLElement /* Search results */ - "search-share": HTMLAnchorElement /* Search sharing */ - "search-suggest": HTMLElement /* Search suggestions */ - "sidebar": HTMLElement /* Sidebar */ - "skip": HTMLAnchorElement /* Skip link */ - "source": HTMLAnchorElement /* Repository information */ - "tabs": HTMLElement /* Navigation tabs */ - "toc": HTMLElement /* Table of contents */ - "top": HTMLAnchorElement /* Back-to-top button */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Retrieve the element for a given component or throw a reference error - * - * @template T - Component type - * - * @param type - Component type - * @param node - Node of reference - * - * @returns Element - */ -export function getComponentElement<T extends ComponentType>( - type: T, node: ParentNode = document -): ComponentTypeMap[T] { - return getElement(`[data-md-component=${type}]`, node) -} - -/** - * Retrieve all elements for a given component - * - * @template T - Component type - * - * @param type - Component type - * @param node - Node of reference - * - * @returns Elements - */ -export function getComponentElements<T extends ComponentType>( - type: T, node: ParentNode = document -): ComponentTypeMap[T][] { - return getElements(`[data-md-component=${type}]`, node) -} diff --git a/src/templates/assets/javascripts/components/announce/index.ts b/src/templates/assets/javascripts/components/announce/index.ts deleted file mode 100644 index dd04b4ff..00000000 --- a/src/templates/assets/javascripts/components/announce/index.ts +++ /dev/null @@ -1,110 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { - EMPTY, - Observable, - Subject, - defer, - finalize, - fromEvent, - map, - tap -} from "rxjs" - -import { feature } from "~/_" -import { getElement } from "~/browser" - -import { Component } from "../_" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Announcement bar - */ -export interface Announce { - hash: number /* Content hash */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch announcement bar - * - * @param el - Announcement bar element - * - * @returns Announcement bar observable - */ -export function watchAnnounce( - el: HTMLElement -): Observable<Announce> { - const button = getElement(".md-typeset > :first-child", el) - return fromEvent(button, "click", { once: true }) - .pipe( - map(() => getElement(".md-typeset", el)), - map(content => ({ hash: __md_hash(content.innerHTML) })) - ) -} - -/** - * Mount announcement bar - * - * @param el - Announcement bar element - * - * @returns Announcement bar component observable - */ -export function mountAnnounce( - el: HTMLElement -): Observable<Component<Announce>> { - if (!feature("announce.dismiss") || !el.childElementCount) - return EMPTY - - /* Support instant navigation - see https://t.ly/3FTme */ - if (!el.hidden) { - const content = getElement(".md-typeset", el) - if (__md_hash(content.innerHTML) === __md_get("__announce")) - el.hidden = true - } - - /* Mount component on subscription */ - return defer(() => { - const push$ = new Subject<Announce>() - push$.subscribe(({ hash }) => { - el.hidden = true - - /* Persist preference in local storage */ - __md_set<number>("__announce", hash) - }) - - /* Create and return component */ - return watchAnnounce(el) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })) - ) - }) -} diff --git a/src/templates/assets/javascripts/components/consent/index.ts b/src/templates/assets/javascripts/components/consent/index.ts deleted file mode 100644 index bc99db58..00000000 --- a/src/templates/assets/javascripts/components/consent/index.ts +++ /dev/null @@ -1,116 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - finalize, - map, - tap -} from "rxjs" - -import { Component } from "../_" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Consent - */ -export interface Consent { - hidden: boolean /* Consent is hidden */ -} - -/** - * Consent defaults - */ -export interface ConsentDefaults { - analytics?: boolean /* Consent for Analytics */ - github?: boolean /* Consent for GitHub */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Watch options - */ -interface WatchOptions { - target$: Observable<HTMLElement> /* Target observable */ -} - -/** - * Mount options - */ -interface MountOptions { - target$: Observable<HTMLElement> /* Target observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch consent - * - * @param el - Consent element - * @param options - Options - * - * @returns Consent observable - */ -export function watchConsent( - el: HTMLElement, { target$ }: WatchOptions -): Observable<Consent> { - return target$ - .pipe( - map(target => ({ hidden: target !== el })) - ) -} - -/* ------------------------------------------------------------------------- */ - -/** - * Mount consent - * - * @param el - Consent element - * @param options - Options - * - * @returns Consent component observable - */ -export function mountConsent( - el: HTMLElement, options: MountOptions -): Observable<Component<Consent>> { - const internal$ = new Subject<Consent>() - internal$.subscribe(({ hidden }) => { - el.hidden = hidden - }) - - /* Create and return component */ - return watchConsent(el, options) - .pipe( - tap(state => internal$.next(state)), - finalize(() => internal$.complete()), - map(state => ({ ref: el, ...state })) - ) -} diff --git a/src/templates/assets/javascripts/components/content/_/index.ts b/src/templates/assets/javascripts/components/content/_/index.ts deleted file mode 100644 index 899a695c..00000000 --- a/src/templates/assets/javascripts/components/content/_/index.ts +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { Observable, merge } from "rxjs" - -import { Viewport, getElements } from "~/browser" - -import { Component } from "../../_" -import { - Annotation, - mountAnnotationBlock -} from "../annotation" -import { - CodeBlock, - mountCodeBlock -} from "../code" -import { - Details, - mountDetails -} from "../details" -import { - Mermaid, - mountMermaid -} from "../mermaid" -import { - DataTable, - mountDataTable -} from "../table" -import { - ContentTabs, - mountContentTabs -} from "../tabs" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Content - */ -export type Content = - | Annotation - | CodeBlock - | ContentTabs - | DataTable - | Details - | Mermaid - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Mount options - */ -interface MountOptions { - viewport$: Observable<Viewport> /* Viewport observable */ - target$: Observable<HTMLElement> /* Location target observable */ - print$: Observable<boolean> /* Media print observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Mount content - * - * This function mounts all components that are found in the content of the - * actual article, including code blocks, data tables and details. - * - * @param el - Content element - * @param options - Options - * - * @returns Content component observable - */ -export function mountContent( - el: HTMLElement, { viewport$, target$, print$ }: MountOptions -): Observable<Component<Content>> { - return merge( - - /* Annotations */ - ...getElements(".annotate:not(.highlight)", el) - .map(child => mountAnnotationBlock(child, { target$, print$ })), - - /* Code blocks */ - ...getElements("pre:not(.mermaid) > code", el) - .map(child => mountCodeBlock(child, { target$, print$ })), - - /* Mermaid diagrams */ - ...getElements("pre.mermaid", el) - .map(child => mountMermaid(child)), - - /* Data tables */ - ...getElements("table:not([class])", el) - .map(child => mountDataTable(child)), - - /* Details */ - ...getElements("details", el) - .map(child => mountDetails(child, { target$, print$ })), - - /* Content tabs */ - ...getElements("[data-tabs]", el) - .map(child => mountContentTabs(child, { viewport$ })) - ) -} diff --git a/src/templates/assets/javascripts/components/content/annotation/_/index.ts b/src/templates/assets/javascripts/components/content/annotation/_/index.ts deleted file mode 100644 index c5138fa4..00000000 --- a/src/templates/assets/javascripts/components/content/annotation/_/index.ts +++ /dev/null @@ -1,272 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - animationFrameScheduler, - auditTime, - combineLatest, - debounceTime, - defer, - delay, - endWith, - filter, - finalize, - fromEvent, - ignoreElements, - map, - merge, - switchMap, - take, - takeUntil, - tap, - throttleTime, - withLatestFrom -} from "rxjs" - -import { - ElementOffset, - getActiveElement, - getElementSize, - watchElementContentOffset, - watchElementFocus, - watchElementOffset, - watchElementVisibility -} from "~/browser" - -import { Component } from "../../../_" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Annotation - */ -export interface Annotation { - active: boolean /* Annotation is active */ - offset: ElementOffset /* Annotation offset */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Mount options - */ -interface MountOptions { - target$: Observable<HTMLElement> /* Location target observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch annotation - * - * @param el - Annotation element - * @param container - Containing element - * - * @returns Annotation observable - */ -export function watchAnnotation( - el: HTMLElement, container: HTMLElement -): Observable<Annotation> { - const offset$ = defer(() => combineLatest([ - watchElementOffset(el), - watchElementContentOffset(container) - ])) - .pipe( - map(([{ x, y }, scroll]): ElementOffset => { - const { width, height } = getElementSize(el) - return ({ - x: x - scroll.x + width / 2, - y: y - scroll.y + height / 2 - }) - }) - ) - - /* Actively watch annotation on focus */ - return watchElementFocus(el) - .pipe( - switchMap(active => offset$ - .pipe( - map(offset => ({ active, offset })), - take(+!active || Infinity) - ) - ) - ) -} - -/** - * Mount annotation - * - * @param el - Annotation element - * @param container - Containing element - * @param options - Options - * - * @returns Annotation component observable - */ -export function mountAnnotation( - el: HTMLElement, container: HTMLElement, { target$ }: MountOptions -): Observable<Component<Annotation>> { - const [tooltip, index] = Array.from(el.children) - - /* Mount component on subscription */ - return defer(() => { - const push$ = new Subject<Annotation>() - const done$ = push$.pipe(ignoreElements(), endWith(true)) - push$.subscribe({ - - /* Handle emission */ - next({ offset }) { - el.style.setProperty("--md-tooltip-x", `${offset.x}px`) - el.style.setProperty("--md-tooltip-y", `${offset.y}px`) - }, - - /* Handle complete */ - complete() { - el.style.removeProperty("--md-tooltip-x") - el.style.removeProperty("--md-tooltip-y") - } - }) - - /* Start animation only when annotation is visible */ - watchElementVisibility(el) - .pipe( - takeUntil(done$) - ) - .subscribe(visible => { - el.toggleAttribute("data-md-visible", visible) - }) - - /* Toggle tooltip presence to mitigate empty lines when copying */ - merge( - push$.pipe(filter(({ active }) => active)), - push$.pipe(debounceTime(250), filter(({ active }) => !active)) - ) - .subscribe({ - - /* Handle emission */ - next({ active }) { - if (active) - el.prepend(tooltip) - else - tooltip.remove() - }, - - /* Handle complete */ - complete() { - el.prepend(tooltip) - } - }) - - /* Toggle tooltip visibility */ - push$ - .pipe( - auditTime(16, animationFrameScheduler) - ) - .subscribe(({ active }) => { - tooltip.classList.toggle("md-tooltip--active", active) - }) - - /* Track relative origin of tooltip */ - push$ - .pipe( - throttleTime(125, animationFrameScheduler), - filter(() => !!el.offsetParent), - map(() => el.offsetParent!.getBoundingClientRect()), - map(({ x }) => x) - ) - .subscribe({ - - /* Handle emission */ - next(origin) { - if (origin) - el.style.setProperty("--md-tooltip-0", `${-origin}px`) - else - el.style.removeProperty("--md-tooltip-0") - }, - - /* Handle complete */ - complete() { - el.style.removeProperty("--md-tooltip-0") - } - }) - - /* Allow to copy link without scrolling to anchor */ - fromEvent<MouseEvent>(index, "click") - .pipe( - takeUntil(done$), - filter(ev => !(ev.metaKey || ev.ctrlKey)) - ) - .subscribe(ev => { - ev.stopPropagation() - ev.preventDefault() - }) - - /* Allow to open link in new tab or blur on close */ - fromEvent<MouseEvent>(index, "mousedown") - .pipe( - takeUntil(done$), - withLatestFrom(push$) - ) - .subscribe(([ev, { active }]) => { - - /* Open in new tab */ - if (ev.button !== 0 || ev.metaKey || ev.ctrlKey) { - ev.preventDefault() - - /* Close annotation */ - } else if (active) { - ev.preventDefault() - - /* Focus parent annotation, if any */ - const parent = el.parentElement!.closest(".md-annotation") - if (parent instanceof HTMLElement) - parent.focus() - else - getActiveElement()?.blur() - } - }) - - /* Open and focus annotation on location target */ - target$ - .pipe( - takeUntil(done$), - filter(target => target === tooltip), - delay(125) - ) - .subscribe(() => el.focus()) - - /* Create and return component */ - return watchAnnotation(el, container) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })) - ) - }) -} diff --git a/src/templates/assets/javascripts/components/content/annotation/block/index.ts b/src/templates/assets/javascripts/components/content/annotation/block/index.ts deleted file mode 100644 index c73b01fa..00000000 --- a/src/templates/assets/javascripts/components/content/annotation/block/index.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { EMPTY, Observable, defer } from "rxjs" - -import { Component } from "../../../_" -import { Annotation } from "../_" -import { mountAnnotationList } from "../list" - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Mount options - */ -interface MountOptions { - target$: Observable<HTMLElement> /* Location target observable */ - print$: Observable<boolean> /* Media print observable */ -} - -/* ---------------------------------------------------------------------------- - * Helper functions - * ------------------------------------------------------------------------- */ - -/** - * Find list element directly following a block - * - * @param el - Annotation block element - * - * @returns List element or nothing - */ -function findList(el: HTMLElement): HTMLElement | undefined { - if (el.nextElementSibling) { - const sibling = el.nextElementSibling as HTMLElement - if (sibling.tagName === "OL") - return sibling - - /* Skip empty paragraphs - see https://bit.ly/3r4ZJ2O */ - else if (sibling.tagName === "P" && !sibling.children.length) - return findList(sibling) - } - - /* Everything else */ - return undefined -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Mount annotation block - * - * @param el - Annotation block element - * @param options - Options - * - * @returns Annotation component observable - */ -export function mountAnnotationBlock( - el: HTMLElement, options: MountOptions -): Observable<Component<Annotation>> { - return defer(() => { - const list = findList(el) - return typeof list !== "undefined" - ? mountAnnotationList(list, el, options) - : EMPTY - }) -} diff --git a/src/templates/assets/javascripts/components/content/annotation/index.ts b/src/templates/assets/javascripts/components/content/annotation/index.ts deleted file mode 100644 index c593b723..00000000 --- a/src/templates/assets/javascripts/components/content/annotation/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./block" -export * from "./list" diff --git a/src/templates/assets/javascripts/components/content/annotation/list/index.ts b/src/templates/assets/javascripts/components/content/annotation/list/index.ts deleted file mode 100644 index 725dd583..00000000 --- a/src/templates/assets/javascripts/components/content/annotation/list/index.ts +++ /dev/null @@ -1,209 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { - EMPTY, - Observable, - Subject, - defer, - endWith, - finalize, - ignoreElements, - merge, - share, - takeUntil -} from "rxjs" - -import { - getElement, - getElements, - getOptionalElement -} from "~/browser" -import { renderAnnotation } from "~/templates" - -import { Component } from "../../../_" -import { - Annotation, - mountAnnotation -} from "../_" - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Mount options - */ -interface MountOptions { - target$: Observable<HTMLElement> /* Location target observable */ - print$: Observable<boolean> /* Media print observable */ -} - -/* ---------------------------------------------------------------------------- - * Helper functions - * ------------------------------------------------------------------------- */ - -/** - * Find all annotation hosts in the containing element - * - * @param container - Containing element - * - * @returns Annotation hosts - */ -function findHosts(container: HTMLElement): HTMLElement[] { - return container.tagName === "CODE" - ? getElements(".c, .c1, .cm", container) - : [container] -} - -/** - * Find all annotation markers in the containing element - * - * @param container - Containing element - * - * @returns Annotation markers - */ -function findMarkers(container: HTMLElement): Text[] { - const markers: Text[] = [] - for (const el of findHosts(container)) { - const nodes: Text[] = [] - - /* Find all text nodes in current element */ - const it = document.createNodeIterator(el, NodeFilter.SHOW_TEXT) - for (let node = it.nextNode(); node; node = it.nextNode()) - nodes.push(node as Text) - - /* Find all markers in each text node */ - for (let text of nodes) { - let match: RegExpExecArray | null - - /* Split text at marker and add to list */ - while ((match = /(\(\d+\))(!)?/.exec(text.textContent!))) { - const [, id, force] = match - if (typeof force === "undefined") { - const marker = text.splitText(match.index) - text = marker.splitText(id.length) - markers.push(marker) - - /* Replace entire text with marker */ - } else { - text.textContent = id - markers.push(text) - break - } - } - } - } - return markers -} - -/** - * Swap the child nodes of two elements - * - * @param source - Source element - * @param target - Target element - */ -function swap(source: HTMLElement, target: HTMLElement): void { - target.append(...Array.from(source.childNodes)) -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Mount annotation list - * - * This function analyzes the containing code block and checks for markers - * referring to elements in the given annotation list. If no markers are found, - * the list is left untouched. Otherwise, list elements are rendered as - * annotations inside the code block. - * - * @param el - Annotation list element - * @param container - Containing element - * @param options - Options - * - * @returns Annotation component observable - */ -export function mountAnnotationList( - el: HTMLElement, container: HTMLElement, { target$, print$ }: MountOptions -): Observable<Component<Annotation>> { - - /* Compute prefix for tooltip anchors */ - const parent = container.closest("[id]") - const prefix = parent?.id - - /* Find and replace all markers with empty annotations */ - const annotations = new Map<string, HTMLElement>() - for (const marker of findMarkers(container)) { - const [, id] = marker.textContent!.match(/\((\d+)\)/)! - if (getOptionalElement(`:scope > li:nth-child(${id})`, el)) { - annotations.set(id, renderAnnotation(id, prefix)) - marker.replaceWith(annotations.get(id)!) - } - } - - /* Keep list if there are no annotations to render */ - if (annotations.size === 0) - return EMPTY - - /* Mount component on subscription */ - return defer(() => { - const push$ = new Subject() - const done$ = push$.pipe(ignoreElements(), endWith(true)) - - /* Retrieve container pairs for swapping */ - const pairs: [HTMLElement, HTMLElement][] = [] - for (const [id, annotation] of annotations) - pairs.push([ - getElement(".md-typeset", annotation), - getElement(`:scope > li:nth-child(${id})`, el) - ]) - - /* Handle print mode - see https://bit.ly/3rgPdpt */ - print$.pipe(takeUntil(done$)) - .subscribe(active => { - el.hidden = !active - - /* Add class to discern list element */ - el.classList.toggle("md-annotation-list", active) - - /* Show annotations in code block or list (print) */ - for (const [inner, child] of pairs) - if (!active) - swap(child, inner) - else - swap(inner, child) - }) - - /* Create and return component */ - return merge(...[...annotations] - .map(([, annotation]) => ( - mountAnnotation(annotation, container, { target$ }) - )) - ) - .pipe( - finalize(() => push$.complete()), - share() - ) - }) -} diff --git a/src/templates/assets/javascripts/components/content/code/_/index.ts b/src/templates/assets/javascripts/components/content/code/_/index.ts deleted file mode 100644 index ccc09339..00000000 --- a/src/templates/assets/javascripts/components/content/code/_/index.ts +++ /dev/null @@ -1,238 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 ClipboardJS from "clipboard" -import { - EMPTY, - Observable, - Subject, - defer, - distinctUntilChanged, - distinctUntilKeyChanged, - filter, - finalize, - map, - mergeWith, - switchMap, - take, - tap -} from "rxjs" - -import { feature } from "~/_" -import { - getElementContentSize, - watchElementSize, - watchElementVisibility -} from "~/browser" -import { renderClipboardButton } from "~/templates" - -import { Component } from "../../../_" -import { - Annotation, - mountAnnotationList -} from "../../annotation" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Code block - */ -export interface CodeBlock { - scrollable: boolean /* Code block overflows */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Mount options - */ -interface MountOptions { - target$: Observable<HTMLElement> /* Location target observable */ - print$: Observable<boolean> /* Media print observable */ -} - -/* ---------------------------------------------------------------------------- - * Data - * ------------------------------------------------------------------------- */ - -/** - * Global sequence number for code blocks - */ -let sequence = 0 - -/* ---------------------------------------------------------------------------- - * Helper functions - * ------------------------------------------------------------------------- */ - -/** - * Find candidate list element directly following a code block - * - * @param el - Code block element - * - * @returns List element or nothing - */ -function findCandidateList(el: HTMLElement): HTMLElement | undefined { - if (el.nextElementSibling) { - const sibling = el.nextElementSibling as HTMLElement - if (sibling.tagName === "OL") - return sibling - - /* Skip empty paragraphs - see https://bit.ly/3r4ZJ2O */ - else if (sibling.tagName === "P" && !sibling.children.length) - return findCandidateList(sibling) - } - - /* Everything else */ - return undefined -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch code block - * - * This function monitors size changes of the viewport, as well as switches of - * content tabs with embedded code blocks, as both may trigger overflow. - * - * @param el - Code block element - * - * @returns Code block observable - */ -export function watchCodeBlock( - el: HTMLElement -): Observable<CodeBlock> { - return watchElementSize(el) - .pipe( - map(({ width }) => { - const content = getElementContentSize(el) - return { - scrollable: content.width > width - } - }), - distinctUntilKeyChanged("scrollable") - ) -} - -/** - * Mount code block - * - * This function ensures that an overflowing code block is focusable through - * keyboard, so it can be scrolled without a mouse to improve on accessibility. - * Furthermore, if code annotations are enabled, they are mounted if and only - * if the code block is currently visible, e.g., not in a hidden content tab. - * - * Note that code blocks may be mounted eagerly or lazily. If they're mounted - * lazily (on first visibility), code annotation anchor links will not work, - * as they are evaluated on initial page load, and code annotations in general - * might feel a little bumpier. - * - * @param el - Code block element - * @param options - Options - * - * @returns Code block and annotation component observable - */ -export function mountCodeBlock( - el: HTMLElement, options: MountOptions -): Observable<Component<CodeBlock | Annotation>> { - const { matches: hover } = matchMedia("(hover)") - - /* Defer mounting of code block - see https://bit.ly/3vHVoVD */ - const factory$ = defer(() => { - const push$ = new Subject<CodeBlock>() - push$.subscribe(({ scrollable }) => { - if (scrollable && hover) - el.setAttribute("tabindex", "0") - else - el.removeAttribute("tabindex") - }) - - /* Render button for Clipboard.js integration */ - if (ClipboardJS.isSupported()) { - if (el.closest(".copy") || ( - feature("content.code.copy") && !el.closest(".no-copy") - )) { - const parent = el.closest("pre")! - parent.id = `__code_${sequence++}` - parent.insertBefore( - renderClipboardButton(parent.id), - el - ) - } - } - - /* Handle code annotations */ - const container = el.closest(".highlight") - if (container instanceof HTMLElement) { - const list = findCandidateList(container) - - /* Mount code annotations, if enabled */ - if (typeof list !== "undefined" && ( - container.classList.contains("annotate") || - feature("content.code.annotate") - )) { - const annotations$ = mountAnnotationList(list, el, options) - - /* Create and return component */ - return watchCodeBlock(el) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })), - mergeWith( - watchElementSize(container) - .pipe( - map(({ width, height }) => width && height), - distinctUntilChanged(), - switchMap(active => active ? annotations$ : EMPTY) - ) - ) - ) - } - } - - /* Create and return component */ - return watchCodeBlock(el) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })) - ) - }) - - /* Mount code block lazily */ - if (feature("content.lazy")) - return watchElementVisibility(el) - .pipe( - filter(visible => visible), - take(1), - switchMap(() => factory$) - ) - - /* Mount code block */ - return factory$ -} diff --git a/src/templates/assets/javascripts/components/content/code/index.ts b/src/templates/assets/javascripts/components/content/code/index.ts deleted file mode 100644 index 3f86e2b4..00000000 --- a/src/templates/assets/javascripts/components/content/code/index.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./_" diff --git a/src/templates/assets/javascripts/components/content/details/index.ts b/src/templates/assets/javascripts/components/content/details/index.ts deleted file mode 100644 index 17bfae45..00000000 --- a/src/templates/assets/javascripts/components/content/details/index.ts +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - defer, - filter, - finalize, - map, - merge, - tap -} from "rxjs" - -import { Component } from "../../_" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Details - */ -export interface Details { - action: "open" | "close" /* Details state */ - reveal?: boolean /* Details is revealed */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Watch options - */ -interface WatchOptions { - target$: Observable<HTMLElement> /* Location target observable */ - print$: Observable<boolean> /* Media print observable */ -} - -/** - * Mount options - */ -interface MountOptions { - target$: Observable<HTMLElement> /* Location target observable */ - print$: Observable<boolean> /* Media print observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch details - * - * @param el - Details element - * @param options - Options - * - * @returns Details observable - */ -export function watchDetails( - el: HTMLDetailsElement, { target$, print$ }: WatchOptions -): Observable<Details> { - let open = true - return merge( - - /* Open and focus details on location target */ - target$ - .pipe( - map(target => target.closest("details:not([open])")!), - filter(details => el === details), - map(() => ({ - action: "open", reveal: true - }) as Details) - ), - - /* Open details on print and close afterwards */ - print$ - .pipe( - filter(active => active || !open), - tap(() => open = el.open), - map(active => ({ - action: active ? "open" : "close" - }) as Details) - ) - ) -} - -/** - * Mount details - * - * This function ensures that `details` tags are opened on anchor jumps and - * prior to printing, so the whole content of the page is visible. - * - * @param el - Details element - * @param options - Options - * - * @returns Details component observable - */ -export function mountDetails( - el: HTMLDetailsElement, options: MountOptions -): Observable<Component<Details>> { - return defer(() => { - const push$ = new Subject<Details>() - push$.subscribe(({ action, reveal }) => { - el.toggleAttribute("open", action === "open") - if (reveal) - el.scrollIntoView() - }) - - /* Create and return component */ - return watchDetails(el, options) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })) - ) - }) -} diff --git a/src/templates/assets/javascripts/components/content/index.ts b/src/templates/assets/javascripts/components/content/index.ts deleted file mode 100644 index a29d8b41..00000000 --- a/src/templates/assets/javascripts/components/content/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./annotation" -export * from "./code" -export * from "./details" -export * from "./table" -export * from "./tabs" diff --git a/src/templates/assets/javascripts/components/content/mermaid/index.css b/src/templates/assets/javascripts/components/content/mermaid/index.css deleted file mode 100644 index 3092b8ec..00000000 --- a/src/templates/assets/javascripts/components/content/mermaid/index.css +++ /dev/null @@ -1,430 +0,0 @@ -/* - * Copyright (c) 2016-2023 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. - */ - -/* ---------------------------------------------------------------------------- - * Rules: general - * ------------------------------------------------------------------------- */ - -/* General node */ -.node circle, -.node ellipse, -.node path, -.node polygon, -.node rect { - fill: var(--md-mermaid-node-bg-color); - stroke: var(--md-mermaid-node-fg-color); -} - -/* General marker */ -marker { - fill: var(--md-mermaid-edge-color) !important; -} - -/* General edge label */ -.edgeLabel .label rect { - fill: transparent; -} - -/* ---------------------------------------------------------------------------- - * Rules: flowcharts - * ------------------------------------------------------------------------- */ - -/* Flowchart node label */ -.label { - color: var(--md-mermaid-label-fg-color); - font-family: var(--md-mermaid-font-family); -} - -/* Flowchart node label container */ -.label foreignObject { - overflow: visible; - line-height: initial; -} - -/* Flowchart edge label in node label */ -.label div .edgeLabel { - color: var(--md-mermaid-label-fg-color); - background-color: var(--md-mermaid-label-bg-color); -} - -/* Flowchart edge label */ -.edgeLabel, -.edgeLabel rect { - color: var(--md-mermaid-edge-color); - background-color: var(--md-mermaid-label-bg-color); - fill: var(--md-mermaid-label-bg-color); -} - -/* Flowchart edge path */ -.edgePath .path, -.flowchart-link { - stroke: var(--md-mermaid-edge-color); - stroke-width: .05rem; -} - -/* Flowchart arrow head */ -.edgePath .arrowheadPath { - fill: var(--md-mermaid-edge-color); - stroke: none; -} - -/* Flowchart subgraph */ -.cluster rect { - fill: var(--md-default-fg-color--lightest); - stroke: var(--md-default-fg-color--lighter); -} - -/* Flowchart subgraph labels */ -.cluster span { - color: var(--md-mermaid-label-fg-color); - font-family: var(--md-mermaid-font-family); -} - -/* Flowchart markers */ -g #flowchart-circleStart, -g #flowchart-circleEnd, -g #flowchart-crossStart, -g #flowchart-crossEnd, -g #flowchart-pointStart, -g #flowchart-pointEnd { - stroke: none; -} - -/* ---------------------------------------------------------------------------- - * Rules: class diagrams - * ------------------------------------------------------------------------- */ - -/* Class group node */ -g.classGroup line, -g.classGroup rect { - fill: var(--md-mermaid-node-bg-color); - stroke: var(--md-mermaid-node-fg-color); -} - -/* Class group node text */ -g.classGroup text { - font-family: var(--md-mermaid-font-family); - fill: var(--md-mermaid-label-fg-color); -} - -/* Class label box */ -.classLabel .box { - background-color: var(--md-mermaid-label-bg-color); - opacity: 1; - fill: var(--md-mermaid-label-bg-color); -} - -/* Class label text */ -.classLabel .label { - font-family: var(--md-mermaid-font-family); - fill: var(--md-mermaid-label-fg-color); -} - -/* Class group divider */ -.node .divider { - stroke: var(--md-mermaid-node-fg-color); -} - -/* Class relation */ -.relation { - stroke: var(--md-mermaid-edge-color); -} - -/* Class relation cardinality */ -.cardinality { - font-family: var(--md-mermaid-font-family); - fill: var(--md-mermaid-label-fg-color); -} - -/* Class relation cardinality text */ -.cardinality text { - fill: inherit !important; -} - -/* Class extension, composition and dependency marker */ -defs #classDiagram-extensionStart, -defs #classDiagram-extensionEnd, -defs #classDiagram-compositionStart, -defs #classDiagram-compositionEnd, -defs #classDiagram-dependencyStart, -defs #classDiagram-dependencyEnd { - fill: var(--md-mermaid-edge-color) !important; - stroke: var(--md-mermaid-edge-color) !important; -} - -/* Class aggregation marker */ -defs #classDiagram-aggregationStart, -defs #classDiagram-aggregationEnd { - fill: var(--md-mermaid-label-bg-color) !important; - stroke: var(--md-mermaid-edge-color) !important; -} - -/* ---------------------------------------------------------------------------- - * Rules: state diagrams - * ------------------------------------------------------------------------- */ - -/* State group node */ -g.stateGroup rect { - fill: var(--md-mermaid-node-bg-color); - stroke: var(--md-mermaid-node-fg-color); -} - -/* State group title */ -g.stateGroup .state-title { - font-family: var(--md-mermaid-font-family); - fill: var(--md-mermaid-label-fg-color) !important; -} - -/* State group background */ -g.stateGroup .composit { - fill: var(--md-mermaid-label-bg-color); -} - -/* State node label */ -.nodeLabel { - color: var(--md-mermaid-label-fg-color); - font-family: var(--md-mermaid-font-family); -} - -/* State start and end marker */ -.start-state, -.node circle.state-start, -.node circle.state-end { - fill: var(--md-mermaid-edge-color); - stroke: none; -} - -/* State end marker */ -.end-state-outer, -.end-state-inner { - fill: var(--md-mermaid-edge-color); -} - -/* State end marker */ -.end-state-inner, -.node circle.state-end { - stroke: var(--md-mermaid-label-bg-color); -} - -/* State transition */ -.transition { - stroke: var(--md-mermaid-edge-color); -} - -/* State fork and join */ -[id^=state-fork] rect, -[id^=state-join] rect { - fill: var(--md-mermaid-edge-color) !important; - stroke: none !important; -} - -/* State cluster (yes, 2x... Mermaid WTF) */ -.statediagram-cluster.statediagram-cluster .inner { - fill: var(--md-default-bg-color); -} - -/* State cluster node */ -.statediagram-cluster rect { - fill: var(--md-mermaid-node-bg-color); - stroke: var(--md-mermaid-node-fg-color); -} - -/* State cluster divider */ -.statediagram-state rect.divider { - fill: var(--md-default-fg-color--lightest); - stroke: var(--md-default-fg-color--lighter); -} - -/* State diagram markers */ -defs #statediagram-barbEnd { - stroke: var(--md-mermaid-edge-color); -} - -/* ---------------------------------------------------------------------------- - * Rules: entity-relationship diagrams - * ------------------------------------------------------------------------- */ - -/* Attribute box */ -.attributeBoxEven, -.attributeBoxOdd { - fill: var(--md-mermaid-node-bg-color); - stroke: var(--md-mermaid-node-fg-color); -} - -/* Entity node */ -.entityBox { - fill: var(--md-mermaid-label-bg-color); - stroke: var(--md-mermaid-node-fg-color); -} - -/* Entity node label */ -.entityLabel { - font-family: var(--md-mermaid-font-family); - fill: var(--md-mermaid-label-fg-color); -} - -/* Entity relationship label container */ -.relationshipLabelBox { - background-color: var(--md-mermaid-label-bg-color); - opacity: 1; - fill: var(--md-mermaid-label-bg-color); - fill-opacity: 1; -} - -/* Entity relationship label */ -.relationshipLabel { - fill: var(--md-mermaid-label-fg-color); -} - -/* Entity relationship line { */ -.relationshipLine { - stroke: var(--md-mermaid-edge-color); -} - -/* Entity relationship line markers */ -defs #ZERO_OR_ONE_START *, -defs #ZERO_OR_ONE_END *, -defs #ZERO_OR_MORE_START *, -defs #ZERO_OR_MORE_END *, -defs #ONLY_ONE_START *, -defs #ONLY_ONE_END *, -defs #ONE_OR_MORE_START *, -defs #ONE_OR_MORE_END * { - stroke: var(--md-mermaid-edge-color) !important; -} - -/* Entity relationship line markers */ -defs #ZERO_OR_MORE_START circle, -defs #ZERO_OR_MORE_END circle { - fill: var(--md-mermaid-label-bg-color); -} - -/* ---------------------------------------------------------------------------- - * Rules: sequence diagrams - * ------------------------------------------------------------------------- */ - -/* Sequence actor */ -.actor { - fill: var(--md-mermaid-sequence-actor-bg-color); - stroke: var(--md-mermaid-sequence-actor-border-color); -} - -/* Sequence actor text */ -text.actor > tspan { - font-family: var(--md-mermaid-font-family); - fill: var(--md-mermaid-sequence-actor-fg-color); -} - -/* Sequence actor line */ -line { - stroke: var(--md-mermaid-sequence-actor-line-color); -} - -/* Sequence actor */ -.actor-man circle, -.actor-man line { - fill: var(--md-mermaid-sequence-actorman-bg-color); - stroke: var(--md-mermaid-sequence-actorman-line-color); -} - -/* Sequence message line */ -.messageLine0, -.messageLine1 { - stroke: var(--md-mermaid-sequence-message-line-color); -} - -/* Sequence note */ -.note { - fill: var(--md-mermaid-sequence-note-bg-color); - stroke: var(--md-mermaid-sequence-note-border-color); -} - -/* Sequence message, loop and note text */ -.messageText, -.loopText, -.loopText > tspan, -.noteText > tspan { - font-family: var(--md-mermaid-font-family) !important; - stroke: none; -} - -/* Sequence message text */ -.messageText { - fill: var(--md-mermaid-sequence-message-fg-color); -} - -/* Sequence loop text */ -.loopText, -.loopText > tspan { - fill: var(--md-mermaid-sequence-loop-fg-color); -} - -/* Sequence note text */ -.noteText > tspan { - fill: var(--md-mermaid-sequence-note-fg-color); -} - -/* Sequence arrow head */ -#arrowhead path { - fill: var(--md-mermaid-sequence-message-line-color); - stroke: none; -} - -/* Sequence loop line */ -.loopLine { - fill: var(--md-mermaid-sequence-loop-bg-color); - stroke: var(--md-mermaid-sequence-loop-border-color); -} - -/* Sequence label box */ -.labelBox { - fill: var(--md-mermaid-sequence-label-bg-color); - stroke: none; -} - -/* Sequence label text */ -.labelText, -.labelText > span { - font-family: var(--md-mermaid-font-family); - fill: var(--md-mermaid-sequence-label-fg-color); -} - -/* Sequence number */ -.sequenceNumber { - fill: var(--md-mermaid-sequence-number-fg-color); -} - -/* Sequence rectangle */ -rect.rect { - fill: var(--md-mermaid-sequence-box-bg-color); - stroke: none; -} - -/* Sequence rectangle text */ -rect.rect + text.text { - fill: var(--md-mermaid-sequence-box-fg-color); -} - -/* Sequence diagram markers */ -defs #sequencenumber { - fill: var(--md-mermaid-sequence-number-bg-color) !important; -} diff --git a/src/templates/assets/javascripts/components/content/mermaid/index.ts b/src/templates/assets/javascripts/components/content/mermaid/index.ts deleted file mode 100644 index 3f6480fd..00000000 --- a/src/templates/assets/javascripts/components/content/mermaid/index.ts +++ /dev/null @@ -1,133 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - map, - of, - shareReplay, - tap -} from "rxjs" - -import { watchScript } from "~/browser" -import { h } from "~/utilities" - -import { Component } from "../../_" - -import themeCSS from "./index.css" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Mermaid diagram - */ -export interface Mermaid {} - -/* ---------------------------------------------------------------------------- - * Data - * ------------------------------------------------------------------------- */ - -/** - * Mermaid instance observable - */ -let mermaid$: Observable<void> - -/** - * Global sequence number for diagrams - */ -let sequence = 0 - -/* ---------------------------------------------------------------------------- - * Helper functions - * ------------------------------------------------------------------------- */ - -/** - * Fetch Mermaid script - * - * @returns Mermaid scripts observable - */ -function fetchScripts(): Observable<void> { - return typeof mermaid === "undefined" || mermaid instanceof Element - ? watchScript("https://unpkg.com/mermaid@9.4.3/dist/mermaid.min.js") - : of(undefined) -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Mount Mermaid diagram - * - * @param el - Code block element - * - * @returns Mermaid diagram component observable - */ -export function mountMermaid( - el: HTMLElement -): Observable<Component<Mermaid>> { - el.classList.remove("mermaid") // Hack: mitigate https://bit.ly/3CiN6Du - mermaid$ ||= fetchScripts() - .pipe( - tap(() => mermaid.initialize({ - startOnLoad: false, - themeCSS, - sequence: { - actorFontSize: "16px", // Hack: mitigate https://bit.ly/3y0NEi3 - messageFontSize: "16px", - noteFontSize: "16px" - } - })), - map(() => undefined), - shareReplay(1) - ) - - /* Render diagram */ - mermaid$.subscribe(() => { - el.classList.add("mermaid") // Hack: mitigate https://bit.ly/3CiN6Du - const id = `__mermaid_${sequence++}` - - /* Create host element to replace code block */ - const host = h("div", { class: "mermaid" }) - const text = el.textContent - - /* Render and inject diagram */ - mermaid.mermaidAPI.render(id, text, (svg: string, fn: Function) => { - - /* Create a shadow root and inject diagram */ - const shadow = host.attachShadow({ mode: "closed" }) - shadow.innerHTML = svg - - /* Replace code block with diagram and bind functions */ - el.replaceWith(host) - fn?.(shadow) - }) - }) - - /* Create and return component */ - return mermaid$ - .pipe( - map(() => ({ ref: el })) - ) -} diff --git a/src/templates/assets/javascripts/components/content/table/index.ts b/src/templates/assets/javascripts/components/content/table/index.ts deleted file mode 100644 index c318e7a6..00000000 --- a/src/templates/assets/javascripts/components/content/table/index.ts +++ /dev/null @@ -1,70 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { Observable, of } from "rxjs" - -import { renderTable } from "~/templates" -import { h } from "~/utilities" - -import { Component } from "../../_" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Data table - */ -export interface DataTable {} - -/* ---------------------------------------------------------------------------- - * Data - * ------------------------------------------------------------------------- */ - -/** - * Sentinel for replacement - */ -const sentinel = h("table") - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Mount data table - * - * This function wraps a data table in another scrollable container, so it can - * be smoothly scrolled on smaller screen sizes and won't break the layout. - * - * @param el - Data table element - * - * @returns Data table component observable - */ -export function mountDataTable( - el: HTMLElement -): Observable<Component<DataTable>> { - el.replaceWith(sentinel) - sentinel.replaceWith(renderTable(el)) - - /* Create and return component */ - return of({ ref: el }) -} diff --git a/src/templates/assets/javascripts/components/content/tabs/index.ts b/src/templates/assets/javascripts/components/content/tabs/index.ts deleted file mode 100644 index f57447e2..00000000 --- a/src/templates/assets/javascripts/components/content/tabs/index.ts +++ /dev/null @@ -1,265 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - animationFrameScheduler, - asyncScheduler, - auditTime, - combineLatest, - defer, - endWith, - finalize, - fromEvent, - ignoreElements, - map, - merge, - skip, - startWith, - subscribeOn, - takeUntil, - tap, - withLatestFrom -} from "rxjs" - -import { feature } from "~/_" -import { - Viewport, - getElement, - getElementContentOffset, - getElementContentSize, - getElementOffset, - getElementSize, - getElements, - watchElementContentOffset, - watchElementSize -} from "~/browser" -import { renderTabbedControl } from "~/templates" - -import { Component } from "../../_" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Content tabs - */ -export interface ContentTabs { - active: HTMLLabelElement /* Active tab label */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Mount options - */ -interface MountOptions { - viewport$: Observable<Viewport> /* Viewport observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch content tabs - * - * @param el - Content tabs element - * - * @returns Content tabs observable - */ -export function watchContentTabs( - el: HTMLElement -): Observable<ContentTabs> { - const inputs = getElements<HTMLInputElement>(":scope > input", el) - const initial = inputs.find(input => input.checked) || inputs[0] - return merge(...inputs.map(input => fromEvent(input, "change") - .pipe( - map(() => getElement<HTMLLabelElement>(`label[for="${input.id}"]`)) - ) - )) - .pipe( - startWith(getElement<HTMLLabelElement>(`label[for="${initial.id}"]`)), - map(active => ({ active })) - ) -} - -/** - * 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 options - Options - * - * @returns Content tabs component observable - */ -export function mountContentTabs( - el: HTMLElement, { viewport$ }: MountOptions -): Observable<Component<ContentTabs>> { - - /* Render content tab previous button for pagination */ - const prev = renderTabbedControl("prev") - el.append(prev) - - /* Render content tab next button for pagination */ - const next = renderTabbedControl("next") - el.append(next) - - /* Mount component on subscription */ - const container = getElement(".tabbed-labels", el) - return defer(() => { - const push$ = new Subject<ContentTabs>() - const done$ = push$.pipe(ignoreElements(), endWith(true)) - combineLatest([push$, watchElementSize(el)]) - .pipe( - auditTime(1, animationFrameScheduler), - takeUntil(done$) - ) - .subscribe({ - - /* Handle emission */ - next([{ active }, size]) { - const offset = getElementOffset(active) - const { width } = getElementSize(active) - - /* Set tab indicator offset and width */ - el.style.setProperty("--md-indicator-x", `${offset.x}px`) - el.style.setProperty("--md-indicator-width", `${width}px`) - - /* Scroll container to active content tab */ - const content = getElementContentOffset(container) - if ( - offset.x < content.x || - offset.x + width > content.x + size.width - ) - container.scrollTo({ - left: Math.max(0, offset.x - 16), - behavior: "smooth" - }) - }, - - /* Handle complete */ - complete() { - el.style.removeProperty("--md-indicator-x") - el.style.removeProperty("--md-indicator-width") - } - }) - - /* Hide content tab buttons on borders */ - combineLatest([ - watchElementContentOffset(container), - watchElementSize(container) - ]) - .pipe( - takeUntil(done$) - ) - .subscribe(([offset, size]) => { - const content = getElementContentSize(container) - prev.hidden = offset.x < 16 - next.hidden = offset.x > content.width - size.width - 16 - }) - - /* Paginate content tab container on click */ - merge( - fromEvent(prev, "click").pipe(map(() => -1)), - fromEvent(next, "click").pipe(map(() => +1)) - ) - .pipe( - takeUntil(done$) - ) - .subscribe(direction => { - const { width } = getElementSize(container) - container.scrollBy({ - left: width * direction, - behavior: "smooth" - }) - }) - - /* Set up linking of content tabs, if enabled */ - if (feature("content.tabs.link")) - push$.pipe( - skip(1), - withLatestFrom(viewport$) - ) - .subscribe(([{ active }, { offset }]) => { - const tab = active.innerText.trim() - if (active.hasAttribute("data-md-switching")) { - active.removeAttribute("data-md-switching") - - /* Determine viewport offset of active tab */ - } else { - const y = el.offsetTop - offset.y - - /* Passively activate other tabs */ - for (const set of getElements("[data-tabs]")) - for (const input of getElements<HTMLInputElement>( - ":scope > input", set - )) { - const label = getElement(`label[for="${input.id}"]`) - if ( - label !== active && - label.innerText.trim() === tab - ) { - label.setAttribute("data-md-switching", "") - input.click() - break - } - } - - /* Bring active tab into view */ - window.scrollTo({ - top: el.offsetTop - y - }) - - /* Persist active tabs in local storage */ - const tabs = __md_get<string[]>("__tabs") || [] - __md_set("__tabs", [...new Set([tab, ...tabs])]) - } - }) - - /* Pause media (audio, video) on switch - see https://bit.ly/3Bk6cel */ - push$.pipe(takeUntil(done$)) - .subscribe(() => { - for (const media of getElements<HTMLAudioElement>("audio, video", el)) - media.pause() - }) - - /* Create and return component */ - return watchContentTabs(el) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })) - ) - }) - .pipe( - subscribeOn(asyncScheduler) - ) -} diff --git a/src/templates/assets/javascripts/components/dialog/index.ts b/src/templates/assets/javascripts/components/dialog/index.ts deleted file mode 100644 index 6ff1bd44..00000000 --- a/src/templates/assets/javascripts/components/dialog/index.ts +++ /dev/null @@ -1,128 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - defer, - delay, - finalize, - map, - merge, - of, - switchMap, - tap -} from "rxjs" - -import { getElement } from "~/browser" - -import { Component } from "../_" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Dialog - */ -export interface Dialog { - message: string /* Dialog message */ - active: boolean /* Dialog is active */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Watch options - */ -interface WatchOptions { - alert$: Subject<string> /* Alert subject */ -} - -/** - * Mount options - */ -interface MountOptions { - alert$: Subject<string> /* Alert subject */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch dialog - * - * @param _el - Dialog element - * @param options - Options - * - * @returns Dialog observable - */ -export function watchDialog( - _el: HTMLElement, { alert$ }: WatchOptions -): Observable<Dialog> { - return alert$ - .pipe( - switchMap(message => merge( - of(true), - of(false).pipe(delay(2000)) - ) - .pipe( - map(active => ({ message, active })) - ) - ) - ) -} - -/** - * Mount dialog - * - * 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. - * - * @param el - Dialog element - * @param options - Options - * - * @returns Dialog component observable - */ -export function mountDialog( - el: HTMLElement, options: MountOptions -): Observable<Component<Dialog>> { - const inner = getElement(".md-typeset", el) - return defer(() => { - const push$ = new Subject<Dialog>() - push$.subscribe(({ message, active }) => { - el.classList.toggle("md-dialog--active", active) - inner.textContent = message - }) - - /* Create and return component */ - return watchDialog(el, options) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })) - ) - }) -} diff --git a/src/templates/assets/javascripts/components/header/_/index.ts b/src/templates/assets/javascripts/components/header/_/index.ts deleted file mode 100644 index 0f33eb48..00000000 --- a/src/templates/assets/javascripts/components/header/_/index.ts +++ /dev/null @@ -1,200 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - bufferCount, - combineLatest, - combineLatestWith, - defer, - distinctUntilChanged, - distinctUntilKeyChanged, - endWith, - filter, - ignoreElements, - map, - of, - shareReplay, - startWith, - switchMap, - takeUntil -} from "rxjs" - -import { feature } from "~/_" -import { - Viewport, - watchElementSize, - watchToggle -} from "~/browser" - -import { Component } from "../../_" -import { Main } from "../../main" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Header - */ -export interface Header { - height: number /* Header visible height */ - hidden: boolean /* Header is hidden */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Watch options - */ -interface WatchOptions { - viewport$: Observable<Viewport> /* Viewport observable */ -} - -/** - * Mount options - */ -interface MountOptions { - viewport$: Observable<Viewport> /* Viewport observable */ - header$: Observable<Header> /* Header observable */ - main$: Observable<Main> /* Main area observable */ -} - -/* ---------------------------------------------------------------------------- - * Helper functions - * ------------------------------------------------------------------------- */ - -/** - * Compute whether the header is hidden - * - * If the user scrolls past a certain threshold, the header can be hidden when - * scrolling down, and shown when scrolling up. - * - * @param options - Options - * - * @returns Toggle observable - */ -function isHidden({ viewport$ }: WatchOptions): Observable<boolean> { - if (!feature("header.autohide")) - return of(false) - - /* Compute direction and turning point */ - const direction$ = viewport$ - .pipe( - map(({ offset: { y } }) => y), - bufferCount(2, 1), - map(([a, b]) => [a < b, b] as const), - distinctUntilKeyChanged(0) - ) - - /* Compute whether header should be hidden */ - const hidden$ = combineLatest([viewport$, direction$]) - .pipe( - filter(([{ offset }, [, y]]) => Math.abs(y - offset.y) > 100), - map(([, [direction]]) => direction), - distinctUntilChanged() - ) - - /* Compute threshold for hiding */ - const search$ = watchToggle("search") - return combineLatest([viewport$, search$]) - .pipe( - map(([{ offset }, search]) => offset.y > 400 && !search), - distinctUntilChanged(), - switchMap(active => active ? hidden$ : of(false)), - startWith(false) - ) -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch header - * - * @param el - Header element - * @param options - Options - * - * @returns Header observable - */ -export function watchHeader( - el: HTMLElement, options: WatchOptions -): Observable<Header> { - return defer(() => combineLatest([ - watchElementSize(el), - isHidden(options) - ])) - .pipe( - map(([{ height }, hidden]) => ({ - height, - hidden - })), - distinctUntilChanged((a, b) => ( - a.height === b.height && - a.hidden === b.hidden - )), - shareReplay(1) - ) -} - -/** - * Mount header - * - * This function manages the different states of the header, i.e. whether it's - * hidden or rendered with a shadow. This depends heavily on the main area. - * - * @param el - Header element - * @param options - Options - * - * @returns Header component observable - */ -export function mountHeader( - el: HTMLElement, { header$, main$ }: MountOptions -): Observable<Component<Header>> { - return defer(() => { - const push$ = new Subject<Main>() - const done$ = push$.pipe(ignoreElements(), endWith(true)) - push$ - .pipe( - distinctUntilKeyChanged("active"), - combineLatestWith(header$) - ) - .subscribe(([{ active }, { hidden }]) => { - el.classList.toggle("md-header--shadow", active && !hidden) - el.hidden = hidden - }) - - /* Link to main area */ - main$.subscribe(push$) - - /* Create and return component */ - return header$ - .pipe( - takeUntil(done$), - map(state => ({ ref: el, ...state })) - ) - }) -} diff --git a/src/templates/assets/javascripts/components/header/index.ts b/src/templates/assets/javascripts/components/header/index.ts deleted file mode 100644 index cf23ec1a..00000000 --- a/src/templates/assets/javascripts/components/header/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2016-2023 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" diff --git a/src/templates/assets/javascripts/components/header/title/index.ts b/src/templates/assets/javascripts/components/header/title/index.ts deleted file mode 100644 index f3bc0d08..00000000 --- a/src/templates/assets/javascripts/components/header/title/index.ts +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { - EMPTY, - Observable, - Subject, - defer, - distinctUntilKeyChanged, - finalize, - map, - tap -} from "rxjs" - -import { - Viewport, - getElementSize, - getOptionalElement, - watchViewportAt -} from "~/browser" - -import { Component } from "../../_" -import { Header } from "../_" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Header - */ -export interface HeaderTitle { - active: boolean /* Header title is active */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Watch options - */ -interface WatchOptions { - viewport$: Observable<Viewport> /* Viewport observable */ - header$: Observable<Header> /* Header observable */ -} - -/** - * Mount options - */ -interface MountOptions { - viewport$: Observable<Viewport> /* Viewport observable */ - header$: Observable<Header> /* Header observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch header title - * - * @param el - Heading element - * @param options - Options - * - * @returns Header title observable - */ -export function watchHeaderTitle( - el: HTMLElement, { viewport$, header$ }: WatchOptions -): Observable<HeaderTitle> { - return watchViewportAt(el, { viewport$, header$ }) - .pipe( - map(({ offset: { y } }) => { - const { height } = getElementSize(el) - return { - active: y >= height - } - }), - distinctUntilKeyChanged("active") - ) -} - -/** - * Mount header title - * - * This function swaps the header title from the site title to the title of the - * current page when the user scrolls past the first headline. - * - * @param el - Header title element - * @param options - Options - * - * @returns Header title component observable - */ -export function mountHeaderTitle( - el: HTMLElement, options: MountOptions -): Observable<Component<HeaderTitle>> { - return defer(() => { - const push$ = new Subject<HeaderTitle>() - push$.subscribe({ - - /* Handle emission */ - next({ active }) { - el.classList.toggle("md-header__title--active", active) - }, - - /* Handle complete */ - complete() { - el.classList.remove("md-header__title--active") - } - }) - - /* Obtain headline, if any */ - const heading = getOptionalElement(".md-content h1") - if (typeof heading === "undefined") - return EMPTY - - /* Create and return component */ - return watchHeaderTitle(heading, options) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })) - ) - }) -} diff --git a/src/templates/assets/javascripts/components/index.ts b/src/templates/assets/javascripts/components/index.ts deleted file mode 100644 index 3d4391d1..00000000 --- a/src/templates/assets/javascripts/components/index.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./announce" -export * from "./consent" -export * from "./content" -export * from "./dialog" -export * from "./header" -export * from "./main" -export * from "./palette" -export * from "./progress" -export * from "./search" -export * from "./sidebar" -export * from "./source" -export * from "./tabs" -export * from "./toc" -export * from "./top" diff --git a/src/templates/assets/javascripts/components/main/index.ts b/src/templates/assets/javascripts/components/main/index.ts deleted file mode 100644 index 2509f9b9..00000000 --- a/src/templates/assets/javascripts/components/main/index.ts +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - combineLatest, - distinctUntilChanged, - distinctUntilKeyChanged, - map, - switchMap -} from "rxjs" - -import { - Viewport, - watchElementSize -} from "~/browser" - -import { Header } from "../header" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Main area - */ -export interface Main { - offset: number /* Main area top offset */ - height: number /* Main area visible height */ - active: boolean /* Main area is active */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Watch options - */ -interface WatchOptions { - viewport$: Observable<Viewport> /* Viewport observable */ - header$: Observable<Header> /* Header observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch main area - * - * This function returns an observable that computes the visual parameters of - * the main area which depends on the viewport vertical offset and height, as - * well as the height of the header element, if the header is fixed. - * - * @param el - Main area element - * @param options - Options - * - * @returns Main area observable - */ -export function watchMain( - el: HTMLElement, { viewport$, header$ }: WatchOptions -): Observable<Main> { - - /* Compute necessary adjustment for header */ - const adjust$ = header$ - .pipe( - map(({ height }) => height), - distinctUntilChanged() - ) - - /* Compute the main area's top and bottom borders */ - const border$ = adjust$ - .pipe( - switchMap(() => watchElementSize(el) - .pipe( - map(({ height }) => ({ - top: el.offsetTop, - bottom: el.offsetTop + height - })), - distinctUntilKeyChanged("bottom") - ) - ) - ) - - /* Compute the main area's offset, visible height and if we scrolled past */ - return combineLatest([adjust$, border$, viewport$]) - .pipe( - map(([header, { top, bottom }, { offset: { y }, size: { height } }]) => { - height = Math.max(0, height - - Math.max(0, top - y, header) - - Math.max(0, height + y - bottom) - ) - return { - offset: top - header, - height, - active: top - header <= y - } - }), - distinctUntilChanged((a, b) => ( - a.offset === b.offset && - a.height === b.height && - a.active === b.active - )) - ) -} diff --git a/src/templates/assets/javascripts/components/palette/index.ts b/src/templates/assets/javascripts/components/palette/index.ts deleted file mode 100644 index cf578f60..00000000 --- a/src/templates/assets/javascripts/components/palette/index.ts +++ /dev/null @@ -1,180 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - asyncScheduler, - defer, - finalize, - fromEvent, - map, - mergeMap, - observeOn, - of, - shareReplay, - startWith, - tap -} from "rxjs" - -import { getElements } from "~/browser" -import { h } from "~/utilities" - -import { - Component, - getComponentElement -} from "../_" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Palette colors - */ -export interface PaletteColor { - scheme?: string /* Color scheme */ - primary?: string /* Primary color */ - accent?: string /* Accent color */ -} - -/** - * Palette - */ -export interface Palette { - index: number /* Palette index */ - color: PaletteColor /* Palette colors */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch color palette - * - * @param inputs - Color palette element - * - * @returns Color palette observable - */ -export function watchPalette( - inputs: HTMLInputElement[] -): Observable<Palette> { - const current = __md_get<Palette>("__palette") || { - index: inputs.findIndex(input => matchMedia( - input.getAttribute("data-md-color-media")! - ).matches) - } - - /* Emit changes in color palette */ - return of(...inputs) - .pipe( - mergeMap(input => fromEvent(input, "change") - .pipe( - map(() => input) - ) - ), - startWith(inputs[Math.max(0, current.index)]), - map(input => ({ - index: inputs.indexOf(input), - color: { - scheme: input.getAttribute("data-md-color-scheme"), - primary: input.getAttribute("data-md-color-primary"), - accent: input.getAttribute("data-md-color-accent") - } - } as Palette)), - shareReplay(1) - ) -} - -/** - * Mount color palette - * - * @param el - Color palette element - * - * @returns Color palette component observable - */ -export function mountPalette( - el: HTMLElement -): Observable<Component<Palette>> { - const meta = h("meta", { name: "theme-color" }) - document.head.appendChild(meta) - - // Add color scheme meta tag - const scheme = h("meta", { name: "color-scheme" }) - document.head.appendChild(scheme) - - /* Mount component on subscription */ - return defer(() => { - const push$ = new Subject<Palette>() - push$.subscribe(palette => { - document.body.setAttribute("data-md-color-switching", "") - - /* Set color palette */ - for (const [key, value] of Object.entries(palette.color)) - document.body.setAttribute(`data-md-color-${key}`, value) - - /* Toggle visibility */ - for (let index = 0; index < inputs.length; index++) { - const label = inputs[index].nextElementSibling - if (label instanceof HTMLElement) - label.hidden = palette.index !== index - } - - /* Persist preference in local storage */ - __md_set("__palette", palette) - }) - - /* Update theme-color meta tag */ - push$ - .pipe( - map(() => { - const header = getComponentElement("header") - const style = window.getComputedStyle(header) - - // Set color scheme - scheme.content = style.colorScheme - - /* Return color in hexadecimal format */ - return style.backgroundColor.match(/\d+/g)! - .map(value => (+value).toString(16).padStart(2, "0")) - .join("") - }) - ) - .subscribe(color => meta.content = `#${color}`) - - /* Revert transition durations after color switch */ - push$.pipe(observeOn(asyncScheduler)) - .subscribe(() => { - document.body.removeAttribute("data-md-color-switching") - }) - - /* 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 })) - ) - }) -} diff --git a/src/templates/assets/javascripts/components/progress/index.ts b/src/templates/assets/javascripts/components/progress/index.ts deleted file mode 100644 index 30c722b8..00000000 --- a/src/templates/assets/javascripts/components/progress/index.ts +++ /dev/null @@ -1,87 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - defer, - finalize, - map, - tap -} from "rxjs" - -import { Component } from "../_" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Progress indicator - */ -export interface Progress { - value: number // Progress value -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Mount options - */ -interface MountOptions { - progress$: Subject<number> // Progress subject -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Mount progress indicator - * - * @param el - Progress indicator element - * @param options - Options - * - * @returns Progress indicator component observable - */ -export function mountProgress( - el: HTMLElement, { progress$ }: MountOptions -): Observable<Component<Progress>> { - - // Mount component on subscription - return defer(() => { - const push$ = new Subject<Progress>() - push$.subscribe(({ value }) => { - el.style.setProperty("--md-progress-value", `${value}`) - }) - - // Create and return component - return progress$ - .pipe( - tap(value => push$.next({ value })), - finalize(() => push$.complete()), - map(value => ({ ref: el, value })) - ) - }) -} diff --git a/src/templates/assets/javascripts/components/search/_/index.ts b/src/templates/assets/javascripts/components/search/_/index.ts deleted file mode 100644 index aa963b47..00000000 --- a/src/templates/assets/javascripts/components/search/_/index.ts +++ /dev/null @@ -1,239 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - NEVER, - Observable, - ObservableInput, - filter, - fromEvent, - merge, - mergeWith -} from "rxjs" - -import { configuration } from "~/_" -import { - Keyboard, - getActiveElement, - getElements, - setToggle -} from "~/browser" -import { - SearchIndex, - SearchResult, - setupSearchWorker -} from "~/integrations" - -import { - Component, - getComponentElement, - getComponentElements -} from "../../_" -import { - SearchQuery, - mountSearchQuery -} from "../query" -import { mountSearchResult } from "../result" -import { - SearchShare, - mountSearchShare -} from "../share" -import { - SearchSuggest, - mountSearchSuggest -} from "../suggest" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Search - */ -export type Search = - | SearchQuery - | SearchResult - | SearchShare - | SearchSuggest - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Mount options - */ -interface MountOptions { - index$: ObservableInput<SearchIndex> /* Search index observable */ - keyboard$: Observable<Keyboard> /* Keyboard observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Mount search - * - * This function sets up the search functionality, including the underlying - * web worker and all keyboard bindings. - * - * @param el - Search element - * @param options - Options - * - * @returns Search component observable - */ -export function mountSearch( - el: HTMLElement, { index$, keyboard$ }: MountOptions -): Observable<Component<Search>> { - const config = configuration() - try { - const worker$ = setupSearchWorker(config.search, index$) - - /* Retrieve query and result components */ - const query = getComponentElement("search-query", el) - const result = getComponentElement("search-result", el) - - /* Always close search on result selection */ - fromEvent<PointerEvent>(el, "click") - .pipe( - filter(({ target }) => ( - target instanceof Element && !!target.closest("a") - )) - ) - .subscribe(() => setToggle("search", false)) - - /* Set up search keyboard handlers */ - keyboard$ - .pipe( - filter(({ mode }) => mode === "search") - ) - .subscribe(key => { - const active = getActiveElement() - switch (key.type) { - - /* Enter: go to first (best) result */ - case "Enter": - if (active === query) { - const anchors = new Map<HTMLAnchorElement, number>() - for (const anchor of getElements<HTMLAnchorElement>( - ":first-child [href]", result - )) { - const article = anchor.firstElementChild! - anchors.set(anchor, parseFloat( - article.getAttribute("data-md-score")! - )) - } - - /* Go to result with highest score, if any */ - if (anchors.size) { - const [[best]] = [...anchors].sort(([, a], [, b]) => b - a) - best.click() - } - - /* Otherwise omit form submission */ - key.claim() - } - break - - /* Escape or Tab: close search */ - case "Escape": - case "Tab": - setToggle("search", false) - query.blur() - break - - /* Vertical arrows: select previous or next search result */ - case "ArrowUp": - case "ArrowDown": - if (typeof active === "undefined") { - query.focus() - } else { - const els = [query, ...getElements( - ":not(details) > [href], summary, details[open] [href]", - result - )] - const i = Math.max(0, ( - Math.max(0, els.indexOf(active)) + els.length + ( - key.type === "ArrowUp" ? -1 : +1 - ) - ) % els.length) - els[i].focus() - } - - /* Prevent scrolling of page */ - key.claim() - break - - /* All other keys: hand to search query */ - default: - if (query !== getActiveElement()) - query.focus() - } - }) - - /* Set up global keyboard handlers */ - keyboard$ - .pipe( - filter(({ mode }) => mode === "global") - ) - .subscribe(key => { - switch (key.type) { - - /* Open search and select query */ - case "f": - case "s": - case "/": - query.focus() - query.select() - - /* Prevent scrolling of page */ - key.claim() - break - } - }) - - /* Create and return component */ - const query$ = mountSearchQuery(query, { worker$ }) - return merge( - query$, - mountSearchResult(result, { worker$, query$ }) - ) - .pipe( - mergeWith( - - /* Search sharing */ - ...getComponentElements("search-share", el) - .map(child => mountSearchShare(child, { query$ })), - - /* Search suggestions */ - ...getComponentElements("search-suggest", el) - .map(child => mountSearchSuggest(child, { worker$, keyboard$ })) - ) - ) - - /* Gracefully handle broken search */ - } catch (err) { - el.hidden = true - return NEVER - } -} diff --git a/src/templates/assets/javascripts/components/search/highlight/.eslintrc b/src/templates/assets/javascripts/components/search/highlight/.eslintrc deleted file mode 100644 index 38a5714d..00000000 --- a/src/templates/assets/javascripts/components/search/highlight/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rules": { - "no-null/no-null": "off" - } -} diff --git a/src/templates/assets/javascripts/components/search/highlight/index.ts b/src/templates/assets/javascripts/components/search/highlight/index.ts deleted file mode 100644 index bc3f94c9..00000000 --- a/src/templates/assets/javascripts/components/search/highlight/index.ts +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - ObservableInput, - combineLatest, - filter, - map, - startWith -} from "rxjs" - -import { getLocation } from "~/browser" -import { - SearchIndex, - setupSearchHighlighter -} from "~/integrations" -import { h } from "~/utilities" - -import { Component } from "../../_" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Search highlighting - */ -export interface SearchHighlight { - nodes: Map<ChildNode, string> /* Map of replacements */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Mount options - */ -interface MountOptions { - index$: ObservableInput<SearchIndex> /* Search index observable */ - location$: Observable<URL> /* Location observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Mount search highlighting - * - * @param el - Content element - * @param options - Options - * - * @returns Search highlighting component observable - */ -export function mountSearchHiglight( - el: HTMLElement, { index$, location$ }: MountOptions -): Observable<Component<SearchHighlight>> { - return combineLatest([ - index$, - location$ - .pipe( - startWith(getLocation()), - filter(url => !!url.searchParams.get("h")) - ) - ]) - .pipe( - map(([index, url]) => setupSearchHighlighter(index.config)( - url.searchParams.get("h")! - )), - map(fn => { - const nodes = new Map<ChildNode, string>() - - /* Traverse text nodes and collect matches */ - const it = document.createNodeIterator(el, NodeFilter.SHOW_TEXT) - for (let node = it.nextNode(); node; node = it.nextNode()) { - if (node.parentElement?.offsetHeight) { - const original = node.textContent! - const replaced = fn(original) - if (replaced.length > original.length) - nodes.set(node as ChildNode, replaced) - } - } - - /* Replace original nodes with matches */ - for (const [node, text] of nodes) { - const { childNodes } = h("span", null, text) - node.replaceWith(...Array.from(childNodes)) - } - - /* Return component */ - return { ref: el, nodes } - }) - ) -} diff --git a/src/templates/assets/javascripts/components/search/index.ts b/src/templates/assets/javascripts/components/search/index.ts deleted file mode 100644 index 846d8685..00000000 --- a/src/templates/assets/javascripts/components/search/index.ts +++ /dev/null @@ -1,28 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./highlight" -export * from "./query" -export * from "./result" -export * from "./share" -export * from "./suggest" diff --git a/src/templates/assets/javascripts/components/search/query/index.ts b/src/templates/assets/javascripts/components/search/query/index.ts deleted file mode 100644 index 4ce21279..00000000 --- a/src/templates/assets/javascripts/components/search/query/index.ts +++ /dev/null @@ -1,206 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - combineLatest, - distinctUntilChanged, - distinctUntilKeyChanged, - endWith, - finalize, - first, - fromEvent, - ignoreElements, - map, - merge, - shareReplay, - takeUntil, - tap -} from "rxjs" - -import { - getElement, - getLocation, - setToggle, - watchElementFocus, - watchToggle -} from "~/browser" -import { - SearchMessage, - SearchMessageType, - isSearchReadyMessage -} from "~/integrations" - -import { Component } from "../../_" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Search query - */ -export interface SearchQuery { - value: string /* Query value */ - focus: boolean /* Query focus */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Watch options - */ -interface WatchOptions { - worker$: Subject<SearchMessage> /* Search worker */ -} - -/** - * Mount options - */ -interface MountOptions { - worker$: Subject<SearchMessage> /* Search worker */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch search query - * - * Note that the focus event which triggers re-reading the current query value - * is delayed by `1ms` so the input's empty state is allowed to propagate. - * - * @param el - Search query element - * @param options - Options - * - * @returns Search query observable - */ -export function watchSearchQuery( - el: HTMLInputElement, { worker$ }: WatchOptions -): Observable<SearchQuery> { - - /* Support search deep linking */ - const { searchParams } = getLocation() - if (searchParams.has("q")) { - setToggle("search", true) - - /* Set query from parameter */ - el.value = searchParams.get("q")! - el.focus() - - /* Remove query parameter on close */ - watchToggle("search") - .pipe( - first(active => !active) - ) - .subscribe(() => { - const url = getLocation() - url.searchParams.delete("q") - history.replaceState({}, "", `${url}`) - }) - } - - /* Intercept focus and input events */ - const focus$ = watchElementFocus(el) - const value$ = merge( - worker$.pipe(first(isSearchReadyMessage)), - fromEvent(el, "keyup"), - focus$ - ) - .pipe( - map(() => el.value), - distinctUntilChanged() - ) - - /* Combine into single observable */ - return combineLatest([value$, focus$]) - .pipe( - map(([value, focus]) => ({ value, focus })), - shareReplay(1) - ) -} - -/** - * Mount search query - * - * @param el - Search query element - * @param options - Options - * - * @returns Search query component observable - */ -export function mountSearchQuery( - el: HTMLInputElement, { worker$ }: MountOptions -): Observable<Component<SearchQuery, HTMLInputElement>> { - const push$ = new Subject<SearchQuery>() - const done$ = push$.pipe(ignoreElements(), endWith(true)) - - /* Handle value change */ - combineLatest([ - worker$.pipe(first(isSearchReadyMessage)), - push$ - ], (_, query) => query) - .pipe( - distinctUntilKeyChanged("value") - ) - .subscribe(({ value }) => worker$.next({ - type: SearchMessageType.QUERY, - data: value - })) - - /* Handle focus change */ - push$ - .pipe( - distinctUntilKeyChanged("focus") - ) - .subscribe(({ focus }) => { - if (focus) - setToggle("search", focus) - }) - - /* Handle reset */ - fromEvent(el.form!, "reset") - .pipe( - takeUntil(done$) - ) - .subscribe(() => el.focus()) - - // Focus search query on label click - note that this is necessary to bring - // up the keyboard on iOS and other mobile platforms, as the search dialog is - // not visible at first, and programatically focusing an input element must - // be triggered by a user interaction - see https://t.ly/Cb30n - const label = getElement("header [for=__search]") - fromEvent(label, "click") - .subscribe(() => el.focus()) - - /* Create and return component */ - return watchSearchQuery(el, { worker$ }) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })), - shareReplay(1) - ) -} diff --git a/src/templates/assets/javascripts/components/search/result/index.ts b/src/templates/assets/javascripts/components/search/result/index.ts deleted file mode 100644 index c3c9ef20..00000000 --- a/src/templates/assets/javascripts/components/search/result/index.ts +++ /dev/null @@ -1,197 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { - EMPTY, - Observable, - Subject, - bufferCount, - filter, - finalize, - first, - fromEvent, - map, - merge, - mergeMap, - of, - share, - skipUntil, - switchMap, - takeUntil, - tap, - withLatestFrom, - zipWith -} from "rxjs" - -import { translation } from "~/_" -import { - getElement, - getOptionalElement, - watchElementBoundary, - watchToggle -} from "~/browser" -import { - SearchMessage, - SearchResult, - isSearchReadyMessage, - isSearchResultMessage -} from "~/integrations" -import { renderSearchResultItem } from "~/templates" -import { round } from "~/utilities" - -import { Component } from "../../_" -import { SearchQuery } from "../query" - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Mount options - */ -interface MountOptions { - query$: Observable<SearchQuery> /* Search query observable */ - worker$: Subject<SearchMessage> /* Search worker */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Mount search result list - * - * This function performs a lazy rendering of the search results, depending on - * the vertical offset of the search result container. - * - * @param el - Search result list element - * @param options - Options - * - * @returns Search result list component observable - */ -export function mountSearchResult( - el: HTMLElement, { worker$, query$ }: MountOptions -): Observable<Component<SearchResult>> { - const push$ = new Subject<SearchResult>() - const boundary$ = watchElementBoundary(el.parentElement!) - .pipe( - filter(Boolean) - ) - - /* Retrieve container */ - const container = el.parentElement! - - /* Retrieve nested components */ - const meta = getElement(":scope > :first-child", el) - const list = getElement(":scope > :last-child", el) - - /* Reveal to accessibility tree – see https://bit.ly/3iAA7t8 */ - watchToggle("search") - .subscribe(active => list.setAttribute( - "role", active ? "list" : "presentation" - )) - - /* Update search result metadata */ - push$ - .pipe( - withLatestFrom(query$), - skipUntil(worker$.pipe(first(isSearchReadyMessage))) - ) - .subscribe(([{ items }, { value }]) => { - switch (items.length) { - - /* No results */ - case 0: - meta.textContent = value.length - ? translation("search.result.none") - : translation("search.result.placeholder") - break - - /* One result */ - case 1: - meta.textContent = translation("search.result.one") - break - - /* Multiple result */ - default: - const count = round(items.length) - meta.textContent = translation("search.result.other", count) - } - }) - - /* Render search result item */ - const render$ = push$ - .pipe( - tap(() => list.innerHTML = ""), - switchMap(({ items }) => merge( - of(...items.slice(0, 10)), - of(...items.slice(10)) - .pipe( - bufferCount(4), - zipWith(boundary$), - switchMap(([chunk]) => chunk) - ) - )), - map(renderSearchResultItem), - share() - ) - - /* Update search result list */ - render$.subscribe(item => list.appendChild(item)) - render$ - .pipe( - mergeMap(item => { - const details = getOptionalElement("details", item) - if (typeof details === "undefined") - return EMPTY - - /* Keep position of details element stable */ - return fromEvent(details, "toggle") - .pipe( - takeUntil(push$), - map(() => details) - ) - }) - ) - .subscribe(details => { - if ( - details.open === false && - details.offsetTop <= container.scrollTop - ) - container.scrollTo({ top: details.offsetTop }) - }) - - /* Filter search result message */ - const result$ = worker$ - .pipe( - filter(isSearchResultMessage), - map(({ data }) => data) - ) - - /* Create and return component */ - return result$ - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })) - ) -} diff --git a/src/templates/assets/javascripts/components/search/share/index.ts b/src/templates/assets/javascripts/components/search/share/index.ts deleted file mode 100644 index 3db382c8..00000000 --- a/src/templates/assets/javascripts/components/search/share/index.ts +++ /dev/null @@ -1,135 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - endWith, - finalize, - fromEvent, - ignoreElements, - map, - takeUntil, - tap -} from "rxjs" - -import { getLocation } from "~/browser" - -import { Component } from "../../_" -import { SearchQuery } from "../query" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Search sharing - */ -export interface SearchShare { - url: URL /* Deep link for sharing */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Watch options - */ -interface WatchOptions { - query$: Observable<SearchQuery> /* Search query observable */ -} - -/** - * Mount options - */ -interface MountOptions { - query$: Observable<SearchQuery> /* Search query observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Mount search sharing - * - * @param _el - Search sharing element - * @param options - Options - * - * @returns Search sharing observable - */ -export function watchSearchShare( - _el: HTMLElement, { query$ }: WatchOptions -): Observable<SearchShare> { - return query$ - .pipe( - map(({ value }) => { - const url = getLocation() - url.hash = "" - - /* Compute readable query strings */ - value = value - .replace(/\s+/g, "+") /* Collapse whitespace */ - .replace(/&/g, "%26") /* Escape '&' character */ - .replace(/=/g, "%3D") /* Escape '=' character */ - - /* Replace query string */ - url.search = `q=${value}` - return { url } - }) - ) -} - -/** - * Mount search sharing - * - * @param el - Search sharing element - * @param options - Options - * - * @returns Search sharing component observable - */ -export function mountSearchShare( - el: HTMLAnchorElement, options: MountOptions -): Observable<Component<SearchShare>> { - const push$ = new Subject<SearchShare>() - const done$ = push$.pipe(ignoreElements(), endWith(true)) - push$.subscribe(({ url }) => { - el.setAttribute("data-clipboard-text", el.href) - el.href = `${url}` - }) - - /* Prevent following of link */ - fromEvent(el, "click") - .pipe( - takeUntil(done$) - ) - .subscribe(ev => ev.preventDefault()) - - /* Create and return component */ - return watchSearchShare(el, options) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })) - ) -} diff --git a/src/templates/assets/javascripts/components/search/suggest/index.ts b/src/templates/assets/javascripts/components/search/suggest/index.ts deleted file mode 100644 index e7881475..00000000 --- a/src/templates/assets/javascripts/components/search/suggest/index.ts +++ /dev/null @@ -1,154 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - asyncScheduler, - combineLatestWith, - distinctUntilChanged, - filter, - finalize, - fromEvent, - map, - merge, - observeOn, - tap -} from "rxjs" - -import { Keyboard } from "~/browser" -import { - SearchMessage, - SearchResult, - isSearchResultMessage -} from "~/integrations" - -import { Component, getComponentElement } from "../../_" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Search suggestions - */ -export interface SearchSuggest {} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Mount options - */ -interface MountOptions { - keyboard$: Observable<Keyboard> /* Keyboard observable */ - worker$: Subject<SearchMessage> /* Search worker */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Mount search suggestions - * - * This function will perform a lazy rendering of the search results, depending - * on the vertical offset of the search result container. - * - * @param el - Search result list element - * @param options - Options - * - * @returns Search result list component observable - */ -export function mountSearchSuggest( - el: HTMLElement, { worker$, keyboard$ }: MountOptions -): Observable<Component<SearchSuggest>> { - const push$ = new Subject<SearchResult>() - - /* Retrieve query component and track all changes */ - const query = getComponentElement("search-query") - const query$ = merge( - fromEvent(query, "keydown"), - fromEvent(query, "focus") - ) - .pipe( - observeOn(asyncScheduler), - map(() => query.value), - distinctUntilChanged(), - ) - - /* Update search suggestions */ - push$ - .pipe( - combineLatestWith(query$), - map(([{ suggest }, value]) => { - const words = value.split(/([\s-]+)/) - if (suggest?.length && words[words.length - 1]) { - const last = suggest[suggest.length - 1] - if (last.startsWith(words[words.length - 1])) - words[words.length - 1] = last - } else { - words.length = 0 - } - return words - }) - ) - .subscribe(words => el.innerHTML = words - .join("") - .replace(/\s/g, " ") - ) - - /* Set up search keyboard handlers */ - keyboard$ - .pipe( - filter(({ mode }) => mode === "search") - ) - .subscribe(key => { - switch (key.type) { - - /* Right arrow: accept current suggestion */ - case "ArrowRight": - if ( - el.innerText.length && - query.selectionStart === query.value.length - ) - query.value = el.innerText - break - } - }) - - /* Filter search result message */ - const result$ = worker$ - .pipe( - filter(isSearchResultMessage), - map(({ data }) => data) - ) - - /* Create and return component */ - return result$ - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(() => ({ ref: el })) - ) -} diff --git a/src/templates/assets/javascripts/components/sidebar/index.ts b/src/templates/assets/javascripts/components/sidebar/index.ts deleted file mode 100644 index 82f3d03e..00000000 --- a/src/templates/assets/javascripts/components/sidebar/index.ts +++ /dev/null @@ -1,227 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - animationFrameScheduler, - asyncScheduler, - auditTime, - combineLatest, - defer, - distinctUntilChanged, - endWith, - finalize, - first, - from, - fromEvent, - ignoreElements, - map, - mergeMap, - observeOn, - takeUntil, - tap, - withLatestFrom -} from "rxjs" - -import { - Viewport, - getElement, - getElementContainer, - getElementOffset, - getElementSize, - getElements -} from "~/browser" - -import { Component } from "../_" -import { Header } from "../header" -import { Main } from "../main" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Sidebar - */ -export interface Sidebar { - height: number /* Sidebar height */ - locked: boolean /* Sidebar is locked */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Watch options - */ -interface WatchOptions { - viewport$: Observable<Viewport> /* Viewport observable */ - main$: Observable<Main> /* Main area observable */ -} - -/** - * Mount options - */ -interface MountOptions { - viewport$: Observable<Viewport> /* Viewport observable */ - header$: Observable<Header> /* Header observable */ - main$: Observable<Main> /* Main area observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch sidebar - * - * This function returns an observable that computes the visual parameters of - * the sidebar which depends on the vertical viewport offset, as well as the - * height of the main area. When the page is scrolled beyond the header, the - * sidebar is locked and fills the remaining space. - * - * @param el - Sidebar element - * @param options - Options - * - * @returns Sidebar observable - */ -export function watchSidebar( - el: HTMLElement, { viewport$, main$ }: WatchOptions -): Observable<Sidebar> { - const parent = el.closest<HTMLElement>(".md-grid")! - const adjust = - parent.offsetTop - - parent.parentElement!.offsetTop - - /* Compute the sidebar's available height and if it should be locked */ - return combineLatest([main$, viewport$]) - .pipe( - map(([{ offset, height }, { offset: { y } }]) => { - height = height - + Math.min(adjust, Math.max(0, y - offset)) - - adjust - return { - height, - locked: y >= offset + adjust - } - }), - distinctUntilChanged((a, b) => ( - a.height === b.height && - a.locked === b.locked - )) - ) -} - -/** - * 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 options - Options - * - * @returns Sidebar component observable - */ -export function mountSidebar( - el: HTMLElement, { header$, ...options }: MountOptions -): Observable<Component<Sidebar>> { - const inner = getElement(".md-sidebar__scrollwrap", el) - const { y } = getElementOffset(inner) - return defer(() => { - const push$ = new Subject<Sidebar>() - const done$ = push$.pipe(ignoreElements(), endWith(true)) - const next$ = push$ - .pipe( - auditTime(0, animationFrameScheduler) - ) - - /* Update sidebar height and offset */ - next$.pipe(withLatestFrom(header$)) - .subscribe({ - - /* Handle emission */ - next([{ height }, { height: offset }]) { - inner.style.height = `${height - 2 * y}px` - el.style.top = `${offset}px` - }, - - /* Handle complete */ - complete() { - inner.style.height = "" - el.style.top = "" - } - }) - - /* Bring active item into view on initial load */ - next$.pipe(first()) - .subscribe(() => { - for (const item of getElements(".md-nav__link--active[href]", el)) { - const container = getElementContainer(item) - if (typeof container !== "undefined") { - const offset = item.offsetTop - container.offsetTop - const { height } = getElementSize(container) - container.scrollTo({ - top: offset - height / 2 - }) - } - } - }) - - /* Handle accessibility for expandable items, see https://bit.ly/3jaod9p */ - from(getElements<HTMLLabelElement>("label[tabindex]", el)) - .pipe( - mergeMap(label => fromEvent(label, "click") - .pipe( - observeOn(asyncScheduler), - map(() => label), - takeUntil(done$) - ) - ) - ) - .subscribe(label => { - const input = getElement<HTMLInputElement>(`[id="${label.htmlFor}"]`) - const nav = getElement(`[aria-labelledby="${label.id}"]`) - nav.setAttribute("aria-expanded", `${input.checked}`) - }) - - /* Create and return component */ - return watchSidebar(el, options) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })) - ) - }) -} diff --git a/src/templates/assets/javascripts/components/source/_/index.ts b/src/templates/assets/javascripts/components/source/_/index.ts deleted file mode 100644 index 5f6c4d11..00000000 --- a/src/templates/assets/javascripts/components/source/_/index.ts +++ /dev/null @@ -1,142 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { - EMPTY, - Observable, - Subject, - catchError, - defer, - filter, - finalize, - map, - of, - shareReplay, - tap -} from "rxjs" - -import { getElement } from "~/browser" -import { ConsentDefaults } from "~/components/consent" -import { renderSourceFacts } from "~/templates" - -import { - Component, - getComponentElements -} from "../../_" -import { - SourceFacts, - fetchSourceFacts -} from "../facts" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Repository information - */ -export interface Source { - facts: SourceFacts /* Repository facts */ -} - -/* ---------------------------------------------------------------------------- - * Data - * ------------------------------------------------------------------------- */ - -/** - * Repository information observable - */ -let fetch$: Observable<Source> - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch repository information - * - * This function tries to read the repository facts from session storage, and - * if unsuccessful, fetches them from the underlying provider. - * - * @param el - Repository information element - * - * @returns Repository information observable - */ -export function watchSource( - el: HTMLAnchorElement -): Observable<Source> { - return fetch$ ||= defer(() => { - const cached = __md_get<SourceFacts>("__source", sessionStorage) - if (cached) { - return of(cached) - } else { - - /* Check if consent is configured and was given */ - const els = getComponentElements("consent") - if (els.length) { - const consent = __md_get<ConsentDefaults>("__consent") - if (!(consent && consent.github)) - return EMPTY - } - - /* Fetch repository facts */ - return fetchSourceFacts(el.href) - .pipe( - tap(facts => __md_set("__source", facts, sessionStorage)) - ) - } - }) - .pipe( - catchError(() => EMPTY), - filter(facts => Object.keys(facts).length > 0), - map(facts => ({ facts })), - shareReplay(1) - ) -} - -/** - * Mount repository information - * - * @param el - Repository information element - * - * @returns Repository information component observable - */ -export function mountSource( - el: HTMLAnchorElement -): Observable<Component<Source>> { - const inner = getElement(":scope > :last-child", el) - return defer(() => { - const push$ = new Subject<Source>() - push$.subscribe(({ facts }) => { - inner.appendChild(renderSourceFacts(facts)) - inner.classList.add("md-source__repository--active") - }) - - /* Create and return component */ - return watchSource(el) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })) - ) - }) -} diff --git a/src/templates/assets/javascripts/components/source/facts/_/index.ts b/src/templates/assets/javascripts/components/source/facts/_/index.ts deleted file mode 100644 index 154f229f..00000000 --- a/src/templates/assets/javascripts/components/source/facts/_/index.ts +++ /dev/null @@ -1,88 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { EMPTY, Observable } from "rxjs" - -import { fetchSourceFactsFromGitHub } from "../github" -import { fetchSourceFactsFromGitLab } from "../gitlab" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Repository facts for repositories - */ -export interface RepositoryFacts { - stars?: number /* Number of stars */ - forks?: number /* Number of forks */ - version?: string /* Latest version */ -} - -/** - * Repository facts for organizations - */ -export interface OrganizationFacts { - repositories?: number /* Number of repositories */ -} - -/* ------------------------------------------------------------------------- */ - -/** - * Repository facts - */ -export type SourceFacts = - | RepositoryFacts - | OrganizationFacts - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Fetch repository facts - * - * @param url - Repository URL - * - * @returns Repository facts observable - */ -export function fetchSourceFacts( - url: string -): Observable<SourceFacts> { - - /* Try to match GitHub repository */ - let match = url.match(/^.+github\.com\/([^/]+)\/?([^/]+)?/i) - if (match) { - const [, user, repo] = match - return fetchSourceFactsFromGitHub(user, repo) - } - - /* Try to match GitLab repository */ - match = url.match(/^.+?([^/]*gitlab[^/]+)\/(.+?)\/?$/i) - if (match) { - const [, base, slug] = match - return fetchSourceFactsFromGitLab(base, slug) - } - - /* Fallback */ - return EMPTY -} diff --git a/src/templates/assets/javascripts/components/source/facts/github/index.ts b/src/templates/assets/javascripts/components/source/facts/github/index.ts deleted file mode 100644 index 12cc55e0..00000000 --- a/src/templates/assets/javascripts/components/source/facts/github/index.ts +++ /dev/null @@ -1,103 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { Repo, User } from "github-types" -import { - EMPTY, - Observable, - catchError, - defaultIfEmpty, - map, - zip -} from "rxjs" - -import { requestJSON } from "~/browser" - -import { SourceFacts } from "../_" - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * GitHub release (partial) - */ -interface Release { - tag_name: string /* Tag name */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Fetch GitHub repository facts - * - * @param user - GitHub user or organization - * @param repo - GitHub repository - * - * @returns Repository facts observable - */ -export function fetchSourceFactsFromGitHub( - user: string, repo?: string -): Observable<SourceFacts> { - if (typeof repo !== "undefined") { - const url = `https://api.github.com/repos/${user}/${repo}` - return zip( - - /* Fetch version */ - requestJSON<Release>(`${url}/releases/latest`) - .pipe( - catchError(() => EMPTY), // @todo refactor instant loading - map(release => ({ - version: release.tag_name - })), - defaultIfEmpty({}) - ), - - /* Fetch stars and forks */ - requestJSON<Repo>(url) - .pipe( - catchError(() => EMPTY), // @todo refactor instant loading - map(info => ({ - stars: info.stargazers_count, - forks: info.forks_count - })), - defaultIfEmpty({}) - ) - ) - .pipe( - map(([release, info]) => ({ ...release, ...info })) - ) - - /* User or organization */ - } else { - const url = `https://api.github.com/users/${user}` - return requestJSON<User>(url) - .pipe( - map(info => ({ - repositories: info.public_repos - })), - defaultIfEmpty({}) - ) - } -} diff --git a/src/templates/assets/javascripts/components/source/facts/gitlab/index.ts b/src/templates/assets/javascripts/components/source/facts/gitlab/index.ts deleted file mode 100644 index d85d4afd..00000000 --- a/src/templates/assets/javascripts/components/source/facts/gitlab/index.ts +++ /dev/null @@ -1,61 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { ProjectSchema } from "gitlab" -import { - EMPTY, - Observable, - catchError, - defaultIfEmpty, - map -} from "rxjs" - -import { requestJSON } from "~/browser" - -import { SourceFacts } from "../_" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Fetch GitLab repository facts - * - * @param base - GitLab base - * @param project - GitLab project - * - * @returns Repository facts observable - */ -export function fetchSourceFactsFromGitLab( - base: string, project: string -): Observable<SourceFacts> { - const url = `https://${base}/api/v4/projects/${encodeURIComponent(project)}` - return requestJSON<ProjectSchema>(url) - .pipe( - catchError(() => EMPTY), // @todo refactor instant loading - map(({ star_count, forks_count }) => ({ - stars: star_count, - forks: forks_count - })), - defaultIfEmpty({}) - ) -} diff --git a/src/templates/assets/javascripts/components/source/facts/index.ts b/src/templates/assets/javascripts/components/source/facts/index.ts deleted file mode 100644 index f9bda64d..00000000 --- a/src/templates/assets/javascripts/components/source/facts/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./github" -export * from "./gitlab" diff --git a/src/templates/assets/javascripts/components/source/index.ts b/src/templates/assets/javascripts/components/source/index.ts deleted file mode 100644 index 7fac4813..00000000 --- a/src/templates/assets/javascripts/components/source/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./facts" diff --git a/src/templates/assets/javascripts/components/tabs/index.ts b/src/templates/assets/javascripts/components/tabs/index.ts deleted file mode 100644 index 1e69df28..00000000 --- a/src/templates/assets/javascripts/components/tabs/index.ts +++ /dev/null @@ -1,144 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - defer, - distinctUntilKeyChanged, - finalize, - map, - of, - switchMap, - tap -} from "rxjs" - -import { feature } from "~/_" -import { - Viewport, - watchElementSize, - watchViewportAt -} from "~/browser" - -import { Component } from "../_" -import { Header } from "../header" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Navigation tabs - */ -export interface Tabs { - hidden: boolean /* Navigation tabs are hidden */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Watch options - */ -interface WatchOptions { - viewport$: Observable<Viewport> /* Viewport observable */ - header$: Observable<Header> /* Header observable */ -} - -/** - * Mount options - */ -interface MountOptions { - viewport$: Observable<Viewport> /* Viewport observable */ - header$: Observable<Header> /* Header observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch navigation tabs - * - * @param el - Navigation tabs element - * @param options - Options - * - * @returns Navigation tabs observable - */ -export function watchTabs( - el: HTMLElement, { viewport$, header$ }: WatchOptions -): Observable<Tabs> { - return watchElementSize(document.body) - .pipe( - switchMap(() => watchViewportAt(el, { header$, viewport$ })), - map(({ offset: { y } }) => { - return { - hidden: y >= 10 - } - }), - distinctUntilKeyChanged("hidden") - ) -} - -/** - * Mount navigation tabs - * - * This function hides the navigation tabs when scrolling past the threshold - * and makes them reappear in a nice CSS animation when scrolling back up. - * - * @param el - Navigation tabs element - * @param options - Options - * - * @returns Navigation tabs component observable - */ -export function mountTabs( - el: HTMLElement, options: MountOptions -): Observable<Component<Tabs>> { - return defer(() => { - const push$ = new Subject<Tabs>() - push$.subscribe({ - - /* Handle emission */ - next({ hidden }) { - el.hidden = hidden - }, - - /* Handle complete */ - complete() { - el.hidden = false - } - }) - - /* Create and return component */ - return ( - feature("navigation.tabs.sticky") - ? of({ hidden: false }) - : watchTabs(el, options) - ) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })) - ) - }) -} diff --git a/src/templates/assets/javascripts/components/toc/index.ts b/src/templates/assets/javascripts/components/toc/index.ts deleted file mode 100644 index 04b8d85f..00000000 --- a/src/templates/assets/javascripts/components/toc/index.ts +++ /dev/null @@ -1,379 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - asyncScheduler, - bufferCount, - combineLatestWith, - debounceTime, - defer, - distinctUntilChanged, - distinctUntilKeyChanged, - endWith, - filter, - finalize, - ignoreElements, - map, - merge, - observeOn, - of, - repeat, - scan, - share, - skip, - startWith, - switchMap, - takeUntil, - tap, - withLatestFrom -} from "rxjs" - -import { feature } from "~/_" -import { - Viewport, - getElement, - getElementContainer, - getElementSize, - getElements, - getLocation, - getOptionalElement, - watchElementSize -} from "~/browser" - -import { - Component, - getComponentElement -} from "../_" -import { Header } from "../header" -import { Main } from "../main" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Table of contents - */ -export interface TableOfContents { - prev: HTMLAnchorElement[][] /* Anchors (previous) */ - next: HTMLAnchorElement[][] /* Anchors (next) */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Watch options - */ -interface WatchOptions { - viewport$: Observable<Viewport> /* Viewport observable */ - header$: Observable<Header> /* Header observable */ -} - -/** - * Mount options - */ -interface MountOptions { - viewport$: Observable<Viewport> /* Viewport observable */ - header$: Observable<Header> /* Header observable */ - main$: Observable<Main> /* Main area observable */ - target$: Observable<HTMLElement> /* Location target observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch table of contents - * - * This is effectively a scroll spy implementation which will account for the - * fixed header and automatically re-calculate anchor offsets when the viewport - * is resized. The returned observable will only emit if the table of contents - * needs to be repainted. - * - * This implementation tracks an anchor element's entire path starting from its - * level up to the top-most anchor element, e.g. `[h3, h2, h1]`. Although the - * Material theme currently doesn't make use of this information, it enables - * the styling of the entire hierarchy through customization. - * - * Note that the current anchor is the last item of the `prev` anchor list. - * - * @param el - Table of contents element - * @param options - Options - * - * @returns Table of contents observable - */ -export function watchTableOfContents( - el: HTMLElement, { viewport$, header$ }: WatchOptions -): Observable<TableOfContents> { - const table = new Map<HTMLAnchorElement, HTMLElement>() - - /* Compute anchor-to-target mapping */ - const anchors = getElements<HTMLAnchorElement>("[href^=\\#]", el) - for (const anchor of anchors) { - const id = decodeURIComponent(anchor.hash.substring(1)) - const target = getOptionalElement(`[id="${id}"]`) - if (typeof target !== "undefined") - table.set(anchor, target) - } - - /* Compute necessary adjustment for header */ - const adjust$ = header$ - .pipe( - distinctUntilKeyChanged("height"), - map(({ height }) => { - const main = getComponentElement("main") - const grid = getElement(":scope > :first-child", main) - return height + 0.8 * ( - grid.offsetTop - - main.offsetTop - ) - }), - share() - ) - - /* Compute partition of previous and next anchors */ - const partition$ = watchElementSize(document.body) - .pipe( - distinctUntilKeyChanged("height"), - - /* Build index to map anchor paths to vertical offsets */ - switchMap(body => defer(() => { - let path: HTMLAnchorElement[] = [] - return of([...table].reduce((index, [anchor, target]) => { - while (path.length) { - const last = table.get(path[path.length - 1])! - if (last.tagName >= target.tagName) { - path.pop() - } else { - break - } - } - - /* If the current anchor is hidden, continue with its parent */ - let offset = target.offsetTop - while (!offset && target.parentElement) { - target = target.parentElement - offset = target.offsetTop - } - - /* Fix anchor offsets in tables - see https://bit.ly/3CUFOcn */ - let parent = target.offsetParent as HTMLElement - for (; parent; parent = parent.offsetParent as HTMLElement) - offset += parent.offsetTop - - /* Map reversed anchor path to vertical offset */ - return index.set( - [...path = [...path, anchor]].reverse(), - offset - ) - }, new Map<HTMLAnchorElement[], number>())) - }) - .pipe( - - /* Sort index by vertical offset (see https://bit.ly/30z6QSO) */ - map(index => new Map([...index].sort(([, a], [, b]) => a - b))), - combineLatestWith(adjust$), - - /* Re-compute partition when viewport offset changes */ - switchMap(([index, adjust]) => viewport$ - .pipe( - scan(([prev, next], { offset: { y }, size }) => { - const last = y + size.height >= Math.floor(body.height) - - /* Look forward */ - while (next.length) { - const [, offset] = next[0] - if (offset - adjust < y || last) { - prev = [...prev, next.shift()!] - } else { - break - } - } - - /* Look backward */ - while (prev.length) { - const [, offset] = prev[prev.length - 1] - if (offset - adjust >= y && !last) { - next = [prev.pop()!, ...next] - } else { - break - } - } - - /* Return partition */ - return [prev, next] - }, [[], [...index]]), - distinctUntilChanged((a, b) => ( - a[0] === b[0] && - a[1] === b[1] - )) - ) - ) - ) - ) - ) - - /* Compute and return anchor list migrations */ - return partition$ - .pipe( - map(([prev, next]) => ({ - prev: prev.map(([path]) => path), - next: next.map(([path]) => path) - })), - - /* Extract anchor list migrations */ - startWith({ prev: [], next: [] }), - bufferCount(2, 1), - map(([a, b]) => { - - /* Moving down */ - if (a.prev.length < b.prev.length) { - return { - prev: b.prev.slice(Math.max(0, a.prev.length - 1), b.prev.length), - next: [] - } - - /* Moving up */ - } else { - return { - prev: b.prev.slice(-1), - next: b.next.slice(0, b.next.length - a.next.length) - } - } - }) - ) -} - -/* ------------------------------------------------------------------------- */ - -/** - * Mount table of contents - * - * @param el - Table of contents element - * @param options - Options - * - * @returns Table of contents component observable - */ -export function mountTableOfContents( - el: HTMLElement, { viewport$, header$, main$, target$ }: MountOptions -): Observable<Component<TableOfContents>> { - return defer(() => { - const push$ = new Subject<TableOfContents>() - const done$ = push$.pipe(ignoreElements(), endWith(true)) - push$.subscribe(({ prev, next }) => { - - /* Look forward */ - for (const [anchor] of next) { - anchor.classList.remove("md-nav__link--passed") - anchor.classList.remove("md-nav__link--active") - } - - /* Look backward */ - for (const [index, [anchor]] of prev.entries()) { - anchor.classList.add("md-nav__link--passed") - anchor.classList.toggle( - "md-nav__link--active", - index === prev.length - 1 - ) - } - }) - - /* Set up following, if enabled */ - if (feature("toc.follow")) { - - /* Toggle smooth scrolling only for anchor clicks */ - const smooth$ = merge( - viewport$.pipe(debounceTime(1), map(() => undefined)), - viewport$.pipe(debounceTime(250), map(() => "smooth" as const)) - ) - - /* Bring active anchor into view */ // @todo: refactor - push$ - .pipe( - filter(({ prev }) => prev.length > 0), - combineLatestWith(main$.pipe(observeOn(asyncScheduler))), - withLatestFrom(smooth$) - ) - .subscribe(([[{ prev }], behavior]) => { - const [anchor] = prev[prev.length - 1] - if (anchor.offsetHeight) { - - /* Retrieve overflowing container and scroll */ - const container = getElementContainer(anchor) - if (typeof container !== "undefined") { - const offset = anchor.offsetTop - container.offsetTop - const { height } = getElementSize(container) - container.scrollTo({ - top: offset - height / 2, - behavior - }) - } - } - }) - } - - /* Set up anchor tracking, if enabled */ - if (feature("navigation.tracking")) - viewport$ - .pipe( - takeUntil(done$), - distinctUntilKeyChanged("offset"), - debounceTime(250), - skip(1), - takeUntil(target$.pipe(skip(1))), - repeat({ delay: 250 }), - withLatestFrom(push$) - ) - .subscribe(([, { prev }]) => { - const url = getLocation() - - /* Set hash fragment to active anchor */ - const anchor = prev[prev.length - 1] - if (anchor && anchor.length) { - const [active] = anchor - const { hash } = new URL(active.href) - if (url.hash !== hash) { - url.hash = hash - history.replaceState({}, "", `${url}`) - } - - /* Reset anchor when at the top */ - } else { - url.hash = "" - history.replaceState({}, "", `${url}`) - } - }) - - /* Create and return component */ - return watchTableOfContents(el, { viewport$, header$ }) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })) - ) - }) -} diff --git a/src/templates/assets/javascripts/components/top/index.ts b/src/templates/assets/javascripts/components/top/index.ts deleted file mode 100644 index 82e88b61..00000000 --- a/src/templates/assets/javascripts/components/top/index.ts +++ /dev/null @@ -1,184 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - Subject, - bufferCount, - combineLatest, - distinctUntilChanged, - distinctUntilKeyChanged, - endWith, - finalize, - fromEvent, - ignoreElements, - map, - repeat, - skip, - takeUntil, - tap -} from "rxjs" - -import { Viewport } from "~/browser" - -import { Component } from "../_" -import { Header } from "../header" -import { Main } from "../main" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Back-to-top button - */ -export interface BackToTop { - hidden: boolean /* Back-to-top button is hidden */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Watch options - */ -interface WatchOptions { - viewport$: Observable<Viewport> /* Viewport observable */ - main$: Observable<Main> /* Main area observable */ - target$: Observable<HTMLElement> /* Location target observable */ -} - -/** - * Mount options - */ -interface MountOptions { - viewport$: Observable<Viewport> /* Viewport observable */ - header$: Observable<Header> /* Header observable */ - main$: Observable<Main> /* Main area observable */ - target$: Observable<HTMLElement> /* Location target observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Watch back-to-top - * - * @param _el - Back-to-top element - * @param options - Options - * - * @returns Back-to-top observable - */ -export function watchBackToTop( - _el: HTMLElement, { viewport$, main$, target$ }: WatchOptions -): Observable<BackToTop> { - - /* Compute direction */ - const direction$ = viewport$ - .pipe( - map(({ offset: { y } }) => y), - bufferCount(2, 1), - map(([a, b]) => a > b && b > 0), - distinctUntilChanged() - ) - - /* Compute whether main area is active */ - const active$ = main$ - .pipe( - map(({ active }) => active) - ) - - /* Compute threshold for hiding */ - return combineLatest([active$, direction$]) - .pipe( - map(([active, direction]) => !(active && direction)), - distinctUntilChanged(), - takeUntil(target$.pipe(skip(1))), - endWith(true), - repeat({ delay: 250 }), - map(hidden => ({ hidden })) - ) -} - -/* ------------------------------------------------------------------------- */ - -/** - * Mount back-to-top - * - * @param el - Back-to-top element - * @param options - Options - * - * @returns Back-to-top component observable - */ -export function mountBackToTop( - el: HTMLElement, { viewport$, header$, main$, target$ }: MountOptions -): Observable<Component<BackToTop>> { - const push$ = new Subject<BackToTop>() - const done$ = push$.pipe(ignoreElements(), endWith(true)) - push$.subscribe({ - - /* Handle emission */ - next({ hidden }) { - el.hidden = hidden - if (hidden) { - el.setAttribute("tabindex", "-1") - el.blur() - } else { - el.removeAttribute("tabindex") - } - }, - - /* Handle complete */ - complete() { - el.style.top = "" - el.hidden = true - el.removeAttribute("tabindex") - } - }) - - /* Watch header height */ - header$ - .pipe( - takeUntil(done$), - distinctUntilKeyChanged("height") - ) - .subscribe(({ height }) => { - el.style.top = `${height + 16}px` - }) - - /* Go back to top */ - fromEvent(el, "click") - .subscribe(ev => { - ev.preventDefault() - window.scrollTo({ top: 0 }) - }) - - /* Create and return component */ - return watchBackToTop(el, { viewport$, main$, target$ }) - .pipe( - tap(state => push$.next(state)), - finalize(() => push$.complete()), - map(state => ({ ref: el, ...state })) - ) -} diff --git a/src/templates/assets/javascripts/integrations/clipboard/index.ts b/src/templates/assets/javascripts/integrations/clipboard/index.ts deleted file mode 100644 index cf46f601..00000000 --- a/src/templates/assets/javascripts/integrations/clipboard/index.ts +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 ClipboardJS from "clipboard" -import { - Observable, - Subject, - map, - tap -} from "rxjs" - -import { translation } from "~/_" -import { getElement } from "~/browser" - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Setup options - */ -interface SetupOptions { - alert$: Subject<string> /* Alert subject */ -} - -/* ---------------------------------------------------------------------------- - * Helper functions - * ------------------------------------------------------------------------- */ - -/** - * Extract text to copy - * - * @param el - HTML element - * - * @returns Extracted text - */ -function extract(el: HTMLElement): string { - el.setAttribute("data-md-copying", "") - const copy = el.closest("[data-copy]") - const text = copy - ? copy.getAttribute("data-copy")! - : el.innerText - el.removeAttribute("data-md-copying") - return text -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Set up Clipboard.js integration - * - * @param options - Options - */ -export function setupClipboardJS( - { alert$ }: SetupOptions -): void { - if (ClipboardJS.isSupported()) { - new Observable<ClipboardJS.Event>(subscriber => { - new ClipboardJS("[data-clipboard-target], [data-clipboard-text]", { - text: el => ( - el.getAttribute("data-clipboard-text")! || - extract(getElement( - el.getAttribute("data-clipboard-target")! - )) - ) - }) - .on("success", ev => subscriber.next(ev)) - }) - .pipe( - tap(ev => { - const trigger = ev.trigger as HTMLElement - trigger.focus() - }), - map(() => translation("clipboard.copied")) - ) - .subscribe(alert$) - } -} diff --git a/src/templates/assets/javascripts/integrations/index.ts b/src/templates/assets/javascripts/integrations/index.ts deleted file mode 100644 index 5d91a9d5..00000000 --- a/src/templates/assets/javascripts/integrations/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./clipboard" -export * from "./instant" -export * from "./search" -export * from "./sitemap" -export * from "./version" diff --git a/src/templates/assets/javascripts/integrations/instant/.eslintrc b/src/templates/assets/javascripts/integrations/instant/.eslintrc deleted file mode 100644 index 5adf108a..00000000 --- a/src/templates/assets/javascripts/integrations/instant/.eslintrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "rules": { - "no-self-assign": "off", - "no-null/no-null": "off" - } -} diff --git a/src/templates/assets/javascripts/integrations/instant/index.ts b/src/templates/assets/javascripts/integrations/instant/index.ts deleted file mode 100644 index d321b751..00000000 --- a/src/templates/assets/javascripts/integrations/instant/index.ts +++ /dev/null @@ -1,446 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { - EMPTY, - Observable, - Subject, - bufferCount, - catchError, - concat, - debounceTime, - distinctUntilKeyChanged, - endWith, - filter, - fromEvent, - ignoreElements, - map, - of, - sample, - share, - skip, - startWith, - switchMap, - take, - withLatestFrom -} from "rxjs" - -import { configuration, feature } from "~/_" -import { - Viewport, - getElement, - getElements, - getLocation, - getOptionalElement, - request, - setLocation, - setLocationHash -} from "~/browser" -import { getComponentElement } from "~/components" - -import { fetchSitemap } from "../sitemap" - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Setup options - */ -interface SetupOptions { - location$: Subject<URL> // Location subject - viewport$: Observable<Viewport> // Viewport observable - progress$: Subject<number> // Progress suject -} - -/* ---------------------------------------------------------------------------- - * Helper functions - * ------------------------------------------------------------------------- */ - -/** - * Create a map of head elements for lookup and replacement - * - * @param head - Document head - * - * @returns Element map - */ -function lookup(head: HTMLHeadElement): Map<string, HTMLElement> { - - // @todo When resolving URLs, we must make sure to use the correct base for - // resolution. The next time we refactor instant loading, we should use the - // location subject as a source, which is also used for anchor links tracking, - // but for now we just rely on canonical. - const canonical = getElement<HTMLLinkElement>("[rel=canonical]", head) - canonical.href = canonical.href.replace("//localhost:", "//127.0.0.1") - - // Create tag map and index elements in head - const tags = new Map<string, HTMLElement>() - for (const el of getElements(":scope > *", head)) { - let html = el.outerHTML - - // If the current element is a style sheet or script, we must resolve the - // URL relative to the current location and make it absolute, so it's easy - // to deduplicate it later on by comparing the outer HTML of tags. We must - // keep identical style sheets and scripts without replacing them. - for (const key of ["href", "src"]) { - const value = el.getAttribute(key)! - if (value === null) - continue - - // Resolve URL relative to current location - const url = new URL(value, canonical.href) - const ref = el.cloneNode() as HTMLElement - - // Set resolved URL and retrieve HTML for deduplication - ref.setAttribute(key, `${url}`) - html = ref.outerHTML - break - } - - // Index element in tag map - tags.set(html, el) - } - - // Return tag map - return tags -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Set up instant navigation - * - * This is a heavily orchestrated operation - see inline comments to learn how - * this works with Material for MkDocs, and how you can hook into it. - * - * @param options - Options - * - * @returns Document observable - */ -export function setupInstantNavigation( - { location$, viewport$, progress$ }: SetupOptions -): Observable<Document> { - const config = configuration() - if (location.protocol === "file:") - return EMPTY - - // Load sitemap immediately, so we have it available when the user initiates - // the first instant navigation request, and canonicalize URLs to the current - // base URL. The base URL will remain stable in between loads, as it's only - // read at the first initialization of the application. - const sitemap$ = fetchSitemap() - .pipe( - map(paths => paths.map(path => `${new URL(path, config.base)}`)) - ) - - // Intercept inter-site navigation - to keep the number of event listeners - // low we use the fact that uncaptured events bubble up to the body. This also - // has the nice property that we don't need to detach and then again attach - // event listeners when instant navigation occurs. - const instant$ = fromEvent<MouseEvent>(document.body, "click") - .pipe( - withLatestFrom(sitemap$), - switchMap(([ev, sitemap]) => { - if (!(ev.target instanceof Element)) - return EMPTY - - // Skip, as target is not within a link - clicks on non-link elements - // are also captured, which we need to exclude from processing - const el = ev.target.closest("a") - if (el === null) - return EMPTY - - // Skip, as link opens in new window - we now know we have captured a - // click on a link, but the link either has a `target` property defined, - // or the user pressed the `meta` or `ctrl` key to open it in a new - // window. Thus, we need to filter those events, too. - if (el.target || ev.metaKey || ev.ctrlKey) - return EMPTY - - // Next, we must check if the URL is relevant for us, i.e., if it's an - // internal link to a page that is managed by MkDocs. Only then we can - // be sure that the structure of the page to be loaded adheres to the - // current document structure and can subsequently be injected into it - // without doing a full reload. For this reason, we must canonicalize - // the URL by removing all search parameters and hash fragments. - const url = new URL(el.href) - url.search = url.hash = "" - - // Skip, if URL is not included in the sitemap - this could be the case - // when linking between versions or languages, or to another page that - // the author included as part of the build, but that is not managed by - // MkDocs. In that case we must not continue with instant navigation. - if (!sitemap.includes(`${url}`)) - return EMPTY - - // We now know that we have a link to an internal page, so we prevent - // the browser from navigation and emit the URL for instant navigation. - // Note that this also includes anchor links, which means we need to - // implement anchor positioning ourselves. The reason for this is that - // if we wouldn't manage anchor links as well, scroll restoration will - // not work correctly (e.g. following an anchor link and scrolling). - ev.preventDefault() - return of(new URL(el.href)) - }), - share() - ) - - // Before fetching for the first time, resolve the absolute favicon position, - // as the browser will try to fetch the icon immediately - instant$.pipe(take(1)) - .subscribe(() => { - const favicon = getOptionalElement<HTMLLinkElement>("link[rel=icon]") - if (typeof favicon !== "undefined") - favicon.href = favicon.href - }) - - // Enable scroll restoration before window unloads - this is essential to - // ensure that full reloads (F5) restore the viewport offset correctly. If - // only popstate events wouldn't reset the scroll position prior to their - // emission, we could just reset this in popstate. Meh. - fromEvent(window, "beforeunload") - .subscribe(() => { - history.scrollRestoration = "auto" - }) - - // When an instant navigation event occurs, disable scroll restoration, since - // we must normalize and synchronize the behavior across all browsers. For - // instance, when the user clicks the back or forward button, the browser - // would immediately jump to the position of the previous document. - instant$.pipe(withLatestFrom(viewport$)) - .subscribe(([url, { offset }]) => { - history.scrollRestoration = "manual" - - // While it would be better UX to defer the history state change until the - // document was fully fetched and parsed, we must schedule it here, since - // popstate events are emitted when history state changes happen. Moreover - // we need to back up the current viewport offset, so we can restore it - // when popstate events occur, e.g., when the browser's back and forward - // buttons are used for navigation. - history.replaceState(offset, "") - history.pushState(null, "", url) - }) - - // Emit URL that should be fetched via instant navigation on location subject, - // which was passed into this function. Instant navigation can be intercepted - // by other parts of the application, which can synchronously back up or - // restore state before instant navigation happens. - instant$.subscribe(location$) - - // Fetch document - when fetching, we could use `responseType: document`, but - // since all MkDocs links are relative, we need to make sure that the current - // location matches the document we just loaded. Otherwise any relative links - // in the document might use the old location. If the request fails for some - // reason, we fall back to regular navigation and set the location explicitly, - // which will force-load the page. Furthermore, we must pre-warm the buffer - // for the duplicate check, or the first click on an anchor link will also - // trigger an instant navigation event, which doesn't make sense. - const response$ = location$ - .pipe( - startWith(getLocation()), - distinctUntilKeyChanged("pathname"), - skip(1), - switchMap(url => request(url, { progress$ }) - .pipe( - catchError(() => { - setLocation(url, true) - return EMPTY - }) - ) - ) - ) - - // Initialize the DOM parser, parse the returned HTML, and replace selected - // components before handing control down to the application - const dom = new DOMParser() - const document$ = response$ - .pipe( - switchMap(res => res.text()), - switchMap(res => { - const next = dom.parseFromString(res, "text/html") - for (const selector of [ - "[data-md-component=announce]", - "[data-md-component=container]", - "[data-md-component=header-topic]", - "[data-md-component=outdated]", - "[data-md-component=logo]", - "[data-md-component=skip]", - ...feature("navigation.tabs.sticky") - ? ["[data-md-component=tabs]"] - : [] - ]) { - const source = getOptionalElement(selector) - const target = getOptionalElement(selector, next) - if ( - typeof source !== "undefined" && - typeof target !== "undefined" - ) { - source.replaceWith(target) - } - } - - // Update meta tags - const source = lookup(document.head) - const target = lookup(next.head) - for (const [html, el] of target) { - - // Hack: skip stylesheets and scripts until we manage to replace them - // entirely in order to omit flashes of white content @todo refactor - if ( - el.getAttribute("rel") === "stylesheet" || - el.hasAttribute("src") - ) - continue - - if (source.has(html)) { - source.delete(html) - } else { - document.head.appendChild(el) - } - } - - // Remove meta tags that are not present in the new document - for (const el of source.values()) - - // Hack: skip stylesheets and scripts until we manage to replace them - // entirely in order to omit flashes of white content @todo refactor - if ( - el.getAttribute("rel") === "stylesheet" || - el.hasAttribute("src") - ) - continue - else - el.remove() - - // After components and meta tags were replaced, re-evaluate scripts - // that were provided by the author as part of Markdown files - const container = getComponentElement("container") - return concat(getElements("script", container)) - .pipe( - switchMap(el => { - const script = next.createElement("script") - if (el.src) { - for (const name of el.getAttributeNames()) - script.setAttribute(name, el.getAttribute(name)!) - el.replaceWith(script) - - // Complete when script is loaded - return new Observable(observer => { - script.onload = () => observer.complete() - }) - - // Complete immediately - } else { - script.textContent = el.textContent - el.replaceWith(script) - return EMPTY - } - }), - ignoreElements(), - endWith(next) - ) - }), - share() - ) - - // Intercept popstate events, e.g. when using the browser's back and forward - // buttons, and emit new location for fetching and parsing - const popstate$ = fromEvent<PopStateEvent>(window, "popstate") - popstate$.pipe(map(getLocation)) - .subscribe(location$) - - // Intercept clicks on anchor links, and scroll document into position - as - // we disabled scroll restoration, we need to do this manually here - location$ - .pipe( - startWith(getLocation()), - bufferCount(2, 1), - filter(([prev, next]) => ( - prev.pathname === next.pathname && - prev.hash !== next.hash - )), - map(([, next]) => next) - ) - .subscribe(url => { - if (history.state !== null || !url.hash) { - window.scrollTo(0, history.state?.y ?? 0) - } else { - history.scrollRestoration = "auto" - setLocationHash(url.hash) - history.scrollRestoration = "manual" - } - }) - - // Intercept clicks on the same anchor link - we must use a distinct pipeline - // for this, or we'd end up in a loop, setting the hash again and again - location$ - .pipe( - sample(instant$), - startWith(getLocation()), - bufferCount(2, 1), - filter(([prev, next]) => ( - prev.pathname === next.pathname && - prev.hash === next.hash - )), - map(([, next]) => next) - ) - .subscribe(url => { - history.scrollRestoration = "auto" - setLocationHash(url.hash) - history.scrollRestoration = "manual" - - // Hack: we need to make sure that we don't end up with multiple history - // entries for the same anchor link, so we just remove the last entry - history.back() - }) - - // After parsing the document, check if the current history entry has a state. - // This may happen when users press the back or forward button to visit a page - // that was already seen. If there's no state, it means a new page was visited - // and we should scroll to the top, unless an anchor is given. - document$.pipe(withLatestFrom(location$)) - .subscribe(([, url]) => { - if (history.state !== null || !url.hash) { - window.scrollTo(0, history.state?.y ?? 0) - } else { - setLocationHash(url.hash) - } - }) - - // If the current history is not empty, register an event listener updating - // the current history state whenever the scroll position changes. This must - // be debounced and cannot be done in popstate, as popstate has already - // removed the entry from the history. - viewport$ - .pipe( - distinctUntilKeyChanged("offset"), - debounceTime(100) - ) - .subscribe(({ offset }) => { - history.replaceState(offset, "") - }) - - // Return document - return document$ -} diff --git a/src/templates/assets/javascripts/integrations/search/_/index.ts b/src/templates/assets/javascripts/integrations/search/_/index.ts deleted file mode 100644 index 0e217fa4..00000000 --- a/src/templates/assets/javascripts/integrations/search/_/index.ts +++ /dev/null @@ -1,332 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { - SearchDocument, - SearchIndex, - SearchOptions, - setupSearchDocumentMap -} from "../config" -import { - Position, - PositionTable, - highlight, - highlightAll, - tokenize -} from "../internal" -import { - SearchQueryTerms, - getSearchQueryTerms, - parseSearchQuery, - segment, - transformSearchQuery -} from "../query" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Search item - */ -export interface SearchItem - extends SearchDocument -{ - score: number /* Score (relevance) */ - terms: SearchQueryTerms /* Search query terms */ -} - -/** - * Search result - */ -export interface SearchResult { - items: SearchItem[][] /* Search items */ - suggest?: string[] /* Search suggestions */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Create field extractor factory - * - * @param table - Position table map - * - * @returns Extractor factory - */ -function extractor(table: Map<string, PositionTable>) { - return (name: keyof SearchDocument) => { - return (doc: SearchDocument) => { - if (typeof doc[name] === "undefined") - return undefined - - /* Compute identifier and initialize table */ - const id = [doc.location, name].join(":") - table.set(id, lunr.tokenizer.table = []) - - /* Return field value */ - return doc[name] - } - } -} - -/** - * Compute the difference of two lists of strings - * - * @param a - 1st list of strings - * @param b - 2nd list of strings - * - * @returns Difference - */ -function difference(a: string[], b: string[]): string[] { - const [x, y] = [new Set(a), new Set(b)] - return [ - ...new Set([...x].filter(value => !y.has(value))) - ] -} - -/* ---------------------------------------------------------------------------- - * Class - * ------------------------------------------------------------------------- */ - -/** - * Search index - */ -export class Search { - - /** - * Search document map - */ - protected map: Map<string, SearchDocument> - - /** - * Search options - */ - protected options: SearchOptions - - /** - * The underlying Lunr.js search index - */ - protected index: lunr.Index - - /** - * Internal position table map - */ - protected table: Map<string, PositionTable> - - /** - * Create the search integration - * - * @param data - Search index - */ - public constructor({ config, docs, options }: SearchIndex) { - const field = extractor(this.table = new Map()) - - /* Set up document map and options */ - this.map = setupSearchDocumentMap(docs) - this.options = options - - /* Set up document index */ - this.index = lunr(function () { - this.metadataWhitelist = ["position"] - this.b(0) - - /* Set up (multi-)language support */ - if (config.lang.length === 1 && config.lang[0] !== "en") { - // @ts-expect-error - namespace indexing not supported - this.use(lunr[config.lang[0]]) - } else if (config.lang.length > 1) { - this.use(lunr.multiLanguage(...config.lang)) - } - - /* Set up custom tokenizer (must be after language setup) */ - this.tokenizer = tokenize as typeof lunr.tokenizer - lunr.tokenizer.separator = new RegExp(config.separator) - - /* Set up custom segmenter, if loaded */ - lunr.segmenter = "TinySegmenter" in lunr - ? new lunr.TinySegmenter() - : undefined - - /* Compute functions to be removed from the pipeline */ - const fns = difference([ - "trimmer", "stopWordFilter", "stemmer" - ], config.pipeline) - - /* Remove functions from the pipeline for registered languages */ - for (const lang of config.lang.map(language => ( - // @ts-expect-error - namespace indexing not supported - language === "en" ? lunr : lunr[language] - ))) - for (const fn of fns) { - this.pipeline.remove(lang[fn]) - this.searchPipeline.remove(lang[fn]) - } - - /* Set up index reference */ - this.ref("location") - - /* Set up index fields */ - this.field("title", { boost: 1e3, extractor: field("title") }) - this.field("text", { boost: 1e0, extractor: field("text") }) - this.field("tags", { boost: 1e6, extractor: field("tags") }) - - /* Add documents to index */ - for (const doc of docs) - this.add(doc, { boost: doc.boost }) - }) - } - - /** - * Search for matching documents - * - * @param query - Search query - * - * @returns Search result - */ - public search(query: string): SearchResult { - - // Experimental Chinese segmentation - query = query.replace(/\p{sc=Han}+/gu, value => { - return [...segment(value, this.index.invertedIndex)] - .join("* ") - }) - - // @todo: move segmenter (above) into transformSearchQuery - query = transformSearchQuery(query) - if (!query) - return { items: [] } - - /* Parse query to extract clauses for analysis */ - const clauses = parseSearchQuery(query) - .filter(clause => ( - clause.presence !== lunr.Query.presence.PROHIBITED - )) - - /* Perform search and post-process results */ - const groups = this.index.search(query) - - /* Apply post-query boosts based on title and search query terms */ - .reduce<SearchItem[]>((item, { ref, score, matchData }) => { - let doc = this.map.get(ref) - if (typeof doc !== "undefined") { - - /* Shallow copy document */ - doc = { ...doc } - if (doc.tags) - doc.tags = [...doc.tags] - - /* Compute and analyze search query terms */ - const terms = getSearchQueryTerms( - clauses, - Object.keys(matchData.metadata) - ) - - /* Highlight matches in fields */ - for (const field of this.index.fields) { - if (typeof doc[field] === "undefined") - continue - - /* Collect positions from matches */ - const positions: Position[] = [] - for (const match of Object.values(matchData.metadata)) - if (typeof match[field] !== "undefined") - positions.push(...match[field].position) - - /* Skip highlighting, if no positions were collected */ - if (!positions.length) - continue - - /* Load table and determine highlighting method */ - const table = this.table.get([doc.location, field].join(":"))! - const fn = Array.isArray(doc[field]) - ? highlightAll - : highlight - - // @ts-expect-error - stop moaning, TypeScript! - doc[field] = fn(doc[field], table, positions, field !== "text") - } - - /* Highlight title and text and apply post-query boosts */ - const boost = +!doc.parent + - Object.values(terms) - .filter(t => t).length / - Object.keys(terms).length - - /* Append item */ - item.push({ - ...doc, - score: score * (1 + boost ** 2), - terms - }) - } - return item - }, []) - - /* Sort search results again after applying boosts */ - .sort((a, b) => b.score - a.score) - - /* Group search results by article */ - .reduce((items, result) => { - const doc = this.map.get(result.location) - if (typeof doc !== "undefined") { - const ref = doc.parent - ? doc.parent.location - : doc.location - items.set(ref, [...items.get(ref) || [], result]) - } - return items - }, new Map<string, SearchItem[]>()) - - /* Ensure that every item set has an article */ - for (const [ref, items] of groups) - if (!items.find(item => item.location === ref)) { - const doc = this.map.get(ref)! - items.push({ ...doc, score: 0, terms: {} }) - } - - /* Generate search suggestions, if desired */ - let suggest: string[] | undefined - if (this.options.suggest) { - const titles = this.index.query(builder => { - for (const clause of clauses) - builder.term(clause.term, { - fields: ["title"], - presence: lunr.Query.presence.REQUIRED, - wildcard: lunr.Query.wildcard.TRAILING - }) - }) - - /* Retrieve suggestions for best match */ - suggest = titles.length - ? Object.keys(titles[0].matchData.metadata) - : [] - } - - /* Return search result */ - return { - items: [...groups.values()], - ...typeof suggest !== "undefined" && { suggest } - } - } -} diff --git a/src/templates/assets/javascripts/integrations/search/config/index.ts b/src/templates/assets/javascripts/integrations/search/config/index.ts deleted file mode 100644 index 3d88d1c6..00000000 --- a/src/templates/assets/javascripts/integrations/search/config/index.ts +++ /dev/null @@ -1,115 +0,0 @@ -/* - * Copyright (c) 2016-2023 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. - */ - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Search configuration - */ -export interface SearchConfig { - lang: string[] /* Search languages */ - separator: string /* Search separator */ - pipeline: SearchPipelineFn[] /* Search pipeline */ -} - -/** - * Search document - */ -export interface SearchDocument { - location: string /* Document location */ - title: string /* Document title */ - text: string /* Document text */ - tags?: string[] /* Document tags */ - boost?: number /* Document boost */ - parent?: SearchDocument /* Document parent */ -} - -/** - * Search options - */ -export interface SearchOptions { - suggest: boolean /* Search suggestions */ -} - -/* ------------------------------------------------------------------------- */ - -/** - * Search index - */ -export interface SearchIndex { - config: SearchConfig /* Search configuration */ - docs: SearchDocument[] /* Search documents */ - options: SearchOptions /* Search options */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Search pipeline function - */ -type SearchPipelineFn = - | "trimmer" /* Trimmer */ - | "stopWordFilter" /* Stop word filter */ - | "stemmer" /* Stemmer */ - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Create a search document map - * - * This function creates a mapping of URLs (including anchors) to the actual - * articles and sections. It relies on the invariant that the search index is - * ordered with the main article appearing before all sections with anchors. - * If this is not the case, the logic music be changed. - * - * @param docs - Search documents - * - * @returns Search document map - */ -export function setupSearchDocumentMap( - docs: SearchDocument[] -): Map<string, SearchDocument> { - const map = new Map<string, SearchDocument>() - for (const doc of docs) { - const [path] = doc.location.split("#") - - /* Add document article */ - const article = map.get(path) - if (typeof article === "undefined") { - map.set(path, doc) - - /* Add document section */ - } else { - map.set(doc.location, doc) - doc.parent = article - } - } - - /* Return search document map */ - return map -} diff --git a/src/templates/assets/javascripts/integrations/search/highlighter/index.ts b/src/templates/assets/javascripts/integrations/search/highlighter/index.ts deleted file mode 100644 index 0fcbb19e..00000000 --- a/src/templates/assets/javascripts/integrations/search/highlighter/index.ts +++ /dev/null @@ -1,93 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 escapeHTML from "escape-html" - -import { SearchConfig } from "../config" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Search highlight function - * - * @param value - Value - * - * @returns Highlighted value - */ -export type SearchHighlightFn = (value: string) => string - -/** - * Search highlight factory function - * - * @param query - Query value - * - * @returns Search highlight function - */ -export type SearchHighlightFactoryFn = (query: string) => SearchHighlightFn - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Create a search highlighter - * - * @param config - Search configuration - * - * @returns Search highlight factory function - */ -export function setupSearchHighlighter( - config: SearchConfig -): SearchHighlightFactoryFn { - // Hack: temporarily remove pure lookaheads and lookbehinds - const regex = config.separator.split("|").map(term => { - const temp = term.replace(/(\(\?[!=<][^)]+\))/g, "") - return temp.length === 0 ? "�" : term - }) - .join("|") - - const separator = new RegExp(regex, "img") - const highlight = (_: unknown, data: string, term: string) => { - return `${data}<mark data-md-highlight>${term}</mark>` - } - - /* Return factory function */ - return (query: string) => { - query = query - .replace(/[\s*+\-:~^]+/g, " ") - .trim() - - /* Create search term match expression */ - const match = new RegExp(`(^|${config.separator}|)(${ - query - .replace(/[|\\{}()[\]^$+*?.-]/g, "\\$&") - .replace(separator, "|") - })`, "img") - - /* Highlight string value */ - return value => escapeHTML(value) - .replace(match, highlight) - .replace(/<\/mark>(\s+)<mark[^>]*>/img, "$1") - } -} diff --git a/src/templates/assets/javascripts/integrations/search/index.ts b/src/templates/assets/javascripts/integrations/search/index.ts deleted file mode 100644 index 94c010bb..00000000 --- a/src/templates/assets/javascripts/integrations/search/index.ts +++ /dev/null @@ -1,27 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./config" -export * from "./highlighter" -export * from "./query" -export * from "./worker" diff --git a/src/templates/assets/javascripts/integrations/search/internal/.eslintrc b/src/templates/assets/javascripts/integrations/search/internal/.eslintrc deleted file mode 100644 index 9368ceb6..00000000 --- a/src/templates/assets/javascripts/integrations/search/internal/.eslintrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "rules": { - "no-fallthrough": "off", - "no-underscore-dangle": "off" - } -} diff --git a/src/templates/assets/javascripts/integrations/search/internal/_/index.ts b/src/templates/assets/javascripts/integrations/search/internal/_/index.ts deleted file mode 100644 index ae8f6104..00000000 --- a/src/templates/assets/javascripts/integrations/search/internal/_/index.ts +++ /dev/null @@ -1,74 +0,0 @@ -/* - * Copyright (c) 2016-2023 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. - */ - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Visitor function - * - * @param start - Start offset - * @param end - End offset - */ -type VisitorFn = ( - start: number, end: number -) => void - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Split a string using the given separator - * - * @param input - Input value - * @param separator - Separator - * @param fn - Visitor function - */ -export function split( - input: string, separator: RegExp, fn: VisitorFn -): void { - separator = new RegExp(separator, "g") - - /* Split string using separator */ - let match: RegExpExecArray | null - let index = 0 - do { - match = separator.exec(input) - - /* Emit non-empty range */ - const until = match?.index ?? input.length - if (index < until) - fn(index, until) - - /* Update last index */ - if (match) { - const [term] = match - index = match.index + term.length - - /* Support zero-length lookaheads */ - if (term.length === 0) - separator.lastIndex = match.index + 1 - } - } while (match) -} diff --git a/src/templates/assets/javascripts/integrations/search/internal/extract/index.ts b/src/templates/assets/javascripts/integrations/search/internal/extract/index.ts deleted file mode 100644 index 2a98b9e1..00000000 --- a/src/templates/assets/javascripts/integrations/search/internal/extract/index.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2016-2023 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. - */ - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Extraction type - * - * This type defines the possible values that are encoded into the first two - * bits of a section that is part of the blocks of a tokenization table. There - * are three types of interest: HTML opening and closing tags, as well as the - * actual text content we need to extract for indexing. - */ -export const enum Extract { - TAG_OPEN = 0, /* HTML opening tag */ - TEXT = 1, /* Text content */ - TAG_CLOSE = 2 /* HTML closing tag */ -} - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Visitor function - * - * @param block - Block index - * @param type - Extraction type - * @param start - Start offset - * @param end - End offset - */ -type VisitorFn = ( - block: number, type: Extract, start: number, end: number -) => void - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Split a string into markup and text sections - * - * This function scans a string and divides it up into sections of markup and - * text. For each section, it invokes the given visitor function with the block - * index, extraction type, as well as start and end offsets. Using a visitor - * function (= streaming data) is ideal for minimizing pressure on the GC. - * - * @param input - Input value - * @param fn - Visitor function - */ -export function extract( - input: string, fn: VisitorFn -): void { - - let block = 0 /* Current block */ - let start = 0 /* Current start offset */ - let end = 0 /* Current end offset */ - - /* Split string into sections */ - for (let stack = 0; end < input.length; end++) { - - /* Opening tag after non-empty section */ - if (input.charAt(end) === "<" && end > start) { - fn(block, Extract.TEXT, start, start = end) - - /* Closing tag */ - } else if (input.charAt(end) === ">") { - if (input.charAt(start + 1) === "/") { - if (--stack === 0) - fn(block++, Extract.TAG_CLOSE, start, end + 1) - - /* Tag is not self-closing */ - } else if (input.charAt(end - 1) !== "/") { - if (stack++ === 0) - fn(block, Extract.TAG_OPEN, start, end + 1) - } - - /* New section */ - start = end + 1 - } - } - - /* Add trailing section */ - if (end > start) - fn(block, Extract.TEXT, start, end) -} diff --git a/src/templates/assets/javascripts/integrations/search/internal/highlight/index.ts b/src/templates/assets/javascripts/integrations/search/internal/highlight/index.ts deleted file mode 100644 index 7cc3bf1a..00000000 --- a/src/templates/assets/javascripts/integrations/search/internal/highlight/index.ts +++ /dev/null @@ -1,162 +0,0 @@ -/* - * Copyright (c) 2016-2023 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. - */ - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Position table - */ -export type PositionTable = number[][] - -/** - * Position - */ -export type Position = number - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Highlight all occurrences in a string - * - * This function receives a field's value (e.g. like `title` or `text`), it's - * position table that was generated during indexing, and the positions found - * when executing the query. It then highlights all occurrences, and returns - * their concatenation. In case of multiple blocks, two are returned. - * - * @param input - Input value - * @param table - Table for indexing - * @param positions - Occurrences - * @param full - Full results - * - * @returns Highlighted string value - */ -export function highlight( - input: string, table: PositionTable, positions: Position[], full = false -): string { - return highlightAll([input], table, positions, full).pop()! -} - -/** - * Highlight all occurrences in a set of strings - * - * @param inputs - Input values - * @param table - Table for indexing - * @param positions - Occurrences - * @param full - Full results - * - * @returns Highlighted string values - */ -export function highlightAll( - inputs: string[], table: PositionTable, positions: Position[], full = false -): string[] { - - /* Map blocks to input values */ - const mapping = [0] - for (let t = 1; t < table.length; t++) { - const prev = table[t - 1] - const next = table[t] - - /* Check if table points to new block */ - const p = prev[prev.length - 1] >>> 2 & 0x3FF - const q = next[0] >>> 12 - - /* Add block to mapping */ - mapping.push(+(p > q) + mapping[mapping.length - 1]) - } - - /* Highlight strings one after another */ - return inputs.map((input, i) => { - let cursor = 0 - - /* Map occurrences to blocks */ - const blocks = new Map<number, number[]>() - for (const p of positions.sort((a, b) => a - b)) { - const index = p & 0xFFFFF - const block = p >>> 20 - if (mapping[block] !== i) - continue - - /* Ensure presence of block group */ - let group = blocks.get(block) - if (typeof group === "undefined") - blocks.set(block, group = []) - - /* Add index to group */ - group.push(index) - } - - /* Just return string, if no occurrences */ - if (blocks.size === 0) - return input - - /* Compute slices */ - const slices: string[] = [] - for (const [block, indexes] of blocks) { - const t = table[block] - - /* Extract positions and length */ - const start = t[0] >>> 12 - const end = t[t.length - 1] >>> 12 - const length = t[t.length - 1] >>> 2 & 0x3FF - - /* Add prefix, if full results are desired */ - if (full && start > cursor) - slices.push(input.slice(cursor, start)) - - /* Extract and highlight slice */ - let slice = input.slice(start, end + length) - for (const j of indexes.sort((a, b) => b - a)) { - - /* Retrieve offset and length of match */ - const p = (t[j] >>> 12) - start - const q = (t[j] >>> 2 & 0x3FF) + p - - /* Wrap occurrence */ - slice = [ - slice.slice(0, p), - "<mark>", - slice.slice(p, q), - "</mark>", - slice.slice(q) - ].join("") - } - - /* Update cursor */ - cursor = end + length - - /* Append slice and abort if we have two */ - if (slices.push(slice) === 2) - break - } - - /* Add suffix, if full results are desired */ - if (full && cursor < input.length) - slices.push(input.slice(cursor)) - - /* Return highlighted slices */ - return slices.join("") - }) -} diff --git a/src/templates/assets/javascripts/integrations/search/internal/index.ts b/src/templates/assets/javascripts/integrations/search/internal/index.ts deleted file mode 100644 index c752329e..00000000 --- a/src/templates/assets/javascripts/integrations/search/internal/index.ts +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./extract" -export * from "./highlight" -export * from "./tokenize" diff --git a/src/templates/assets/javascripts/integrations/search/internal/tokenize/index.ts b/src/templates/assets/javascripts/integrations/search/internal/tokenize/index.ts deleted file mode 100644 index f5089bc9..00000000 --- a/src/templates/assets/javascripts/integrations/search/internal/tokenize/index.ts +++ /dev/null @@ -1,136 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { split } from "../_" -import { - Extract, - extract -} from "../extract" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Split a string or set of strings into tokens - * - * This tokenizer supersedes the default tokenizer that is provided by Lunr.js, - * as it is aware of HTML tags and allows for multi-character splitting. - * - * It takes the given inputs, splits each of them into markup and text sections, - * tokenizes and segments (if necessary) each of them, and then indexes them in - * a table by using a compact bit representation. Bitwise techniques are used - * to write and read from the table during indexing and querying. - * - * @see https://bit.ly/3W3Xw4J - Search: better, faster, smaller - * - * @param input - Input value(s) - * - * @returns Tokens - */ -export function tokenize( - input?: string | string[] -): lunr.Token[] { - const tokens: lunr.Token[] = [] - if (typeof input === "undefined") - return tokens - - /* Tokenize strings one after another */ - const inputs = Array.isArray(input) ? input : [input] - for (let i = 0; i < inputs.length; i++) { - const table = lunr.tokenizer.table - const total = table.length - - /* Split string into sections and tokenize content blocks */ - extract(inputs[i], (block, type, start, end) => { - table[block += total] ||= [] - switch (type) { - - /* Handle markup */ - case Extract.TAG_OPEN: - case Extract.TAG_CLOSE: - table[block].push( - start << 12 | - end - start << 2 | - type - ) - break - - /* Handle text content */ - case Extract.TEXT: - const section = inputs[i].slice(start, end) - split(section, lunr.tokenizer.separator, (index, until) => { - - /** - * Apply segmenter after tokenization. Note that the segmenter will - * also split words at word boundaries, which is not what we want, - * so we need to check if we can somehow mitigate this behavior. - */ - if (typeof lunr.segmenter !== "undefined") { - const subsection = section.slice(index, until) - if (/^[MHIK]$/.test(lunr.segmenter.ctype_(subsection))) { - const segments = lunr.segmenter.segment(subsection) - for (let s = 0, l = 0; s < segments.length; s++) { - - /* Add block to section */ - table[block] ||= [] - table[block].push( - start + index + l << 12 | - segments[s].length << 2 | - type - ) - - /* Add token with position */ - tokens.push(new lunr.Token( - segments[s].toLowerCase(), { - position: block << 20 | table[block].length - 1 - } - )) - - /* Keep track of length */ - l += segments[s].length - } - return - } - } - - /* Add block to section */ - table[block].push( - start + index << 12 | - until - index << 2 | - type - ) - - /* Add token with position */ - tokens.push(new lunr.Token( - section.slice(index, until).toLowerCase(), { - position: block << 20 | table[block].length - 1 - } - )) - }) - } - }) - } - - /* Return tokens */ - return tokens -} diff --git a/src/templates/assets/javascripts/integrations/search/query/.eslintrc b/src/templates/assets/javascripts/integrations/search/query/.eslintrc deleted file mode 100644 index 3031c7e3..00000000 --- a/src/templates/assets/javascripts/integrations/search/query/.eslintrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "rules": { - "no-control-regex": "off", - "@typescript-eslint/no-explicit-any": "off" - } -} diff --git a/src/templates/assets/javascripts/integrations/search/query/_/index.ts b/src/templates/assets/javascripts/integrations/search/query/_/index.ts deleted file mode 100644 index 14482e43..00000000 --- a/src/templates/assets/javascripts/integrations/search/query/_/index.ts +++ /dev/null @@ -1,172 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { split } from "../../internal" -import { transform } from "../transform" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Search query clause - */ -export interface SearchQueryClause { - presence: lunr.Query.presence /* Clause presence */ - term: string /* Clause term */ -} - -/* ------------------------------------------------------------------------- */ - -/** - * Search query terms - */ -export type SearchQueryTerms = Record<string, boolean> - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Transform search query - * - * This function lexes the given search query and applies the transformation - * function to each term, preserving markup like `+` and `-` modifiers. - * - * @param query - Search query - * - * @returns Search query - */ -export function transformSearchQuery( - query: string -): string { - - /* Split query terms with tokenizer */ - return transform(query, part => { - const terms: string[] = [] - - /* Initialize lexer and analyze part */ - const lexer = new lunr.QueryLexer(part) - lexer.run() - - /* Extract and tokenize term from lexeme */ - for (const { type, str: term, start, end } of lexer.lexemes) - switch (type) { - - /* Hack: remove colon - see https://bit.ly/3wD3T3I */ - case "FIELD": - if (!["title", "text", "tags"].includes(term)) - part = [ - part.slice(0, end), - " ", - part.slice(end + 1) - ].join("") - break - - /* Tokenize term */ - case "TERM": - split(term, lunr.tokenizer.separator, (...range) => { - terms.push([ - part.slice(0, start), - term.slice(...range), - part.slice(end) - ].join("")) - }) - } - - /* Return terms */ - return terms - }) -} - -/* ------------------------------------------------------------------------- */ - -/** - * Parse a search query for analysis - * - * Lunr.js itself has a bug where it doesn't detect or remove wildcards for - * query clauses, so we must do this here. - * - * @see https://bit.ly/3DpTGtz - GitHub issue - * - * @param value - Query value - * - * @returns Search query clauses - */ -export function parseSearchQuery( - value: string -): SearchQueryClause[] { - const query = new lunr.Query(["title", "text", "tags"]) - const parser = new lunr.QueryParser(value, query) - - /* Parse Search query */ - parser.parse() - for (const clause of query.clauses) { - clause.usePipeline = true - - /* Handle leading wildcard */ - if (clause.term.startsWith("*")) { - clause.wildcard = lunr.Query.wildcard.LEADING - clause.term = clause.term.slice(1) - } - - /* Handle trailing wildcard */ - if (clause.term.endsWith("*")) { - clause.wildcard = lunr.Query.wildcard.TRAILING - clause.term = clause.term.slice(0, -1) - } - } - - /* Return query clauses */ - return query.clauses -} - -/** - * Analyze the search query clauses in regard to the search terms found - * - * @param query - Search query clauses - * @param terms - Search terms - * - * @returns Search query terms - */ -export function getSearchQueryTerms( - query: SearchQueryClause[], terms: string[] -): SearchQueryTerms { - const clauses = new Set<SearchQueryClause>(query) - - /* Match query clauses against terms */ - const result: SearchQueryTerms = {} - for (let t = 0; t < terms.length; t++) - for (const clause of clauses) - if (terms[t].startsWith(clause.term)) { - result[clause.term] = true - clauses.delete(clause) - } - - /* Annotate unmatched non-stopword query clauses */ - for (const clause of clauses) - if (lunr.stopWordFilter?.(clause.term)) - result[clause.term] = false - - /* Return query terms */ - return result -} diff --git a/src/templates/assets/javascripts/integrations/search/query/index.ts b/src/templates/assets/javascripts/integrations/search/query/index.ts deleted file mode 100644 index 763e2fd4..00000000 --- a/src/templates/assets/javascripts/integrations/search/query/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./segment" -export * from "./transform" diff --git a/src/templates/assets/javascripts/integrations/search/query/segment/index.ts b/src/templates/assets/javascripts/integrations/search/query/segment/index.ts deleted file mode 100644 index b96796f4..00000000 --- a/src/templates/assets/javascripts/integrations/search/query/segment/index.ts +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 - * ------------------------------------------------------------------------- */ - -/** - * Segment a search query using the inverted index - * - * This function implements a clever approach to text segmentation for Asian - * languages, as it used the information already available in the search index. - * The idea is to greedily segment the search query based on the tokens that are - * already part of the index, as described in the linked issue. - * - * @see https://bit.ly/3lwjrk7 - GitHub issue - * - * @param query - Query value - * @param index - Inverted index - * - * @returns Segmented query value - */ -export function segment( - query: string, index: object -): Iterable<string> { - const segments = new Set<string>() - - /* Segment search query */ - const wordcuts = new Uint16Array(query.length) - for (let i = 0; i < query.length; i++) - for (let j = i + 1; j < query.length; j++) { - const value = query.slice(i, j) - if (value in index) - wordcuts[i] = j - i - } - - /* Compute longest matches with minimum overlap */ - const stack = [0] - for (let s = stack.length; s > 0;) { - const p = stack[--s] - for (let q = 1; q < wordcuts[p]; q++) - if (wordcuts[p + q] > wordcuts[p] - q) { - segments.add(query.slice(p, p + q)) - stack[s++] = p + q - } - - /* Continue at end of query string */ - const q = p + wordcuts[p] - if (wordcuts[q] && q < query.length - 1) - stack[s++] = q - - /* Add current segment */ - segments.add(query.slice(p, q)) - } - - // @todo fix this case in the code block above, this is a hotfix - if (segments.has("")) - return new Set([query]) - - /* Return segmented query value */ - return segments -} diff --git a/src/templates/assets/javascripts/integrations/search/query/transform/index.ts b/src/templates/assets/javascripts/integrations/search/query/transform/index.ts deleted file mode 100644 index 41497786..00000000 --- a/src/templates/assets/javascripts/integrations/search/query/transform/index.ts +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2016-2023 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. - */ - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Visitor function - * - * @param value - String value - * - * @returns String term(s) - */ -type VisitorFn = ( - value: string -) => string | string[] - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Default transformation function - * - * 1. Trim excess whitespace from left and right. - * - * 2. Search for parts in quotation marks and prepend a `+` modifier to denote - * that the resulting document must contain all parts, converting the query - * to an `AND` query (as opposed to the default `OR` behavior). While users - * may expect parts enclosed in quotation marks to map to span queries, i.e. - * for which order is important, Lunr.js doesn't support them, so the best - * we can do is to convert the parts to an `AND` query. - * - * 3. Replace control characters which are not located at the beginning of the - * query or preceded by white space, or are not followed by a non-whitespace - * character or are at the end of the query string. Furthermore, filter - * unmatched quotation marks. - * - * 4. Split the query string at whitespace, then pass each part to the visitor - * function for tokenization, and append a wildcard to every resulting term - * that is not explicitly marked with a `+`, `-`, `~` or `^` modifier, since - * it ensures consistent and stable ranking when multiple terms are entered. - * Also, if a fuzzy or boost modifier are given, but no numeric value has - * been entered, default to 1 to not induce a query error. - * - * @param query - Query value - * @param fn - Visitor function - * - * @returns Transformed query value - */ -export function transform( - query: string, fn: VisitorFn = term => term -): string { - return query - - /* => 1 */ - .trim() - - /* => 2 */ - .split(/"([^"]+)"/g) - .map((parts, index) => index & 1 - ? parts.replace(/^\b|^(?![^\x00-\x7F]|$)|\s+/g, " +") - : parts - ) - .join("") - - /* => 3 */ - .replace(/"|(?:^|\s+)[*+\-:^~]+(?=\s+|$)/g, "") - - /* => 4 */ - .split(/\s+/g) - .reduce((prev, term) => { - const next = fn(term) - return [...prev, ...Array.isArray(next) ? next : [next]] - }, [] as string[]) - .map(term => /([~^]$)/.test(term) ? `${term}1` : term) - .map(term => /(^[+-]|[~^]\d+$)/.test(term) ? term : `${term}*`) - .join(" ") -} diff --git a/src/templates/assets/javascripts/integrations/search/worker/_/index.ts b/src/templates/assets/javascripts/integrations/search/worker/_/index.ts deleted file mode 100644 index 26713573..00000000 --- a/src/templates/assets/javascripts/integrations/search/worker/_/index.ts +++ /dev/null @@ -1,95 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 RTICULAR 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 { - ObservableInput, - Subject, - first, - merge, - of, - switchMap -} from "rxjs" - -import { feature } from "~/_" -import { watchToggle, watchWorker } from "~/browser" - -import { SearchIndex } from "../../config" -import { - SearchMessage, - SearchMessageType -} from "../message" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Set up search worker - * - * This function creates and initializes a web worker that is used for search, - * so that the user interface doesn't freeze. In general, the application does - * not care how search is implemented, as long as the web worker conforms to - * the format expected by the application as defined in `SearchMessage`. This - * allows the author to implement custom search functionality, by providing a - * custom web worker via configuration. - * - * Material for MkDocs' built-in search implementation makes use of Lunr.js, an - * efficient and fast implementation for client-side search. Leveraging a tiny - * iframe-based web worker shim, search is even supported for the `file://` - * protocol, enabling search for local non-hosted builds. - * - * If the protocol is `file://`, search initialization is deferred to mitigate - * freezing, as it's now synchronous by design - see https://bit.ly/3C521EO - * - * @see https://bit.ly/3igvtQv - How to implement custom search - * - * @param url - Worker URL - * @param index$ - Search index observable input - * - * @returns Search worker - */ -export function setupSearchWorker( - url: string, index$: ObservableInput<SearchIndex> -): Subject<SearchMessage> { - const worker$ = watchWorker<SearchMessage>(url) - merge( - of(location.protocol !== "file:"), - watchToggle("search") - ) - .pipe( - first(active => active), - switchMap(() => index$) - ) - .subscribe(({ config, docs }) => worker$.next({ - type: SearchMessageType.SETUP, - data: { - config, - docs, - options: { - suggest: feature("search.suggest") - } - } - })) - - /* Return search worker */ - return worker$ -} diff --git a/src/templates/assets/javascripts/integrations/search/worker/index.ts b/src/templates/assets/javascripts/integrations/search/worker/index.ts deleted file mode 100644 index 7120ad6e..00000000 --- a/src/templates/assets/javascripts/integrations/search/worker/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./message" diff --git a/src/templates/assets/javascripts/integrations/search/worker/main/.eslintrc b/src/templates/assets/javascripts/integrations/search/worker/main/.eslintrc deleted file mode 100644 index 3df9d551..00000000 --- a/src/templates/assets/javascripts/integrations/search/worker/main/.eslintrc +++ /dev/null @@ -1,6 +0,0 @@ -{ - "rules": { - "no-console": "off", - "@typescript-eslint/no-misused-promises": "off" - } -} diff --git a/src/templates/assets/javascripts/integrations/search/worker/main/index.ts b/src/templates/assets/javascripts/integrations/search/worker/main/index.ts deleted file mode 100644 index 2df38080..00000000 --- a/src/templates/assets/javascripts/integrations/search/worker/main/index.ts +++ /dev/null @@ -1,192 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 RTICULAR 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 lunr from "lunr" - -import { getElement } from "~/browser/element/_" -import "~/polyfills" - -import { Search } from "../../_" -import { SearchConfig } from "../../config" -import { - SearchMessage, - SearchMessageType -} from "../message" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Add support for `iframe-worker` shim - * - * While `importScripts` is synchronous when executed inside of a web worker, - * it's not possible to provide a synchronous shim implementation. The cool - * thing is that awaiting a non-Promise will convert it into a Promise, so - * extending the type definition to return a `Promise` shouldn't break anything. - * - * @see https://bit.ly/2PjDnXi - GitHub comment - * - * @param urls - Scripts to load - * - * @returns Promise resolving with no result - */ -declare global { - function importScripts(...urls: string[]): Promise<void> | void -} - -/* ---------------------------------------------------------------------------- - * Data - * ------------------------------------------------------------------------- */ - -/** - * Search index - */ -let index: Search - -/* ---------------------------------------------------------------------------- - * Helper functions - * ------------------------------------------------------------------------- */ - -/** - * Fetch (= import) multi-language support through `lunr-languages` - * - * This function automatically imports the stemmers necessary to process the - * languages which are defined as part of the search configuration. - * - * If the worker runs inside of an `iframe` (when using `iframe-worker` as - * a shim), the base URL for the stemmers to be loaded must be determined by - * searching for the first `script` element with a `src` attribute, which will - * contain the contents of this script. - * - * @param config - Search configuration - * - * @returns Promise resolving with no result - */ -async function setupSearchLanguages( - config: SearchConfig -): Promise<void> { - let base = "../lunr" - - /* Detect `iframe-worker` and fix base URL */ - if (typeof parent !== "undefined" && "IFrameWorker" in parent) { - const worker = getElement<HTMLScriptElement>("script[src]")! - const [path] = worker.src.split("/worker") - - /* Prefix base with path */ - base = base.replace("..", path) - } - - /* Add scripts for languages */ - const scripts = [] - for (const lang of config.lang) { - switch (lang) { - - /* Add segmenter for Japanese */ - case "ja": - scripts.push(`${base}/tinyseg.js`) - break - - /* Add segmenter for Hindi and Thai */ - case "hi": - case "th": - scripts.push(`${base}/wordcut.js`) - break - } - - /* Add language support */ - if (lang !== "en") - scripts.push(`${base}/min/lunr.${lang}.min.js`) - } - - /* Add multi-language support */ - if (config.lang.length > 1) - scripts.push(`${base}/min/lunr.multi.min.js`) - - /* Load scripts synchronously */ - if (scripts.length) - await importScripts( - `${base}/min/lunr.stemmer.support.min.js`, - ...scripts - ) -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Message handler - * - * @param message - Source message - * - * @returns Target message - */ -export async function handler( - message: SearchMessage -): Promise<SearchMessage> { - switch (message.type) { - - /* Search setup message */ - case SearchMessageType.SETUP: - await setupSearchLanguages(message.data.config) - index = new Search(message.data) - return { - type: SearchMessageType.READY - } - - /* Search query message */ - case SearchMessageType.QUERY: - const query = message.data - try { - return { - type: SearchMessageType.RESULT, - data: index.search(query) - } - - /* Return empty result in case of error */ - } catch (err) { - console.warn(`Invalid query: ${query} – see https://bit.ly/2s3ChXG`) - console.warn(err) - return { - type: SearchMessageType.RESULT, - data: { items: [] } - } - } - - /* All other messages */ - default: - throw new TypeError("Invalid message type") - } -} - -/* ---------------------------------------------------------------------------- - * Worker - * ------------------------------------------------------------------------- */ - -/* Expose Lunr.js in global scope, or stemmers won't work */ -self.lunr = lunr - -/* Handle messages */ -addEventListener("message", async ev => { - postMessage(await handler(ev.data)) -}) diff --git a/src/templates/assets/javascripts/integrations/search/worker/message/index.ts b/src/templates/assets/javascripts/integrations/search/worker/message/index.ts deleted file mode 100644 index 54d5001e..00000000 --- a/src/templates/assets/javascripts/integrations/search/worker/message/index.ts +++ /dev/null @@ -1,112 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 RTICULAR 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 { SearchResult } from "../../_" -import { SearchIndex } from "../../config" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Search message type - */ -export const enum SearchMessageType { - SETUP, /* Search index setup */ - READY, /* Search index ready */ - QUERY, /* Search query */ - RESULT /* Search results */ -} - -/* ------------------------------------------------------------------------- */ - -/** - * Message containing the data necessary to setup the search index - */ -export interface SearchSetupMessage { - type: SearchMessageType.SETUP /* Message type */ - data: SearchIndex /* Message data */ -} - -/** - * Message indicating the search index is ready - */ -export interface SearchReadyMessage { - type: SearchMessageType.READY /* Message type */ -} - -/** - * Message containing a search query - */ -export interface SearchQueryMessage { - type: SearchMessageType.QUERY /* Message type */ - data: string /* Message data */ -} - -/** - * Message containing results for a search query - */ -export interface SearchResultMessage { - type: SearchMessageType.RESULT /* Message type */ - data: SearchResult /* Message data */ -} - -/* ------------------------------------------------------------------------- */ - -/** - * Message exchanged with the search worker - */ -export type SearchMessage = - | SearchSetupMessage - | SearchReadyMessage - | SearchQueryMessage - | SearchResultMessage - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Type guard for search ready messages - * - * @param message - Search worker message - * - * @returns Test result - */ -export function isSearchReadyMessage( - message: SearchMessage -): message is SearchReadyMessage { - return message.type === SearchMessageType.READY -} - -/** - * Type guard for search result messages - * - * @param message - Search worker message - * - * @returns Test result - */ -export function isSearchResultMessage( - message: SearchMessage -): message is SearchResultMessage { - return message.type === SearchMessageType.RESULT -} diff --git a/src/templates/assets/javascripts/integrations/sitemap/index.ts b/src/templates/assets/javascripts/integrations/sitemap/index.ts deleted file mode 100644 index 08695bad..00000000 --- a/src/templates/assets/javascripts/integrations/sitemap/index.ts +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { - EMPTY, - Observable, - catchError, - defaultIfEmpty, - map, - of, - tap -} from "rxjs" - -import { configuration } from "~/_" -import { getElements, requestXML } from "~/browser" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Sitemap, i.e. a list of URLs - */ -export type Sitemap = string[] - -/* ---------------------------------------------------------------------------- - * Helper functions - * ------------------------------------------------------------------------- */ - -/** - * Preprocess a list of URLs - * - * This function replaces the `site_url` in the sitemap with the actual base - * URL, to allow instant navigation to work in occasions like Netlify previews. - * - * @param urls - URLs - * - * @returns URL path parts - */ -function preprocess(urls: Sitemap): Sitemap { - if (urls.length < 2) - return [""] - - /* Take the first two URLs and remove everything after the last slash */ - const [root, next] = [...urls] - .sort((a, b) => a.length - b.length) - .map(url => url.replace(/[^/]+$/, "")) - - /* Compute common prefix */ - let index = 0 - if (root === next) - index = root.length - else - while (root.charCodeAt(index) === next.charCodeAt(index)) - index++ - - /* Remove common prefix and return in original order */ - return urls.map(url => url.replace(root.slice(0, index), "")) -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Fetch the sitemap for the given base URL - * - * @param base - Base URL - * - * @returns Sitemap observable - */ -export function fetchSitemap(base?: URL): Observable<Sitemap> { - const cached = __md_get<Sitemap>("__sitemap", sessionStorage, base) - if (cached) { - return of(cached) - } else { - const config = configuration() - return requestXML(new URL("sitemap.xml", base || config.base)) - .pipe( - map(sitemap => preprocess(getElements("loc", sitemap) - .map(node => node.textContent!) - )), - catchError(() => EMPTY), // @todo refactor instant loading - defaultIfEmpty([]), - tap(sitemap => __md_set("__sitemap", sitemap, sessionStorage, base)) - ) - } -} diff --git a/src/templates/assets/javascripts/integrations/version/.eslintrc b/src/templates/assets/javascripts/integrations/version/.eslintrc deleted file mode 100644 index 38a5714d..00000000 --- a/src/templates/assets/javascripts/integrations/version/.eslintrc +++ /dev/null @@ -1,5 +0,0 @@ -{ - "rules": { - "no-null/no-null": "off" - } -} diff --git a/src/templates/assets/javascripts/integrations/version/index.ts b/src/templates/assets/javascripts/integrations/version/index.ts deleted file mode 100644 index 38d78f17..00000000 --- a/src/templates/assets/javascripts/integrations/version/index.ts +++ /dev/null @@ -1,186 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { - EMPTY, - Subject, - catchError, - combineLatest, - filter, - fromEvent, - map, - of, - switchMap, - withLatestFrom -} from "rxjs" - -import { configuration } from "~/_" -import { - getElement, - getLocation, - requestJSON, - setLocation -} from "~/browser" -import { getComponentElements } from "~/components" -import { - Version, - renderVersionSelector -} from "~/templates" - -import { fetchSitemap } from "../sitemap" - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Setup options - */ -interface SetupOptions { - document$: Subject<Document> /* Document subject */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Set up version selector - * - * @param options - Options - */ -export function setupVersionSelector( - { document$ }: SetupOptions -): void { - const config = configuration() - const versions$ = requestJSON<Version[]>( - new URL("../versions.json", config.base) - ) - .pipe( - catchError(() => EMPTY) // @todo refactor instant loading - ) - - /* Determine current version */ - const current$ = versions$ - .pipe( - map(versions => { - const [, current] = config.base.match(/([^/]+)\/?$/)! - return versions.find(({ version, aliases }) => ( - version === current || aliases.includes(current) - )) || versions[0] - }) - ) - - /* Intercept inter-version navigation */ - versions$ - .pipe( - map(versions => new Map(versions.map(version => [ - `${new URL(`../${version.version}/`, config.base)}`, - version - ]))), - switchMap(urls => fromEvent<MouseEvent>(document.body, "click") - .pipe( - filter(ev => !ev.metaKey && !ev.ctrlKey), - withLatestFrom(current$), - switchMap(([ev, current]) => { - if (ev.target instanceof Element) { - const el = ev.target.closest("a") - if (el && !el.target && urls.has(el.href)) { - const url = el.href - // This is a temporary hack to detect if a version inside the - // version selector or on another part of the site was clicked. - // If we're inside the version selector, we definitely want to - // find the same page, as we might have different deployments - // due to aliases. However, if we're outside the version - // selector, we must abort here, because we might otherwise - // interfere with instant navigation. We need to refactor this - // at some point together with instant navigation. - // - // See https://github.com/squidfunk/mkdocs-material/issues/4012 - if (!ev.target.closest(".md-version")) { - const version = urls.get(url)! - if (version === current) - return EMPTY - } - ev.preventDefault() - return of(url) - } - } - return EMPTY - }), - switchMap(url => { - const { version } = urls.get(url)! - return fetchSitemap(new URL(url)) - .pipe( - map(sitemap => { - const location = getLocation() - const path = location.href.replace(config.base, "") - return sitemap.includes(path.split("#")[0]) - ? new URL(`../${version}/${path}`, config.base) - : new URL(url) - }) - ) - }) - ) - ) - ) - .subscribe(url => setLocation(url, true)) - - /* Render version selector and warning */ - combineLatest([versions$, current$]) - .subscribe(([versions, current]) => { - const topic = getElement(".md-header__topic") - topic.appendChild(renderVersionSelector(versions, current)) - }) - - /* Integrate outdated version banner with instant navigation */ - document$.pipe(switchMap(() => current$)) - .subscribe(current => { - - /* Check if version state was already determined */ - let outdated = __md_get("__outdated", sessionStorage) - if (outdated === null) { - outdated = true - - /* Obtain and normalize default versions */ - let ignored = config.version?.default || "latest" - if (!Array.isArray(ignored)) - ignored = [ignored] - - /* Check if version is considered a default */ - main: for (const ignore of ignored) - for (const alias of current.aliases) - if (new RegExp(ignore, "i").test(alias)) { - outdated = false - break main - } - - /* Persist version state in session storage */ - __md_set("__outdated", outdated, sessionStorage) - } - - /* Unhide outdated version banner */ - if (outdated) - for (const warning of getComponentElements("outdated")) - warning.hidden = false - }) -} diff --git a/src/templates/assets/javascripts/patches/indeterminate/index.ts b/src/templates/assets/javascripts/patches/indeterminate/index.ts deleted file mode 100644 index 9b7b0d5a..00000000 --- a/src/templates/assets/javascripts/patches/indeterminate/index.ts +++ /dev/null @@ -1,85 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - fromEvent, - map, - mergeMap, - switchMap, - takeWhile, - tap, - withLatestFrom -} from "rxjs" - -import { getElements } from "~/browser" - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Patch options - */ -interface PatchOptions { - document$: Observable<Document> /* Document observable */ - tablet$: Observable<boolean> /* Media tablet observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Patch indeterminate checkboxes - * - * This function replaces the indeterminate "pseudo state" with the actual - * indeterminate state, which is used to keep navigation always expanded. - * - * @param options - Options - */ -export function patchIndeterminate( - { document$, tablet$ }: PatchOptions -): void { - document$ - .pipe( - switchMap(() => getElements<HTMLInputElement>( - ".md-toggle--indeterminate" - )), - tap(el => { - el.indeterminate = true - el.checked = false - }), - mergeMap(el => fromEvent(el, "change") - .pipe( - takeWhile(() => el.classList.contains("md-toggle--indeterminate")), - map(() => el) - ) - ), - withLatestFrom(tablet$) - ) - .subscribe(([el, tablet]) => { - el.classList.remove("md-toggle--indeterminate") - if (tablet) - el.checked = false - }) -} diff --git a/src/templates/assets/javascripts/patches/index.ts b/src/templates/assets/javascripts/patches/index.ts deleted file mode 100644 index b6e65fc0..00000000 --- a/src/templates/assets/javascripts/patches/index.ts +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./indeterminate" -export * from "./scrollfix" -export * from "./scrolllock" diff --git a/src/templates/assets/javascripts/patches/scrollfix/index.ts b/src/templates/assets/javascripts/patches/scrollfix/index.ts deleted file mode 100644 index 607c46a0..00000000 --- a/src/templates/assets/javascripts/patches/scrollfix/index.ts +++ /dev/null @@ -1,100 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - filter, - fromEvent, - map, - mergeMap, - switchMap, - tap -} from "rxjs" - -import { getElements } from "~/browser" - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Patch options - */ -interface PatchOptions { - document$: Observable<Document> /* Document observable */ -} - -/* ---------------------------------------------------------------------------- - * Helper functions - * ------------------------------------------------------------------------- */ - -/** - * Check whether the given device is an Apple device - * - * @returns Test result - */ -function isAppleDevice(): boolean { - return /(iPad|iPhone|iPod)/.test(navigator.userAgent) -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Patch all elements with `data-md-scrollfix` attributes - * - * This is a year-old patch which ensures that overflow scrolling works at the - * top and bottom of containers on iOS by ensuring a `1px` scroll offset upon - * the start of a touch event. - * - * @see https://bit.ly/2SCtAOO - Original source - * - * @param options - Options - */ -export function patchScrollfix( - { document$ }: PatchOptions -): void { - document$ - .pipe( - switchMap(() => getElements("[data-md-scrollfix]")), - tap(el => el.removeAttribute("data-md-scrollfix")), - filter(isAppleDevice), - mergeMap(el => fromEvent(el, "touchstart") - .pipe( - map(() => el) - ) - ) - ) - .subscribe(el => { - const top = el.scrollTop - - /* We're at the top of the container */ - if (top === 0) { - el.scrollTop = 1 - - /* We're at the bottom of the container */ - } else if (top + el.offsetHeight === el.scrollHeight) { - el.scrollTop = top - 1 - } - }) -} diff --git a/src/templates/assets/javascripts/patches/scrolllock/index.ts b/src/templates/assets/javascripts/patches/scrolllock/index.ts deleted file mode 100644 index 4ec3e103..00000000 --- a/src/templates/assets/javascripts/patches/scrolllock/index.ts +++ /dev/null @@ -1,89 +0,0 @@ -/* - * Copyright (c) 2016-2023 Martin Donath <martin.donath@squidfunk.com> - * - * Permission is hereby granted, free of charge, to any person obtaining a copy - * of this software and associated documentation files (the "Software"), to - * deal in the Software without restriction, including without limitation the - * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or - * sell copies of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL THE - * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS - * IN THE SOFTWARE. - */ - -import { - Observable, - combineLatest, - delay, - map, - of, - switchMap, - withLatestFrom -} from "rxjs" - -import { - Viewport, - watchToggle -} from "~/browser" - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Patch options - */ -interface PatchOptions { - viewport$: Observable<Viewport> /* Viewport observable */ - tablet$: Observable<boolean> /* Media tablet observable */ -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Patch the document body to lock when search is open - * - * For mobile and tablet viewports, the search is rendered full screen, which - * leads to scroll leaking when at the top or bottom of the search result. This - * function locks the body when the search is in full screen mode, and restores - * the scroll position when leaving. - * - * @param options - Options - */ -export function patchScrolllock( - { viewport$, tablet$ }: PatchOptions -): void { - combineLatest([watchToggle("search"), tablet$]) - .pipe( - map(([active, tablet]) => active && !tablet), - switchMap(active => of(active) - .pipe( - delay(active ? 400 : 100) - ) - ), - withLatestFrom(viewport$) - ) - .subscribe(([active, { offset: { y }}]) => { - if (active) { - document.body.setAttribute("data-md-scrolllock", "") - document.body.style.top = `-${y}px` - } else { - const value = -1 * parseInt(document.body.style.top, 10) - document.body.removeAttribute("data-md-scrolllock") - document.body.style.top = "" - if (value) - window.scrollTo(0, value) - } - }) -} diff --git a/src/templates/assets/javascripts/polyfills/index.ts b/src/templates/assets/javascripts/polyfills/index.ts deleted file mode 100644 index 2aec8290..00000000 --- a/src/templates/assets/javascripts/polyfills/index.ts +++ /dev/null @@ -1,96 +0,0 @@ -/* - * Copyright (c) 2016-2023 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. - */ - -/* ---------------------------------------------------------------------------- - * Polyfills - * ------------------------------------------------------------------------- */ - -/* Polyfill `Object.entries` */ -if (!Object.entries) - Object.entries = function (obj: object) { - const data: [string, string][] = [] - for (const key of Object.keys(obj)) - // @ts-expect-error - ignore property access warning - data.push([key, obj[key]]) - - /* Return entries */ - return data - } - -/* Polyfill `Object.values` */ -if (!Object.values) - Object.values = function (obj: object) { - const data: string[] = [] - for (const key of Object.keys(obj)) - // @ts-expect-error - ignore property access warning - data.push(obj[key]) - - /* Return values */ - return data - } - -/* ------------------------------------------------------------------------- */ - -/* Polyfills for `Element` */ -if (typeof Element !== "undefined") { - - /* Polyfill `Element.scrollTo` */ - if (!Element.prototype.scrollTo) - Element.prototype.scrollTo = function ( - x?: ScrollToOptions | number, y?: number - ): void { - if (typeof x === "object") { - this.scrollLeft = x.left! - this.scrollTop = x.top! - } else { - this.scrollLeft = x! - this.scrollTop = y! - } - } - - /* Polyfill `Element.replaceWith` */ - if (!Element.prototype.replaceWith) - Element.prototype.replaceWith = function ( - ...nodes: Array<string | Node> - ): void { - const parent = this.parentNode - if (parent) { - if (nodes.length === 0) - parent.removeChild(this) - - /* Replace children and create text nodes */ - for (let i = nodes.length - 1; i >= 0; i--) { - let node = nodes[i] - if (typeof node === "string") - node = document.createTextNode(node) - else if (node.parentNode) - node.parentNode.removeChild(node) - - /* Replace child or insert before previous sibling */ - if (!i) - parent.replaceChild(node, this) - else - parent.insertBefore(this.previousSibling!, node) - } - } - } -} diff --git a/src/templates/assets/javascripts/templates/annotation/index.tsx b/src/templates/assets/javascripts/templates/annotation/index.tsx deleted file mode 100644 index 9b8f85f5..00000000 --- a/src/templates/assets/javascripts/templates/annotation/index.tsx +++ /dev/null @@ -1,65 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { h } from "~/utilities" - -import { renderTooltip } from "../tooltip" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Render an annotation - * - * @param id - Annotation identifier - * @param prefix - Tooltip identifier prefix - * - * @returns Element - */ -export function renderAnnotation( - id: string | number, prefix?: string -): HTMLElement { - prefix = prefix ? `${prefix}_annotation_${id}` : undefined - - /* Render tooltip with anchor, if given */ - if (prefix) { - const anchor = prefix ? `#${prefix}` : undefined - return ( - <aside class="md-annotation" tabIndex={0}> - {renderTooltip(prefix)} - <a href={anchor} class="md-annotation__index" tabIndex={-1}> - <span data-md-annotation-id={id}></span> - </a> - </aside> - ) - } else { - return ( - <aside class="md-annotation" tabIndex={0}> - {renderTooltip(prefix)} - <span class="md-annotation__index" tabIndex={-1}> - <span data-md-annotation-id={id}></span> - </span> - </aside> - ) - } -} diff --git a/src/templates/assets/javascripts/templates/clipboard/index.tsx b/src/templates/assets/javascripts/templates/clipboard/index.tsx deleted file mode 100644 index 95dbf12a..00000000 --- a/src/templates/assets/javascripts/templates/clipboard/index.tsx +++ /dev/null @@ -1,45 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { h } from "~/utilities" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Render a 'copy-to-clipboard' button - * - * @param id - Unique identifier - * - * @returns Element - */ -export function renderClipboardButton(id: string): HTMLElement { - return ( - <button - class="md-clipboard md-icon" - title={translation("clipboard.copy")} - data-clipboard-target={`#${id} > code`} - ></button> - ) -} diff --git a/src/templates/assets/javascripts/templates/index.ts b/src/templates/assets/javascripts/templates/index.ts deleted file mode 100644 index b50b93b8..00000000 --- a/src/templates/assets/javascripts/templates/index.ts +++ /dev/null @@ -1,29 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./annotation" -export * from "./clipboard" -export * from "./search" -export * from "./source" -export * from "./tabbed" -export * from "./table" -export * from "./version" diff --git a/src/templates/assets/javascripts/templates/search/index.tsx b/src/templates/assets/javascripts/templates/search/index.tsx deleted file mode 100644 index 350c0505..00000000 --- a/src/templates/assets/javascripts/templates/search/index.tsx +++ /dev/null @@ -1,170 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { ComponentChild } from "preact" - -import { configuration, feature, translation } from "~/_" -import { SearchItem } from "~/integrations/search" -import { h } from "~/utilities" - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Render flag - */ -const enum Flag { - TEASER = 1, /* Render teaser */ - PARENT = 2 /* Render as parent */ -} - -/* ---------------------------------------------------------------------------- - * Helper function - * ------------------------------------------------------------------------- */ - -/** - * Render a search document - * - * @param document - Search document - * @param flag - Render flags - * - * @returns Element - */ -function renderSearchDocument( - document: SearchItem, flag: Flag -): HTMLElement { - const parent = flag & Flag.PARENT - const teaser = flag & Flag.TEASER - - /* Render missing query terms */ - const missing = Object.keys(document.terms) - .filter(key => !document.terms[key]) - .reduce<ComponentChild[]>((list, key) => [ - ...list, <del>{key}</del>, " " - ], []) - .slice(0, -1) - - /* Assemble query string for highlighting */ - const config = configuration() - const url = new URL(document.location, config.base) - if (feature("search.highlight")) - url.searchParams.set("h", Object.entries(document.terms) - .filter(([, match]) => match) - .reduce((highlight, [value]) => `${highlight} ${value}`.trim(), "") - ) - - /* Render article or section, depending on flags */ - const { tags } = configuration() - return ( - <a href={`${url}`} class="md-search-result__link" tabIndex={-1}> - <article - class="md-search-result__article md-typeset" - data-md-score={document.score.toFixed(2)} - > - {parent > 0 && <div class="md-search-result__icon md-icon"></div>} - {parent > 0 && <h1>{document.title}</h1>} - {parent <= 0 && <h2>{document.title}</h2>} - {teaser > 0 && document.text.length > 0 && - document.text - } - {document.tags && document.tags.map(tag => { - const type = tags - ? tag in tags - ? `md-tag-icon md-tag--${tags[tag]}` - : "md-tag-icon" - : "" - return ( - <span class={`md-tag ${type}`}>{tag}</span> - ) - })} - {teaser > 0 && missing.length > 0 && - <p class="md-search-result__terms"> - {translation("search.result.term.missing")}: {...missing} - </p> - } - </article> - </a> - ) -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Render a search result - * - * @param result - Search result - * - * @returns Element - */ -export function renderSearchResultItem( - result: SearchItem[] -): HTMLElement { - const threshold = result[0].score - const docs = [...result] - - const config = configuration() - - /* Find and extract parent article */ - const parent = docs.findIndex(doc => { - const l = `${new URL(doc.location, config.base)}` // @todo hacky - return !l.includes("#") - }) - const [article] = docs.splice(parent, 1) - - /* Determine last index above threshold */ - let index = docs.findIndex(doc => doc.score < threshold) - if (index === -1) - index = docs.length - - /* Partition sections */ - const best = docs.slice(0, index) - const more = docs.slice(index) - - /* Render children */ - const children = [ - renderSearchDocument(article, Flag.PARENT | +(!parent && index === 0)), - ...best.map(section => renderSearchDocument(section, Flag.TEASER)), - ...more.length ? [ - <details class="md-search-result__more"> - <summary tabIndex={-1}> - <div> - {more.length > 0 && more.length === 1 - ? translation("search.result.more.one") - : translation("search.result.more.other", more.length) - } - </div> - </summary> - {...more.map(section => renderSearchDocument(section, Flag.TEASER))} - </details> - ] : [] - ] - - /* Render search result */ - return ( - <li class="md-search-result__item"> - {children} - </li> - ) -} diff --git a/src/templates/assets/javascripts/templates/source/index.tsx b/src/templates/assets/javascripts/templates/source/index.tsx deleted file mode 100644 index b59a8f67..00000000 --- a/src/templates/assets/javascripts/templates/source/index.tsx +++ /dev/null @@ -1,47 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { SourceFacts } from "~/components" -import { h, round } from "~/utilities" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Render repository facts - * - * @param facts - Repository facts - * - * @returns Element - */ -export function renderSourceFacts(facts: SourceFacts): HTMLElement { - return ( - <ul class="md-source__facts"> - {Object.entries(facts).map(([key, value]) => ( - <li class={`md-source__fact md-source__fact--${key}`}> - {typeof value === "number" ? round(value) : value} - </li> - ))} - </ul> - ) -} diff --git a/src/templates/assets/javascripts/templates/tabbed/index.tsx b/src/templates/assets/javascripts/templates/tabbed/index.tsx deleted file mode 100644 index b283ac66..00000000 --- a/src/templates/assets/javascripts/templates/tabbed/index.tsx +++ /dev/null @@ -1,56 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { h } from "~/utilities" - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * Tabbed control type - */ -type TabbedControlType = - | "prev" - | "next" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Render control for content tabs - * - * @param type - Control type - * - * @returns Element - */ -export function renderTabbedControl( - type: TabbedControlType -): HTMLElement { - const classes = `tabbed-control tabbed-control--${type}` - return ( - <div class={classes} hidden> - <button class="tabbed-button" tabIndex={-1} aria-hidden="true"></button> - </div> - ) -} diff --git a/src/templates/assets/javascripts/templates/table/index.tsx b/src/templates/assets/javascripts/templates/table/index.tsx deleted file mode 100644 index 1fcba152..00000000 --- a/src/templates/assets/javascripts/templates/table/index.tsx +++ /dev/null @@ -1,44 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { h } from "~/utilities" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Render a table inside a wrapper to improve scrolling on mobile - * - * @param table - Table element - * - * @returns Element - */ -export function renderTable(table: HTMLElement): HTMLElement { - return ( - <div class="md-typeset__scrollwrap"> - <div class="md-typeset__table"> - {table} - </div> - </div> - ) -} diff --git a/src/templates/assets/javascripts/templates/tooltip/index.tsx b/src/templates/assets/javascripts/templates/tooltip/index.tsx deleted file mode 100644 index ec583490..00000000 --- a/src/templates/assets/javascripts/templates/tooltip/index.tsx +++ /dev/null @@ -1,42 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { h } from "~/utilities" - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Render a tooltip - * - * @param id - Tooltip identifier - * - * @returns Element - */ -export function renderTooltip(id?: string): HTMLElement { - return ( - <div class="md-tooltip" id={id}> - <div class="md-tooltip__inner md-typeset"></div> - </div> - ) -} diff --git a/src/templates/assets/javascripts/templates/version/index.tsx b/src/templates/assets/javascripts/templates/version/index.tsx deleted file mode 100644 index 4aff7aa7..00000000 --- a/src/templates/assets/javascripts/templates/version/index.tsx +++ /dev/null @@ -1,92 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { configuration, translation } from "~/_" -import { h } from "~/utilities" - -/* ---------------------------------------------------------------------------- - * Types - * ------------------------------------------------------------------------- */ - -/** - * Version - */ -export interface Version { - version: string /* Version identifier */ - title: string /* Version title */ - aliases: string[] /* Version aliases */ -} - -/* ---------------------------------------------------------------------------- - * Helper functions - * ------------------------------------------------------------------------- */ - -/** - * Render a version - * - * @param version - Version - * - * @returns Element - */ -function renderVersion(version: Version): HTMLElement { - const config = configuration() - - /* Ensure trailing slash - see https://bit.ly/3rL5u3f */ - const url = new URL(`../${version.version}/`, config.base) - return ( - <li class="md-version__item"> - <a href={`${url}`} class="md-version__link"> - {version.title} - </a> - </li> - ) -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * Render a version selector - * - * @param versions - Versions - * @param active - Active version - * - * @returns Element - */ -export function renderVersionSelector( - versions: Version[], active: Version -): HTMLElement { - return ( - <div class="md-version"> - <button - class="md-version__current" - aria-label={translation("select.version")} - > - {active.title} - </button> - <ul class="md-version__list"> - {versions.map(renderVersion)} - </ul> - </div> - ) -} diff --git a/src/templates/assets/javascripts/utilities/h/.eslintrc b/src/templates/assets/javascripts/utilities/h/.eslintrc deleted file mode 100644 index d79b45b0..00000000 --- a/src/templates/assets/javascripts/utilities/h/.eslintrc +++ /dev/null @@ -1,7 +0,0 @@ -{ - "rules": { - "@typescript-eslint/no-explicit-any": "off", - "@typescript-eslint/no-namespace": "off", - "jsdoc/require-jsdoc": "off" - } -} diff --git a/src/templates/assets/javascripts/utilities/h/index.ts b/src/templates/assets/javascripts/utilities/h/index.ts deleted file mode 100644 index 08d809f1..00000000 --- a/src/templates/assets/javascripts/utilities/h/index.ts +++ /dev/null @@ -1,132 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 { JSX as JSXInternal } from "preact" - -/* ---------------------------------------------------------------------------- - * Helper types - * ------------------------------------------------------------------------- */ - -/** - * HTML attributes - */ -type Attributes = - & JSXInternal.HTMLAttributes - & JSXInternal.SVGAttributes - & Record<string, any> - -/** - * Child element - */ -type Child = - | ChildNode - | HTMLElement - | Text - | string - | number - -/* ---------------------------------------------------------------------------- - * Helper functions - * ------------------------------------------------------------------------- */ - -/** - * Append a child node to an element - * - * @param el - Element - * @param child - Child node(s) - */ -function appendChild(el: HTMLElement, child: Child | Child[]): void { - - /* Handle primitive types (including raw HTML) */ - if (typeof child === "string" || typeof child === "number") { - el.innerHTML += child.toString() - - /* Handle nodes */ - } else if (child instanceof Node) { - el.appendChild(child) - - /* Handle nested children */ - } else if (Array.isArray(child)) { - for (const node of child) - appendChild(el, node) - } -} - -/* ---------------------------------------------------------------------------- - * Functions - * ------------------------------------------------------------------------- */ - -/** - * JSX factory - * - * @template T - Element type - * - * @param tag - HTML tag - * @param attributes - HTML attributes - * @param children - Child elements - * - * @returns Element - */ -export function h<T extends keyof HTMLElementTagNameMap>( - tag: T, attributes?: Attributes | null, ...children: Child[] -): HTMLElementTagNameMap[T] - -export function h<T extends h.JSX.Element>( - tag: string, attributes?: Attributes | null, ...children: Child[] -): T - -export function h<T extends h.JSX.Element>( - tag: string, attributes?: Attributes | null, ...children: Child[] -): T { - const el = document.createElement(tag) - - /* Set attributes, if any */ - if (attributes) - for (const attr of Object.keys(attributes)) { - if (typeof attributes[attr] === "undefined") - continue - - /* Set default attribute or boolean */ - if (typeof attributes[attr] !== "boolean") - el.setAttribute(attr, attributes[attr]) - else - el.setAttribute(attr, "") - } - - /* Append child nodes */ - for (const child of children) - appendChild(el, child) - - /* Return element */ - return el as T -} - -/* ---------------------------------------------------------------------------- - * Namespace - * ------------------------------------------------------------------------- */ - -export declare namespace h { - namespace JSX { - type Element = HTMLElement - type IntrinsicElements = JSXInternal.IntrinsicElements - } -} diff --git a/src/templates/assets/javascripts/utilities/index.ts b/src/templates/assets/javascripts/utilities/index.ts deleted file mode 100644 index 42886e0b..00000000 --- a/src/templates/assets/javascripts/utilities/index.ts +++ /dev/null @@ -1,24 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 "./h" -export * from "./round" diff --git a/src/templates/assets/javascripts/utilities/round/index.ts b/src/templates/assets/javascripts/utilities/round/index.ts deleted file mode 100644 index 3e6bf91a..00000000 --- a/src/templates/assets/javascripts/utilities/round/index.ts +++ /dev/null @@ -1,50 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 - * ------------------------------------------------------------------------- */ - -/** - * Round a number for display with repository facts - * - * This is a reverse-engineered version of GitHub's weird rounding algorithm - * for stars, forks and all other numbers. While all numbers below `1,000` are - * returned as-is, bigger numbers are converted to fixed numbers: - * - * - `1,049` => `1k` - * - `1,050` => `1.1k` - * - `1,949` => `1.9k` - * - `1,950` => `2k` - * - * @param value - Original value - * - * @returns Rounded value - */ -export function round(value: number): string { - if (value > 999) { - const digits = +((value - 950) % 1000 > 99) - return `${((value + 0.000001) / 1000).toFixed(digits)}k` - } else { - return value.toString() - } -} diff --git a/src/templates/assets/javascripts/workers/search.ts b/src/templates/assets/javascripts/workers/search.ts deleted file mode 100644 index e995b1ff..00000000 --- a/src/templates/assets/javascripts/workers/search.ts +++ /dev/null @@ -1,23 +0,0 @@ -/* - * Copyright (c) 2016-2023 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 RTICULAR 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 "~/integrations/search/worker/main" diff --git a/src/templates/assets/stylesheets/_config.scss b/src/templates/assets/stylesheets/_config.scss deleted file mode 100644 index e64b8e29..00000000 --- a/src/templates/assets/stylesheets/_config.scss +++ /dev/null @@ -1,42 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Variables: breakpoints -// ---------------------------------------------------------------------------- - -// Device-specific breakpoints -$break-devices: ( - mobile: ( - portrait: px2em(220px) px2em(479.75px), - landscape: px2em(480px) px2em(719.75px) - ), - tablet: ( - portrait: px2em(720px) px2em(959.75px), - landscape: px2em(960px) px2em(1219.75px) - ), - screen: ( - small: px2em(1220px) px2em(1599.75px), - medium: px2em(1600px) px2em(1999.75px), - large: px2em(2000px) - ) -); diff --git a/src/templates/assets/stylesheets/main.scss b/src/templates/assets/stylesheets/main.scss deleted file mode 100644 index 2b203d3d..00000000 --- a/src/templates/assets/stylesheets/main.scss +++ /dev/null @@ -1,86 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Dependencies -// ---------------------------------------------------------------------------- - -@import "material-color"; -@import "material-shadows"; - -// ---------------------------------------------------------------------------- -// Local imports -// ---------------------------------------------------------------------------- - -@import "utilities/break"; -@import "utilities/convert"; - -@import "config"; - -@import "main/resets"; -@import "main/colors"; -@import "main/icons"; -@import "main/typeset"; - -@import "main/components/author"; -@import "main/components/banner"; -@import "main/components/base"; -@import "main/components/clipboard"; -@import "main/components/consent"; -@import "main/components/content"; -@import "main/components/dialog"; -@import "main/components/feedback"; -@import "main/components/footer"; -@import "main/components/form"; -@import "main/components/header"; -@import "main/components/meta"; -@import "main/components/nav"; -@import "main/components/pagination"; -@import "main/components/post"; -@import "main/components/progress"; -@import "main/components/search"; -@import "main/components/select"; -@import "main/components/sidebar"; -@import "main/components/source"; -@import "main/components/status"; -@import "main/components/tabs"; -@import "main/components/tag"; -@import "main/components/tooltip"; -@import "main/components/top"; -@import "main/components/version"; - -@import "main/extensions/markdown/admonition"; -@import "main/extensions/markdown/footnotes"; -@import "main/extensions/markdown/toc"; - -@import "main/extensions/pymdownx/arithmatex"; -@import "main/extensions/pymdownx/critic"; -@import "main/extensions/pymdownx/details"; -@import "main/extensions/pymdownx/emoji"; -@import "main/extensions/pymdownx/highlight"; -@import "main/extensions/pymdownx/keys"; -@import "main/extensions/pymdownx/tabbed"; -@import "main/extensions/pymdownx/tasklist"; - -@import "main/integrations/mermaid"; - -@import "main/modifiers"; diff --git a/src/templates/assets/stylesheets/main/_colors.scss b/src/templates/assets/stylesheets/main/_colors.scss deleted file mode 100644 index 68969fe9..00000000 --- a/src/templates/assets/stylesheets/main/_colors.scss +++ /dev/null @@ -1,153 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Color variables -:root { - @extend %root; - - // Primary color shades - --md-primary-fg-color: hsla(#{hex2hsl($clr-indigo-500)}, 1); - --md-primary-fg-color--light: hsla(#{hex2hsl($clr-indigo-400)}, 1); - --md-primary-fg-color--dark: hsla(#{hex2hsl($clr-indigo-700)}, 1); - --md-primary-bg-color: hsla(0, 0%, 100%, 1); - --md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7); - - // Accent color shades - --md-accent-fg-color: hsla(#{hex2hsl($clr-indigo-a200)}, 1); - --md-accent-fg-color--transparent: hsla(#{hex2hsl($clr-indigo-a200)}, 0.1); - --md-accent-bg-color: hsla(0, 0%, 100%, 1); - --md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7); -} - -// ---------------------------------------------------------------------------- - -// Allow to explicitly use color schemes in nested content -[data-md-color-scheme="default"] { - @extend %root; - - // Indicate that the site is rendered with a light color scheme - color-scheme: light; - - // Hide images for dark mode - img[src$="#only-dark"], - img[src$="#gh-dark-mode-only"] { - display: none; - } -} - -// ---------------------------------------------------------------------------- -// Placeholders -// ---------------------------------------------------------------------------- - -// Default theme, i.e. light mode -%root { - - // Color hue in the range [0,360] - change this variable to alter the tone - // of the theme, e.g. to make it more redish or greenish - --md-hue: 225deg; - - // Default color shades - --md-default-fg-color: hsla(0, 0%, 0%, 0.87); - --md-default-fg-color--light: hsla(0, 0%, 0%, 0.54); - --md-default-fg-color--lighter: hsla(0, 0%, 0%, 0.32); - --md-default-fg-color--lightest: hsla(0, 0%, 0%, 0.07); - --md-default-bg-color: hsla(0, 0%, 100%, 1); - --md-default-bg-color--light: hsla(0, 0%, 100%, 0.7); - --md-default-bg-color--lighter: hsla(0, 0%, 100%, 0.3); - --md-default-bg-color--lightest: hsla(0, 0%, 100%, 0.12); - - // Code color shades - --md-code-fg-color: hsla(200, 18%, 26%, 1); - --md-code-bg-color: hsla(200, 0%, 96%, 1); - - // Code highlighting color shades - --md-code-hl-color: hsla(#{hex2hsl($clr-blue-a200)}, 1); - --md-code-hl-color--light: hsla(#{hex2hsl($clr-blue-a200)}, 0.1); - --md-code-hl-number-color: hsla(0, 67%, 50%, 1); - --md-code-hl-special-color: hsla(340, 83%, 47%, 1); - --md-code-hl-function-color: hsla(291, 45%, 50%, 1); - --md-code-hl-constant-color: hsla(250, 63%, 60%, 1); - --md-code-hl-keyword-color: hsla(219, 54%, 51%, 1); - --md-code-hl-string-color: hsla(150, 63%, 30%, 1); - --md-code-hl-name-color: var(--md-code-fg-color); - --md-code-hl-operator-color: var(--md-default-fg-color--light); - --md-code-hl-punctuation-color: var(--md-default-fg-color--light); - --md-code-hl-comment-color: var(--md-default-fg-color--light); - --md-code-hl-generic-color: var(--md-default-fg-color--light); - --md-code-hl-variable-color: var(--md-default-fg-color--light); - - // Typeset color shades - --md-typeset-color: var(--md-default-fg-color); - - // Typeset `a` color shades - --md-typeset-a-color: var(--md-primary-fg-color); - - // Typeset `del` and `ins` color shades - --md-typeset-del-color: hsla(6, 90%, 60%, 0.15); - --md-typeset-ins-color: hsla(150, 90%, 44%, 0.15); - - // Typeset `kbd` color shades - --md-typeset-kbd-color: hsla(0, 0%, 98%, 1); - --md-typeset-kbd-accent-color: hsla(0, 100%, 100%, 1); - --md-typeset-kbd-border-color: hsla(0, 0%, 72%, 1); - - // Typeset `mark` color shades - --md-typeset-mark-color: hsla(#{hex2hsl($clr-yellow-a200)}, 0.5); - - // Typeset `table` color shades - --md-typeset-table-color: hsla(0, 0%, 0%, 0.12); - --md-typeset-table-color--light: hsla(0, 0%, 0%, 0.035); - - // Admonition color shades - --md-admonition-fg-color: var(--md-default-fg-color); - --md-admonition-bg-color: var(--md-default-bg-color); - - // Warning color shades - --md-warning-fg-color: hsla(0, 0%, 0%, 0.87); - --md-warning-bg-color: hsla(60, 100%, 80%, 1); - - // Footer color shades - --md-footer-fg-color: hsla(0, 0%, 100%, 1); - --md-footer-fg-color--light: hsla(0, 0%, 100%, 0.7); - --md-footer-fg-color--lighter: hsla(0, 0%, 100%, 0.45); - --md-footer-bg-color: hsla(0, 0%, 0%, 0.87); - --md-footer-bg-color--dark: hsla(0, 0%, 0%, 0.32); - - // Shadow depth 1 - --md-shadow-z1: - 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.05), - 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.1); - - // Shadow depth 2 - --md-shadow-z2: - 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.1), - 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.25); - - // Shadow depth 3 - --md-shadow-z3: - 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.2), - 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.35); -} diff --git a/src/templates/assets/stylesheets/main/_icons.scss b/src/templates/assets/stylesheets/main/_icons.scss deleted file mode 100644 index 9853e93d..00000000 --- a/src/templates/assets/stylesheets/main/_icons.scss +++ /dev/null @@ -1,37 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Icon -.md-icon { - - // SVG defaults - svg { - display: block; - width: px2rem(24px); - height: px2rem(24px); - fill: currentcolor; - } -} diff --git a/src/templates/assets/stylesheets/main/_modifiers.scss b/src/templates/assets/stylesheets/main/_modifiers.scss deleted file mode 100644 index 4b2b046a..00000000 --- a/src/templates/assets/stylesheets/main/_modifiers.scss +++ /dev/null @@ -1,48 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // [tablet +]: Allow for rendering content as sidebars - @include break-from-device(tablet) { - - // Modifier to float block elements - .inline { - float: inline-start; - width: px2rem(234px); - margin-inline-end: px2rem(16px); - margin-top: 0; - margin-bottom: px2rem(16px); - - // Modifier to move to end (ltr: right, rtl: left) - &.end { - float: inline-end; - margin-inline: px2rem(16px) 0; - } - } - } -} diff --git a/src/templates/assets/stylesheets/main/_resets.scss b/src/templates/assets/stylesheets/main/_resets.scss deleted file mode 100644 index c6fc4b28..00000000 --- a/src/templates/assets/stylesheets/main/_resets.scss +++ /dev/null @@ -1,118 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Enforce correct box model and prevent adjustments of font size after -// orientation changes in IE and iOS -html { - box-sizing: border-box; - text-size-adjust: none; -} - -// All elements shall inherit the document default -*, -*::before, -*::after { - box-sizing: inherit; - - // [reduced motion]: Disable all transitions - @media (prefers-reduced-motion) { - transition: none !important; // stylelint-disable-line - } -} - -// Remove margin in all browsers -body { - margin: 0; -} - -// Reset tap outlines on iOS and Android -a, -button, -label, -input { - -webkit-tap-highlight-color: transparent; -} - -// Reset link styles -a { - color: inherit; - text-decoration: none; -} - -// Normalize horizontal separator styles -hr { - box-sizing: content-box; - display: block; - height: px2rem(1px); - padding: 0; - overflow: visible; - border: 0; -} - -// Normalize font-size in all browsers -small { - font-size: 80%; -} - -// Prevent subscript and superscript from affecting line-height -sub, -sup { - line-height: 1em; -} - -// Remove border on image -img { - border-style: none; -} - -// Reset table styles -table { - border-spacing: 0; - border-collapse: separate; -} - -// Reset table cell styles -td, -th { - font-weight: 400; - vertical-align: top; -} - -// Reset button styles -button { - padding: 0; - margin: 0; - font-family: inherit; - font-size: inherit; - background: transparent; - border: 0; -} - -// Reset input styles -input { - border: 0; - outline: none; -} diff --git a/src/templates/assets/stylesheets/main/_typeset.scss b/src/templates/assets/stylesheets/main/_typeset.scss deleted file mode 100644 index 1c322859..00000000 --- a/src/templates/assets/stylesheets/main/_typeset.scss +++ /dev/null @@ -1,603 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules: font definitions -// ---------------------------------------------------------------------------- - -// Enable font-smoothing in Webkit and FF -body { - -webkit-font-smoothing: antialiased; - -moz-osx-font-smoothing: grayscale; - - // Font with fallback for body copy - --md-text-font-family: - var(--md-text-font, _), - -apple-system, BlinkMacSystemFont, Helvetica, Arial, sans-serif; - - // Font with fallback for code - --md-code-font-family: - var(--md-code-font, _), - SFMono-Regular, Consolas, Menlo, monospace; -} - -// Define default fonts -body, -input, -aside { - font-family: var(--md-text-font-family); - font-feature-settings: "kern", "liga"; - color: var(--md-typeset-color); -} - -// Define monospaced fonts -code, -pre, -kbd { - font-family: var(--md-code-font-family); - font-feature-settings: "kern"; -} - -// ---------------------------------------------------------------------------- -// Rules: typesetted content -// ---------------------------------------------------------------------------- - -// General variables -:root { - --md-typeset-table-sort-icon: svg-load("material/sort.svg"); - --md-typeset-table-sort-icon--asc: svg-load("material/sort-ascending.svg"); - --md-typeset-table-sort-icon--desc: svg-load("material/sort-descending.svg"); -} - -// ---------------------------------------------------------------------------- - -// Content that is typeset - if possible, all margins, paddings and font sizes -// should be set in ems, so nested blocks (e.g. admonitions) render correctly. -.md-typeset { - font-size: px2rem(16px); - line-height: 1.6; - color-adjust: exact; - - // [print]: We'll use a smaller `font-size` for printing, so code examples - // don't break too early, and `16px` looks too big anyway. - @media print { - font-size: px2rem(13.6px); - } - - // Default spacing - ul, - ol, - dl, - figure, - blockquote, - pre { - margin-block: 1em; - } - - // Headline on level 1 - h1 { - margin: 0 0 px2em(40px, 32px); - font-size: px2em(32px); - font-weight: 300; - line-height: 1.3; - color: var(--md-default-fg-color--light); - letter-spacing: -0.01em; - } - - // Headline on level 2 - h2 { - margin: px2em(40px, 25px) 0 px2em(16px, 25px); - font-size: px2em(25px); - font-weight: 300; - line-height: 1.4; - letter-spacing: -0.01em; - } - - // Headline on level 3 - h3 { - margin: px2em(32px, 20px) 0 px2em(16px, 20px); - font-size: px2em(20px); - font-weight: 400; - line-height: 1.5; - letter-spacing: -0.01em; - } - - // Headline on level 3 following level 2 - h2 + h3 { - margin-top: px2em(16px, 20px); - } - - // Headline on level 4 - h4 { - margin: px2em(16px) 0; - font-weight: 700; - letter-spacing: -0.01em; - } - - // Headline on level 5-6 - h5, - h6 { - margin: px2em(16px, 12.8px) 0; - font-size: px2em(12.8px); - font-weight: 700; - color: var(--md-default-fg-color--light); - letter-spacing: -0.01em; - } - - // Headline on level 5 - h5 { - text-transform: uppercase; - } - - // Horizontal separator - hr { - display: flow-root; - margin: 1.5em 0; - border-bottom: px2rem(1px) solid var(--md-default-fg-color--lightest); - } - - // Text link - a { - color: var(--md-typeset-a-color); - word-break: break-word; - - // Also enable color transition on pseudo elements - &, - &::before { - transition: color 125ms; - } - - // Text link on focus/hover - &:is(:focus, :hover) { - color: var(--md-accent-fg-color); - - // Inline code block - code { - background-color: var(--md-accent-fg-color--transparent); - } - } - - // Inline code block - code { - color: currentcolor; - transition: background-color 125ms; - } - - // Show outline for keyboard devices - &.focus-visible { - outline-color: var(--md-accent-fg-color); - outline-offset: px2rem(4px); - } - } - - // Code block - code, - pre, - kbd { - font-variant-ligatures: none; - color: var(--md-code-fg-color); - direction: ltr; - - // [print]: Wrap text and hide scollbars - @media print { - white-space: pre-wrap; - } - } - - // Inline code block - code { - padding: 0 px2em(4px, 13.6px); - font-size: px2em(13.6px); - word-break: break-word; - background-color: var(--md-code-bg-color); - border-radius: px2rem(2px); - box-decoration-break: clone; - - // Hide outline for pointer devices - &:not(.focus-visible) { - outline: none; - -webkit-tap-highlight-color: transparent; - } - } - - // Unformatted content - pre { - position: relative; - display: flow-root; - line-height: 1.4; - - // Code block - > code { - display: block; - padding: px2em(10.5px, 13.6px) px2em(16px, 13.6px); - margin: 0; - overflow: auto; - word-break: normal; - touch-action: auto; - outline-color: var(--md-accent-fg-color); - box-shadow: none; - box-decoration-break: slice; - scrollbar-width: thin; - scrollbar-color: var(--md-default-fg-color--lighter) transparent; - - // Code block on hover - &:hover { - scrollbar-color: var(--md-accent-fg-color) transparent; - } - - // Webkit scrollbar - &::-webkit-scrollbar { - width: px2rem(4px); - height: px2rem(4px); - } - - // Webkit scrollbar thumb - &::-webkit-scrollbar-thumb { - background-color: var(--md-default-fg-color--lighter); - - // Webkit scrollbar thumb on hover - &:hover { - background-color: var(--md-accent-fg-color); - } - } - } - } - - // Keyboard key - kbd { - display: inline-block; - padding: 0 px2em(8px, 12px); - font-size: px2em(12px); - color: var(--md-default-fg-color); - word-break: break-word; - vertical-align: text-top; - background-color: var(--md-typeset-kbd-color); - border-radius: px2rem(2px); - box-shadow: - 0 px2rem(2px) 0 px2rem(1px) var(--md-typeset-kbd-border-color), - 0 px2rem(2px) 0 var(--md-typeset-kbd-border-color), - 0 px2rem(-2px) px2rem(4px) var(--md-typeset-kbd-accent-color) inset; - } - - // Text highlighting marker - mark { - color: inherit; - word-break: break-word; - background-color: var(--md-typeset-mark-color); - box-decoration-break: clone; - } - - // Abbreviation - abbr { - text-decoration: none; - cursor: help; - border-bottom: px2rem(1px) dotted var(--md-default-fg-color--light); - - // Show tooltip for touch devices - @media (hover: none) { - - // Tooltip - &[title]:is(:focus, :hover)::after { - position: absolute; - inset-inline: px2rem(16px); - padding: px2rem(4px) px2rem(6px); - margin-top: 2em; - font-size: px2rem(14px); - color: var(--md-default-bg-color); - content: attr(title); - background-color: var(--md-default-fg-color); - border-radius: px2rem(2px); - box-shadow: var(--md-shadow-z3); - } - } - } - - // Small text - small { - opacity: 0.75; - } - - // Superscript and subscript - sup, - sub { - margin-inline-start: px2em(1px, 12.8px); - } - - // Blockquotes, possibly nested - blockquote { - padding-inline-start: px2rem(12px); - margin-inline: 0; - color: var(--md-default-fg-color--light); - border-inline-start: px2rem(4px) solid var(--md-default-fg-color--lighter); - } - - // Unordered list - ul { - list-style-type: disc; - } - - // Unordered and ordered list - ul, - ol { - padding: 0; - margin-inline-start: px2em(10px); - - // Adjust display mode if not hidden - &:not([hidden]) { - display: flow-root; - } - - // Nested ordered list - ol { - list-style-type: lower-alpha; - - // Triply nested ordered list - ol { - list-style-type: lower-roman; - } - } - - // List element - li { - margin-inline-start: px2em(20px); - margin-bottom: 0.5em; - - // Adjust spacing - p, - blockquote { - margin: 0.5em 0; - } - - // Adjust spacing on last child - &:last-child { - margin-bottom: 0; - } - - // Nested list - :is(ul, ol) { - margin-block: 0.5em; - margin-inline-start: px2em(10px); - } - } - } - - // Definition list - dd { - margin-block: 1em 1.5em; - margin-inline-start: px2em(30px); - } - - // Image or video - img, - svg, - video { - max-width: 100%; - height: auto; - } - - // Image - img { - - // Adjust spacing when left-aligned - &[align="left"] { - margin: 1em; - margin-left: 0; - } - - // Adjust spacing when right-aligned - &[align="right"] { - margin: 1em; - margin-right: 0; - } - - // Adjust spacing when sole children - &[align]:only-child { - margin-top: 0; - } - } - - // Figure - figure { - display: flow-root; - width: fit-content; - max-width: 100%; - margin: 1em auto; - text-align: center; - - // Figure images - img { - display: block; - } - } - - // Figure caption - figcaption { - max-width: px2rem(480px); - margin: 1em auto; - font-style: italic; - } - - // Limit width to container - iframe { - max-width: 100%; - } - - // Data table - table:not([class]) { - display: inline-block; - max-width: 100%; - overflow: auto; - font-size: px2rem(12.8px); - touch-action: auto; - background-color: var(--md-default-bg-color); - border: px2rem(1px) solid var(--md-typeset-table-color); - border-radius: px2rem(2px); - - // [print]: Reset display mode so table header wraps when printing - @media print { - display: table; - } - - // Due to margin collapse because of the necessary inline-block hack, we - // cannot increase the bottom margin on the table, so we just increase the - // top margin on the following element - + * { - margin-top: 1.5em; - } - - // Elements in table heading and cell - :is(th, td) > * { - - // Adjust spacing on first child - &:first-child { - margin-top: 0; - } - - // Adjust spacing on last child - &:last-child { - margin-bottom: 0; - } - } - - // Table heading and cell - :is(th, td):not([align]) { - text-align: left; - - // Adjust for right-to-left languages - [dir="rtl"] & { - text-align: right; - } - } - - // Table heading - th { - min-width: px2rem(100px); - padding: px2em(12px, 12.8px) px2em(16px, 12.8px); - font-weight: 700; - vertical-align: top; - } - - // Table cell - td { - padding: px2em(12px, 12.8px) px2em(16px, 12.8px); - vertical-align: top; - border-top: px2rem(1px) solid var(--md-typeset-table-color); - } - - // Table body row - tbody tr { - transition: background-color 125ms; - - // Table row on hover - &:hover { - background-color: var(--md-typeset-table-color--light); - box-shadow: 0 px2rem(1px) 0 var(--md-default-bg-color) inset; - } - } - - // Text link in table - a { - word-break: normal; - } - } - - // Sortable table - table th[role="columnheader"] { - cursor: pointer; - - // Sort icon - &::after { - display: inline-block; - width: 1.2em; - height: 1.2em; - margin-inline-start: 0.5em; - vertical-align: text-bottom; - content: ""; - transition: background-color 125ms; - mask-image: var(--md-typeset-table-sort-icon); - mask-repeat: no-repeat; - mask-size: contain; - } - - // Show sort icon on hover - &:hover::after { - background-color: var(--md-default-fg-color--lighter); - } - - // Sort ascending icon - &[aria-sort="ascending"]::after { - background-color: var(--md-default-fg-color--light); - mask-image: var(--md-typeset-table-sort-icon--asc); - } - - // Sort descending icon - &[aria-sort="descending"]::after { - background-color: var(--md-default-fg-color--light); - mask-image: var(--md-typeset-table-sort-icon--desc); - } - } - - // Data table scroll wrapper - &__scrollwrap { - margin: 1em px2rem(-16px); - overflow-x: auto; - touch-action: auto; - } - - // Data table wrapper - &__table { - display: inline-block; - padding: 0 px2rem(16px); - margin-bottom: 0.5em; - - // [print]: Reset display mode so table header wraps when printing - @media print { - display: block; - } - - // Data table - html & table { - display: table; - width: 100%; - margin: 0; - overflow: hidden; - } - } -} - -// ---------------------------------------------------------------------------- -// Rules: top-level -// ---------------------------------------------------------------------------- - -// [mobile -]: Align with body copy -@include break-to-device(mobile) { - - // Top-level unformatted content - .md-content__inner > pre { - margin: 1em px2rem(-16px); - - // Code block - code { - border-radius: 0; - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_author.scss b/src/templates/assets/stylesheets/main/components/_author.scss deleted file mode 100644 index 111baf40..00000000 --- a/src/templates/assets/stylesheets/main/components/_author.scss +++ /dev/null @@ -1,86 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Author, i.e., GitHub user - .md-author { - position: relative; - display: block; - flex-shrink: 0; - width: px2rem(32px); - height: px2rem(32px); - overflow: hidden; - transition: - color 125ms, - transform 125ms; - - // Author image - img { - display: block; - border-radius: 100%; - } - - // More authors - &--more { - font-size: px2rem(12px); - font-weight: 700; - line-height: px2rem(32px); - color: var(--md-default-fg-color--lighter); - text-align: center; - background: var(--md-default-fg-color--lightest); - } - - // Enlarge image - &--long { - width: px2rem(48px); - height: px2rem(48px); - } - } - - // Author link - a.md-author { - transform: scale(1); - - // Author image - img { - filter: grayscale(100%) opacity(75%); - transition: filter 125ms; - } - - // Author on focus/hover - &:is(:focus, :hover) { - z-index: 1; - transform: scale(1.1); - - // Author image - img { - filter: grayscale(0%); - } - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_banner.scss b/src/templates/assets/stylesheets/main/components/_banner.scss deleted file mode 100644 index 8fe08c0f..00000000 --- a/src/templates/assets/stylesheets/main/components/_banner.scss +++ /dev/null @@ -1,68 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Banner for announcements and warnings -.md-banner { - overflow: auto; - color: var(--md-footer-fg-color); - background-color: var(--md-footer-bg-color); - - // [print]: Hide banner - @media print { - display: none; - } - - // Banner with warning - &--warning { - color: var(--md-warning-fg-color); - background-color: var(--md-warning-bg-color); - } - - // Banner wrapper - &__inner { - padding: 0 px2rem(16px); - margin: px2rem(12px) auto; - font-size: px2rem(14px); - } - - // Banner button - &__button { - float: inline-end; - color: inherit; - cursor: pointer; - transition: opacity 250ms; - - // [no-js]: Hide button - .no-js & { - display: none; - } - - // Button on hover - &:hover { - opacity: 0.7; - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_base.scss b/src/templates/assets/stylesheets/main/components/_base.scss deleted file mode 100644 index 33f834ed..00000000 --- a/src/templates/assets/stylesheets/main/components/_base.scss +++ /dev/null @@ -1,182 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules: base grid and containers -// ---------------------------------------------------------------------------- - -// Stretch container to viewport and set base `font-size` -html { - height: 100%; - overflow-x: hidden; - // Hack: normally, we would set the base `font-size` to `62.5%`, so we can - // base all calculations on `10px`, but Chromium and Chrome define a minimal - // `font-size` of `12px` if the system language is set to Chinese. For this - // reason we just double the `font-size` and set it to `20px`. - // - // See https://github.com/squidfunk/mkdocs-material/issues/911 - font-size: 125%; - - // [screen medium +]: Set base `font-size` to `11px` - @include break-from-device(screen medium) { - font-size: 137.5%; - } - - // [screen large +]: Set base `font-size` to `12px` - @include break-from-device(screen large) { - font-size: 150%; - } -} - -// Stretch body to container - flexbox is used, so the footer will always be -// aligned to the bottom of the viewport -body { - position: relative; - display: flex; - flex-direction: column; - width: 100%; - min-height: 100%; - // Hack: reset `font-size` to `10px`, so the spacing for all inline elements - // is correct again. Otherwise the spacing would be based on `20px`. - font-size: px2rem(10px); - background-color: var(--md-default-bg-color); - - // [print]: Omit flexbox layout due to a Firefox bug (https://mzl.la/39DgR3m) - @media print { - display: block; - } - - // Body in locked state - &[data-md-scrolllock] { - - // [tablet portrait -]: Omit scroll bubbling - @include break-to-device(tablet portrait) { - position: fixed; - } - } -} - -// ---------------------------------------------------------------------------- - -// Grid container - this class is applied to wrapper elements within the -// header, content area and footer, and makes sure that their width is limited -// to `1220px`, and they are rendered centered if the screen is larger. -.md-grid { - max-width: px2rem(1220px); - margin-inline: auto; -} - -// Main container -.md-container { - display: flex; - flex-direction: column; - flex-grow: 1; - - // [print]: Omit flexbox layout due to a Firefox bug (https://mzl.la/39DgR3m) - @media print { - display: block; - } -} - -// Main area - stretch to remaining space of container -.md-main { - flex-grow: 1; - - // Main area wrapper - &__inner { - display: flex; - height: 100%; - margin-top: px2rem(24px + 6px); - } -} - -// Add ellipsis in case of overflowing text -.md-ellipsis { - overflow: hidden; - text-overflow: ellipsis; -} - -// ---------------------------------------------------------------------------- -// Rules: navigational elements -// ---------------------------------------------------------------------------- - -// Toggle - this class is applied to checkbox elements, which are used to -// implement the CSS-only drawer and navigation, as well as the search -.md-toggle { - display: none; -} - -// Option - this class is applied to radio elements, which are used to -// implement the color palette toggle -.md-option { - position: absolute; - width: 0; - height: 0; - opacity: 0; - - // Option label for checked radio button - &:checked + label:not([hidden]) { - display: block; - } - - // Show outline for keyboard devices - &.focus-visible + label { - outline-style: auto; - outline-color: var(--md-accent-fg-color); - } -} - -// Skip link -.md-skip { - position: fixed; - // Hack: if we don't set the negative `z-index`, the skip link will force the - // creation of new layers when code blocks are near the header on scrolling - z-index: -1; - padding: px2rem(6px) px2rem(10px); - margin: px2rem(10px); - font-size: px2rem(12.8px); - color: var(--md-default-bg-color); - background-color: var(--md-default-fg-color); - border-radius: px2rem(2px); - outline-color: var(--md-accent-fg-color); - opacity: 0; - transform: translateY(px2rem(8px)); - - // Show skip link on focus - &:focus { - z-index: 10; - opacity: 1; - transition: - transform 250ms cubic-bezier(0.4, 0, 0.2, 1), - opacity 175ms 75ms; - transform: translateY(0); - } -} - -// ---------------------------------------------------------------------------- -// Rules: print styles -// ---------------------------------------------------------------------------- - -// Add margins to page -@page { - margin: 25mm; -} diff --git a/src/templates/assets/stylesheets/main/components/_clipboard.scss b/src/templates/assets/stylesheets/main/components/_clipboard.scss deleted file mode 100644 index c07c9c67..00000000 --- a/src/templates/assets/stylesheets/main/components/_clipboard.scss +++ /dev/null @@ -1,102 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Clipboard button variables -:root { - --md-clipboard-icon: svg-load("material/content-copy.svg"); -} - -// ---------------------------------------------------------------------------- - -// Clipboard button -.md-clipboard { - position: absolute; - top: px2em(8px); - right: px2em(8px); - z-index: 1; - width: px2em(24px); - height: px2em(24px); - color: var(--md-default-fg-color--lightest); - cursor: pointer; - border-radius: px2rem(2px); - outline-color: var(--md-accent-fg-color); - outline-offset: px2rem(2px); - transition: color 250ms; - - // [print]: Hide button - @media print { - display: none; - } - - // Hide outline for pointer devices - &:not(.focus-visible) { - outline: none; - -webkit-tap-highlight-color: transparent; - } - - // Darken color on code block hover - :hover > & { - color: var(--md-default-fg-color--light); - } - - // Button on focus/hover - &:is(:focus, :hover) { - color: var(--md-accent-fg-color); - } - - // Button icon - the width and height are defined in `em`, so the size is - // automatically adjusted for nested code blocks (e.g. in admonitions) - &::after { - display: block; - width: px2em(18px); - height: px2em(18px); - margin: 0 auto; - content: ""; - background-color: currentcolor; - mask-image: var(--md-clipboard-icon); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - } - - // Inline clipboard button - &--inline { - cursor: pointer; - - // Code block - code { - transition: - color 250ms, - background-color 250ms; - } - - // Code block on focus/hover - &:is(:focus, :hover) code { - color: var(--md-accent-fg-color); - background-color: var(--md-accent-fg-color--transparent); - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_consent.scss b/src/templates/assets/stylesheets/main/components/_consent.scss deleted file mode 100644 index 5502460c..00000000 --- a/src/templates/assets/stylesheets/main/components/_consent.scss +++ /dev/null @@ -1,127 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Keyframes -// ---------------------------------------------------------------------------- - -// Show consent -@keyframes consent { - 0% { - opacity: 0; - transform: translateY(100%); - } - - 100% { - opacity: 1; - transform: translateY(0); - } -} - -// Show consent overlay -@keyframes overlay { - 0% { - opacity: 0; - } - - 100% { - opacity: 1; - } -} - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Consent -.md-consent { - - // Consent overlay - &__overlay { - position: fixed; - top: 0; - z-index: 5; - width: 100%; - height: 100%; - background-color: hsla(0, 0%, 0%, 0.54); - opacity: 1; - backdrop-filter: blur(px2rem(2px)); - animation: overlay 250ms both; - } - - // Consent wrapper - &__inner { - position: fixed; - bottom: 0; - z-index: 5; - width: 100%; - max-height: 100%; - padding: 0; - overflow: auto; - background-color: var(--md-default-bg-color); - border: 0; - border-radius: px2rem(2px); - box-shadow: - 0 0 px2rem(4px) rgba(0, 0, 0, 0.1), - 0 px2rem(4px) px2rem(8px) rgba(0, 0, 0, 0.2); - animation: consent 500ms cubic-bezier(0.1, 0.7, 0.1, 1) both; - } - - // Consent form - &__form { - padding: px2rem(16px); - } - - // Consent settings - &__settings { - display: none; - margin: 1em 0; - - // Show settings - input:checked + & { - display: block; - } - } - - // Consent controls - &__controls { - margin-bottom: px2rem(16px); - - // Consent control button - .md-typeset & .md-button { - display: inline; - - // [tablet +]: Align buttons horizontally - @include break-to-device(mobile) { - display: block; - width: 100%; - margin-top: px2rem(8px); - text-align: center; - } - } - } - - // Ensure users realize that labels are clickaböe - label { - cursor: pointer; - } -} diff --git a/src/templates/assets/stylesheets/main/components/_content.scss b/src/templates/assets/stylesheets/main/components/_content.scss deleted file mode 100644 index 7c945749..00000000 --- a/src/templates/assets/stylesheets/main/components/_content.scss +++ /dev/null @@ -1,97 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Content area -.md-content { - flex-grow: 1; - // Hack: we must use `min-width: 0`, so the content area is capped by the - // dimensions of its parent. Otherwise, long code blocks might lead to a - // wider content area which will overflow. See https://bit.ly/3bP3f8k - min-width: 0; - - // Content wrapper - &__inner { - padding-top: px2rem(12px); - margin: 0 px2rem(16px) px2rem(24px); - - // [screen +]: Adjust spacing between content area and sidebars - @include break-from-device(screen) { - - // Sidebar with navigation is visible - .md-sidebar--primary:not([hidden]) ~ .md-content > & { - margin-inline-start: px2rem(24px); - } - - // Sidebar with table of contents is visible - .md-sidebar--secondary:not([hidden]) ~ .md-content > & { - margin-inline-end: px2rem(24px); - } - } - - // Hack: add pseudo element for spacing, as the overflow of the content - // container may not be hidden due to an imminent offset error on targets - &::before { - display: block; - height: px2rem(8px); - content: ""; - } - - // Adjust spacing on last child - > :last-child { - margin-bottom: 0; - } - } - - // Button inside of the content area - these buttons are meant for actions on - // a document-level, i.e. linking to related source code files, printing etc. - &__button { - float: inline-end; - padding: 0; - margin: px2rem(8px) 0; - margin-inline-start: px2rem(8px); - - // [print]: Hide buttons - @media print { - display: none; - } - - // Adjust default link color for icons - .md-typeset & { - color: var(--md-default-fg-color--lighter); - } - - // Align with body copy located next to icon - svg { - display: inline; - vertical-align: top; - - // Adjust for right-to-left languages - [dir="rtl"] & { - transform: scaleX(-1); - } - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_dialog.scss b/src/templates/assets/stylesheets/main/components/_dialog.scss deleted file mode 100644 index 16782ede..00000000 --- a/src/templates/assets/stylesheets/main/components/_dialog.scss +++ /dev/null @@ -1,65 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Dialog -.md-dialog { - position: fixed; - bottom: px2rem(16px); - z-index: 4; - min-width: px2rem(222px); - padding: px2rem(8px) px2rem(12px); - pointer-events: none; - background-color: var(--md-default-fg-color); - border-radius: px2rem(2px); - box-shadow: var(--md-shadow-z3); - opacity: 0; - transition: - transform 0ms 400ms, - opacity 400ms; - transform: translateY(100%); - inset-inline-end: px2rem(16px); - - // [print]: Hide dialog - @media print { - display: none; - } - - // Active dialog - &--active { - pointer-events: initial; - opacity: 1; - transition: - transform 400ms cubic-bezier(0.075, 0.85, 0.175, 1), - opacity 400ms; - transform: translateY(0); - } - - // Dialog wrapper - &__inner { - font-size: px2rem(14px); - color: var(--md-default-bg-color); - } -} diff --git a/src/templates/assets/stylesheets/main/components/_feedback.scss b/src/templates/assets/stylesheets/main/components/_feedback.scss deleted file mode 100644 index bbcd00e9..00000000 --- a/src/templates/assets/stylesheets/main/components/_feedback.scss +++ /dev/null @@ -1,110 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Was this page helpful? -.md-feedback { - margin: 2em 0 1em; - text-align: center; - - // Feedback fieldset - fieldset { - padding: 0; - margin: 0; - border: none; - } - - // Feedback title - &__title { - margin: 1em auto; - font-weight: 700; - } - - // Feedback wrapper - &__inner { - position: relative; - } - - // Feedback list - &__list { - position: relative; - display: flex; - flex-wrap: wrap; - align-content: baseline; - justify-content: center; - - // Feedback icon on hover - &:hover .md-icon:not(:disabled) { - color: var(--md-default-fg-color--lighter); - } - - // Adjust height after submission - :disabled & { - min-height: px2rem(36px); - } - } - - // Feedback icon - &__icon { - flex-shrink: 0; - margin: 0 px2rem(2px); - color: var(--md-default-fg-color--light); - cursor: pointer; - transition: color 125ms; - - // Feedback icon on hover - &:not(:disabled).md-icon:hover { - color: var(--md-accent-fg-color); - } - - // Feedback icon after submit - &:disabled { - color: var(--md-default-fg-color--lightest); - pointer-events: none; - } - } - - // Feedback note - &__note { - position: relative; - opacity: 0; - transition: - transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1), - opacity 150ms; - transform: translateY(px2rem(8px)); - - // Feedback note value - > * { - max-width: px2rem(320px); - margin: 0 auto; - } - - // Show after submission - :disabled & { - opacity: 1; - transform: translateY(0); - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_footer.scss b/src/templates/assets/stylesheets/main/components/_footer.scss deleted file mode 100644 index 9fabc05b..00000000 --- a/src/templates/assets/stylesheets/main/components/_footer.scss +++ /dev/null @@ -1,201 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Footer -.md-footer { - color: var(--md-footer-fg-color); - background-color: var(--md-footer-bg-color); - - // [print]: Hide footer - @media print { - display: none; - } - - // Footer wrapper - &__inner { - justify-content: space-between; - padding: px2rem(4px); - overflow: auto; - - // Footer is visible - &:not([hidden]) { - display: flex; - } - } - - // Footer link to previous and next page - &__link { - display: flex; - // Hack: some browsers induce ellipsis on flex children that are set to - // `overflow: hidden` and `text-overflow: ellipsis`. Enforcing growth by - // a tiny factor seems to get rid of the ellipsis and renders the text as - // it should - see https://bit.ly/2ZUCXQ8 - flex-grow: 0.01; - align-items: end; - max-width: 100%; - margin-block: px2rem(20px) px2rem(8px); - overflow: hidden; - outline-color: var(--md-accent-fg-color); - transition: opacity 250ms; - - // Footer link on focus/hover - &:is(:focus, :hover) { - opacity: 0.7; - } - - // Adjust for right-to-left languages - [dir="rtl"] & svg { - transform: scaleX(-1); - } - - // [mobile -]: Adjust width to 25/75 and hide title - @include break-to-device(mobile) { - - // Footer link to previous page - &--prev { - flex-shrink: 0; - - // Hide footer title - .md-footer__title { - display: none; - } - } - } - - // Footer link to next page - &--next { - margin-inline-start: auto; - text-align: right; - - // Adjust for right-to-left languages - [dir="rtl"] & { - text-align: left; - } - } - } - - // Footer title - &__title { - flex-grow: 1; - max-width: calc(100% - #{px2rem(48px)}); - padding: 0 px2rem(20px); - margin-bottom: px2rem(14px); - font-size: px2rem(18px); - white-space: nowrap; - } - - // Footer link button - &__button { - padding: px2rem(8px); - margin: px2rem(4px); - } - - // Footer link direction (i.e. prev and next) - &__direction { - font-size: px2rem(12.8px); - opacity: 0.7; - } -} - -// Footer metadata -.md-footer-meta { - background-color: var(--md-footer-bg-color--dark); - - // Footer metadata wrapper - &__inner { - display: flex; - flex-wrap: wrap; - justify-content: space-between; - padding: px2rem(4px); - } - - // Lighten color for non-hovered text links - html &.md-typeset a { - color: var(--md-footer-fg-color--light); - - // Text link on focus/hover - &:is(:focus, :hover) { - color: var(--md-footer-fg-color); - } - } -} - -// ---------------------------------------------------------------------------- - -// Copyright and theme information -.md-copyright { - width: 100%; - padding: px2rem(8px) 0; - margin: auto px2rem(12px); - font-size: px2rem(12.8px); - color: var(--md-footer-fg-color--lighter); - - // [tablet portrait +]: Show copyright and social links in one line - @include break-from-device(tablet portrait) { - width: auto; - } - - // Footer copyright highlight - this is the upper part of the copyright and - // theme information, which will include a darker color than the theme link - &__highlight { - color: var(--md-footer-fg-color--light); - } -} - -// ---------------------------------------------------------------------------- - -// Social links -.md-social { - display: inline-flex; - gap: px2rem(4px); - padding: px2rem(4px) 0 px2rem(12px); - margin: 0 px2rem(8px); - - // [tablet portrait +]: Show copyright and social links in one line - @include break-from-device(tablet portrait) { - padding: px2rem(12px) 0; - } - - // Footer social link - &__link { - display: inline-block; - width: px2rem(32px); - height: px2rem(32px); - text-align: center; - - // Adjust line-height to match height for correct alignment - &::before { - line-height: 1.9; - } - - // Fill icon with current color - svg { - max-height: px2rem(16px); - vertical-align: -25%; - fill: currentcolor; - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_form.scss b/src/templates/assets/stylesheets/main/components/_form.scss deleted file mode 100644 index 49b59e42..00000000 --- a/src/templates/assets/stylesheets/main/components/_form.scss +++ /dev/null @@ -1,83 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Form button - .md-button { - display: inline-block; - padding: px2em(10px) px2em(32px); - font-weight: 700; - color: var(--md-primary-fg-color); - cursor: pointer; - border: px2rem(2px) solid currentcolor; - border-radius: px2rem(2px); - transition: - color 125ms, - background-color 125ms, - border-color 125ms; - - // Primary button - &--primary { - color: var(--md-primary-bg-color); - background-color: var(--md-primary-fg-color); - border-color: var(--md-primary-fg-color); - } - - // Button on focus/hover - &:is(:focus, :hover) { - color: var(--md-accent-bg-color); - background-color: var(--md-accent-fg-color); - border-color: var(--md-accent-fg-color); - } - } - - // Form input - .md-input { - height: px2rem(36px); - padding: 0 px2rem(12px); - font-size: px2rem(16px); - border-bottom: px2rem(2px) solid var(--md-default-fg-color--lighter); - border-start-start-radius: px2rem(2px); - border-start-end-radius: px2rem(2px); - box-shadow: var(--md-shadow-z1); - transition: - border 250ms, - box-shadow 250ms; - - // Input on focus/hover - &:is(:focus, :hover) { - border-bottom-color: var(--md-accent-fg-color); - box-shadow: var(--md-shadow-z2); - } - - // Stretch to full width - &--stretch { - width: 100%; - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_header.scss b/src/templates/assets/stylesheets/main/components/_header.scss deleted file mode 100644 index e51f3f99..00000000 --- a/src/templates/assets/stylesheets/main/components/_header.scss +++ /dev/null @@ -1,270 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Header - by default, the header will be sticky and stay always on top of the -// viewport. If this behavior is not desired, just set `position: static`. -.md-header { - position: sticky; - inset-inline: 0; - top: 0; - z-index: 4; - display: block; - color: var(--md-primary-bg-color); - background-color: var(--md-primary-fg-color); - // Hack: reduce jitter by adding a transparent box shadow of the same size - // so the size of the layer doesn't change during animation - box-shadow: - 0 0 px2rem(4px) rgba(0, 0, 0, 0), - 0 px2rem(4px) px2rem(8px) rgba(0, 0, 0, 0); - - // [print]: Hide header - @media print { - display: none; - } - - // Header is hidden - &[hidden] { - transition: - transform 250ms cubic-bezier(0.8, 0, 0.6, 1), - box-shadow 250ms; - transform: translateY(-100%); - } - - // Header in shadow state, i.e. shadow is visible - &--shadow { - box-shadow: - 0 0 px2rem(4px) rgba(0, 0, 0, 0.1), - 0 px2rem(4px) px2rem(8px) rgba(0, 0, 0, 0.2); - transition: - transform 250ms cubic-bezier(0.1, 0.7, 0.1, 1), - box-shadow 250ms; - } - - // Header wrapper - &__inner { - display: flex; - align-items: center; - padding: 0 px2rem(4px); - } - - // Header button - &__button { - position: relative; - z-index: 1; - padding: px2rem(8px); - margin: px2rem(4px); - color: currentcolor; - vertical-align: middle; - cursor: pointer; - outline-color: var(--md-accent-fg-color); - transition: opacity 250ms; - - // Button on hover - &:hover { - opacity: 0.7; - } - - // Header button is visible - &:not([hidden]) { - display: inline-block; - } - - // Hide outline for pointer devices - &:not(.focus-visible) { - outline: none; - -webkit-tap-highlight-color: transparent; - } - - // Button with logo, pointing to `config.site_url` - &.md-logo { - padding: px2rem(8px); - margin: px2rem(4px); - - // [tablet -]: Hide button - @include break-to-device(tablet) { - display: none; - } - - // Image or icon - :is(img, svg) { - display: block; - width: auto; - height: px2rem(24px); - fill: currentcolor; - } - } - - // Button for search - &[for="__search"] { - - // [tablet landscape +]: Hide button - @include break-from-device(tablet landscape) { - display: none; - } - - // [no-js]: Hide button - .no-js & { - display: none; - } - - // Adjust for right-to-left languages - [dir="rtl"] & svg { - transform: scaleX(-1); - } - } - - // Button for drawer - &[for="__drawer"] { - - // [screen +]: Hide button - @include break-from-device(screen) { - display: none; - } - } - } - - // Header topic - &__topic { - position: absolute; - display: flex; - max-width: 100%; - white-space: nowrap; - transition: - transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1), - opacity 150ms; - - // Second header topic - title of the current page - & + & { - z-index: -1; - pointer-events: none; - opacity: 0; - transition: - transform 400ms cubic-bezier(1, 0.7, 0.1, 0.1), - opacity 150ms; - transform: translateX(px2rem(25px)); - - // Adjust for right-to-left languages - [dir="rtl"] & { - transform: translateX(px2rem(-25px)); - } - } - - // Adjust font weight of site title - &:first-child { - font-weight: 700; - } - } - - // Header title - &__title { - flex-grow: 1; - height: px2rem(48px); - margin-inline-start: px2rem(20px); - margin-inline-end: px2rem(8px); - font-size: px2rem(18px); - line-height: px2rem(48px); - - // Header title in active state, i.e. page title is visible - &--active .md-header__topic { - z-index: -1; - pointer-events: none; - opacity: 0; - transition: - transform 400ms cubic-bezier(1, 0.7, 0.1, 0.1), - opacity 150ms; - transform: translateX(px2rem(-25px)); - - // Adjust for right-to-left languages - [dir="rtl"] & { - transform: translateX(px2rem(25px)); - } - - // Second header topic - title of the current page - + .md-header__topic { - z-index: 0; - pointer-events: initial; - opacity: 1; - transition: - transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1), - opacity 150ms; - transform: translateX(0); - } - } - - // Add ellipsis in case of overflowing text - > .md-header__ellipsis { - position: relative; - width: 100%; - height: 100%; - } - } - - // Header option - &__option { - display: flex; - flex-shrink: 0; - max-width: 100%; - white-space: nowrap; - transition: - max-width 0ms 250ms, - opacity 250ms 250ms; - - // Hide toggle when search is active - [data-md-toggle="search"]:checked ~ .md-header & { - max-width: 0; - opacity: 0; - transition: - max-width 0ms, - opacity 0ms; - } - - // Hack: Firefox 117 introduces a bug where the browser scrolls the page by - // a small amount to the top every time the header button is focused. After - // investigating, we're confident that it seems to be caused by the input - // field being too close to the border - see https://t.ly/APO8l - > input { - bottom: 0; - } - } - - // Repository information container - &__source { - display: none; - - // [tablet landscape +]: Show repository information - @include break-from-device(tablet landscape) { - display: block; - width: px2rem(234px); - max-width: px2rem(234px); - margin-inline-start: px2rem(20px); - } - - // [screen +]: Adjust spacing of search bar - @include break-from-device(screen) { - margin-inline-start: px2rem(28px); - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_meta.scss b/src/templates/assets/stylesheets/main/components/_meta.scss deleted file mode 100644 index aaeae8df..00000000 --- a/src/templates/assets/stylesheets/main/components/_meta.scss +++ /dev/null @@ -1,67 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Metadata -.md-meta { - font-size: px2rem(14px); - line-height: 1.3; - color: var(--md-default-fg-color--light); - - // Metadata list - &__list { - display: inline-flex; - flex-wrap: wrap; - padding: 0; - margin: 0; - list-style: none; - } - - // Metadata item separator - &__item:not(:last-child)::after { - margin-inline: px2rem(4px); - content: "·"; - } - - // Metadata link - &__link { - color: var(--md-typeset-a-color); - - // Metadata link on focus/hover - &:is(:focus, :hover) { - color: var(--md-accent-fg-color); - } - } -} - -// Draft -.md-draft { - display: inline-block; - padding-inline: px2em(8px, 14px); - font-weight: 700; - color: hsla(255, 100%, 100%); - background-color: $clr-red-a400; - border-radius: px2em(2px); -} diff --git a/src/templates/assets/stylesheets/main/components/_nav.scss b/src/templates/assets/stylesheets/main/components/_nav.scss deleted file mode 100644 index 673918af..00000000 --- a/src/templates/assets/stylesheets/main/components/_nav.scss +++ /dev/null @@ -1,761 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Navigation variables -:root { - --md-nav-icon--prev: svg-load("material/arrow-left.svg"); - --md-nav-icon--next: svg-load("material/chevron-right.svg"); - --md-toc-icon: svg-load("material/table-of-contents.svg"); -} - -// ---------------------------------------------------------------------------- - -// Navigation -.md-nav { - font-size: px2rem(14px); - line-height: 1.3; - - // Navigation title - &__title { - display: block; - padding: 0 px2rem(12px); - overflow: hidden; - font-weight: 700; - color: var(--md-default-fg-color--light); - text-overflow: ellipsis; - - // Navigaton button - .md-nav__button { - display: none; - - // Stretch images based on height, as it's the smaller dimension - img { - width: auto; - height: 100%; - } - - // Button with logo, pointing to `config.site_url` - &.md-logo { - - // Image or icon - :is(img, svg) { - display: block; - width: auto; - max-width: 100%; - height: px2rem(48px); - object-fit: contain; - fill: currentcolor; - } - } - } - } - - // Navigation list - &__list { - padding: 0; - margin: 0; - list-style: none; - } - - // Navigation link - &__link { - display: flex; - gap: px2rem(8px); - align-items: flex-start; - margin-top: 0.625em; - transition: color 125ms; - scroll-snap-align: start; - - // Navigation link that was passed - &--passed { - color: var(--md-default-fg-color--light); - } - - // Active link - .md-nav__item &--active { - - // Also enable color transitions on inline code blocks - &, - code { - color: var(--md-typeset-a-color); - } - } - - // Navigation link title - .md-ellipsis { - // Hack: Safari exhibits a bug where the text will sometimes disappear - // and the element will become unclickable. Setting `position: relative` - // seems to fix the issue - see https://bit.ly/3HljM1T - position: relative; - } - - // Always align navigation icons to the end - .md-icon:last-child { - margin-inline-start: auto; - } - - // Navigation link icon - svg { - flex-shrink: 0; - height: 1.3em; - fill: currentcolor; - } - - // Navigation link on focus/hover - &:is([href], [for]):is(:focus, :hover) { - color: var(--md-accent-fg-color); - cursor: pointer; - } - - // Show outline for keyboard devices - &.focus-visible { - outline-color: var(--md-accent-fg-color); - outline-offset: px2rem(4px); - } - - // Navigation link for table of contents - .md-nav--primary &[for="__toc"] { - display: none; - - // Table of contents icon - .md-icon::after { - display: block; - width: 100%; - height: 100%; - mask-image: var(--md-toc-icon); - background-color: currentcolor; - } - - // Hide table of contents - ~ .md-nav { - display: none; - } - } - } - - // Navigation container (for section index pages) - &__container > .md-nav__link { - margin-top: 0; - - // Stretch first child - &:first-child { - flex-grow: 1; - // Hack: if a very long word is used, it can push the arrow out of sight. - // Setting this property contains the text - see https://t.ly/E02vp - min-width: 0; - } - } - - // Navigation icon - &__icon { - flex-shrink: 0; - } - - // Repository information container - &__source { - display: none; - } - - // [tablet -]: Layered navigation - @include break-to-device(tablet) { - - // Primary and nested navigation - &--primary, - &--primary & { - position: absolute; - inset-inline: 0; - top: 0; - z-index: 1; - display: flex; - flex-direction: column; - height: 100%; - background-color: var(--md-default-bg-color); - } - - // Primary navigation - &--primary { - - // Navigation title and item - :is(.md-nav__title, .md-nav__item) { - font-size: px2rem(16px); - line-height: 1.5; - } - - // Navigation title - .md-nav__title { - position: relative; - height: px2rem(112px); - padding: px2rem(60px) px2rem(16px) px2rem(4px); - line-height: px2rem(48px); - color: var(--md-default-fg-color--light); - white-space: nowrap; - cursor: pointer; - background-color: var(--md-default-fg-color--lightest); - - // Navigation icon - .md-nav__icon { - position: absolute; - top: px2rem(8px); - inset-inline-start: px2rem(8px); - display: block; - width: px2rem(24px); - height: px2rem(24px); - margin: px2rem(4px); - - // Navigation icon in link to previous level - &::after { - display: block; - width: 100%; - height: 100%; - content: ""; - background-color: currentcolor; - mask-image: var(--md-nav-icon--prev); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - } - } - - // Navigation list - ~ .md-nav__list { - overflow-y: auto; - touch-action: pan-y; - background-color: var(--md-default-bg-color); - box-shadow: - 0 px2rem(1px) 0 var(--md-default-fg-color--lightest) inset; - scroll-snap-type: y mandatory; - - // Omit border on first child - > :first-child { - border-top: 0; - } - } - - // Top-level navigation title - &[for="__drawer"] { - font-weight: 700; - color: var(--md-primary-bg-color); - background-color: var(--md-primary-fg-color); - } - - // Button with logo, pointing to `config.site_url` - .md-logo { - position: absolute; - inset-inline: px2rem(4px); - top: px2rem(4px); - display: block; - padding: px2rem(8px); - margin: px2rem(4px); - } - } - - // Navigation list - .md-nav__list { - flex: 1; - } - - // Navigation item - .md-nav__item { - border-top: px2rem(1px) solid var(--md-default-fg-color--lightest); - - // Navigation link in active navigation - &--active > .md-nav__link { - color: var(--md-typeset-a-color); - - // Navigation link on focus/hover - &:is(:focus, :hover) { - color: var(--md-accent-fg-color); - } - } - } - - // Navigation link - .md-nav__link { - padding: px2rem(12px) px2rem(16px); - margin-top: 0; - - // Navigation link icon - svg { - margin-top: 0.1em; - } - - // Adjust spacing on nested link - > .md-nav__link { - padding: 0; - } - - // Navigation icon - .md-nav__icon { - width: px2rem(24px); - height: px2rem(24px); - margin-inline-end: px2rem(-4px); - font-size: px2rem(24px); - - // Navigation icon in link to next level - &::after { - display: block; - width: 100%; - height: 100%; - content: ""; - background-color: currentcolor; - mask-image: var(--md-nav-icon--next); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - } - } - } - - // Flip icon vertically - .md-nav__icon { - - // Adjust for right-to-left languages - [dir="rtl"] &::after { - transform: scale(-1); - } - } - - // Table of contents contained in primary navigation - .md-nav--secondary { - - // Navigation on level 2-6 - .md-nav { - position: static; - background-color: transparent; - - // Navigation link on level 3 - .md-nav__link { - padding-inline-start: px2rem(28px); - } - - // Navigation link on level 4 - .md-nav .md-nav__link { - padding-inline-start: px2rem(40px); - } - - // Navigation link on level 5 - .md-nav .md-nav .md-nav__link { - padding-inline-start: px2rem(52px); - } - - // Navigation link on level 6 - .md-nav .md-nav .md-nav .md-nav__link { - padding-inline-start: px2rem(64px); - } - } - } - } - - // Table of contents - &--secondary { - background-color: transparent; - } - - // Hide nested navigation - &__toggle ~ & { - display: flex; - opacity: 0; - transition: - transform 250ms cubic-bezier(0.8, 0, 0.6, 1), - opacity 125ms 50ms; - transform: translateX(100%); - - // Adjust for right-to-left languages - [dir="rtl"] & { - transform: translateX(-100%); - } - } - - // Show nested navigation when toggle is active - &__toggle:checked ~ & { - opacity: 1; - transition: - transform 250ms cubic-bezier(0.4, 0, 0.2, 1), - opacity 125ms 125ms; - transform: translateX(0); - - // Navigation list - > .md-nav__list { - // Hack: promote to own layer to reduce jitter - backface-visibility: hidden; - } - } - } - - // [tablet portrait -]: Layered navigation with table of contents - @include break-to-device(tablet portrait) { - - // Show link to table of contents - &--primary &__link[for="__toc"] { - display: flex; - - // Show table of contents icon - .md-icon::after { - content: ""; - } - - // Hide navigation link to current page - + .md-nav__link { - display: none; - } - - // Show table of contents - ~ .md-nav { - display: flex; - } - } - - // Repository information container - &__source { - display: block; - padding: 0 px2rem(4px); - color: var(--md-primary-bg-color); - background-color: var(--md-primary-fg-color--dark); - } - } - - // [tablet landscape]: Layered navigation with table of contents - @include break-at-device(tablet landscape) { - - // Show link to integrated table of contents - &--integrated &__link[for="__toc"] { - display: flex; - - // Show table of contents icon - .md-icon::after { - content: ""; - } - - // Hide navigation link to current page - + .md-nav__link { - display: none; - } - - // Show table of contents - ~ .md-nav { - display: flex; - } - } - } - - // [tablet landscape +]: Tree-like table of contents - @include break-from-device(tablet landscape) { - margin-bottom: px2rem(-8px); - - // Table of contents - &--secondary { - - // Navigation title - .md-nav__title { - position: sticky; - top: 0; - // Hack: because of the hack that we need to make .md-ellipsis work in - // Safari, we need to set `z-index` here as - see https://bit.ly/3s5M2jm - z-index: 1; - background: var(--md-default-bg-color); - box-shadow: 0 0 px2rem(8px) px2rem(8px) var(--md-default-bg-color); - - // Adjust snapping behavior - &[for="__toc"] { - scroll-snap-align: start; - } - - // Hide navigation icon - .md-nav__icon { - display: none; - } - } - - // Adjust spacing for navigation list - same reason as below - .md-nav__list { - padding-inline-start: px2rem(12px); - padding-bottom: px2rem(8px); - } - - // Adjust spacing for navigation link - before this change, we set spacing - // on the left and right of a navigation item, but this led to the problem - // of cropped focus outlines, because we must set `overflow: hidden` on - // the navigation list for smooth expand and collapse transitions. - .md-nav__item > .md-nav__link { - margin-inline-end: px2rem(8px); - } - } - } - - // [screen +]: Tree-like navigation - @include break-from-device(screen) { - margin-bottom: px2rem(-8px); - transition: max-height 250ms cubic-bezier(0.86, 0, 0.07, 1); - - // Primary navigation - &--primary { - - // Navigation title - .md-nav__title { - position: sticky; - top: 0; - // Hack: because of the hack that we need to make .md-ellipsis work in - // Safari, we need to set `z-index` here as - see https://bit.ly/3s5M2jm - z-index: 1; - background: var(--md-default-bg-color); - box-shadow: 0 0 px2rem(8px) px2rem(8px) var(--md-default-bg-color); - - // Adjust snapping behavior - &[for="__drawer"] { - scroll-snap-align: start; - } - - // Hide navigation icon - .md-nav__icon { - display: none; - } - } - - // Adjust spacing for navigation list - same reason as below - .md-nav__list { - padding-inline-start: px2rem(12px); - padding-bottom: px2rem(8px); - } - - // Adjust spacing for navigation link - before this change, we set spacing - // on the left and right of a navigation item, but this led to the problem - // of cropped focus outlines, because we must set `overflow: hidden` on - // the navigation list for smooth expand and collapse transitions. - .md-nav__item > .md-nav__link { - margin-inline-end: px2rem(8px); - } - } - - // Hide nested navigation - &__toggle ~ & { - display: grid; - grid-template-rows: 0fr; - visibility: collapse; - opacity: 0; - transition: - grid-template-rows 250ms cubic-bezier(0.86, 0, 0.07, 1), - opacity 250ms, - visibility 0ms 250ms; - - // Navigation list - > .md-nav__list { - overflow: hidden; - } - } - - // Show nested navigation when toggle is active or indeterminate - &__toggle:is(:checked, :indeterminate) ~ & { - grid-template-rows: 1fr; - visibility: visible; - opacity: 1; - transition: - grid-template-rows 250ms cubic-bezier(0.86, 0, 0.07, 1), - opacity 150ms 100ms, - visibility 0ms; - } - - // Hide navigation title in nested navigation - &__item--nested > & > &__title { - display: none; - } - - // Navigation section - &__item--section { - display: block; - margin: 1.25em 0; - - // Adjust spacing on last child - &:last-child { - margin-bottom: 0; - } - - // Show navigation link as title - > .md-nav__link { - font-weight: 700; - - // Make labels discernable from links - &[for] { - color: var(--md-default-fg-color--light); - } - - // Omit clicks if not a section index page - &:not(.md-nav__container) { - pointer-events: none; - } - - // Hide navigation icon - > [for], - .md-icon { - display: none; - } - } - - // Navigation - > .md-nav { - display: block; - margin-inline-start: px2rem(-12px); - visibility: visible; - opacity: 1; - - // Adjust spacing on next level item - > .md-nav__list > .md-nav__item { - padding: 0; - } - } - } - - // Navigation icon - &__icon { - width: px2rem(18px); - height: px2rem(18px); - border-radius: 100%; - transition: background-color 250ms; - - // Navigation icon on hover - &:hover { - background-color: var(--md-accent-fg-color--transparent); - } - - // Navigation icon content - &::after { - display: inline-block; - width: 100%; - height: 100%; - vertical-align: px2rem(-2px); - content: ""; - background-color: currentcolor; - border-radius: 100%; - transition: transform 250ms; - mask-image: var(--md-nav-icon--next); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - - // Adjust for right-to-left languages - [dir="rtl"] & { - transform: rotate(180deg); - } - - // Navigation icon - rotate icon when toggle is active or indeterminate - .md-nav__item--nested .md-nav__toggle:checked ~ .md-nav__link &, - .md-nav__item--nested .md-nav__toggle:indeterminate ~ .md-nav__link & { - transform: rotate(90deg); - } - } - } - - // Modifier for when navigation tabs are rendered - &--lifted { - - // Hide site title - > .md-nav__title { - display: none; - } - - // Hide level 0 navigation items - > .md-nav__list > .md-nav__item { - display: none; - - // Active parent navigation item - &--active { - display: block; - - // Show navigation link as title - > .md-nav__link { - position: sticky; - top: 0; - z-index: 1; - margin-top: 0; - background: var(--md-default-bg-color); - box-shadow: 0 0 px2rem(8px) px2rem(8px) var(--md-default-bg-color); - - // Omit clicks if not a section index page - &:not(.md-nav__container) { - pointer-events: none; - } - } - - // Adjust spacing for navigation section - &.md-nav__item--section { - margin: 0; - } - } - - // Adjust spacing for nested navigation - > .md-nav { - margin-inline-start: px2rem(-12px); - } - - // Make labels discernable from links - > [for] { - color: var(--md-default-fg-color--light); - } - } - - // Hack: Always show active navigation tab on breakpoint screen, despite - // of checkbox being checked or not - see https://t.ly/Qc311 - .md-nav[data-md-level="1"] { - grid-template-rows: 1fr; - visibility: visible; - opacity: 1; - } - } - - // Modifier for when table of contents is rendered in primary navigation - &--integrated > .md-nav__list > .md-nav__item--active { - - // Add spacing to container for non-nested navigation items - &:not(.md-nav__item--nested) { - padding: 0 px2rem(12px); - - // Remove padding as it's given by container - > .md-nav__link { - padding: 0; - } - } - - // Show integrated table of contents - .md-nav--secondary { - display: block; - margin-bottom: 1.25em; - visibility: visible; - border-inline-start: px2rem(1px) solid var(--md-primary-fg-color); - opacity: 1; - - // Navigation list - > .md-nav__list { - padding-bottom: 0; - overflow: visible; - } - - // Hide table of contents title - > .md-nav__title { - display: none; - } - } - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_pagination.scss b/src/templates/assets/stylesheets/main/components/_pagination.scss deleted file mode 100644 index a010bf43..00000000 --- a/src/templates/assets/stylesheets/main/components/_pagination.scss +++ /dev/null @@ -1,85 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Pagination -.md-pagination { - display: flex; - gap: px2rem(8px); - align-items: center; - justify-content: center; - font-size: px2rem(16px); - font-weight: 700; - - // Pagination item - > * { - display: flex; - align-items: center; - justify-content: center; - min-width: px2rem(36px); - height: px2rem(36px); - text-align: center; - border-radius: px2rem(4px); - } - - // Active pagination item - &__current { - color: var(--md-default-fg-color--light); - background-color: var(--md-default-fg-color--lightest); - } - - // Pagination link - &__link { - transition: - color 125ms, - background-color 125ms; - - // Pagination link on focus/hover - &:is(:focus, :hover) { - color: var(--md-accent-fg-color); - background-color: var(--md-accent-fg-color--transparent); - - // Pagination icon - svg { - color: var(--md-accent-fg-color); - } - } - - // Show outline for keyboard devices - &.focus-visible { - outline-color: var(--md-accent-fg-color); - outline-offset: px2rem(4px); - } - - // Pagination icon - svg { - display: block; - width: px2rem(24px); - max-height: 100%; - color: var(--md-default-fg-color--lighter); - fill: currentcolor; - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_post.scss b/src/templates/assets/stylesheets/main/components/_post.scss deleted file mode 100644 index cf6ce019..00000000 --- a/src/templates/assets/stylesheets/main/components/_post.scss +++ /dev/null @@ -1,196 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Post -.md-post { - - // Post backlink - &__back { - padding-bottom: px2rem(24px); - margin-bottom: px2rem(24px); - border-bottom: px2rem(1px) solid var(--md-default-fg-color--lightest); - - // [tablet -]: Hide post backlink - @include break-to-device(tablet) { - display: none; - } - - // Adjust for right-to-left languages - [dir="rtl"] & { - - // Flip icon vertically - svg { - transform: scaleX(-1); - } - } - } - - // Post authors - &__authors { - display: flex; - flex-direction: column; - gap: px2rem(12px); - margin: 0 px2rem(12px) px2rem(24px); - } - - // Post metadata - .md-post__meta { - - // Navigation link - a { - transition: color 125ms; - - // Navigation link on focus/hover - &:is(:focus, :hover) { - color: var(--md-accent-fg-color); - } - } - } - - // Post navigation title @todo - generalize - &__title { - font-weight: 700; - color: var(--md-default-fg-color--light); - } - - // Post excerpt - &--excerpt { - margin-bottom: px2rem(64px); - - // Post excerpt header - .md-post__header { - display: flex; - gap: px2rem(12px); - align-items: center; - min-height: px2rem(32px); - } - - // Post excerpt authors - .md-post__authors { - display: inline-flex; - flex-direction: row; - gap: px2rem(4px); - align-items: center; - min-height: px2rem(48px); - margin: 0; - } - - // Post excerpt metadata - .md-post__meta .md-meta__list { - margin-inline-end: px2rem(8px); - } - - // Post excerpt content - .md-post__content > :first-child { - --md-scroll-margin: #{px2rem(120px)}; - - margin-top: 0; - } - } - - // Add margin to table of contents - > .md-nav--secondary { - margin: 1em 0; - } -} - -// ---------------------------------------------------------------------------- - -// Post author profile -.md-profile { - display: flex; - gap: px2rem(12px); - align-items: center; - width: 100%; - font-size: px2rem(14px); - line-height: 1.4; - - // Post author description - &__description { - flex-grow: 1; - } -} - -// ---------------------------------------------------------------------------- - -// Content area for post -.md-content--post { - display: flex; - - // [tablet -]: Switch to inverted column layout - @include break-to-device(tablet) { - flex-flow: column-reverse; - } - - // Content wrapper - > .md-content__inner { - min-width: 0; - - // [screen +]: Adjust spacing between content area and sidebars - @include break-from-device(screen) { - margin-inline-start: px2rem(24px); - } - } -} - -// Sidebar for post -.md-sidebar.md-sidebar--post { - - // [tablet -]: Adjust spacing - @include break-to-device(tablet) { - position: initial; - width: 100%; - padding: 0; - - .md-sidebar__inner { - padding: 0; - } - - .md-post__meta { - margin-inline: px2rem(12px); - } - - .md-nav__item { - display: inline; - border: none; - } - - .md-nav__list { - display: inline-flex; - flex-wrap: wrap; - gap: px2rem(12px); - padding-block: px2rem(12px); - } - - .md-nav__link { - padding: 0; - } - - .md-nav { - position: initial; - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_progress.scss b/src/templates/assets/stylesheets/main/components/_progress.scss deleted file mode 100644 index 7386ae33..00000000 --- a/src/templates/assets/stylesheets/main/components/_progress.scss +++ /dev/null @@ -1,53 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Progress variables -:root { - --md-progress-value: 0; - --md-progress-delay: 400ms; -} - -// ---------------------------------------------------------------------------- - -// Progress indicator -.md-progress { - position: fixed; - top: 0; - z-index: 4; - width: 100%; - height: px2rem(1.5px); - background: var(--md-primary-bg-color); - opacity: - min( - clamp(0, var(--md-progress-value), 1), - clamp(0, 100 - var(--md-progress-value), 1) - ); - transition: - transform 500ms cubic-bezier(0.19, 1, 0.22, 1), - opacity 250ms var(--md-progress-delay); - transform: scaleX(calc(var(--md-progress-value) * 1%)); - transform-origin: left; -} diff --git a/src/templates/assets/stylesheets/main/components/_search.scss b/src/templates/assets/stylesheets/main/components/_search.scss deleted file mode 100644 index e0f36b0c..00000000 --- a/src/templates/assets/stylesheets/main/components/_search.scss +++ /dev/null @@ -1,707 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Search variables -:root { - --md-search-result-icon: svg-load("material/file-search-outline.svg"); -} - -// ---------------------------------------------------------------------------- - -// Search -.md-search { - position: relative; - - // [tablet landscape +]: Header-embedded search - @include break-from-device(tablet landscape) { - padding: px2rem(4px) 0; - } - - // [no-js]: Hide search - .no-js & { - display: none; - } - - // Search overlay - &__overlay { - z-index: 1; - opacity: 0; - - // [tablet portrait -]: Search modal - @include break-to-device(tablet portrait) { - position: absolute; - top: px2rem(-20px); - width: px2rem(40px); - height: px2rem(40px); - overflow: hidden; - pointer-events: none; - background-color: var(--md-default-bg-color); - border-radius: px2rem(20px); - transition: - transform 300ms 100ms, - opacity 200ms 200ms; - transform-origin: center; - inset-inline-start: px2rem(-44px); - - // Show overlay when search is active - [data-md-toggle="search"]:checked ~ .md-header & { - opacity: 1; - transition: - transform 400ms, - opacity 100ms; - } - } - - // [tablet landscape +]: Header-embedded search - @include break-from-device(tablet landscape) { - position: fixed; - top: 0; - width: 0; - height: 0; - cursor: pointer; - background-color: hsla(0, 0%, 0%, 0.54); - transition: - width 0ms 250ms, - height 0ms 250ms, - opacity 250ms; - inset-inline-start: 0; - - // Show overlay when search is active - [data-md-toggle="search"]:checked ~ .md-header & { - width: 100%; - // Hack: when the header is translated upon scrolling, a new layer is - // induced, which means that the height will now refer to the height of - // the header, albeit positioning is fixed. This should be mitigated - // in all cases when setting the height to 2x the viewport. - height: 200vh; - opacity: 1; - transition: - width 0ms, - height 0ms, - opacity 250ms; - } - } - - // Adjust appearance when search is active - [data-md-toggle="search"]:checked ~ .md-header & { - - // [mobile portrait -]: Scale up 45 times - @include break-to-device(mobile portrait) { - transform: scale(45); - } - - // [mobile landscape]: Scale up 60 times - @include break-at-device(mobile landscape) { - transform: scale(60); - } - - // [tablet portrait]: Scale up 75 times - @include break-at-device(tablet portrait) { - transform: scale(75); - } - } - } - - // Search wrapper - &__inner { - // Hack: promote to own layer to reduce jitter - backface-visibility: hidden; - - // [tablet portrait -]: Search modal - @include break-to-device(tablet portrait) { - position: fixed; - top: 0; - z-index: 2; - width: 0; - height: 0; - overflow: hidden; - opacity: 0; - transition: - width 0ms 300ms, - height 0ms 300ms, - transform 150ms 150ms cubic-bezier(0.4, 0, 0.2, 1), - opacity 150ms 150ms; - transform: translateX(5%); - inset-inline-start: 0; - - // Adjust for right-to-left languages - [dir="rtl"] & { - transform: translateX(-5%); - } - - // Adjust appearance when search is active - [data-md-toggle="search"]:checked ~ .md-header & { - width: 100%; - height: 100%; - opacity: 1; - transition: - width 0ms 0ms, - height 0ms 0ms, - transform 150ms 150ms cubic-bezier(0.1, 0.7, 0.1, 1), - opacity 150ms 150ms; - transform: translateX(0); - } - } - - // [tablet landscape +]: Header-embedded search - @include break-from-device(tablet landscape) { - position: relative; - float: inline-end; - width: px2rem(234px); - padding: px2rem(2px) 0; - transition: width 250ms cubic-bezier(0.1, 0.7, 0.1, 1); - } - - // Adjust appearance when search is active - [data-md-toggle="search"]:checked ~ .md-header & { - - // [tablet landscape]: Omit overlaying header title - @include break-at-device(tablet landscape) { - width: px2rem(468px); - } - - // [screen +]: Match width of content area - @include break-from-device(screen) { - width: px2rem(688px); - } - } - } - - // Search form - &__form { - position: relative; - z-index: 2; - height: px2rem(48px); - background-color: var(--md-default-bg-color); - box-shadow: 0 0 px2rem(12px) transparent; - transition: - color 250ms, - background-color 250ms; - - // [tablet landscape +]: Header-embedded search - @include break-from-device(tablet landscape) { - height: px2rem(36px); - background-color: hsla(0, 0%, 0%, 0.26); - border-radius: px2rem(2px); - - // Search form on hover - &:hover { - background-color: hsla(0, 0%, 100%, 0.12); - } - } - - // Adjust appearance when search is active - [data-md-toggle="search"]:checked ~ .md-header & { - color: var(--md-default-fg-color); - background-color: var(--md-default-bg-color); - border-radius: px2rem(2px) px2rem(2px) 0 0; - box-shadow: 0 0 px2rem(12px) hsla(0, 0%, 0%, 0.07); - } - } - - // Search input - &__input { - position: relative; - z-index: 2; - width: 100%; - height: 100%; - padding-inline: px2rem(72px) px2rem(44px); - font-size: px2rem(18px); - text-overflow: ellipsis; - background: transparent; - - // Search placeholder - &::placeholder { - transition: color 250ms; - } - - // Search icon and placeholder - ~ .md-search__icon, - &::placeholder { - color: var(--md-default-fg-color--light); - } - - // Remove the "x" rendered by Internet Explorer - &::-ms-clear { - display: none; - } - - // [tablet portrait -]: Search modal - @include break-to-device(tablet portrait) { - width: 100%; - height: px2rem(48px); - font-size: px2rem(18px); - } - - // [tablet landscape +]: Header-embedded search - @include break-from-device(tablet landscape) { - padding-inline-start: px2rem(44px); - font-size: px2rem(16px); - color: inherit; - - // Search placeholder - &::placeholder { - color: var(--md-primary-bg-color--light); - } - - // Search icon - + .md-search__icon { - color: var(--md-primary-bg-color); - } - - // Adjust appearance when search is active - [data-md-toggle="search"]:checked ~ .md-header & { - text-overflow: clip; - - // Search icon and placeholder - + .md-search__icon { - color: var(--md-default-fg-color--light); - } - - // Search placeholder - &::placeholder { - color: transparent; - } - } - } - } - - // Search icon - &__icon { - display: inline-block; - width: px2rem(24px); - height: px2rem(24px); - cursor: pointer; - transition: - color 250ms, - opacity 250ms; - - // Search icon on hover - &:hover { - opacity: 0.7; - } - - // Search focus button - &[for="__search"] { - position: absolute; - top: px2rem(6px); - inset-inline-start: px2rem(10px); - z-index: 2; - - // Adjust for right-to-left languages - [dir="rtl"] & svg { - transform: scaleX(-1); - } - - // [tablet portrait -]: Search modal - @include break-to-device(tablet portrait) { - top: px2rem(12px); - inset-inline-start: px2rem(16px); - - // Hide the magnifying glass - svg:first-child { - display: none; - } - } - - // [tablet landscape +]: Header-embedded search - @include break-from-device(tablet landscape) { - pointer-events: none; - - // Hide the back arrow - svg:last-child { - display: none; - } - } - } - } - - // Search options - &__options { - position: absolute; - top: px2rem(6px); - inset-inline-end: px2rem(10px); - z-index: 2; - pointer-events: none; - - // [tablet portrait -]: Search modal - @include break-to-device(tablet portrait) { - top: px2rem(12px); - inset-inline-end: px2rem(16px); - } - - // Search option buttons - > .md-icon { - margin-inline-start: px2rem(4px); - color: var(--md-default-fg-color--light); - opacity: 0; - transition: - transform 150ms cubic-bezier(0.1, 0.7, 0.1, 1), - opacity 150ms; - transform: scale(0.75); - - // Hide outline for pointer devices - &:not(.focus-visible) { - outline: none; - -webkit-tap-highlight-color: transparent; - } - - // Show buttons when search is active and input non-empty - [data-md-toggle="search"]:checked ~ .md-header // stylelint-disable-line - .md-search__input:valid ~ & { - pointer-events: initial; - opacity: 1; - transform: scale(1); - - // Search focus icon - &:hover { - opacity: 0.7; - } - } - } - } - - // Search suggestions - &__suggest { - position: absolute; - top: 0; - display: flex; - align-items: center; - width: 100%; - height: 100%; - padding-inline: px2rem(72px) px2rem(44px); - font-size: px2rem(18px); - color: var(--md-default-fg-color--lighter); - white-space: nowrap; - opacity: 0; - transition: opacity 50ms; - - // [tablet landscape +]: Header-embedded search - @include break-from-device(tablet landscape) { - padding-inline-start: px2rem(44px); - font-size: px2rem(16px); - } - - // Show suggestions when search is active - [data-md-toggle="search"]:checked ~ .md-header & { - opacity: 1; - transition: opacity 300ms 100ms; - } - } - - // Search output - &__output { - position: absolute; - z-index: 1; - width: 100%; - overflow: hidden; - border-end-start-radius: px2rem(2px); - border-end-end-radius: px2rem(2px); - - // [tablet portrait -]: Search modal - @include break-to-device(tablet portrait) { - top: px2rem(48px); - bottom: 0; - } - - // [tablet landscape +]: Header-embedded search - @include break-from-device(tablet landscape) { - top: px2rem(38px); - opacity: 0; - transition: opacity 400ms; - - // Show output when search is active - [data-md-toggle="search"]:checked ~ .md-header & { - box-shadow: var(--md-shadow-z3); - opacity: 1; - } - } - } - - // Search scroll wrapper - &__scrollwrap { - height: 100%; - overflow-y: auto; - // Hack: Chrome 88+ has weird overscroll behavior. Overall, scroll snapping - // seems to be something that is not ready for prime time on some browsers. - // scroll-snap-type: y mandatory; - touch-action: pan-y; - background-color: var(--md-default-bg-color); - // Hack: promote to own layer to reduce jitter - backface-visibility: hidden; - - // Mitigiate excessive repaints on non-retina devices - @media (max-resolution: 1dppx) { - transform: translateZ(0); - } - - // [tablet landscape]: Set fixed width to omit unnecessary reflow - @include break-at-device(tablet landscape) { - width: px2rem(468px); - } - - // [screen +]: Set fixed width to omit unnecessary reflow - @include break-from-device(screen) { - width: px2rem(688px); - } - - // [tablet landscape +]: Limit height to viewport - @include break-from-device(tablet landscape) { - max-height: 0; - scrollbar-width: thin; - scrollbar-color: var(--md-default-fg-color--lighter) transparent; - - // Show scroll wrapper when search is active - [data-md-toggle="search"]:checked ~ .md-header & { - max-height: 75vh; - } - - // Search scroll wrapper on hover - &:hover { - scrollbar-color: var(--md-accent-fg-color) transparent; - } - - // Webkit scrollbar - &::-webkit-scrollbar { - width: px2rem(4px); - height: px2rem(4px); - } - - // Webkit scrollbar thumb - &::-webkit-scrollbar-thumb { - background-color: var(--md-default-fg-color--lighter); - - // Webkit scrollbar thumb on hover - &:hover { - background-color: var(--md-accent-fg-color); - } - } - } - } -} - -// Search result -.md-search-result { - color: var(--md-default-fg-color); - word-break: break-word; - - // Search result metadata - &__meta { - padding: 0 px2rem(16px); - font-size: px2rem(12.8px); - line-height: px2rem(36px); - color: var(--md-default-fg-color--light); - background-color: var(--md-default-fg-color--lightest); - scroll-snap-align: start; - - // [tablet landscape +]: Adjust spacing - @include break-from-device(tablet landscape) { - padding-inline-start: px2rem(44px); - } - } - - // Search result list - &__list { - padding: 0; - margin: 0; - list-style: none; - // Hack: omit accidental text selection on fast toggle of more button - user-select: none; - } - - // Search result item - &__item { - box-shadow: 0 px2rem(-1px) var(--md-default-fg-color--lightest); - - // Omit border on first child - &:first-child { - box-shadow: none; - } - } - - // Search result link - &__link { - display: block; - outline: none; - transition: background-color 250ms; - scroll-snap-align: start; - - // Search result link on focus/hover - &:is(:focus, :hover) { - background-color: var(--md-accent-fg-color--transparent); - } - - // Adjust spacing on last child of last link - &:last-child p:last-child { - margin-bottom: px2rem(12px); - } - } - - // Search result more container - &__more > summary { - position: sticky; - top: 0; - z-index: 1; - display: block; - cursor: pointer; - outline: none; - scroll-snap-align: start; - - // Hide native details marker - &::marker { - display: none; - } - - // Hide native details marker - legacy, must be split into a seprate rule, - // so older browsers don't consider the selector list as invalid - &::-webkit-details-marker { - display: none; - } - - // Search result more button - > div { - padding: px2em(12px) px2rem(16px); - font-size: px2rem(12.8px); - color: var(--md-typeset-a-color); - transition: - color 250ms, - background-color 250ms; - - // [tablet landscape +]: Adjust spacing - @include break-from-device(tablet landscape) { - padding-inline-start: px2rem(44px); - } - } - - // Search result more link on focus/hover - &:is(:focus, :hover) > div { - color: var(--md-accent-fg-color); - background-color: var(--md-accent-fg-color--transparent); - } - } - - // Adjust background for more container in open state - &__more[open] > summary { - background-color: var(--md-default-bg-color); - // box-shadow: 0 px2rem(-1px) hsla(0, 0%, 0%, 0.07) inset; - } - - // Search result article - &__article { - position: relative; - padding: 0 px2rem(16px); - overflow: hidden; - - // [tablet landscape +]: Adjust spacing - @include break-from-device(tablet landscape) { - padding-inline-start: px2rem(44px); - } - } - - // Search result icon - &__icon { - position: absolute; - inset-inline-start: 0; - width: px2rem(24px); - height: px2rem(24px); - margin: px2rem(10px); - color: var(--md-default-fg-color--light); - - // [tablet portrait -]: Hide icon - @include break-to-device(tablet portrait) { - display: none; - } - - // Search result icon content - &::after { - display: inline-block; - width: 100%; - height: 100%; - content: ""; - background-color: currentcolor; - mask-image: var(--md-search-result-icon); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - - // Adjust for right-to-left languages - [dir="rtl"] & { - transform: scaleX(-1); - } - } - } - - // Typesetted content - .md-typeset { - font-size: px2rem(12.8px); - line-height: 1.6; - color: var(--md-default-fg-color--light); - - // Search result article title - h1 { - margin: px2rem(11px) 0; - font-size: px2rem(16px); - font-weight: 400; - line-height: 1.4; - color: var(--md-default-fg-color); - - // Search term highlighting - mark { - text-decoration: none; - } - } - - // Search result section title - h2 { - margin: 0.5em 0; - font-size: px2rem(12.8px); - font-weight: 700; - line-height: 1.6; - color: var(--md-default-fg-color); - - // Search term highlighting - mark { - text-decoration: none; - } - } - } - - // Search result terms - &__terms { - display: block; - margin: 0.5em 0; - font-size: px2rem(12.8px); - font-style: italic; - color: var(--md-default-fg-color); - } - - // Search term highlighting - mark { - color: var(--md-accent-fg-color); - text-decoration: underline; - background-color: transparent; - } -} diff --git a/src/templates/assets/stylesheets/main/components/_select.scss b/src/templates/assets/stylesheets/main/components/_select.scss deleted file mode 100644 index ed597a39..00000000 --- a/src/templates/assets/stylesheets/main/components/_select.scss +++ /dev/null @@ -1,115 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Selection -.md-select { - position: relative; - z-index: 1; - - // Selection tooltip - &__inner { - position: absolute; - top: calc(100% - #{px2rem(4px)}); - left: 50%; - max-height: 0; - margin-top: px2rem(4px); - color: var(--md-default-fg-color); - background-color: var(--md-default-bg-color); - border-radius: px2rem(2px); - box-shadow: var(--md-shadow-z2); - opacity: 0; - transition: - transform 250ms 375ms, - opacity 250ms 250ms, - max-height 0ms 500ms; - transform: translate3d(-50%, px2rem(6px), 0); - - // Selection bubble on parent focus/hover - .md-select:is(:focus-within, :hover) & { - max-height: px2rem(200px); - opacity: 1; - transition: - transform 250ms cubic-bezier(0.1, 0.7, 0.1, 1), - opacity 250ms, - max-height 0ms; - transform: translate3d(-50%, 0, 0); - } - - // Selection bubble handle - &::after { - position: absolute; - top: 0; - left: 50%; - width: 0; - height: 0; - margin-top: px2rem(-4px); - margin-left: px2rem(-4px); - content: ""; - border: px2rem(4px) solid transparent; - border-top: 0; - border-bottom-color: var(--md-default-bg-color); - } - } - - // Selection list - &__list { - max-height: inherit; - padding: 0; - margin: 0; - overflow: auto; - font-size: px2rem(16px); - list-style-type: none; - border-radius: px2rem(2px); - } - - // Selection item - &__item { - line-height: px2rem(36px); - } - - // Selection link - &__link { - display: block; - width: 100%; - padding-inline: px2rem(12px) px2rem(24px); - cursor: pointer; - outline: none; - transition: - background-color 250ms, - color 250ms; - scroll-snap-align: start; - - // Link on focus/hover - &:is(:focus, :hover) { - color: var(--md-accent-fg-color); - } - - // Link on focus - &:focus { - background-color: var(--md-default-fg-color--lightest); - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_sidebar.scss b/src/templates/assets/stylesheets/main/components/_sidebar.scss deleted file mode 100644 index 8a320c04..00000000 --- a/src/templates/assets/stylesheets/main/components/_sidebar.scss +++ /dev/null @@ -1,209 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Sidebar -.md-sidebar { - position: sticky; - top: px2rem(48px); - flex-shrink: 0; - align-self: flex-start; - width: px2rem(242px); - padding: px2rem(24px) 0; - - // [print]: Hide sidebar - @media print { - display: none; - } - - // Primary sidebar with navigation - &--primary { - - // [tablet -]: Show navigation as drawer - @include break-to-device(tablet) { - position: fixed; - top: 0; - z-index: 5; - display: block; - width: px2rem(242px); - height: 100%; - background-color: var(--md-default-bg-color); - transition: - transform 250ms cubic-bezier(0.4, 0, 0.2, 1), - box-shadow 250ms; - transform: translateX(0); - inset-inline-start: px2rem(-242px); - - // Show sidebar when drawer is active - [data-md-toggle="drawer"]:checked ~ .md-container & { - box-shadow: var(--md-shadow-z3); - transform: translateX(px2rem(242px)); - - // Adjust for right-to-left languages - [dir="rtl"] & { - transform: translateX(px2rem(-242px)); - } - } - - // Stretch scroll wrapper for primary sidebar - .md-sidebar__scrollwrap { - position: absolute; - inset: 0; - margin: 0; - scroll-snap-type: none; - overflow: hidden; - } - } - } - - // [screen +]: Show navigation as sidebar - @include break-from-device(screen) { - height: 0; - - // [no-js]: Switch to native sticky behavior - .no-js & { - height: auto; - } - - // Adjust spacing for sticky navigation tabs - .md-header--lifted ~ .md-container & { - top: px2rem(96px); - } - } - - // Secondary sidebar with table of contents - &--secondary { - display: none; - order: 2; - - // [tablet landscape +]: Show table of contents as sidebar - @include break-from-device(tablet landscape) { - height: 0; - - // [no-js]: Switch to native sticky behavior - .no-js & { - height: auto; - } - - // Sidebar is visible - &:not([hidden]) { - display: block; - } - - // Ensure smooth scrolling on iOS - .md-sidebar__scrollwrap { - touch-action: pan-y; - } - } - } - - // Sidebar scroll wrapper - &__scrollwrap { - margin: 0 px2rem(4px); - overflow-y: auto; - // Hack: promote to own layer to reduce jitter - backface-visibility: hidden; - // Hack: Chrome 81+ exhibits a strange bug, where it scrolls the container - // to the bottom if `scroll-snap-type` is set on the initial render. For - // this reason, we disable scroll snapping until this is resolved (#1667). - // scroll-snap-type: y mandatory; - scrollbar-width: thin; - scrollbar-gutter: stable; - scrollbar-color: var(--md-default-fg-color--lighter) transparent; - - // Webkit scrollbar - &::-webkit-scrollbar { - width: px2rem(4px); - height: px2rem(4px); - } - - // Sidebar scroll wrapper on focus/hover - &:is(:focus-within, :hover) { - scrollbar-color: var(--md-accent-fg-color) transparent; - - // Webkit scrollbar thumb - &::-webkit-scrollbar-thumb { - background-color: var(--md-default-fg-color--lighter); - - // Webkit scrollbar thumb on hover - &:hover { - background-color: var(--md-accent-fg-color); - } - } - } - } - - // Hack: the scrollbar is only visible when the sidebar's contents overflow, - // which is nice, but leads to the problem where the chevrons of expandable - // sections will jump by `4px` when the sidebar is shown. We wanted to fix - // this problem for so long, but haven't found a clean way of doing it. - // Until now. The following declaration is only applied to Webkit browsers - // (e.g. Chrome and Safari), which support styling of scrollbars. The trick - // is to add conditional padding on the side of the scrollbar only if the - // sidebar's content doesn't overflow. This hack is inspired and adapted - // from Ayke van Laëthem's year old trick – see https://bit.ly/3Sb1qql - @supports selector(::-webkit-scrollbar) { - - // Sidebar scroll wrapper - &__scrollwrap { - scrollbar-gutter: auto; - } - - // Sidebar wrapper - &__inner { - padding-inline-end: calc(100% - #{px2rem(230px)}); - } - } -} - -// [tablet -]: Show overlay on active drawer -@include break-to-device(tablet) { - - // Drawer overlay - .md-overlay { - position: fixed; - top: 0; - z-index: 5; - width: 0; - height: 0; - background-color: hsla(0, 0%, 0%, 0.54); - opacity: 0; - transition: - width 0ms 250ms, - height 0ms 250ms, - opacity 250ms; - - // Show overlay when drawer is active - [data-md-toggle="drawer"]:checked ~ & { - width: 100%; - height: 100%; - opacity: 1; - transition: - width 0ms, - height 0ms, - opacity 250ms; - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_source.scss b/src/templates/assets/stylesheets/main/components/_source.scss deleted file mode 100644 index a2b72009..00000000 --- a/src/templates/assets/stylesheets/main/components/_source.scss +++ /dev/null @@ -1,182 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Keyframes -// ---------------------------------------------------------------------------- - -// Show repository facts -@keyframes facts { - 0% { - height: 0; - } - - 100% { - height: px2rem(13px); - } -} - -// Show repository fact -@keyframes fact { - 0% { - opacity: 0; - transform: translateY(100%); - } - - 50% { - opacity: 0; - } - - 100% { - opacity: 1; - transform: translateY(0%); - } -} - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Repository information variables -:root { - --md-source-forks-icon: svg-load("octicons/repo-forked-16.svg"); - --md-source-repositories-icon: svg-load("octicons/repo-16.svg"); - --md-source-stars-icon: svg-load("octicons/star-16.svg"); - --md-source-version-icon: svg-load("octicons/tag-16.svg"); -} - -// ---------------------------------------------------------------------------- - -// Repository information -.md-source { - display: block; - font-size: px2rem(13px); - line-height: 1.2; - white-space: nowrap; - outline-color: var(--md-accent-fg-color); - // Hack: promote to own layer to reduce jitter - backface-visibility: hidden; - transition: opacity 250ms; - - // Repository information on hover - &:hover { - opacity: 0.7; - } - - // Repository icon - &__icon { - display: inline-block; - width: px2rem(40px); - height: px2rem(48px); - vertical-align: middle; - - // Align with margin only (as opposed to normal button alignment) - svg { - margin-inline-start: px2rem(12px); - margin-top: px2rem(12px); - } - - // Adjust spacing if icon is present - + .md-source__repository { - padding-inline-start: px2rem(40px); - margin-inline-start: px2rem(-40px); - } - } - - // Repository name - &__repository { - display: inline-block; - max-width: calc(100% - #{px2rem(24px)}); - margin-inline-start: px2rem(12px); - overflow: hidden; - text-overflow: ellipsis; - vertical-align: middle; - } - - // Repository facts - &__facts { - display: flex; - gap: px2rem(8px); - width: 100%; - padding: 0; - margin: px2rem(2px) 0 0; - overflow: hidden; - font-size: px2rem(11px); - list-style-type: none; - opacity: 0.75; - - // Show after the data was loaded - .md-source__repository--active & { - animation: facts 250ms ease-in; - } - } - - // Repository fact - &__fact { - overflow: hidden; - text-overflow: ellipsis; - - // Show after the data was loaded - .md-source__repository--active & { - animation: fact 400ms ease-out; - } - - // Repository fact icon - &::before { - display: inline-block; - width: px2rem(12px); - height: px2rem(12px); - margin-inline-end: px2rem(2px); - vertical-align: text-top; - content: ""; - background-color: currentcolor; - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - } - - // Adjust spacing for 2nd+ fact - &:nth-child(1n+2) { - flex-shrink: 0; - } - - // Repository fact: version - &--version::before { - mask-image: var(--md-source-version-icon); - } - - // Repository fact: stars - &--stars::before { - mask-image: var(--md-source-stars-icon); - } - - // Repository fact: forks - &--forks::before { - mask-image: var(--md-source-forks-icon); - } - - // Repository fact: repositories - &--repositories::before { - mask-image: var(--md-source-repositories-icon); - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_status.scss b/src/templates/assets/stylesheets/main/components/_status.scss deleted file mode 100644 index 9e096021..00000000 --- a/src/templates/assets/stylesheets/main/components/_status.scss +++ /dev/null @@ -1,73 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Status variables -:root { - --md-status: svg-load("material/information-outline.svg"); - --md-status--new: svg-load("material/alert-decagram.svg"); - --md-status--deprecated: svg-load("material/trash-can.svg"); - --md-status--encrypted: svg-load("material/shield-lock.svg"); -} - -// ---------------------------------------------------------------------------- - -// Status -.md-status { - - // Status icon - &::after { - display: inline-block; - width: px2em(18px); - height: px2em(18px); - vertical-align: text-bottom; - content: ""; - background-color: var(--md-default-fg-color--light); - mask-image: var(--md-status); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - } - - // Status icon on hover - &:hover::after { - background-color: currentcolor; - } - - // Status: new - &--new::after { - mask-image: var(--md-status--new); - } - - // Status: deprecated - &--deprecated::after { - mask-image: var(--md-status--deprecated); - } - - // Status: encrypted - &--encrypted::after { - mask-image: var(--md-status--encrypted); - } -} diff --git a/src/templates/assets/stylesheets/main/components/_tabs.scss b/src/templates/assets/stylesheets/main/components/_tabs.scss deleted file mode 100644 index 0da3384b..00000000 --- a/src/templates/assets/stylesheets/main/components/_tabs.scss +++ /dev/null @@ -1,133 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Navigation tabs -.md-tabs { - // Must be higher than the z-index of the back-to-top button, or the button - // will overlay the navigation tabs bar when scrolling up fast. - z-index: 3; - display: block; - width: 100%; - overflow: auto; - line-height: 1.3; - color: var(--md-primary-bg-color); - background-color: var(--md-primary-fg-color); - - // [print]: Hide tabs - @media print { - display: none; - } - - // [tablet -]: Hide tabs - @include break-to-device(tablet) { - display: none; - } - - // Navigation tabs are hidden - &[hidden] { - pointer-events: none; - } - - // Navigation tabs list - &__list { - display: flex; - padding: 0; - margin: 0; - margin-inline-start: px2rem(4px); - overflow: auto; - white-space: nowrap; - list-style: none; - contain: content; - // Hack: don't show scrollbar when navigation tabs overflow, which should - // only happen in rare occasions, as adding too many top level sections is - // discouraged, since hiding content on horitontal axis doesn't lead to a - // good user experience. It's just harder to discover. - scrollbar-width: none; - - // Hack: see above - &::-webkit-scrollbar { - display: none; - } - } - - // Navigation tabs item - &__item { - height: px2rem(48px); - padding-inline: px2rem(12px); - - // Navigation tabs link in active navigation - &--active .md-tabs__link { - color: inherit; - opacity: 1; - } - } - - // Navigation tabs link - could be defined as block elements and aligned via - // line height, but this would imply more repaints when scrolling - &__link { - display: flex; - margin-top: px2rem(16px); - font-size: px2rem(14px); - outline-color: var(--md-accent-fg-color); - outline-offset: px2rem(4px); - // Hack: save a repaint when tabs are appearing on scrolling up - backface-visibility: hidden; - opacity: 0.7; - transition: - transform 400ms cubic-bezier(0.1, 0.7, 0.1, 1), - opacity 250ms; - - // Navigation tabs link on focus/hover - &:is(:focus, :hover) { - color: inherit; - opacity: 1; - } - - // Navigation tabs link icon - svg { - height: 1.3em; - margin-inline-end: px2rem(8px); - fill: currentcolor; - } - - // Delay transitions by a small amount - @for $i from 2 through 16 { - .md-tabs__item:nth-child(#{$i}) & { - transition-delay: 20ms * ($i - 1); - } - } - - // Hide tabs upon scrolling - disable transition to minimizes repaints - // while scrolling down, while scrolling up seems to be okay - .md-tabs[hidden] & { - opacity: 0; - transition: - transform 0ms 100ms, - opacity 100ms; - transform: translateY(50%); - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_tag.scss b/src/templates/assets/stylesheets/main/components/_tag.scss deleted file mode 100644 index 9f31829d..00000000 --- a/src/templates/assets/stylesheets/main/components/_tag.scss +++ /dev/null @@ -1,105 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Tag variables -:root { - --md-tag-icon: svg-load("material/pound.svg"); -} - -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Tag list - .md-tags { - display: inline-flex; - flex-wrap: wrap; - gap: px2em(8px); - margin-top: px2em(-2px); - margin-bottom: px2em(12px); - } - - // Tag - .md-tag { - display: inline-flex; - gap: px2em(8px); - align-items: center; - padding: px2em(4px, 12.8px) px2em(10px, 12.8px); - font-size: px2rem(12.8px); // Fallback - font-size: min(px2em(12.8px), px2rem(12.8px)); - font-weight: 700; - line-height: 1.6; - letter-spacing: initial; - background: var(--md-default-fg-color--lightest); - border-radius: px2rem(48px); - - // Linked tag - &[href] { - color: inherit; - outline: none; - -webkit-tap-highlight-color: transparent; - transition: - color 125ms, - background-color 125ms; - - // Linked tag on focus/hover - &:is(:focus, :hover) { - color: var(--md-accent-bg-color); - background-color: var(--md-accent-fg-color); - } - } - - // Tag inside headline - [id] > & { - vertical-align: text-top; - } - } - - // Tag icon - .md-tag-icon { - - // Tag icon content - &::before { - display: inline-block; - width: 1.2em; - height: 1.2em; - vertical-align: text-bottom; - content: ""; - background-color: var(--md-default-fg-color--lighter); - transition: background-color 125ms; - mask-image: var(--md-tag-icon); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - } - - // Linked tag on focus/hover - &[href]:is(:focus, :hover)::before { - background-color: var(--md-accent-bg-color); - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_tooltip.scss b/src/templates/assets/stylesheets/main/components/_tooltip.scss deleted file mode 100644 index 421e5858..00000000 --- a/src/templates/assets/stylesheets/main/components/_tooltip.scss +++ /dev/null @@ -1,292 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Keyframes -// ---------------------------------------------------------------------------- - -// Continuous pulse animation -@keyframes pulse { - 0% { - transform: scale(0.95); - } - - 75% { - transform: scale(1); - } - - 100% { - transform: scale(0.95); - } -} - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Tooltip variables -:root { - --md-annotation-bg-icon: svg-load("material/circle.svg"); - --md-annotation-icon: svg-load("material/plus-circle.svg"); - --md-tooltip-width: #{px2rem(400px)}; -} - -// ---------------------------------------------------------------------------- - -// Tooltip -.md-tooltip { - position: absolute; - top: var(--md-tooltip-y); - left: - clamp( - var(--md-tooltip-0, #{px2rem(0px)}) + #{px2rem(16px)}, - var(--md-tooltip-x), - 100vw + - var(--md-tooltip-0, #{px2rem(0px)}) + #{px2rem(16px)} - - var(--md-tooltip-width) - - 2 * #{px2rem(16px)} - ); - // Hack: set an explicit `z-index` so we can transition it to ensure that any - // following elements are not overlaying the tooltip during the transition. - z-index: 0; - width: var(--md-tooltip-width); - max-width: calc(100vw - 2 * #{px2rem(16px)}); - font-family: var(--md-text-font-family); - color: var(--md-default-fg-color); - background-color: var(--md-default-bg-color); - border-radius: px2rem(2px); - box-shadow: var(--md-shadow-z2); - opacity: 0; - transition: - transform 0ms 250ms, - opacity 250ms, - z-index 250ms; - transform: translateY(px2rem(-8px)); - // Hack: promote to own layer to reduce jitter - backface-visibility: hidden; - - // Active tooltip - &--active { - z-index: 2; - opacity: 1; - transition: - transform 250ms cubic-bezier(0.1, 0.7, 0.1, 1), - opacity 250ms, - z-index 0ms; - transform: translateY(0); - } - - // Show outline on target and for keyboard devices - :is(.focus-visible > &, &:target) { - outline: var(--md-accent-fg-color) auto; - } - - // Tooltip wrapper - &__inner { - padding: px2rem(16px); - font-size: px2rem(12.8px); - - // Adjust spacing on first child - &.md-typeset > :first-child { - margin-top: 0; - } - - // Adjust spacing on last child - &.md-typeset > :last-child { - margin-bottom: 0; - } - } -} - -// ---------------------------------------------------------------------------- - -// Annotation -.md-annotation { - font-weight: 400; - white-space: normal; - vertical-align: text-bottom; - outline: none; - - // Adjust for right-to-left languages - [dir="rtl"] & { - direction: rtl; - } - - // Annotation index in code block - code & { - font-family: var(--md-code-font-family); - font-size: inherit; - } - - // Annotation is not hidden (e.g. when copying) - &:not([hidden]) { - display: inline-block; - // Hack: ensure that the line height doesn't exceed the line height of the - // hosting line, because it will lead to dancing pixels. - line-height: 1.25; - } - - // Annotation index - &__index { - position: relative; - z-index: 0; - display: inline-block; - margin-inline: 0.4ch; - vertical-align: text-top; - cursor: pointer; - user-select: none; - outline: none; - - // Hack: increase specificity to override default for anchors in typesetted - // content, because transitions are defined on anchor elements - .md-annotation & { - transition: z-index 250ms; - } - - // Hack: Work around Firefox bug that renders a subpixel outline when - // rotating a mask image element. - // https://bugzilla.mozilla.org/show_bug.cgi?id=1671784 - overflow: hidden; // stylelint-disable-line order/properties-order - border-radius: 0.01px; - - // [screen]: Render annotation markers as icons - @media screen { - width: 2.2ch; - - // Annotation is visible - [data-md-visible] > & { - animation: pulse 2000ms infinite; - } - - // Annotation marker background - &::before { - position: absolute; - top: -0.1ch; - z-index: -1; - width: 2.2ch; - height: 2.2ch; - content: ""; - background: var(--md-default-bg-color); - mask-image: var(--md-annotation-bg-icon); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - } - - // Annotation marker – the marker must be positioned absolutely behind - // the index, because it shouldn't impact the rendering of a code block. - // Otherwise, small rounding differences in browsers can sometimes mess up - // alignment of text following an annotation. - &::after { - position: absolute; - top: -0.1ch; - z-index: -1; - width: 2.2ch; - height: 2.2ch; - content: ""; - background-color: var(--md-default-fg-color--lighter); - transition: - background-color 250ms, - transform 250ms; - // Hack: promote to own layer to reduce jitter - transform: scale(1.0001); - mask-image: var(--md-annotation-icon); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - - // Annotation marker for active tooltip - .md-tooltip--active + & { - transform: rotate(45deg); - } - - // Annotation marker for active tooltip or on hover - :is(.md-tooltip--active + &, :hover > &) { - background-color: var(--md-accent-fg-color); - } - } - } - - // Annotation index for active tooltip - .md-tooltip--active + & { - z-index: 2; - transition-duration: 0ms; - animation-play-state: paused; - } - - // Annotation marker - [data-md-annotation-id] { - display: inline-block; - - // [print]: Render annotation markers as numbers - @media print { - padding: 0 0.6ch; - font-weight: 700; - color: var(--md-default-bg-color); - white-space: nowrap; - background: var(--md-default-fg-color--lighter); - border-radius: 2ch; - - // Annotation marker content - &::after { - content: attr(data-md-annotation-id); - } - } - } - } -} - -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Annotation list - .md-annotation-list { - list-style: none; - counter-reset: xxx; - - // Annotation list item - li { - position: relative; - - // Annotation list marker - &::before { - position: absolute; - top: px2em(4px); - inset-inline-start: px2em(-34px); - min-width: 2ch; - height: 2ch; - padding: 0 0.6ch; - font-size: px2em(14.2px); - font-weight: 700; - line-height: 1.25; - color: var(--md-default-bg-color); - text-align: center; - content: counter(xxx); - counter-increment: xxx; - background: var(--md-default-fg-color--lighter); - border-radius: 2ch; - } - } - } -} diff --git a/src/templates/assets/stylesheets/main/components/_top.scss b/src/templates/assets/stylesheets/main/components/_top.scss deleted file mode 100644 index c24d44d1..00000000 --- a/src/templates/assets/stylesheets/main/components/_top.scss +++ /dev/null @@ -1,83 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Back-to-top button -.md-top { - position: fixed; - top: px2rem(48px + 16px); - z-index: 2; - display: block; - padding: px2rem(8px) px2rem(16px); - margin-inline-start: 50%; - font-size: px2rem(14px); - color: var(--md-default-fg-color--light); - cursor: pointer; - background-color: var(--md-default-bg-color); - border-radius: px2rem(32px); - outline: none; - box-shadow: var(--md-shadow-z2); - transition: - color 125ms, - background-color 125ms, - transform 125ms cubic-bezier(0.4, 0, 0.2, 1), - opacity 125ms; - transform: translate(-50%, 0); - - // [print]: Hide back-to-top button - @media print { - display: none; - } - - // Adjust for right-to-left languages - [dir="rtl"] & { - transform: translate(50%, 0); - } - - // Back-to-top button is hidden - &[hidden] { - pointer-events: none; - opacity: 0; - transition-duration: 0ms; - transform: translate(-50%, px2rem(4px)); - - // Adjust for right-to-left languages - [dir="rtl"] & { - transform: translate(50%, px2rem(4px)); - } - } - - // Back-to-top button on focus/hover - &:is(:focus, :hover) { - color: var(--md-accent-bg-color); - background-color: var(--md-accent-fg-color); - } - - // Inline icon - svg { - display: inline-block; - vertical-align: -0.5em; - } -} diff --git a/src/templates/assets/stylesheets/main/components/_version.scss b/src/templates/assets/stylesheets/main/components/_version.scss deleted file mode 100644 index 3f85d6cd..00000000 --- a/src/templates/assets/stylesheets/main/components/_version.scss +++ /dev/null @@ -1,150 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Keyframes -// ---------------------------------------------------------------------------- - -// See https://github.com/squidfunk/mkdocs-material/issues/2429 -@keyframes hoverfix { - 0% { - pointer-events: none; - } -} - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Version selection variables -:root { - --md-version-icon: svg-load("fontawesome/solid/caret-down.svg"); -} - -// ---------------------------------------------------------------------------- - -// Version selection -.md-version { - flex-shrink: 0; - height: px2rem(48px); - font-size: px2rem(16px); - - // Current selection - &__current { - position: relative; - // Hack: in general, we would use `vertical-align` to align the version at - // the bottom with the title, but since the list uses absolute positioning, - // this won't work consistently. Furthermore, we would need to use inline - // positioning to align the links, which looks jagged. - top: px2rem(1px); - margin-inline: px2rem(28px) px2rem(8px); - color: inherit; - cursor: pointer; - outline: none; - - // Version selection icon - &::after { - display: inline-block; - width: px2rem(8px); - height: px2rem(12px); - margin-inline-start: px2rem(8px); - content: ""; - background-color: currentcolor; - mask-image: var(--md-version-icon); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - } - } - - // Version selection list - &__list { - position: absolute; - top: px2rem(3px); - z-index: 3; - max-height: 0; - padding: 0; - margin: px2rem(4px) px2rem(16px); - overflow: auto; - color: var(--md-default-fg-color); - list-style-type: none; - background-color: var(--md-default-bg-color); - border-radius: px2rem(2px); - box-shadow: var(--md-shadow-z2); - opacity: 0; - transition: - max-height 0ms 500ms, - opacity 250ms 250ms; - scroll-snap-type: y mandatory; - - // Version selection list on parent focus/hover - .md-version:is(:focus-within, :hover) & { - max-height: px2rem(200px); - opacity: 1; - transition: - max-height 0ms, - opacity 250ms; - } - - // Fix hover on touch devices - @media (pointer: coarse), (hover: none) { - // Switch off on hover - .md-version:hover & { - animation: hoverfix 250ms forwards; - } - - // Enable on focus - .md-version:focus-within & { - animation: none; - } - } - } - - // Version selection item - &__item { - line-height: px2rem(36px); - } - - // Version selection link - &__link { - display: block; - width: 100%; - padding-inline: px2rem(12px) px2rem(24px); - white-space: nowrap; - cursor: pointer; - outline: none; - transition: - color 250ms, - background-color 250ms; - scroll-snap-align: start; - - // Link on focus/hover - &:is(:focus, :hover) { - color: var(--md-accent-fg-color); - } - - // Link on focus - &:focus { - background-color: var(--md-default-fg-color--lightest); - } - } -} diff --git a/src/templates/assets/stylesheets/main/extensions/markdown/_admonition.scss b/src/templates/assets/stylesheets/main/extensions/markdown/_admonition.scss deleted file mode 100644 index bf517989..00000000 --- a/src/templates/assets/stylesheets/main/extensions/markdown/_admonition.scss +++ /dev/null @@ -1,195 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -@use "sass:color"; -@use "sass:list"; - -// ---------------------------------------------------------------------------- -// Variables -// ---------------------------------------------------------------------------- - -/// Admonition flavours -$admonitions: ( - "note": pencil-circle $clr-blue-a200, - "abstract": clipboard-text $clr-light-blue-a400, - "info": information $clr-cyan-a700, - "tip": fire $clr-teal-a700, - "success": check $clr-green-a700, - "question": help-circle $clr-light-green-a700, - "warning": alert $clr-orange-a400, - "failure": close $clr-red-a200, - "danger": lightning-bolt-circle $clr-red-a400, - "bug": shield-bug $clr-pink-a400, - "example": test-tube $clr-deep-purple-a200, - "quote": format-quote-close $clr-grey -) !default; - -// ---------------------------------------------------------------------------- -// Rules: layout -// ---------------------------------------------------------------------------- - -// Admonition variables -:root { - @each $name, $props in $admonitions { - --md-admonition-icon--#{$name}: - svg-load("material/#{list.nth($props, 1)}.svg"); - } -} - -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Admonition - note that all styles also apply to details tags, which are - // rendered as collapsible admonitions with summary elements as titles. - .admonition { - display: flow-root; - padding: 0 px2rem(12px); - margin: px2em(20px, 12.8px) 0; - font-size: px2rem(12.8px); - color: var(--md-admonition-fg-color); - background-color: var(--md-admonition-bg-color); - border: px2rem(1.5px) solid $clr-blue-a200; - border-radius: px2rem(4px); - box-shadow: var(--md-shadow-z1); - transition: box-shadow 125ms; - page-break-inside: avoid; - - // [print]: Omit shadow as it may lead to rendering errors - @media print { - box-shadow: none; - } - - // Admonition on focus - &:focus-within { - box-shadow: 0 0 0 px2rem(4px) color.adjust($clr-blue-a200, $alpha: -0.9); - } - - // Hack: Chrome exhibits a weird issue where it will set nested elements to - // content-box. Doesn't happen in other browsers, so looks like a bug. - > * { - box-sizing: border-box; - } - - // Adjust vertical spacing for nested admonitions - .admonition { - margin-top: 1em; - margin-bottom: 1em; - } - - // Adjust spacing for contained table wrappers - .md-typeset__scrollwrap { - margin: 1em px2rem(-12px); - } - - // Adjust spacing for contained tables - .md-typeset__table { - padding: 0 px2rem(12px); - } - - // Adjust spacing for single-child tabbed block container - > .tabbed-set:only-child { - margin-top: 0; - } - - // Adjust spacing on last child - html & > :last-child { - margin-bottom: px2rem(12px); - } - } - - // Admonition title - .admonition-title { - position: relative; - padding-block: px2rem(8px); - padding-inline: px2rem(40px) px2rem(12px); - margin-block: 0; - margin-inline: px2rem(-12px); - font-weight: 700; - background-color: color.adjust($clr-blue-a200, $alpha: -0.9); - border: none; - border-inline-start-width: px2rem(4px); - border-start-start-radius: px2rem(2px); - border-start-end-radius: px2rem(2px); - - // Adjust spacing for title-only admonitions - html &:last-child { - margin-bottom: 0; - } - - // Admonition icon - &::before { - position: absolute; - top: px2em(10px); - width: px2rem(20px); - height: px2rem(20px); - content: ""; - background-color: $clr-blue-a200; - inset-inline-start: px2rem(12px); - mask-image: var(--md-admonition-icon--note); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - } - - // Inline code block - code { - box-shadow: 0 0 0 px2rem(1px) var(--md-default-fg-color--lightest); - } - } -} - -// ---------------------------------------------------------------------------- -// Rules: flavours -// ---------------------------------------------------------------------------- - -// Define admonition flavors -@each $name, $props in $admonitions { - $tint: list.nth($props, 2); - - // Admonition flavour - .md-typeset .admonition.#{$name} { - border-color: $tint; - - // Admonition on focus - &:focus-within { - box-shadow: 0 0 0 px2rem(4px) color.adjust($tint, $alpha: -0.9); - } - } - - // Admonition flavour title - .md-typeset .#{$name} > .admonition-title { - background-color: color.adjust($tint, $alpha: -0.9); - - // Admonition icon - &::before { - background-color: $tint; - mask-image: var(--md-admonition-icon--#{$name}); - } - - // Details marker - &::after { - color: $tint; - } - } -} diff --git a/src/templates/assets/stylesheets/main/extensions/markdown/_footnotes.scss b/src/templates/assets/stylesheets/main/extensions/markdown/_footnotes.scss deleted file mode 100644 index 59447d89..00000000 --- a/src/templates/assets/stylesheets/main/extensions/markdown/_footnotes.scss +++ /dev/null @@ -1,146 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Footnotes variables -:root { - --md-footnotes-icon: svg-load("material/keyboard-return.svg"); -} - -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Footnote container - .footnote { - font-size: px2rem(12.8px); - color: var(--md-default-fg-color--light); - - // Footnote list - omit left indentation - > ol { - margin-inline-start: 0; - - // Footnote item - footnote items can contain lists, so we need to scope - // the spacing adjustments to the top-level footnote item. - > li { - transition: color 125ms; - - // Darken color on target - &:target { - color: var(--md-default-fg-color); - } - - // Show backreferences on footnote focus without transition - &:focus-within .footnote-backref { - opacity: 1; - transition: none; - transform: translateX(0); - } - - // Show backreferences on footnote hover/target - &:is(:hover, :target) .footnote-backref { - opacity: 1; - transform: translateX(0); - } - - // Adjust spacing on first child - > :first-child { - margin-top: 0; - } - } - } - } - - // Footnote reference - .footnote-ref { - font-size: px2em(12px, 16px); - font-weight: 700; - - // Hack: increase specificity to override default - html & { - outline-offset: px2rem(2px); - } - } - - // Show outline for all devices - [id^="fnref:"]:target > .footnote-ref { - outline: auto; - } - - // Footnote backreference - .footnote-backref { - display: inline-block; - // Hack: omit Unicode arrow for replacement with icon - font-size: 0; - color: var(--md-typeset-a-color); - vertical-align: text-bottom; - opacity: 0; - transition: - color 250ms, - transform 250ms 250ms, - opacity 125ms 250ms; - transform: translateX(px2rem(5px)); - - // [print]: Show footnote backreferences - @media print { - color: var(--md-typeset-a-color); - opacity: 1; - transform: translateX(0); - } - - // Adjust for right-to-left languages - [dir="rtl"] & { - transform: translateX(px2rem(-5px)); - } - - // Adjust color on hover - &:hover { - color: var(--md-accent-fg-color); - } - - // Footnote backreference icon - &::before { - display: inline-block; - width: px2rem(16px); - height: px2rem(16px); - content: ""; - background-color: currentcolor; - mask-image: var(--md-footnotes-icon); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - - // Adjust for right-to-left languages - [dir="rtl"] & { - - // Flip icon vertically - svg { - transform: scaleX(-1); - } - } - } - } -} diff --git a/src/templates/assets/stylesheets/main/extensions/markdown/_toc.scss b/src/templates/assets/stylesheets/main/extensions/markdown/_toc.scss deleted file mode 100644 index 8284a5c0..00000000 --- a/src/templates/assets/stylesheets/main/extensions/markdown/_toc.scss +++ /dev/null @@ -1,92 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Headerlink - .headerlink { - display: inline-block; - margin-inline-start: px2rem(10px); - color: var(--md-default-fg-color--lighter); - opacity: 0; - transition: - color 250ms, - opacity 125ms; - - // [print]: Hide headerlinks - @media print { - display: none; - } - } - - // Show headerlinks on parent hover - :is(:hover, :target) > .headerlink, - .headerlink:focus { - opacity: 1; - transition: - color 250ms, - opacity 125ms; - } - - // Adjust color on parent target or focus/hover - :target > .headerlink, - .headerlink:is(:focus, :hover) { - color: var(--md-accent-fg-color); - } - - // Adjust scroll margin for all elements with `id` attributes - :target { - --md-scroll-margin: #{px2rem(48px + 24px)}; - --md-scroll-offset: #{px2rem(0px)}; - // Scroll margin is finally ready for prime time - before, we used a hack - // for anchor correction based on pseudo elements but those times are gone. - scroll-margin-top: - calc( - var(--md-scroll-margin) - - var(--md-scroll-offset) - ); - - // [screen +]: Sticky navigation tabs - @include break-from-device(screen) { - - // Adjust scroll margin for sticky navigation tabs - .md-header--lifted ~ .md-container & { - --md-scroll-margin: #{px2rem(96px + 24px)}; - } - } - } - - // Adjust scroll offset for headlines of level 1-3 - :is(h1, h2, h3):target { - --md-scroll-offset: #{px2rem(4px)}; - } - - // Adjust scroll offset for headlines of level 4 - h4:target { - --md-scroll-offset: #{px2rem(3px)}; - } -} diff --git a/src/templates/assets/stylesheets/main/extensions/pymdownx/_arithmatex.scss b/src/templates/assets/stylesheets/main/extensions/pymdownx/_arithmatex.scss deleted file mode 100644 index fe8ffd62..00000000 --- a/src/templates/assets/stylesheets/main/extensions/pymdownx/_arithmatex.scss +++ /dev/null @@ -1,52 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Arithmatex container - div.arithmatex { - overflow: auto; - - // [mobile -]: Align with body copy - @include break-to-device(mobile) { - margin: 0 px2rem(-16px); - } - - // Arithmatex content - > * { - width: min-content; - padding: 0 px2rem(16px); - margin-inline: auto !important; // stylelint-disable-line - touch-action: auto; - - // MathJax container - see https://bit.ly/3HR8YJ5 - mjx-container { - margin: 0 !important; // stylelint-disable-line - } - } - } -} diff --git a/src/templates/assets/stylesheets/main/extensions/pymdownx/_critic.scss b/src/templates/assets/stylesheets/main/extensions/pymdownx/_critic.scss deleted file mode 100644 index 683705ce..00000000 --- a/src/templates/assets/stylesheets/main/extensions/pymdownx/_critic.scss +++ /dev/null @@ -1,76 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Deletion - del.critic { - background-color: var(--md-typeset-del-color); - box-decoration-break: clone; - } - - // Addition - ins.critic { - background-color: var(--md-typeset-ins-color); - box-decoration-break: clone; - } - - // Comment - .critic.comment { - color: var(--md-code-hl-comment-color); - box-decoration-break: clone; - - // Comment opening mark - &::before { - content: "/* "; - } - - // Comment closing mark - &::after { - content: " */"; - } - } - - // Critic block - .critic.block { - display: block; - padding-inline: px2rem(16px); - margin: 1em 0; - overflow: auto; - box-shadow: none; - - // Adjust spacing on first child - > :first-child { - margin-top: 0.5em; - } - - // Adjust spacing on last child - > :last-child { - margin-bottom: 0.5em; - } - } -} diff --git a/src/templates/assets/stylesheets/main/extensions/pymdownx/_details.scss b/src/templates/assets/stylesheets/main/extensions/pymdownx/_details.scss deleted file mode 100644 index 8eea678a..00000000 --- a/src/templates/assets/stylesheets/main/extensions/pymdownx/_details.scss +++ /dev/null @@ -1,121 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Details variables -:root { - --md-details-icon: svg-load("material/chevron-right.svg"); -} - -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Details - details { - @extend .admonition; - - display: flow-root; - padding-top: 0; - overflow: visible; - - // Details title icon - rotate icon on transition to open state - &[open] > summary::after { - transform: rotate(90deg); - } - - // Adjust spacing for details in closed state - &:not([open]) { - padding-bottom: 0; - box-shadow: none; - - // Hack: we cannot set `overflow: hidden` on the `details` element (which - // is why we set it to `overflow: visible`, as the outline would not be - // visible when focusing. Therefore, we must set the border radius on the - // summary explicitly. - > summary { - border-radius: px2rem(2px); - } - } - } - - // Details title - summary { - @extend .admonition-title; - - display: block; - min-height: px2rem(20px); - padding-inline-end: px2rem(36px); - cursor: pointer; - border-start-start-radius: px2rem(2px); - border-start-end-radius: px2rem(2px); - - // Show outline for keyboard devices - &.focus-visible { - outline-color: var(--md-accent-fg-color); - outline-offset: px2rem(4px); - } - - // Hide outline for pointer devices - &:not(.focus-visible) { - outline: none; - -webkit-tap-highlight-color: transparent; - } - - // Details marker - &::after { - position: absolute; - top: px2em(10px); - width: px2rem(20px); - height: px2rem(20px); - content: ""; - background-color: currentcolor; - transition: transform 250ms; - transform: rotate(0deg); - inset-inline-end: px2rem(8px); - mask-image: var(--md-details-icon); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - - // Adjust for right-to-left languages - [dir="rtl"] & { - transform: rotate(180deg); - } - } - - // Hide native details marker - modern - &::marker { - display: none; - } - - // Hide native details marker - legacy, must be split into a seprate rule, - // so older browsers don't consider the selector list as invalid - &::-webkit-details-marker { - display: none; - } - } -} diff --git a/src/templates/assets/stylesheets/main/extensions/pymdownx/_emoji.scss b/src/templates/assets/stylesheets/main/extensions/pymdownx/_emoji.scss deleted file mode 100644 index 8b351013..00000000 --- a/src/templates/assets/stylesheets/main/extensions/pymdownx/_emoji.scss +++ /dev/null @@ -1,43 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Emoji and icon container - :is(.emojione, .twemoji, .gemoji) { - display: inline-flex; - height: px2em(18px); - vertical-align: text-top; - - // Icon - inlined via mkdocs-material-extensions - svg { - width: px2em(18px); - max-height: 100%; - fill: currentcolor; - } - } -} diff --git a/src/templates/assets/stylesheets/main/extensions/pymdownx/_highlight.scss b/src/templates/assets/stylesheets/main/extensions/pymdownx/_highlight.scss deleted file mode 100644 index 7d297677..00000000 --- a/src/templates/assets/stylesheets/main/extensions/pymdownx/_highlight.scss +++ /dev/null @@ -1,382 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules: syntax highlighting -// ---------------------------------------------------------------------------- - -// Code block -.highlight { - - // .o = Operator - // .ow = Operator, word - :is(.o, .ow) { - color: var(--md-code-hl-operator-color); - } - - .p { // Punctuation - color: var(--md-code-hl-punctuation-color); - } - - // .cpf = Comment, preprocessor file - // .l = Literal - // .s = Literal, string - // .sb = Literal, string backticks - // .sc = Literal, string char - // .s2 = Literal, string double - // .si = Literal, string interpol - // .s1 = Literal, string single - // .ss = Literal, string symbol - :is(.cpf, .l, .s, .sb, .sc, .s2, .si, .s1, .ss) { - color: var(--md-code-hl-string-color); - } - - // .cp = Comment, pre-processor - // .se = Literal, string escape - // .sh = Literal, string heredoc - // .sr = Literal, string regex - // .sx = Literal, string other - :is(.cp, .se, .sh, .sr, .sx) { - color: var(--md-code-hl-special-color); - } - - // .m = Number - // .mb = Number, binary - // .mf = Number, float - // .mh = Number, hex - // .mi = Number, integer - // .il = Number, integer long - // .mo = Number, octal - :is(.m, .mb, .mf, .mh, .mi, .il, .mo) { - color: var(--md-code-hl-number-color); - } - - // .k = Keyword, - // .kd = Keyword, declaration - // .kn = Keyword, namespace - // .kp = Keyword, pseudo - // .kr = Keyword, reserved - // .kt = Keyword, type - :is(.k, .kd, .kn, .kp, .kr, .kt) { - color: var(--md-code-hl-keyword-color); - } - - // .kc = Keyword, constant - // .n = Name - :is(.kc, .n) { - color: var(--md-code-hl-name-color); - } - - // .no = Name, constant - // .nb = Name, builtin - // .bp = Name, builtin pseudo - :is(.no, .nb, .bp) { - color: var(--md-code-hl-constant-color); - } - - // .nc = Name, class - // .ne = Name, exception - // .nf = Name, function - // .nn = Name, namespace - :is(.nc, .ne, .nf, .nn) { - color: var(--md-code-hl-function-color); - } - - // .nd = Name, decorator - // .ni = Name, entity - // .nl = Name, label - // .nt = Name, tag - :is(.nd, .ni, .nl, .nt) { - color: var(--md-code-hl-keyword-color); - } - - // .c = Comment - // .cm = Comment, multiline - // .c1 = Comment, single - // .ch = Comment, shebang - // .cs = Comment, special - // .sd = Literal, string doc - :is(.c, .cm, .c1, .ch, .cs, .sd) { - color: var(--md-code-hl-comment-color); - } - - // .na = Name, attribute - // .nv = Variable, - // .vc = Variable, class - // .vg = Variable, global - // .vi = Variable, instance - :is(.na, .nv, .vc, .vg, .vi) { - color: var(--md-code-hl-variable-color); - } - - // .ge = Generic, emph - // .gr = Generic, error - // .gh = Generic, heading - // .go = Generic, output - // .gp = Generic, prompt - // .gs = Generic, strong - // .gu = Generic, subheading - // .gt = Generic, traceback - :is(.ge, .gr, .gh, .go, .gp, .gs, .gu, .gt) { - color: var(--md-code-hl-generic-color); - } - - // .gd = Diff, delete - // .gi = Diff, insert - :is(.gd, .gi) { - padding: 0 px2em(2px); - margin: 0 px2em(-2px); - border-radius: px2rem(2px); - } - - .gd { // Diff, delete - background-color: var(--md-typeset-del-color); - } - - .gi { // Diff, insert - background-color: var(--md-typeset-ins-color); - } - - // Highlighted line - .hll { - display: block; - padding: 0 px2em(16px, 13.6px); - margin: 0 px2em(-16px, 13.6px); - background-color: var(--md-code-hl-color--light); - box-shadow: 2px 0 0 0 var(--md-code-hl-color) inset; - } - - // Code block title - span.filename { - position: relative; - display: flow-root; - padding: px2em(9px, 13.6px) px2em(16px, 13.6px); - margin-top: 1em; - font-size: px2em(13.6px); - font-weight: 700; - background-color: var(--md-code-bg-color); - border-bottom: px2rem(1px) solid var(--md-default-fg-color--lightest); - border-top-left-radius: px2rem(2px); - border-top-right-radius: px2rem(2px); - - // Adjust spacing for code block - + pre { - margin-top: 0; - - // Remove rounded border on top side - > code { - border-top-left-radius: 0; - border-top-right-radius: 0; - } - } - } - - // Code block line numbers (pymdownx-inline) - [data-linenos]::before { - position: sticky; - left: px2em(-16px, 13.6px); - // A `z-index` of 3 is necessary for ensuring that code block annotations - // don't overlay line numbers, as active annotations have a `z-index` of 2. - z-index: 3; - float: left; - padding-left: px2em(16px, 13.6px); - margin-right: px2em(16px, 13.6px); - margin-left: px2em(-16px, 13.6px); - color: var(--md-default-fg-color--light); - content: attr(data-linenos); - user-select: none; - background-color: var(--md-code-bg-color); - box-shadow: px2rem(-1px) 0 var(--md-default-fg-color--lightest) inset; - } - - // Code block line anchors - Chrome and Safari seem to have a strange bug - // where scroll margin is not applied to anchors inside code blocks. Setting - // positioning to absolute seems to fix the problem. Interestingly, this does - // not happen in Firefox. Furthermore we must set `visibility: hidden` or - // the copy to clipboard functionality will include an empty line between - // each set of lines. - code a[id] { - position: absolute; - visibility: hidden; - } - - // Copying in progress - this class is set before the content is copied and - // removed after copying is done to mitigate whitespace-related issues. - code[data-md-copying] { - - // Temporarily remove highlighted lines - see https://bit.ly/32iVGWh - .hll { - display: contents; - } - - // Temporarily remove annotations - .md-annotation { - display: none; - } - } -} - -// ---------------------------------------------------------------------------- -// Rules: layout -// ---------------------------------------------------------------------------- - -// Code block with line numbers -.highlighttable { - display: flow-root; - - // Set table elements to block layout, because otherwise the whole flexbox - // hacking won't work correctly - :is(tbody, td) { - display: block; - padding: 0; - } - - // We need to use flexbox layout, because otherwise it's not possible to - // make the code container scroll while keeping the line numbers static - tr { - display: flex; - } - - // The pre tags are nested inside a table, so we need to omit the margin - // because it collapses below all the overflows - pre { - margin: 0; - } - - // Code block title container - th.filename { - flex-grow: 1; - padding: 0; - text-align: left; - - // Adjust spacing - span.filename { - margin-top: 0; - } - } - - // Code block line numbers - disable user selection, so code can be easily - // copied without accidentally also copying the line numbers - .linenos { - padding: px2em(10.5px, 13.6px) px2em(16px, 13.6px); - padding-right: 0; - font-size: px2em(13.6px); - user-select: none; - background-color: var(--md-code-bg-color); - border-top-left-radius: px2rem(2px); - border-bottom-left-radius: px2rem(2px); - } - - // Code block line numbers container - .linenodiv { - padding-right: px2em(8px, 13.6px); - box-shadow: px2rem(-1px) 0 var(--md-default-fg-color--lightest) inset; - - // Adjust colors and alignment - pre { - color: var(--md-default-fg-color--light); - text-align: right; - } - } - - // Code block container - stretch to remaining space - .code { - flex: 1; - min-width: 0; - } -} - -// Code block line numbers container -.linenodiv a { - color: inherit; -} - -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Code block with line numbers - unfortunately, these selectors need to be - // overly specific so they don't bleed into code blocks in annotations. - .highlighttable { - margin: 1em 0; - direction: ltr; - - // Remove rounded borders on code blocks - > tbody > tr > .code > div > pre > code { - border-top-left-radius: 0; - border-bottom-left-radius: 0; - } - } - - // Code block result container - .highlight + .result { - padding: 0 px2em(16px); - margin-top: calc(-1em + #{px2em(-2px)}); - overflow: visible; - border: px2rem(1px) solid var(--md-code-bg-color); - border-top-width: px2rem(2px); - border-bottom-right-radius: px2rem(2px); - border-bottom-left-radius: px2rem(2px); - - // Clearfix, because we can't use overflow: auto - &::after { - display: block; - clear: both; - content: ""; - } - } -} - -// ---------------------------------------------------------------------------- -// Rules: top-level -// ---------------------------------------------------------------------------- - -// [mobile -]: Align with body copy -@include break-to-device(mobile) { - - // Top-level code block - .md-content__inner > .highlight { - margin: 1em px2rem(-16px); - - // Remove rounded borders - > .filename, - > pre > code { - border-radius: 0; - } - - // Code block with line numbers - unfortunately, these selectors need to be - // overly specific so they don't bleed into code blocks in annotations. - > .highlighttable > tbody > tr > .filename span.filename, - > .highlighttable > tbody > tr > .linenos, - > .highlighttable > tbody > tr > .code > div > pre > code { - border-radius: 0; - } - - // Code block result container - + .result { - margin-inline: px2rem(-16px); - border-inline-width: 0; - border-radius: 0; - } - } -} diff --git a/src/templates/assets/stylesheets/main/extensions/pymdownx/_keys.scss b/src/templates/assets/stylesheets/main/extensions/pymdownx/_keys.scss deleted file mode 100644 index 8749f08c..00000000 --- a/src/templates/assets/stylesheets/main/extensions/pymdownx/_keys.scss +++ /dev/null @@ -1,115 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Keyboard key - .keys { - - // Keyboard key icon - kbd:is(::before, ::after) { - position: relative; - margin: 0; - color: inherit; - -moz-osx-font-smoothing: initial; - -webkit-font-smoothing: initial; - } - - // Surrounding text - span { - padding: 0 px2em(3.2px); - color: var(--md-default-fg-color--light); - } - - // Define keyboard keys with left icon - @each $name, $code in ( - - // Modifiers - "alt": "\2387", - "left-alt": "\2387", - "right-alt": "\2387", - "command": "\2318", - "left-command": "\2318", - "right-command": "\2318", - "control": "\2303", - "left-control": "\2303", - "right-control": "\2303", - "meta": "\25C6", - "left-meta": "\25C6", - "right-meta": "\25C6", - "option": "\2325", - "left-option": "\2325", - "right-option": "\2325", - "shift": "\21E7", - "left-shift": "\21E7", - "right-shift": "\21E7", - "super": "\2756", - "left-super": "\2756", - "right-super": "\2756", - "windows": "\229E", - "left-windows": "\229E", - "right-windows": "\229E", - - // Other keys - "arrow-down": "\2193", - "arrow-left": "\2190", - "arrow-right": "\2192", - "arrow-up": "\2191", - "backspace": "\232B", - "backtab": "\21E4", - "caps-lock": "\21EA", - "clear": "\2327", - "context-menu": "\2630", - "delete": "\2326", - "eject": "\23CF", - "end": "\2913", - "escape": "\238B", - "home": "\2912", - "insert": "\2380", - "page-down": "\21DF", - "page-up": "\21DE", - "print-screen": "\2399" - ) { - .key-#{$name}::before { - padding-right: px2em(6.4px); - content: $code; - } - } - - // Define keyboard keys with right icon - @each $name, $code in ( - "tab": "\21E5", - "num-enter": "\2324", - "enter": "\23CE" - ) { - .key-#{$name}::after { - padding-left: px2em(6.4px); - content: $code; - } - } - } -} diff --git a/src/templates/assets/stylesheets/main/extensions/pymdownx/_tabbed.scss b/src/templates/assets/stylesheets/main/extensions/pymdownx/_tabbed.scss deleted file mode 100644 index 9df91bfc..00000000 --- a/src/templates/assets/stylesheets/main/extensions/pymdownx/_tabbed.scss +++ /dev/null @@ -1,400 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Tabbed variables -:root { - --md-tabbed-icon--prev: svg-load("material/chevron-left.svg"); - --md-tabbed-icon--next: svg-load("material/chevron-right.svg"); -} - -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Tabbed container - .tabbed-set { - position: relative; - display: flex; - flex-flow: column wrap; - margin: 1em 0; - border-radius: px2rem(2px); - - // Tab radio button - the Tabbed extension will generate radio buttons with - // labels, so tabs can be triggered without the necessity for JavaScript. - // This is pretty cool, as it has great accessibility out-of-the box, so - // we just hide the radio button and toggle the label color for indication. - > input { - position: absolute; - width: 0; - height: 0; - opacity: 0; - - // Adjust scroll margin - &:target { - --md-scroll-offset: #{px2em(10px, 16px)}; - } - - // Tab label states - @for $i from 20 through 1 { - &:nth-child(#{$i}) { - - // Tab is active - &:checked { - - // Tab label - ~ .tabbed-labels > :nth-child(#{$i}) { - @extend %tabbed-label; - } - - // Tab content - ~ .tabbed-content > :nth-child(#{$i}) { - @extend %tabbed-content; - } - } - - // Tab label on keyboard focus - &.focus-visible ~ .tabbed-labels > :nth-child(#{$i}) { - @extend %tabbed-label-focus-visible; - } - } - } - - // Tab indicator on keyboard focus - &.focus-visible ~ .tabbed-labels::before { - background-color: var(--md-accent-fg-color); - } - } - } - - // Tabbed labels - .tabbed-labels { - display: flex; - max-width: 100%; - overflow: auto; - box-shadow: 0 px2rem(-1px) var(--md-default-fg-color--lightest) inset; - -ms-overflow-style: none; // IE, Edge - scrollbar-width: none; // Firefox - - // [print]: Move one layer up for ordering - @media print { - display: contents; - } - - // [screen and no reduced motion]: Disable animation - @media screen { - - // [js]: Show animated tab indicator - .js & { - position: relative; - - // Tab indicator - &::before { - position: absolute; - bottom: 0; - left: 0; - display: block; - width: var(--md-indicator-width); - height: 2px; - content: ""; - background: var(--md-default-fg-color); - transition: - width 225ms, - background-color 250ms, - transform 250ms; - transition-timing-function: cubic-bezier(0.4, 0, 0.2, 1); - transform: translateX(var(--md-indicator-x)); - } - } - } - - // Webkit scrollbar - &::-webkit-scrollbar { - display: none; // Chrome, Safari - } - - // Tab label - > label { - flex-shrink: 0; - width: auto; - padding: px2em(10px, 12.8px) 1.25em px2em(8px, 12.8px); - font-size: px2rem(12.8px); - font-weight: 700; - color: var(--md-default-fg-color--light); - white-space: nowrap; - cursor: pointer; - border-bottom: px2rem(2px) solid transparent; - border-radius: px2rem(2px) px2rem(2px) 0 0; - transition: - background-color 250ms, - color 250ms; - scroll-margin-inline-start: px2rem(20px); - - // [print]: Intersperse labels with containers - @media print { - - // Ensure correct order of labels - @for $i from 1 through 20 { - &:nth-child(#{$i}) { - order: $i; - } - } - } - - // Tab label on hover - &:hover { - color: var(--md-default-fg-color); - } - } - } - - // Tabbed content - .tabbed-content { - width: 100%; - - // [print]: Move one layer up for ordering - @media print { - display: contents; - } - } - - // Tabbed block - .tabbed-block { - display: none; - - // [print]: Intersperse labels with containers - @media print { - display: block; - - // Ensure correct order of containers - @for $i from 1 through 20 { - &:nth-child(#{$i}) { - order: $i; - } - } - } - - // Code block is the first child of a tab - remove margin and mirror - // previous (now deprecated) SuperFences code block grouping behavior - > pre:first-child, - > .highlight:first-child > pre { - margin: 0; - - // Remove rounded borders on code block - > code { - border-top-left-radius: 0; - border-top-right-radius: 0; - } - } - - // Code block is the first child of a tab - remove margin and mirror - // previous (now deprecated) SuperFences code block grouping behavior - > .highlight:first-child { - - // Code block title - remove spacing and rounded borders - > .filename { - margin: 0; - border-top-left-radius: 0; - border-top-right-radius: 0; - } - - // Code block with line numbers - unfortunately, these selectors need to - // be overly specific so they don't bleed into code blocks in annotations. - > .highlighttable { - margin: 0; - - // Remove rounded borders on line numbers and titles - > tbody > tr > .filename span.filename, - > tbody > tr > .linenos { - margin: 0; - border-top-left-radius: 0; - border-top-right-radius: 0; - } - - // Remove rounded borders on code blocks - > tbody > tr > .code > div > pre > code { - border-top-left-radius: 0; - border-top-right-radius: 0; - } - } - - // Code block result container - adjust spacing - + .result { - margin-top: px2em(-2px); - } - } - - // Adjust spacing for nested tabbed container - > .tabbed-set { - margin: 0; - } - } - - // Tabbed button - .tabbed-button { - display: block; - align-self: center; - width: px2rem(18px); - height: px2rem(18px); - margin-top: px2rem(2px); - color: var(--md-default-fg-color--light); - pointer-events: initial; - cursor: pointer; - border-radius: 100%; - transition: background-color 250ms; - - // Tabbed button on hover - &:hover { - color: var(--md-accent-fg-color); - background-color: var(--md-accent-fg-color--transparent); - } - - // Tabbed button icon - &::after { - display: block; - width: 100%; - height: 100%; - content: ""; - background-color: currentcolor; - transition: - background-color 250ms, - transform 250ms; - mask-image: var(--md-tabbed-icon--prev); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - } - } - - // Tabbed control - .tabbed-control { - position: absolute; - display: flex; - justify-content: start; - width: px2rem(24px); - height: px2rem(38px); - pointer-events: none; - background: - linear-gradient( - to right, - var(--md-default-bg-color) 60%, - transparent - ); - transition: opacity 125ms; - - // Adjust for right-to-left languages - [dir="rtl"] & { - transform: rotate(180deg); - } - - // Tabbed control is hidden - &[hidden] { - opacity: 0; - } - - // Tabbed control next - &--next { - right: 0; - justify-content: end; - background: - linear-gradient( - to left, - var(--md-default-bg-color) 60%, - transparent - ); - - // Tabbed button icon content - .tabbed-button::after { - mask-image: var(--md-tabbed-icon--next); - } - } - } -} - -// ---------------------------------------------------------------------------- -// Rules: top-level -// ---------------------------------------------------------------------------- - -// [mobile -]: Align with body copy -@include break-to-device(mobile) { - - // Top-level tabbed labels - .md-content__inner > .tabbed-set .tabbed-labels { - max-width: 100vw; - padding-inline-start: px2rem(16px); - margin: 0 px2rem(-16px); - scroll-padding-inline-start: px2rem(16px); - - // Hack: some browsers ignore the right padding on flex containers, - // see https://bit.ly/3lsPS3S - &::after { - padding-inline-end: px2rem(16px); - content: ""; - } - - // Tabbed control previous - ~ .tabbed-control--prev { - width: px2rem(40px); - padding-inline-start: px2rem(16px); - margin-inline-start: px2rem(-16px); - } - - // Tabbed control next - ~ .tabbed-control--next { - width: px2rem(40px); - padding-inline-end: px2rem(16px); - margin-inline-end: px2rem(-16px); - } - } -} - -// ---------------------------------------------------------------------------- -// Placeholders: improve colocation for better compression -// ---------------------------------------------------------------------------- - -// Tab label placeholder -%tabbed-label { - - // [screen]: Show active state - @media screen { - color: var(--md-default-fg-color); - - // [no-js]: Show border (indicator is animated with JavaScript) - .no-js & { - border-color: var(--md-default-fg-color); - } - } -} - -// Tab label on keyboard focus placeholder -%tabbed-label-focus-visible { - color: var(--md-accent-fg-color); -} - -// Tab content placeholder -%tabbed-content { - display: block; -} diff --git a/src/templates/assets/stylesheets/main/extensions/pymdownx/_tasklist.scss b/src/templates/assets/stylesheets/main/extensions/pymdownx/_tasklist.scss deleted file mode 100644 index a1d1117c..00000000 --- a/src/templates/assets/stylesheets/main/extensions/pymdownx/_tasklist.scss +++ /dev/null @@ -1,78 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Tasklist variables -:root { - --md-tasklist-icon: svg-load("octicons/check-circle-fill-24.svg"); - --md-tasklist-icon--checked: svg-load("octicons/check-circle-fill-24.svg"); -} - -// ---------------------------------------------------------------------------- - -// Scoped in typesetted content to match specificity of regular content -.md-typeset { - - // Tasklist item - .task-list-item { - position: relative; - list-style-type: none; - - // Make checkbox items align with normal list items, but position - // everything in ems for correct layout at smaller font sizes - [type="checkbox"] { - position: absolute; - top: 0.45em; - inset-inline-start: -2em; - } - } - - // Hide native checkbox, when custom classes are enabled - .task-list-control [type="checkbox"] { - z-index: -1; - opacity: 0; - } - - // Tasklist indicator in unchecked state - .task-list-indicator::before { - position: absolute; - top: 0.15em; - width: px2em(20px); - height: px2em(20px); - content: ""; - background-color: var(--md-default-fg-color--lightest); - inset-inline-start: px2em(-24px); - mask-image: var(--md-tasklist-icon); - mask-position: center; - mask-repeat: no-repeat; - mask-size: contain; - } - - // Tasklist indicator in checked state - [type="checkbox"]:checked + .task-list-indicator::before { - background-color: $clr-green-a400; - mask-image: var(--md-tasklist-icon--checked); - } -} diff --git a/src/templates/assets/stylesheets/main/integrations/_mermaid.scss b/src/templates/assets/stylesheets/main/integrations/_mermaid.scss deleted file mode 100644 index d0325f39..00000000 --- a/src/templates/assets/stylesheets/main/integrations/_mermaid.scss +++ /dev/null @@ -1,67 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Mermaid variables -:root > * { - --md-mermaid-font-family: var(--md-text-font-family), sans-serif; - - // General colors - --md-mermaid-edge-color: var(--md-code-fg-color); - --md-mermaid-node-bg-color: var(--md-accent-fg-color--transparent); - --md-mermaid-node-fg-color: var(--md-accent-fg-color); - --md-mermaid-label-bg-color: var(--md-default-bg-color); - --md-mermaid-label-fg-color: var(--md-code-fg-color); - - // Sequence diagram colors - --md-mermaid-sequence-actor-bg-color: var(--md-mermaid-label-bg-color); - --md-mermaid-sequence-actor-fg-color: var(--md-mermaid-label-fg-color); - --md-mermaid-sequence-actor-border-color: var(--md-mermaid-node-fg-color); - --md-mermaid-sequence-actor-line-color: var(--md-default-fg-color--lighter); - --md-mermaid-sequence-actorman-bg-color: var(--md-mermaid-label-bg-color); - --md-mermaid-sequence-actorman-line-color: var(--md-mermaid-node-fg-color); - --md-mermaid-sequence-box-bg-color: var(--md-mermaid-node-bg-color); - --md-mermaid-sequence-box-fg-color: var(--md-mermaid-edge-color); - --md-mermaid-sequence-label-bg-color: var(--md-mermaid-node-bg-color); - --md-mermaid-sequence-label-fg-color: var(--md-mermaid-node-fg-color); - --md-mermaid-sequence-loop-bg-color: var(--md-mermaid-node-bg-color); - --md-mermaid-sequence-loop-fg-color: var(--md-mermaid-edge-color); - --md-mermaid-sequence-loop-border-color: var(--md-mermaid-node-fg-color); - --md-mermaid-sequence-message-fg-color: var(--md-mermaid-edge-color); - --md-mermaid-sequence-message-line-color: var(--md-mermaid-edge-color); - --md-mermaid-sequence-note-bg-color: var(--md-mermaid-label-bg-color); - --md-mermaid-sequence-note-fg-color: var(--md-mermaid-edge-color); - --md-mermaid-sequence-note-border-color: var(--md-mermaid-label-fg-color); - --md-mermaid-sequence-number-bg-color: var(--md-mermaid-node-fg-color); - --md-mermaid-sequence-number-fg-color: var(--md-accent-bg-color); -} - -// ---------------------------------------------------------------------------- - -// Mermaid container -.mermaid { - margin: 1em 0; - line-height: normal; -} diff --git a/src/templates/assets/stylesheets/palette.scss b/src/templates/assets/stylesheets/palette.scss deleted file mode 100644 index ff73a982..00000000 --- a/src/templates/assets/stylesheets/palette.scss +++ /dev/null @@ -1,40 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Dependencies -// ---------------------------------------------------------------------------- - -@import "material-color"; - -// ---------------------------------------------------------------------------- -// Local imports -// ---------------------------------------------------------------------------- - -@import "utilities/break"; -@import "utilities/convert"; - -@import "config"; - -@import "palette/scheme"; -@import "palette/accent"; -@import "palette/primary"; diff --git a/src/templates/assets/stylesheets/palette/_accent.scss b/src/templates/assets/stylesheets/palette/_accent.scss deleted file mode 100644 index 9f69b596..00000000 --- a/src/templates/assets/stylesheets/palette/_accent.scss +++ /dev/null @@ -1,61 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Define accent colors -@each $name, $color in ( - "red": $clr-red-a400, - "pink": $clr-pink-a400, - "purple": $clr-purple-a200, - "deep-purple": $clr-deep-purple-a200, - "indigo": $clr-indigo-a200, - "blue": $clr-blue-a200, - "light-blue": $clr-light-blue-a700, - "cyan": $clr-cyan-a700, - "teal": $clr-teal-a700, - "green": $clr-green-a700, - "light-green": $clr-light-green-a700, - "lime": $clr-lime-a700, - "yellow": $clr-yellow-a700, - "amber": $clr-amber-a700, - "orange": $clr-orange-a400, - "deep-orange": $clr-deep-orange-a200 -) { - - // Color palette - [data-md-color-accent="#{$name}"] { - --md-accent-fg-color: hsla(#{hex2hsl($color)}, 1); - --md-accent-fg-color--transparent: hsla(#{hex2hsl($color)}, 0.1); - - // Inverted text for lighter shades - @if index("lime" "yellow" "amber" "orange", $name) { - --md-accent-bg-color: hsla(0, 0%, 0%, 0.87); - --md-accent-bg-color--light: hsla(0, 0%, 0%, 0.54); - } @else { - --md-accent-bg-color: hsla(0, 0%, 100%, 1); - --md-accent-bg-color--light: hsla(0, 0%, 100%, 0.7); - } - } -} diff --git a/src/templates/assets/stylesheets/palette/_primary.scss b/src/templates/assets/stylesheets/palette/_primary.scss deleted file mode 100644 index a8653f0f..00000000 --- a/src/templates/assets/stylesheets/palette/_primary.scss +++ /dev/null @@ -1,203 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -@use "sass:list"; - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Define primary colors -@each $name, $colors in ( - "red": $clr-red-400 $clr-red-300 $clr-red-600, - "pink": $clr-pink-500 $clr-pink-400 $clr-pink-700, - "purple": $clr-purple-400 $clr-purple-300 $clr-purple-600, - "deep-purple": $clr-deep-purple-400 $clr-deep-purple-300 $clr-deep-purple-500, - "indigo": $clr-indigo-500 $clr-indigo-400 $clr-indigo-700, - "blue": $clr-blue-500 $clr-blue-400 $clr-blue-700, - "light-blue": $clr-light-blue-500 $clr-light-blue-400 $clr-light-blue-700, - "cyan": $clr-cyan-500 $clr-cyan-400 $clr-cyan-700, - "teal": $clr-teal-500 $clr-teal-400 $clr-teal-700, - "green": $clr-green-500 $clr-green-400 $clr-green-700, - "light-green": $clr-light-green-500 $clr-light-green-400 $clr-light-green-700, - "lime": $clr-lime-500 $clr-lime-400 $clr-lime-700, - "yellow": $clr-yellow-500 $clr-yellow-400 $clr-yellow-700, - "amber": $clr-amber-500 $clr-amber-400 $clr-amber-700, - "orange": $clr-orange-400 $clr-orange-400 $clr-orange-600, - "deep-orange": $clr-deep-orange-400 $clr-deep-orange-300 $clr-deep-orange-600, - "brown": $clr-brown-500 $clr-brown-400 $clr-brown-700, - "grey": $clr-grey-600 $clr-grey-500 $clr-grey-700, - "blue-grey": $clr-blue-grey-600 $clr-blue-grey-500 $clr-blue-grey-700 -) { - - // Color palette - [data-md-color-primary="#{$name}"] { - --md-primary-fg-color: hsl(#{hex2hsl(list.nth($colors, 1))}); - --md-primary-fg-color--light: hsl(#{hex2hsl(list.nth($colors, 2))}); - --md-primary-fg-color--dark: hsl(#{hex2hsl(list.nth($colors, 3))}); - - // Inverted text for lighter shades - @if index("lime" "yellow" "amber" "orange", $name) { - --md-primary-bg-color: hsla(0, 0%, 0%, 0.87); - --md-primary-bg-color--light: hsla(0, 0%, 0%, 0.54); - } @else { - --md-primary-bg-color: hsla(0, 0%, 100%, 1); - --md-primary-bg-color--light: hsla(0, 0%, 100%, 0.7); - } - - // Typeset color shades - @if index("grey" "blue-grey", $name) { - --md-typeset-a-color: hsl(#{hex2hsl($clr-indigo-500)}); - } - } -} - -// ---------------------------------------------------------------------------- - -// Adjust link colors for light primary colors -@each $name, $color in ( - "light-green": hsl(88, 58%, 43%), - "lime": hsl(66, 88%, 32%), - "yellow": hsl(54, 100%, 36%), - "amber": hsl(45, 100%, 41%), - "orange": hsl(36, 100%, 45%) -) { - [data-md-color-primary="#{$name}"]:not([data-md-color-scheme="slate"]) { - --md-typeset-a-color: #{$color}; - } -} - -// ---------------------------------------------------------------------------- -// Rules: white -// ---------------------------------------------------------------------------- - -// Define primary colors for white -[data-md-color-primary="white"] { - --md-primary-fg-color: hsla(var(--md-hue), 0%, 100%, 1); - --md-primary-fg-color--light: hsla(var(--md-hue), 0%, 100%, 0.7); - --md-primary-fg-color--dark: hsla(var(--md-hue), 0%, 0%, 0.07); - --md-primary-bg-color: hsla(var(--md-hue), 0%, 0%, 0.87); - --md-primary-bg-color--light: hsla(var(--md-hue), 0%, 0%, 0.54); - - // Typeset `a` color shades - --md-typeset-a-color: hsl(#{hex2hsl($clr-indigo-500)}); - - // Form button - .md-button { - color: var(--md-typeset-a-color); - - // Primary button - &--primary { - color: hsla(var(--md-hue), 0%, 100%, 1); - background-color: var(--md-typeset-a-color); - border-color: var(--md-typeset-a-color); - } - } - - // [tablet portrait +]: Header-embedded search - @include break-from-device(tablet landscape) { - - // Search form - .md-search__form { - background-color: hsla(var(--md-hue), 0%, 0%, 0.07); - - // Search form on hover - &:hover { - background-color: hsla(var(--md-hue), 0%, 0%, 0.32); - } - } - - // Search icon - .md-search__input + .md-search__icon { - color: hsla(var(--md-hue), 0%, 0%, 0.87); - } - } - - // [screen +]: Add bottom border for tabs - @include break-from-device(screen) { - - // Navigation tabs - .md-tabs { - border-bottom: px2rem(1px) solid hsla(0, 0%, 0%, 0.07); - } - } -} - -// ---------------------------------------------------------------------------- -// Rules: black -// ---------------------------------------------------------------------------- - -// Define primary colors for black -[data-md-color-primary="black"] { - --md-primary-fg-color: hsla(var(--md-hue), 15%, 9%, 1); - --md-primary-fg-color--light: hsla(var(--md-hue), 15%, 9%, 0.54); - --md-primary-fg-color--dark: hsla(var(--md-hue), 15%, 9%, 1); - --md-primary-bg-color: hsla(var(--md-hue), 15%, 100%, 1); - --md-primary-bg-color--light: hsla(var(--md-hue), 15%, 100%, 0.7); - - // Typeset `a` color shades - --md-typeset-a-color: hsl(#{hex2hsl($clr-indigo-500)}); - - // Form button - .md-button { - color: var(--md-typeset-a-color); - - // Primary button - &--primary { - color: hsla(var(--md-hue), 0%, 100%, 1); - background-color: var(--md-typeset-a-color); - border-color: var(--md-typeset-a-color); - } - } - - // Header - .md-header { - background-color: hsla(var(--md-hue), 15%, 9%, 1); - } - - // [tablet portrait -]: Layered navigation - @include break-to-device(tablet portrait) { - - // Repository information container - .md-nav__source { - background-color: hsla(var(--md-hue), 15%, 11%, 0.87); - } - } - - // [tablet -]: Layered navigation - @include break-to-device(tablet) { - - // Site title in main navigation - html & .md-nav--primary .md-nav__title[for="__drawer"] { - background-color: hsla(var(--md-hue), 15%, 9%, 1); - } - } - - // [screen +]: Set background color for tabs - @include break-from-device(screen) { - - // Navigation tabs - .md-tabs { - background-color: hsla(var(--md-hue), 15%, 9%, 1); - } - } -} diff --git a/src/templates/assets/stylesheets/palette/_scheme.scss b/src/templates/assets/stylesheets/palette/_scheme.scss deleted file mode 100644 index 0a9f9823..00000000 --- a/src/templates/assets/stylesheets/palette/_scheme.scss +++ /dev/null @@ -1,145 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -// ---------------------------------------------------------------------------- -// Rules -// ---------------------------------------------------------------------------- - -// Only use dark mode on screens -@media screen { - - // Slate theme, i.e. dark mode - [data-md-color-scheme="slate"] { - - // Indicate that the site is rendered with a dark color scheme - color-scheme: dark; - - // Default color shades - --md-default-fg-color: hsla(var(--md-hue), 15%, 90%, 0.82); - --md-default-fg-color--light: hsla(var(--md-hue), 15%, 90%, 0.56); - --md-default-fg-color--lighter: hsla(var(--md-hue), 15%, 90%, 0.32); - --md-default-fg-color--lightest: hsla(var(--md-hue), 15%, 90%, 0.12); - --md-default-bg-color: hsla(var(--md-hue), 15%, 14%, 1); - --md-default-bg-color--light: hsla(var(--md-hue), 15%, 14%, 0.54); - --md-default-bg-color--lighter: hsla(var(--md-hue), 15%, 14%, 0.26); - --md-default-bg-color--lightest: hsla(var(--md-hue), 15%, 14%, 0.07); - - // Code color shades - --md-code-fg-color: hsla(var(--md-hue), 18%, 86%, 0.82); - --md-code-bg-color: hsla(var(--md-hue), 15%, 18%, 1); - - // Code highlighting color shades - --md-code-hl-color--light: hsla(#{hex2hsl($clr-blue-a200)}, 0.15); - --md-code-hl-number-color: hsla(6, 74%, 63%, 1); - --md-code-hl-special-color: hsla(340, 83%, 66%, 1); - --md-code-hl-function-color: hsla(291, 57%, 65%, 1); - --md-code-hl-constant-color: hsla(250, 62%, 70%, 1); - --md-code-hl-keyword-color: hsla(219, 66%, 64%, 1); - --md-code-hl-string-color: hsla(150, 58%, 44%, 1); - --md-code-hl-name-color: var(--md-code-fg-color); - --md-code-hl-operator-color: var(--md-default-fg-color--light); - --md-code-hl-punctuation-color: var(--md-default-fg-color--light); - --md-code-hl-comment-color: var(--md-default-fg-color--light); - --md-code-hl-generic-color: var(--md-default-fg-color--light); - --md-code-hl-variable-color: var(--md-default-fg-color--light); - - // Typeset color shades - --md-typeset-color: var(--md-default-fg-color); - - // Typeset `a` color shades - --md-typeset-a-color: var(--md-primary-fg-color); - - // Typeset `kbd` color shades - --md-typeset-kbd-color: hsla(var(--md-hue), 15%, 90%, 0.12); - --md-typeset-kbd-accent-color: hsla(var(--md-hue), 15%, 90%, 0.2); - --md-typeset-kbd-border-color: hsla(var(--md-hue), 15%, 14%, 1); - - // Typeset `mark` color shades - --md-typeset-mark-color: hsla(#{hex2hsl($clr-blue-a200)}, 0.3); - - // Typeset `table` color shades - --md-typeset-table-color: hsla(var(--md-hue), 15%, 95%, 0.12); - --md-typeset-table-color--light: hsla(var(--md-hue), 15%, 95%, 0.035); - - // Admonition color shades - --md-admonition-fg-color: var(--md-default-fg-color); - --md-admonition-bg-color: var(--md-default-bg-color); - - // Footer color shades - --md-footer-bg-color: hsla(var(--md-hue), 15%, 10%, 0.87); - --md-footer-bg-color--dark: hsla(var(--md-hue), 15%, 8%, 1); - - // Shadow depth 1 - --md-shadow-z1: - 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.05), - 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.1); - - // Shadow depth 2 - --md-shadow-z2: - 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.25), - 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.25); - - // Shadow depth 3 - --md-shadow-z3: - 0 #{px2rem(4px)} #{px2rem(10px)} hsla(0, 0%, 0%, 0.4), - 0 0 #{px2rem(1px)} hsla(0, 0%, 0%, 0.35); - - // Hide images for light mode - img[src$="#only-light"], - img[src$="#gh-light-mode-only"] { - display: none; - } - } - - // -------------------------------------------------------------------------- - - // Adjust link colors for dark primary colors - @each $name, $color in ( - "pink": hsl(340, 81%, 63%), - "purple": hsl(291, 53%, 63%), - "deep-purple": hsl(262, 73%, 70%), - "indigo": hsl(219, 76%, 62%), - "teal": hsl(174, 100%, 40%), - "green": hsl(122, 39%, 60%), - "deep-orange": hsl(14, 100%, 65%), - "brown": hsl(16, 45%, 56%), - - // Set neutral colors to indigo - "grey": hsl(219, 66%, 62%), - "blue-grey": hsl(219, 66%, 62%), - "white": hsl(219, 66%, 62%), - "black": hsl(219, 66%, 62%) - ) { - [data-md-color-scheme="slate"][data-md-color-primary="#{$name}"] { - --md-typeset-a-color: #{$color}; - } - } - - // -------------------------------------------------------------------------- - - // Switching in progress - disable all transitions temporarily - [data-md-color-switching] *, - [data-md-color-switching] *::before, - [data-md-color-switching] *::after { - transition-duration: 0ms !important; // stylelint-disable-line - } -} diff --git a/src/templates/assets/stylesheets/utilities/_break.scss b/src/templates/assets/stylesheets/utilities/_break.scss deleted file mode 100644 index 7ccd8622..00000000 --- a/src/templates/assets/stylesheets/utilities/_break.scss +++ /dev/null @@ -1,219 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -@use "sass:list"; -@use "sass:map"; -@use "sass:math"; - -// ---------------------------------------------------------------------------- -// Variables -// ---------------------------------------------------------------------------- - -/// -/// Device-specific breakpoints -/// -/// @example -/// $break-devices: ( -/// mobile: ( -/// portrait: 220px 479px, -/// landscape: 480px 719px -/// ), -/// tablet: ( -/// portrait: 720px 959px, -/// landscape: 960px 1219px -/// ), -/// screen: ( -/// small: 1220px 1599px, -/// medium: 1600px 1999px, -/// large: 2000px -/// ) -/// ); -/// -$break-devices: () !default; - -// ---------------------------------------------------------------------------- -// Helpers -// ---------------------------------------------------------------------------- - -/// -/// Choose minimum and maximum device widths -/// -@function break-select-min-max($devices) { - $min: 1000000; - $max: 0; - @each $key, $value in $devices { - @while type-of($value) == map { - $value: break-select-min-max($value); - } - @if type-of($value) == list { - @each $number in $value { - @if type-of($number) == number { - $min: math.min($number, $min); - @if $max { - $max: math.max($number, $max); - } - } @else { - @error "Invalid number: #{$number}"; - } - } - } @else if type-of($value) == number { - $min: math.min($value, $min); - $max: null; - } @else { - @error "Invalid value: #{$value}"; - } - } - @return $min, $max; -} - -/// -/// Select minimum and maximum widths for a device breakpoint -/// -@function break-select-device($device) { - $current: $break-devices; - @for $n from 1 through length($device) { - @if type-of($current) == map { - $current: map.get($current, list.nth($device, $n)); - } @else { - @error "Invalid device map: #{$devices}"; - } - } - @if type-of($current) == list or type-of($current) == number { - $current: (default: $current); - } - @return break-select-min-max($current); -} - -// ---------------------------------------------------------------------------- -// Mixins -// ---------------------------------------------------------------------------- - -/// -/// A minimum-maximum media query breakpoint -/// -@mixin break-at($breakpoint) { - @if type-of($breakpoint) == number { - @media screen and (min-width: $breakpoint) { - @content; - } - } @else if type-of($breakpoint) == list { - $min: list.nth($breakpoint, 1); - $max: list.nth($breakpoint, 2); - @if type-of($min) == number and type-of($max) == number { - @media screen and (min-width: $min) and (max-width: $max) { - @content; - } - } @else { - @error "Invalid breakpoint: #{$breakpoint}"; - } - } @else { - @error "Invalid breakpoint: #{$breakpoint}"; - } -} - -/// -/// An orientation media query breakpoint -/// -@mixin break-at-orientation($breakpoint) { - @if type-of($breakpoint) == string { - @media screen and (orientation: $breakpoint) { - @content; - } - } @else { - @error "Invalid breakpoint: #{$breakpoint}"; - } -} - -/// -/// A maximum-aspect-ratio media query breakpoint -/// -@mixin break-at-ratio($breakpoint) { - @if type-of($breakpoint) == number { - @media screen and (max-aspect-ratio: $breakpoint) { - @content; - } - } @else { - @error "Invalid breakpoint: #{$breakpoint}"; - } -} - -/// -/// A minimum-maximum media query device breakpoint -/// -@mixin break-at-device($device) { - @if type-of($device) == string { - $device: $device,; - } - @if type-of($device) == list { - $breakpoint: break-select-device($device); - @if list.nth($breakpoint, 2) { - $min: list.nth($breakpoint, 1); - $max: list.nth($breakpoint, 2); - - @media screen and (min-width: $min) and (max-width: $max) { - @content; - } - } @else { - @error "Invalid device: #{$device}"; - } - } @else { - @error "Invalid device: #{$device}"; - } -} - -/// -/// A minimum media query device breakpoint -/// -@mixin break-from-device($device) { - @if type-of($device) == string { - $device: $device,; - } - @if type-of($device) == list { - $breakpoint: break-select-device($device); - $min: list.nth($breakpoint, 1); - - @media screen and (min-width: $min) { - @content; - } - } @else { - @error "Invalid device: #{$device}"; - } -} - -/// -/// A maximum media query device breakpoint -/// -@mixin break-to-device($device) { - @if type-of($device) == string { - $device: $device,; - } - @if type-of($device) == list { - $breakpoint: break-select-device($device); - $max: list.nth($breakpoint, 2); - - @media screen and (max-width: $max) { - @content; - } - } @else { - @error "Invalid device: #{$device}"; - } -} diff --git a/src/templates/assets/stylesheets/utilities/_convert.scss b/src/templates/assets/stylesheets/utilities/_convert.scss deleted file mode 100644 index 8199c9c8..00000000 --- a/src/templates/assets/stylesheets/utilities/_convert.scss +++ /dev/null @@ -1,79 +0,0 @@ -//// -/// Copyright (c) 2016-2023 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 -//// - -@use "sass:math"; - -// ---------------------------------------------------------------------------- -// Helpers -// ---------------------------------------------------------------------------- - -/// -/// Strip units from a number -/// -@function strip-units($number) { - @return math.div($number, ($number * 0 + 1)); -} - -/// -/// Convert color in HEX to HSL -/// -/// Note, that we need to strip the `deg` units from the `hue` value, as they -/// were added in Color Level 4, which not all browsers support. -/// -@function hex2hsl($color) { - @return - round(strip-units(hue($color))), - round(saturation($color)), - round(lightness($color)); -} - -// ---------------------------------------------------------------------------- - -/// -/// Convert font size in px to em -/// -@function px2em($size, $base: 16px) { - @if unit($size) == px { - @if unit($base) == px { - @return math.div($size, $base) * 1em; - } @else { - @error "Invalid base: #{$base} - unit must be 'px'"; - } - } @else { - @error "Invalid size: #{$size} - unit must be 'px'"; - } -} - -/// -/// Convert font size in px to rem -/// -@function px2rem($size, $base: 20px) { - @if unit($size) == px { - @if unit($base) == px { - @return math.div($size, $base) * 1rem; - } @else { - @error "Invalid base: #{$base} - unit must be 'px'"; - } - } @else { - @error "Invalid size: #{$size} - unit must be 'px'"; - } -} diff --git a/src/templates/base.html b/src/templates/base.html deleted file mode 100644 index 8323e76e..00000000 --- a/src/templates/base.html +++ /dev/null @@ -1,445 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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 "partials/language.html" as lang with context %} - -<!doctype html> -<html lang="{{ lang.t('language') }}" class="no-js"> - <head> - - <!-- Meta tags --> - {% block site_meta %} - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width,initial-scale=1" /> - - <!-- Page description --> - {% if page.meta and page.meta.description %} - <meta name="description" content="{{ page.meta.description }}" /> - {% elif config.site_description %} - <meta name="description" content="{{ config.site_description }}" /> - {% endif %} - - <!-- Page author --> - {% if page.meta and page.meta.author %} - <meta name="author" content="{{ page.meta.author }}" /> - {% elif config.site_author %} - <meta name="author" content="{{ config.site_author }}" /> - {% endif %} - - <!-- Canonical --> - {% if page.canonical_url %} - <link rel="canonical" href="{{ page.canonical_url }}" /> - {% endif %} - - <!-- Previous page --> - {% if page.previous_page %} - <link rel="prev" href="{{ page.previous_page.url | url }}" /> - {% endif %} - - <!-- Next page --> - {% if page.next_page %} - <link rel="next" href="{{ page.next_page.url | url }}" /> - {% endif %} - - <!-- RSS feed --> - {% if "rss" in config.plugins %} - <link - rel="alternate" - type="application/rss+xml" - title="{{ lang.t('rss.created') }}" - href="{{ 'feed_rss_created.xml' | url }}" - /> - <link - rel="alternate" - type="application/rss+xml" - title="{{ lang.t('rss.updated') }}" - href="{{ 'feed_rss_updated.xml' | url }}" - /> - {% endif %} - - <!-- Favicon --> - <link rel="icon" href="{{ config.theme.favicon | url }}" /> - - <!-- Generator banner --> - <meta - name="generator" - content="mkdocs-{{ mkdocs_version }}, $md-name$-$md-version$" - /> - {% endblock %} - - <!-- Site title --> - {% block htmltitle %} - {% if page.meta and page.meta.title %} - <title>{{ page.meta.title }} - {{ config.site_name }}</title> - {% elif page.title and not page.is_homepage %} - <title>{{ page.title | striptags }} - {{ config.site_name }}</title> - {% else %} - <title>{{ config.site_name }}</title> - {% endif %} - {% endblock %} - - <!-- Theme-related style sheets --> - {% block styles %} - <link rel="stylesheet" href="{{ 'assets/stylesheets/main.css' | url }}" /> - - <!-- Extra color palette --> - {% if config.theme.palette %} - {% set palette = config.theme.palette %} - <link - rel="stylesheet" - href="{{ 'assets/stylesheets/palette.css' | url }}" - /> - {% endif %} - - <!-- Custom icons --> - {% include "partials/icons.html" %} - {% endblock %} - - <!-- JavaScript libraries --> - {% block libs %} - {% for script in config.extra.polyfills %} - {{ script | script_tag }} - {% endfor %} - {% endblock %} - - <!-- Webfonts --> - {% block fonts %} - - <!-- Load fonts from Google --> - {% if config.theme.font != false %} - {% set text = config.theme.font.get("text", "Roboto") %} - {% set code = config.theme.font.get("code", "Roboto Mono") %} - <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin /> - <link - rel="stylesheet" - href="https://fonts.googleapis.com/css?family={{ - text | replace(' ', '+') + ':300,300i,400,400i,700,700i%7C' + - code | replace(' ', '+') + ':400,400i,700,700i' - }}&display=fallback" - /> - <style> - :root { - --md-text-font: "{{ text }}"; - --md-code-font: "{{ code }}"; - } - </style> - {% endif %} - {% endblock %} - - <!-- Custom style sheets --> - {% for path in config.extra_css %} - <link rel="stylesheet" href="{{ path | url }}" /> - {% endfor %} - - <!-- Helper functions for inline scripts --> - {% include "partials/javascripts/base.html" %} - - <!-- Analytics --> - {% block analytics %} - {% include "partials/integrations/analytics.html" %} - {% endblock %} - - <!-- Meta tags from front matter or plugins --> - {% if page.meta and page.meta.meta %} - {% for tag in page.meta.meta %} - <meta - {% for key, value in tag.items() %} - {{ key }}="{{value}}" - {% endfor %} - /> - {% endfor %} - {% endif %} - - <!-- Custom front matter --> - {% block extrahead %}{% endblock %} - </head> - - <!-- Set text direction and color palette, if defined --> - {% set direction = config.theme.direction or lang.t("direction") %} - {% if config.theme.palette %} - {% set palette = config.theme.palette %} - {% if not palette is mapping %} - {% set palette = palette | first %} - {% endif %} - {% set scheme = palette.scheme | d("default", true) %} - {% set primary = palette.primary | d("indigo", true) %} - {% set accent = palette.accent | d("indigo", true) %} - <body - dir="{{ direction }}" - data-md-color-scheme="{{ scheme | replace(' ', '-') }}" - data-md-color-primary="{{ primary | replace(' ', '-') }}" - data-md-color-accent="{{ accent | replace(' ', '-') }}" - > - {% else %} - <body dir="{{ direction }}"> - {% endif %} - {% set features = config.theme.features or [] %} - - <!-- User preference: color palette --> - {% if not config.theme.palette is mapping %} - {% include "partials/javascripts/palette.html" %} - {% endif %} - - <!-- - State toggles - we need to set autocomplete="off" in order to reset the - drawer on back button invocation in some browsers - --> - <input - class="md-toggle" - data-md-toggle="drawer" - type="checkbox" - id="__drawer" - autocomplete="off" - /> - <input - class="md-toggle" - data-md-toggle="search" - type="checkbox" - id="__search" - autocomplete="off" - /> - - <!-- Overlay for expanded drawer --> - <label class="md-overlay" for="__drawer"></label> - - <!-- Skip to content --> - <div data-md-component="skip"> - {% if page.toc | first is defined %} - {% set skip = page.toc | first %} - <a href="{{ skip.url | url }}" class="md-skip"> - {{ lang.t("action.skip") }} - </a> - {% endif %} - </div> - - <!-- Announcement bar --> - <div data-md-component="announce"> - {% if self.announce() %} - <aside class="md-banner"> - <div class="md-banner__inner md-grid md-typeset"> - - <!-- Button to dismiss announcement --> - {% if "announce.dismiss" in features %} - <button - class="md-banner__button md-icon" - aria-label="{{ lang.t('announce.dismiss') }}" - > - {% set icon = config.theme.icon.close or "material/close" %} - {% include ".icons/" ~ icon ~ ".svg" %} - </button> - {% endif %} - - <!-- Announcement bar content --> - {% block announce %}{% endblock %} - </div> - {% if "announce.dismiss" in features %} - {% include "partials/javascripts/announce.html" %} - {% endif %} - </aside> - {% endif %} - </div> - - <!-- Version warning --> - {% if config.extra.version %} - <div data-md-color-scheme="default" data-md-component="outdated" hidden> - {% if self.outdated() %} - <aside class="md-banner md-banner--warning"> - <div class="md-banner__inner md-grid md-typeset"> - {% block outdated %}{% endblock %} - </div> - {% include "partials/javascripts/outdated.html" %} - </aside> - {% endif %} - </div> - {% endif %} - - <!-- Header --> - {% block header %} - {% include "partials/header.html" %} - {% endblock %} - - <!-- Container --> - <div class="md-container" data-md-component="container"> - - <!-- Hero teaser --> - {% block hero %}{% endblock %} - - <!-- Navigation tabs (collapsing) --> - {% block tabs %} - {% if "navigation.tabs.sticky" not in features %} - {% if "navigation.tabs" in features %} - {% include "partials/tabs.html" %} - {% endif %} - {% endif %} - {% endblock %} - - <!-- Main area --> - <main class="md-main" data-md-component="main"> - <div class="md-main__inner md-grid"> - - <!-- Sidebars --> - {% block site_nav %} - - <!-- Navigation --> - {% if nav %} - {% if page.meta and page.meta.hide %} - {% set hidden = "hidden" if "navigation" in page.meta.hide %} - {% endif %} - <div - class="md-sidebar md-sidebar--primary" - data-md-component="sidebar" - data-md-type="navigation" - {{ hidden }} - > - <div class="md-sidebar__scrollwrap"> - <div class="md-sidebar__inner"> - {% include "partials/nav.html" %} - </div> - </div> - </div> - {% endif %} - - <!-- Table of contents --> - {% if "toc.integrate" not in features %} - {% if page.meta and page.meta.hide %} - {% set hidden = "hidden" if "toc" in page.meta.hide %} - {% endif %} - <div - class="md-sidebar md-sidebar--secondary" - data-md-component="sidebar" - data-md-type="toc" - {{ hidden }} - > - <div class="md-sidebar__scrollwrap"> - <div class="md-sidebar__inner"> - {% include "partials/toc.html" %} - </div> - </div> - </div> - {% endif %} - {% endblock %} - - <!-- Page content --> - {% block container %} - <div class="md-content" data-md-component="content"> - <article class="md-content__inner md-typeset"> - {% block content %} - {% include "partials/content.html" %} - {% endblock %} - </article> - </div> - {% endblock %} - - <!-- User preference: content --> - {% include "partials/javascripts/content.html" %} - </div> - - <!-- Back-to-top button --> - {% if "navigation.top" in features %} - {% include "partials/top.html" %} - {% endif %} - </main> - - <!-- Footer --> - {% block footer %} - {% include "partials/footer.html" %} - {% endblock %} - </div> - - <!-- Dialog --> - <div class="md-dialog" data-md-component="dialog"> - <div class="md-dialog__inner md-typeset"></div> - </div> - - <!-- Progress indicator --> - {% if "navigation.instant.progress" in features %} - {% include "partials/progress.html" %} - {% endif %} - - <!-- Consent --> - {% if config.extra.consent %} - <div class="md-consent" data-md-component="consent" id="__consent" hidden> - <div class="md-consent__overlay"></div> - <aside class="md-consent__inner"> - <form class="md-consent__form md-grid md-typeset" name="consent"> - {% include "partials/consent.html" %} - </form> - </aside> - </div> - - <!-- User preference: consent --> - {% include "partials/javascripts/consent.html" %} - {% endif %} - - <!-- Theme-related configuration --> - {% block config %} - {%- set app = { - "base": base_url, - "features": features, - "translations": {}, - "search": "assets/javascripts/workers/search.js" | url - } -%} - - <!-- Versioning --> - {%- if config.extra.version -%} - {%- set _ = app.update({ "version": config.extra.version }) -%} - {%- endif -%} - - <!-- Tags --> - {%- if config.extra.tags -%} - {%- set _ = app.update({ "tags": config.extra.tags }) -%} - {%- endif -%} - - <!-- Translations --> - {%- set translations = app.translations -%} - {%- for key in [ - "clipboard.copy", - "clipboard.copied", - "search.result.placeholder", - "search.result.none", - "search.result.one", - "search.result.other", - "search.result.more.one", - "search.result.more.other", - "search.result.term.missing", - "select.version" - ] -%} - {%- set _ = translations.update({ key: lang.t(key) }) -%} - {%- endfor -%} - - <!-- Configuration --> - <script id="__config" type="application/json"> - {{- app | tojson -}} - </script> - {% endblock %} - - <!-- Theme-related JavaScript --> - {% block scripts %} - <script src="{{ 'assets/javascripts/bundle.js' | url }}"></script> - - <!-- Custom JavaScript --> - {% for script in config.extra_javascript %} - {{ script | script_tag }} - {% endfor %} - {% endblock %} - </body> -</html> diff --git a/src/templates/blog-post.html b/src/templates/blog-post.html deleted file mode 100644 index 73fb669f..00000000 --- a/src/templates/blog-post.html +++ /dev/null @@ -1,164 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -{% extends "main.html" %} - -{% import "partials/nav-item.html" as item with context %} - -<!-- Page content --> -{% block container %} - <div class="md-content md-content--post" data-md-component="content"> - - <!-- Sidebar --> - <div - class="md-sidebar md-sidebar--post" - data-md-component="sidebar" - data-md-type="navigation" - > - <div class="md-sidebar__scrollwrap"> - <div class="md-sidebar__inner md-post"> - <nav class="md-nav md-nav--primary"> - - <!-- Back to overview link --> - <div class="md-post__back"> - <div class="md-nav__title md-nav__container"> - <a href="{{ page.parent.url | url }}" class=" md-nav__link"> - {% include ".icons/material/arrow-left.svg" %} - <span class="md-ellipsis"> - {{ lang.t("blog.index") }} - </span> - </a> - </div> - </div> - - <!-- Post authors --> - {% if page.authors %} - <div class="md-post__authors md-typeset"> - {% for author in page.authors %} - <div class="md-profile md-post__profile"> - <span class="md-author md-author--long"> - <img src="{{ author.avatar }}" alt="{{ author.name }}" /> - </span> - <span class="md-profile__description"> - <strong>{{ author.name }}</strong><br /> - {{ author.description }} - </span> - </div> - {% endfor %} - </div> - {% endif %} - - <!-- Post metadata --> - <ul class="md-post__meta md-nav__list"> - <li class="md-nav__item md-nav__item--section"> - <div class="md-post__title"> - <span class="md-ellipsis"> - {{ lang.t("blog.meta") }} - </span> - </div> - <nav class="md-nav"> - <ul class="md-nav__list"> - - <!-- Post date --> - <li class="md-nav__item"> - <div class="md-nav__link"> - {% include ".icons/material/calendar.svg" %} - <time - datetime="{{ page.config.date.created }}" - class="md-ellipsis" - > - {{- page.config.date.created | date -}} - </time> - </div> - </li> - - <!-- Post date updated --> - {% if page.config.date.updated %} - <li class="md-nav__item"> - <div class="md-nav__link"> - {% include ".icons/material/calendar-clock.svg" %} - <time - datetime="{{ page.config.date.updated }}" - class="md-ellipsis" - > - {{- page.config.date.updated | date -}} - </time> - </div> - </li> - {% endif %} - - <!-- Post categories --> - {% if page.categories %} - <li class="md-nav__item"> - <div class="md-nav__link"> - {% include ".icons/material/bookshelf.svg" %} - <span class="md-ellipsis"> - {{ lang.t("blog.categories.in") }} - {% for category in page.categories %} - <a href="{{ category.url | url }}"> - {{- category.title -}} - </a> - {%- if loop.revindex > 1 %}, {% endif -%} - {% endfor -%} - </span> - </div> - </li> - {% endif %} - - <!-- Post readtime --> - {% if page.config.readtime %} - {% set time = page.config.readtime %} - <li class="md-nav__item"> - <div class="md-nav__link"> - {% include ".icons/material/clock-outline.svg" %} - <span class="md-ellipsis"> - {% if time == 1 %} - {{ lang.t("readtime.one") }} - {% else %} - {{ lang.t("readtime.other") | replace("#", time) }} - {% endif %} - </span> - </div> - </li> - {% endif %} - </ul> - </nav> - </li> - </ul> - </nav> - - <!-- Table of contents, if integrated --> - {% if "toc.integrate" in features %} - {% include "partials/toc.html" %} - {% endif %} - </div> - </div> - </div> - - <!-- Page content --> - <article class="md-content__inner md-typeset"> - {% block content %} - {% include "partials/content.html" %} - {% endblock %} - </article> - </div> -{% endblock %} diff --git a/src/templates/blog.html b/src/templates/blog.html deleted file mode 100644 index eedc77d9..00000000 --- a/src/templates/blog.html +++ /dev/null @@ -1,48 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -{% extends "main.html" %} - -<!-- Page content --> -{% block container %} - <div class="md-content" data-md-component="content"> - <div class="md-content__inner"> - - <!-- Header --> - <header class="md-typeset"> - {{ page.content }} - </header> - - <!-- Posts --> - {% for post in posts %} - {% include "partials/post.html" %} - {% endfor %} - - <!-- Pagination --> - {% if pagination %} - {% block pagination %} - {% include "partials/pagination.html" %} - {% endblock %} - {% endif %} - </div> - </div> -{% endblock %} diff --git a/src/templates/main.html b/src/templates/main.html deleted file mode 100644 index 3b77d200..00000000 --- a/src/templates/main.html +++ /dev/null @@ -1,23 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -{% extends "base.html" %} diff --git a/src/templates/mkdocs_theme.yml b/src/templates/mkdocs_theme.yml deleted file mode 100644 index aaa47f5e..00000000 --- a/src/templates/mkdocs_theme.yml +++ /dev/null @@ -1,50 +0,0 @@ -# Copyright (c) 2016-2023 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. - -# Language for theme localization -language: en - -# Text direction (can be ltr or rtl), default: ltr -direction: - -# Feature flags for functionality that alters behavior significantly, and thus -# may be a matter of taste -features: [] - -# Fonts used by Material, automatically loaded from Google Fonts - see the site -# for a list of available fonts -font: - - # Default font for text - text: Roboto - - # Fixed-width font for code listings - code: Roboto Mono - -# From Material 5.x on, icons are inlined into the HTML and CSS as SVGs. -# Icons that are part of the HTML can be configured and replaced -icon: - -# Favicon to be rendered -favicon: assets/images/favicon.png - -# Static pages to build -static_templates: - - 404.html diff --git a/src/templates/partials/actions.html b/src/templates/partials/actions.html deleted file mode 100644 index 75fcb8eb..00000000 --- a/src/templates/partials/actions.html +++ /dev/null @@ -1,54 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Actions --> -{% if page.edit_url %} - - <!-- Edit button --> - {% if "content.action.edit" in features %} - <a - href="{{ page.edit_url }}" - title="{{ lang.t('action.edit') }}" - class="md-content__button md-icon" - > - {% set icon = config.theme.icon.edit or "material/file-edit-outline" %} - {% include ".icons/" ~ icon ~ ".svg" %} - </a> - {% endif %} - - <!-- View button --> - {% if "content.action.view" in features %} - {% if "/blob/" in page.edit_url %} - {% set part = "blob" %} - {% else %} - {% set part = "edit" %} - {% endif %} - <a - href="{{ page.edit_url | replace(part, 'raw') }}" - title="{{ lang.t('action.view') }}" - class="md-content__button md-icon" - > - {% set icon = config.theme.icon.view or "material/file-eye-outline" %} - {% include ".icons/" ~ icon ~ ".svg" %} - </a> - {% endif %} -{% endif %} diff --git a/src/templates/partials/alternate.html b/src/templates/partials/alternate.html deleted file mode 100644 index 7d7c925b..00000000 --- a/src/templates/partials/alternate.html +++ /dev/null @@ -1,49 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Site language selector --> -<div class="md-header__option"> - <div class="md-select"> - {% set icon = config.theme.icon.alternate or "material/translate" %} - <button - class="md-header__button md-icon" - aria-label="{{ lang.t('select.language') }}" - > - {% include ".icons/" ~ icon ~ ".svg" %} - </button> - <div class="md-select__inner"> - <ul class="md-select__list"> - {% for alt in config.extra.alternate %} - <li class="md-select__item"> - <a - href="{{ alt.link | url }}" - hreflang="{{ alt.lang }}" - class="md-select__link" - > - {{ alt.name }} - </a> - </li> - {% endfor %} - </ul> - </div> - </div> -</div> diff --git a/src/templates/partials/comments.html b/src/templates/partials/comments.html deleted file mode 100644 index 6641d20e..00000000 --- a/src/templates/partials/comments.html +++ /dev/null @@ -1,23 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Comment system --> diff --git a/src/templates/partials/consent.html b/src/templates/partials/consent.html deleted file mode 100644 index c84622bc..00000000 --- a/src/templates/partials/consent.html +++ /dev/null @@ -1,107 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Determine cookies --> -{% set cookies = config.extra.consent.cookies | d({}) %} -{% if config.extra.analytics %} - {% if "analytics" not in cookies %} - {% set _ = cookies.update({ "analytics": "Google Analytics" }) %} - {% endif %} -{% endif %} -{% if config.repo_url and "github.com" in config.repo_url %} - {% if "github" not in cookies %} - {% set _ = cookies.update({ "github": "GitHub" }) %} - {% endif %} -{% endif %} - -<!-- Determine actions --> -{% set actions = config.extra.consent.actions %} -{% if not actions %} - {% set actions = ["accept", "manage"] %} -{% endif %} - -<!-- Determine initial settings state --> -{% if "manage" not in actions %} - {% set checked = "checked" %} -{% endif %} - -<!-- Consent title --> -<h4>{{ config.extra.consent.title }}</h4> -<p>{{ config.extra.consent.description }}</p> - -<!-- Consent settings --> -<input - class="md-toggle" - type="checkbox" - id="__settings" - {{ checked }} -/> -<div class="md-consent__settings"> - <ul class="task-list"> - {% for type in cookies %} - {% set checked = "" %} - {% if cookies[type] is string %} - {% set name = cookies[type] %} - {% set checked = "checked" %} - {% else %} - {% set name = cookies[type].name %} - {% if cookies[type].checked %} - {% set checked = "checked" %} - {% endif %} - {% endif %} - <li class="task-list-item"> - <label class="task-list-control"> - <input type="checkbox" name="{{ type }}" {{ checked }}> - <span class="task-list-indicator"></span> - {{ name }} - </label> - </li> - {% endfor %} - </ul> -</div> - -<!-- Consent controls --> -<div class="md-consent__controls"> - {% for action in actions %} - - <!-- Button to accept cookies --> - {% if action == "accept" %} - <button class="md-button md-button--primary"> - {{- lang.t("consent.accept") -}} - </button> - {% endif %} - - <!-- Button to reject cookies --> - {% if action == "reject" %} - <button type="reset" class="md-button md-button--primary"> - {{- lang.t("consent.reject") -}} - </button> - {% endif %} - - <!-- Button to manage settings --> - {% if action == "manage" %} - <label class="md-button" for="__settings"> - {{- lang.t("consent.manage") -}} - </label> - {% endif %} - {% endfor %} -</div> diff --git a/src/templates/partials/content.html b/src/templates/partials/content.html deleted file mode 100644 index 2b78b09b..00000000 --- a/src/templates/partials/content.html +++ /dev/null @@ -1,54 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Tags --> -{% if "material/tags" in config.plugins and tags %} - {% include "partials/tags.html" %} -{% endif %} - -<!-- Actions --> -{% include "partials/actions.html" %} - -<!-- - Hack: check whether the content contains a h1 headline. If it doesn't, the - page title (or respectively site name) is used as the main headline. ---> -{% if "\x3ch1" not in page.content %} - <h1>{{ page.title | d(config.site_name, true)}}</h1> -{% endif %} - -<!-- Page content --> -{{ page.content }} - -<!-- Source file information --> -{% if page.meta and ( - page.meta.git_revision_date_localized or - page.meta.revision_date -) %} - {% include "partials/source-file.html" %} -{% endif %} - -<!-- Was this page helpful? --> -{% include "partials/feedback.html" %} - -<!-- Comment system --> -{% include "partials/comments.html" %} diff --git a/src/templates/partials/copyright.html b/src/templates/partials/copyright.html deleted file mode 100644 index 070948d2..00000000 --- a/src/templates/partials/copyright.html +++ /dev/null @@ -1,39 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Copyright and theme information --> -<div class="md-copyright"> - {% if config.copyright %} - <div class="md-copyright__highlight"> - {{ config.copyright }} - </div> - {% endif %} - {% if not config.extra.generator == false %} - Made with - <a - href="https://squidfunk.github.io/mkdocs-material/" - target="_blank" rel="noopener" - > - Material for MkDocs - </a> - {% endif %} -</div> diff --git a/src/templates/partials/feedback.html b/src/templates/partials/feedback.html deleted file mode 100644 index bf27c640..00000000 --- a/src/templates/partials/feedback.html +++ /dev/null @@ -1,79 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Determine feedback configuration --> -{% if config.extra.analytics %} - {% set feedback = config.extra.analytics.feedback %} -{% endif %} - -<!-- Determine whether to show feedback --> -{% if page.meta and page.meta.hide %} - {% if "feedback" in page.meta.hide %} - {% set feedback = None %} - {% endif %} -{% endif %} - -<!-- Was this page helpful? --> -{% if feedback %} - <form class="md-feedback" name="feedback" hidden> - <fieldset> - <legend class="md-feedback__title"> - {{ feedback.title }} - </legend> - <div class="md-feedback__inner"> - - <!-- Feedback ratings --> - <div class="md-feedback__list"> - {% for rating in feedback.ratings %} - <button - class="md-feedback__icon md-icon" - type="submit" - title="{{ rating.name }}" - data-md-value="{{ rating.data }}" - > - {% include ".icons/" ~ rating.icon ~ ".svg" %} - </button> - {% endfor %} - </div> - - <!-- Feedback rating notes (shown after submission) --> - <div class="md-feedback__note"> - {% for rating in feedback.ratings %} - <div data-md-value="{{ rating.data }}" hidden> - {% set url = "/" ~ page.url %} - - <!-- Determine title --> - {% if page.meta and page.meta.title %} - {% set title = page.meta.title | urlencode %} - {% else %} - {% set title = page.title | urlencode %} - {% endif %} - - <!-- Replace {url} and {title} placeholders in note --> - {{ rating.note.format(url = url, title = title) }} - </div> - {% endfor %} - </div> - </div> - </fieldset> - </form> -{% endif %} diff --git a/src/templates/partials/footer.html b/src/templates/partials/footer.html deleted file mode 100644 index ebe9278f..00000000 --- a/src/templates/partials/footer.html +++ /dev/null @@ -1,98 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Footer --> -<footer class="md-footer"> - - <!-- Link to previous and/or next page --> - {% if "navigation.footer" in features %} - {% if page.previous_page or page.next_page %} - {% if page.meta and page.meta.hide %} - {% set hidden = "hidden" if "footer" in page.meta.hide %} - {% endif %} - <nav - class="md-footer__inner md-grid" - aria-label="{{ lang.t('footer') }}" - {{ hidden }} - > - - <!-- Link to previous page --> - {% if page.previous_page %} - {% set direction = lang.t("footer.previous") %} - <a - href="{{ page.previous_page.url | url }}" - class="md-footer__link md-footer__link--prev" - aria-label="{{ direction }}: {{ page.previous_page.title | e }}" - > - <div class="md-footer__button md-icon"> - {% set icon = config.theme.icon.previous or "material/arrow-left" %} - {% include ".icons/" ~ icon ~ ".svg" %} - </div> - <div class="md-footer__title"> - <span class="md-footer__direction"> - {{ direction }} - </span> - <div class="md-ellipsis"> - {{ page.previous_page.title }} - </div> - </div> - </a> - {% endif %} - - <!-- Link to next page --> - {% if page.next_page %} - {% set direction = lang.t("footer.next") %} - <a - href="{{ page.next_page.url | url }}" - class="md-footer__link md-footer__link--next" - aria-label="{{ direction }}: {{ page.next_page.title | e }}" - > - <div class="md-footer__title"> - <span class="md-footer__direction"> - {{ direction }} - </span> - <div class="md-ellipsis"> - {{ page.next_page.title }} - </div> - </div> - <div class="md-footer__button md-icon"> - {% set icon = config.theme.icon.next or "material/arrow-right" %} - {% include ".icons/" ~ icon ~ ".svg" %} - </div> - </a> - {% endif %} - </nav> - {% endif %} - {% endif %} - - <!-- Further information --> - <div class="md-footer-meta md-typeset"> - <div class="md-footer-meta__inner md-grid"> - {% include "partials/copyright.html" %} - - <!-- Social links --> - {% if config.extra.social %} - {% include "partials/social.html" %} - {% endif %} - </div> - </div> -</footer> diff --git a/src/templates/partials/header.html b/src/templates/partials/header.html deleted file mode 100644 index 9b6d2e2e..00000000 --- a/src/templates/partials/header.html +++ /dev/null @@ -1,112 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Determine classes --> -{% set class = "md-header" %} -{% if "navigation.tabs.sticky" in features %} - {% set class = class ~ " md-header--shadow md-header--lifted" %} -{% elif "navigation.tabs" not in features %} - {% set class = class ~ " md-header--shadow" %} -{% endif %} - -<!-- Header --> -<header class="{{ class }}" data-md-component="header"> - <nav - class="md-header__inner md-grid" - aria-label="{{ lang.t('header') }}" - > - - <!-- Link to home --> - <a - href="{{ config.extra.homepage | d(nav.homepage.url, true) | url }}" - title="{{ config.site_name | e }}" - class="md-header__button md-logo" - aria-label="{{ config.site_name }}" - data-md-component="logo" - > - {% include "partials/logo.html" %} - </a> - - <!-- Button to open drawer --> - <label class="md-header__button md-icon" for="__drawer"> - {% set icon = config.theme.icon.menu or "material/menu" %} - {% include ".icons/" ~ icon ~ ".svg" %} - </label> - - <!-- Header title --> - <div class="md-header__title" data-md-component="header-title"> - <div class="md-header__ellipsis"> - <div class="md-header__topic"> - <span class="md-ellipsis"> - {{ config.site_name }} - </span> - </div> - <div class="md-header__topic" data-md-component="header-topic"> - <span class="md-ellipsis"> - {% if page.meta and page.meta.title %} - {{ page.meta.title }} - {% else %} - {{ page.title }} - {% endif %} - </span> - </div> - </div> - </div> - - <!-- Color palette toggle --> - {% if config.theme.palette %} - {% if not config.theme.palette is mapping %} - {% include "partials/palette.html" %} - {% endif %} - {% endif %} - - <!-- Site language selector --> - {% if config.extra.alternate %} - {% include "partials/alternate.html" %} - {% endif %} - - <!-- Button to open search modal --> - {% if "material/search" in config.plugins %} - <label class="md-header__button md-icon" for="__search"> - {% set icon = config.theme.icon.search or "material/magnify" %} - {% include ".icons/" ~ icon ~ ".svg" %} - </label> - - <!-- Search interface --> - {% include "partials/search.html" %} - {% endif %} - - <!-- Repository information --> - {% if config.repo_url %} - <div class="md-header__source"> - {% include "partials/source.html" %} - </div> - {% endif %} - </nav> - - <!-- Navigation tabs (sticky) --> - {% if "navigation.tabs.sticky" in features %} - {% if "navigation.tabs" in features %} - {% include "partials/tabs.html" %} - {% endif %} - {% endif %} -</header> diff --git a/src/templates/partials/icons.html b/src/templates/partials/icons.html deleted file mode 100644 index 17dd20d8..00000000 --- a/src/templates/partials/icons.html +++ /dev/null @@ -1,72 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Custom admonition icons --> -{% if config.theme.icon.admonition %} - {% set style = ["\x3cstyle\x3e:root{"] %} - {% for type, icon in config.theme.icon.admonition.items() %} - {% import ".icons/" ~ icon ~ ".svg" as icon %} - {% set _ = style.append( - "--md-admonition-icon--" ~ type ~ ":" ~ - "url('data:image/svg+xml;charset=utf-8," ~ - icon | replace("\n", "") ~ - "');" - ) %} - {% endfor %} - {% set _ = style.append("}\x3c/style\x3e") %} - {{ style | join }} -{% endif %} - -<!-- Custom annotation icon --> -{% if config.theme.icon.annotation %} - {% set style = ["\x3cstyle\x3e:root{"] %} - {% import ".icons/" ~ config.theme.icon.annotation ~ ".svg" as icon %} - {% set _ = style.append( - "--md-annotation-icon:" ~ - "url('data:image/svg+xml;charset=utf-8," ~ - icon | replace("\n", "") ~ - "');" - ) %} - {% set _ = style.append("}\x3c/style\x3e") %} - {{ style | join }} -{% endif %} - -<!-- Custom tag icons --> -{% if config.theme.icon.tag %} - {% set style = ["\x3cstyle\x3e"] %} - {% for type, icon in config.theme.icon.tag.items() %} - {% import ".icons/" ~ icon ~ ".svg" as icon %} - {% if type != "default" %} - {% set modifier = "--" ~ type %} - {% endif %} - {% set _ = style.append( - ".md-tag" ~ modifier ~ "{" ~ - "--md-tag-icon:" ~ - "url('data:image/svg+xml;charset=utf-8," ~ - icon | replace("\n", "") ~ - "');" ~ - "}" - ) %} - {% endfor %} - {% set _ = style.append("\x3c/style\x3e") %} - {{ style | join }} -{% endif %} diff --git a/src/templates/partials/integrations/analytics.html b/src/templates/partials/integrations/analytics.html deleted file mode 100644 index 4b483046..00000000 --- a/src/templates/partials/integrations/analytics.html +++ /dev/null @@ -1,49 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Determine analytics provider --> -{% if config.extra.analytics %} - {% set provider = config.extra.analytics.provider %} -{% endif %} - -<!-- Set up analytics provider --> -{% if provider %} - {% include "partials/integrations/analytics/" ~ provider ~ ".html" %} - - <!-- Consent necessary --> - {% if config.extra.consent %} - <script> - if (typeof __md_analytics !== "undefined") { - var consent = __md_get("__consent") - if (consent && consent.analytics) - __md_analytics() - } - </script> - - <!-- Consent unnecessary --> - {% else %} - <script> - if (typeof __md_analytics !== "undefined") - __md_analytics() - </script> - {% endif %} -{% endif %} diff --git a/src/templates/partials/integrations/analytics/google.html b/src/templates/partials/integrations/analytics/google.html deleted file mode 100644 index a9fa37d9..00000000 --- a/src/templates/partials/integrations/analytics/google.html +++ /dev/null @@ -1,97 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Determine analytics property --> -{% if config.extra.analytics %} - {% set property = config.extra.analytics.property | d("", true) %} -{% endif %} - -<!-- Integrate with Google Analytics 4 --> -<script id="__analytics"> - function __md_analytics() { - window.dataLayer = window.dataLayer || [] - function gtag() { dataLayer.push(arguments) } - - /* Set up integration and send page view */ - gtag("js", new Date()) - gtag("config", "{{ property }}") - - /* Register event handlers after documented loaded */ - document.addEventListener("DOMContentLoaded", function() { - - /* Set up search tracking */ - if (document.forms.search) { - var query = document.forms.search.query - query.addEventListener("blur", function() { - if (this.value) - gtag("event", "search", { search_term: this.value }) - }) - } - - /* Set up feedback, i.e. "Was this page helpful?" */ - document$.subscribe(function() { - var feedback = document.forms.feedback - if (typeof feedback === "undefined") - return - - /* Send feedback to Google Analytics */ - for (var button of feedback.querySelectorAll("[type=submit]")) { - button.addEventListener("click", function(ev) { - ev.preventDefault() - - /* Retrieve and send data */ - var page = document.location.pathname - var data = this.getAttribute("data-md-value") - gtag("event", "feedback", { page, data }) - - /* Disable form and show note, if given */ - feedback.firstElementChild.disabled = true - var note = feedback.querySelector( - ".md-feedback__note [data-md-value='" + data + "']" - ) - if (note) - note.hidden = false - }) - - /* Show feedback */ - feedback.hidden = false - } - }) - - /* Send page view on location change */ - location$.subscribe(function(url) { - gtag("config", "{{ property }}", { - page_path: url.pathname - }) - }) - }) - - /* Create script tag */ - var script = document.createElement("script") - script.async = true - script.src = "https://www.googletagmanager.com/gtag/js?id={{ property }}" - - /* Inject script tag */ - var container = document.getElementById("__analytics") - container.insertAdjacentElement("afterEnd", script) - } -</script> diff --git a/src/templates/partials/javascripts/announce.html b/src/templates/partials/javascripts/announce.html deleted file mode 100644 index f13961b2..00000000 --- a/src/templates/partials/javascripts/announce.html +++ /dev/null @@ -1,31 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Announcement bar --> -<script> - var el = document.querySelector("[data-md-component=announce]") - if (el) { - var content = el.querySelector(".md-typeset") - if (__md_hash(content.innerHTML) === __md_get("__announce")) - el.hidden = true - } -</script> diff --git a/src/templates/partials/javascripts/base.html b/src/templates/partials/javascripts/base.html deleted file mode 100644 index f0eeeb8a..00000000 --- a/src/templates/partials/javascripts/base.html +++ /dev/null @@ -1,48 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- - A collection of functions used from within some partials to allow the usage - of state saved in local or session storage, e.g. to model preferences. ---> -<script> - - /* Compute base path once to integrate with instant loading */ - __md_scope = new URL("{{ config.extra.scope | d(base_url) }}", location) - - /* Compute hash from the given string - see https://bit.ly/3pvPjXG */ - __md_hash = v => [...v].reduce((h, c) => (h << 5) - h + c.charCodeAt(0), 0) - - /* Fetch the value for a key from the given storage */ - __md_get = (key, storage = localStorage, scope = __md_scope) => ( - JSON.parse(storage.getItem(scope.pathname + "." + key)) - ) - - /* Persist a key-value pair in the given storage */ - __md_set = (key, value, storage = localStorage, scope = __md_scope) => { - try { - storage.setItem(scope.pathname + "." + key, JSON.stringify(value)) - } catch (err) { - /* Uncritical, just swallow */ - } - } -</script> diff --git a/src/templates/partials/javascripts/consent.html b/src/templates/partials/javascripts/consent.html deleted file mode 100644 index 13730da7..00000000 --- a/src/templates/partials/javascripts/consent.html +++ /dev/null @@ -1,61 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- User-preference: consent --> -<script> - var consent = __md_get("__consent") - if (consent) { - for (var input of document.forms.consent.elements) - if (input.name) - input.checked = consent[input.name] || false - - /* Show consent with a small delay, but not if browsing locally */ - } else if (location.protocol !== "file:") { - setTimeout(function() { - var el = document.querySelector("[data-md-component=consent]") - el.hidden = false - }, 250) - } - - /* Intercept submission of consent form */ - var form = document.forms.consent - for (var action of ["submit", "reset"]) - form.addEventListener(action, function(ev) { - ev.preventDefault() - - /* Reject all cookies */ - if (ev.type === "reset") - for (var input of document.forms.consent.elements) - if (input.name) - input.checked = false - - /* Grab and serialize form data */ - __md_set("__consent", Object.fromEntries( - Array.from(new FormData(form).keys()) - .map(function(key) { return [key, true] }) - )) - - /* Remove anchor to omit consent from reappearing and reload */ - location.hash = ''; - location.reload() - }) -</script> diff --git a/src/templates/partials/javascripts/content.html b/src/templates/partials/javascripts/content.html deleted file mode 100644 index d361f18b..00000000 --- a/src/templates/partials/javascripts/content.html +++ /dev/null @@ -1,39 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- User-preference: link content tabs --> -{% if "content.tabs.link" in features %} - <script> - var tabs = __md_get("__tabs") - if (Array.isArray(tabs)) - main: for (var set of document.querySelectorAll(".tabbed-set")) { - var labels = set.querySelector(".tabbed-labels") - for (var tab of tabs) - for (var label of labels.getElementsByTagName("label")) - if (label.innerText.trim() === tab) { - var input = document.getElementById(label.htmlFor) - input.checked = true - continue main - } - } - </script> -{% endif %} diff --git a/src/templates/partials/javascripts/outdated.html b/src/templates/partials/javascripts/outdated.html deleted file mode 100644 index 576f3c85..00000000 --- a/src/templates/partials/javascripts/outdated.html +++ /dev/null @@ -1,29 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Version warning --> -<script> - var el = document.querySelector("[data-md-component=outdated]") - var outdated = __md_get("__outdated", sessionStorage) - if (outdated === true && el) - el.hidden = false -</script> diff --git a/src/templates/partials/javascripts/palette.html b/src/templates/partials/javascripts/palette.html deleted file mode 100644 index a2daef1d..00000000 --- a/src/templates/partials/javascripts/palette.html +++ /dev/null @@ -1,29 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- User preference: color palette --> -<script> - var palette = __md_get("__palette") - if (palette && typeof palette.color === "object") - for (var key of Object.keys(palette.color)) - document.body.setAttribute("data-md-color-" + key, palette.color[key]) -</script> diff --git a/src/templates/partials/language.html b/src/templates/partials/language.html deleted file mode 100644 index e37b953b..00000000 --- a/src/templates/partials/language.html +++ /dev/null @@ -1,28 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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 translations for given language and fallback --> -{% import "partials/languages/" ~ config.theme.language ~ ".html" as lang %} -{% import "partials/languages/en.html" as fallback %} - -<!-- Re-export translations --> -{% macro t(key) %}{{ lang.t(key) or fallback.t(key) or key }}{% endmacro %} diff --git a/src/templates/partials/languages/af.html b/src/templates/partials/languages/af.html deleted file mode 100644 index b7f9f8fa..00000000 --- a/src/templates/partials/languages/af.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Afrikaans --> -{% macro t(key) %}{{ { - "language": "af", - "action.edit": "Wysig hierdie bladsy", - "action.skip": "Slaan oor na inhoud", - "action.view": "Bekyk bron van hierdie bladsy", - "announce.dismiss": "Moenie dit weer wys nie", - "blog.archive": "Argief", - "blog.categories": "Kategorieë", - "blog.categories.in": "binne", - "blog.continue": "Lees verder", - "blog.draft": "Konsep", - "blog.index": "Terug na indeks", - "blog.meta": "Metadata", - "blog.references": "Verwante skakels", - "clipboard.copy": "Kopieer na knipbord", - "clipboard.copied": "gekopieer na knipbord", - "consent.accept": "Aanvaar", - "consent.manage": "Bestuur instellings", - "consent.reject": "Verwerp", - "footer": "Voetskrif", - "footer.next": "Volgende", - "footer.previous": "Vorige", - "header": "Kopskrif", - "meta.comments": "Kommentaar", - "meta.source": "Bron", - "nav": "Navigasie", - "readtime.one": "1 minuut se lees", - "readtime.other": "# minuut se lees", - "rss.created": "RSS-voer geskep", - "rss.updated": "RSS-voer van opgedateerde inhoud", - "search": "Soek", - "search.config.lang": "nl", - "search.placeholder": "Soek", - "search.share": "Deel", - "search.reset": "Terugstel", - "search.result.initializer": "Inisialisering van soektog", - "search.result.placeholder": "Tik om te begin soek", - "search.result.none": "Geen ooreenstemmende dokumente", - "search.result.one": "1 ooreenstemmende dokument", - "search.result.other": "# ooreenstemmende dokumente", - "search.result.more.one": "1 meer op hierdie bladsy", - "search.result.more.other": "# meer op hierdie bladsy", - "search.result.term.missing": "Vermis", - "select.language": "Kies taal", - "select.version": "Kies weergawe", - "source": "Slaan oor na inhoud", - "source.file.contributors": "Medewerkers", - "source.file.date.created": "Geskep", - "source.file.date.updated": "Laaste opdatering", - "tabs": "Duimgids", - "toc": "Inhoudsopgawe", - "top": "Terug na bo" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/ar.html b/src/templates/partials/languages/ar.html deleted file mode 100644 index 4d5da33a..00000000 --- a/src/templates/partials/languages/ar.html +++ /dev/null @@ -1,77 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Arabic --> -{% macro t(key) %}{{ { - "language": "ar", - "direction": "rtl", - "action.edit": "عدل الصفحة", - "action.skip": "انتقل إلى المحتوى", - "action.view": "عرض مصدر هذه الصفحة", - "announce.dismiss": "لا تظهر هذا مرة أخرى", - "blog.archive": "أرشيف", - "blog.categories": "فئات", - "blog.categories.in": "ضمن", - "blog.continue": "أكمل القراءة", - "blog.draft": "مسودة", - "blog.index": "رجوع إلى الفهرس", - "blog.meta": "بيانات وصفية", - "blog.references": "روابط ذات علاقة", - "clipboard.copy": "نسخ إلى الحافظة", - "clipboard.copied": "تم النسخ الى الحافظة", - "consent.accept": "قبول", - "consent.manage": "إدارة الإعدادات", - "consent.reject": "رفض", - "footer": "هامش سفلي", - "footer.next": "التالية", - "footer.previous": "السابقة", - "header": "عنوان العارضة", - "meta.comments": "التعليقات", - "meta.source": "المصدر", - "nav": "تصفح", - "readtime.one": "قراءة لمدة دقيقة", - "readtime.other": "دقائق قراءة #", - "rss.created": "ملقم بالخلاصات", - "rss.updated": "ملقم بالخلاصات المحدثة", - "search": "إبحث", - "search.config.pipeline": " ", - "search.placeholder": "بحث", - "search.share": "شارك", - "search.reset": "مسح كلي", - "search.result.initializer": "بدء البحث", - "search.result.placeholder": "اكتب لبدء البحث", - "search.result.none": "لا توجد نتائج", - "search.result.one": "نتائج البحث مستند واحد", - "search.result.other": "نتائج البحث # مستندات", - "search.result.more.one": "أكثر من 1 في هذه الصفحة", - "search.result.more.other": "أكثر من # في هذه الصفحة", - "search.result.term.missing": "مفقود", - "select.language": "إختر اللغة", - "select.version": "إختر الإصدار", - "source": "اذهب إلى المصدر", - "source.file.contributors": "المساهمون", - "source.file.date.created": "خلقت", - "source.file.date.updated": "اخر تحديث", - "tabs": "نوافذ", - "toc": "جدول المحتويات", - "top": "عد إلى الأعلى" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/be.html b/src/templates/partials/languages/be.html deleted file mode 100644 index c36c8402..00000000 --- a/src/templates/partials/languages/be.html +++ /dev/null @@ -1,77 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Belarusian --> -{% macro t(key) %}{{ { - "language": "be", - "direction": "ltr", - "action.edit": "Правіць старонку", - "action.skip": "Перайсці да зместа", - "action.view": "Паглядзець зыходны код старонкі", - "announce.dismiss": "Больш не паказваць", - "blog.archive": "Заархіваваць", - "blog.categories": "Катэгорыі", - "blog.categories.in": "у", - "blog.continue": "Працягнуць чытаць", - "blog.draft": "Чарнавік", - "blog.index": "Вярнуцца на хатнюю", - "blog.meta": "Метаданыя", - "blog.references": "Спасылкі па тэме", - "clipboard.copy": "Скапіраваць у буфер абмена", - "clipboard.copied": "Скапіравана ў буфер абмена", - "consent.accept": "Прыняць", - "consent.manage": "Кіраваць наладамі", - "consent.reject": "Адхіліць", - "footer": "Ніжні калантытул", - "footer.next": "Наступная", - "footer.previous": "Папярэдняя", - "header": "Верхні калантытул", - "meta.comments": "Каментарыі", - "meta.source": "Зыходны код", - "nav": "Навігацыя", - "readtime.one": "Прачытанне зойме 1 хв", - "readtime.other": "Прачытанне зойме # хв", - "rss.created": "RSS стужка", - "rss.updated": "RSS стужка з абноўленым зместам", - "search": "Пошук", - "search.config.lang": "ru", - "search.placeholder": "Пошук", - "search.share": "Падзяліцца", - "search.reset": "Ачысціць", - "search.result.initializer": "Пачынаем пошук", - "search.result.placeholder": "Пачніце друкаваць для пошуку", - "search.result.none": "Нічога ня знойдзена", - "search.result.one": "Адзін адпаведны дакумент", - "search.result.other": "Адпаведных дакументаў: #", - "search.result.more.one": "Яшчэ 1 на гэтай старонцы", - "search.result.more.other": "Яшчэ # на гэтай старонцы", - "search.result.term.missing": "Адсутнічае", - "select.language": "Выберыце мову", - "select.version": "Выберыце версію", - "source": "Перайсці ў рэпазітар", - "source.file.contributors": "Укладальнікі", - "source.file.date.created": "Створана", - "source.file.date.updated": "Апошняе абнаўленне", - "tabs": "Укладкі", - "toc": "Змест", - "top": "Вярнуцца да пачатку" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/bg.html b/src/templates/partials/languages/bg.html deleted file mode 100644 index f36fd437..00000000 --- a/src/templates/partials/languages/bg.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Bulgarian --> -{% macro t(key) %}{{ { - "language": "bg", - "action.edit": "Редактирай тази страница", - "action.skip": "Към съдържанието", - "action.view": "Виж съдържанието на тази страница", - "announce.dismiss": "Не показвай повече", - "blog.archive": "Архив", - "blog.categories": "Категории", - "blog.categories.in": "В", - "blog.continue": "Продължи четенето", - "blog.draft": "Чернова", - "blog.index": "Назад към индекса", - "blog.meta": "Метаданни", - "blog.references": "Свързани линкове", - "clipboard.copy": "Копирай", - "clipboard.copied": "Копирано", - "consent.accept": "Приеми", - "consent.manage": "Управление на настойките", - "consent.reject": "Откажи", - "footer": "Долен колонтитул", - "footer.next": "Следваща", - "footer.previous": "Предишна", - "header": "Горен колонтитул", - "meta.comments": "Коментари", - "meta.source": "Код", - "nav": "Навигация", - "readtime.one": "1 мин четено", - "readtime.other": "# мин четено", - "rss.created": "RSS публикации", - "rss.updated": "RSS публикации с актуализирано съдържание", - "search": "Търси", - "search.config.lang": "ru", - "search.placeholder": "Търси", - "search.share": "Сподели", - "search.reset": "Изчисти", - "search.result.initializer": "Инициализирано търсене", - "search.result.placeholder": "Започнете да пишете, за да търсите", - "search.result.none": "Няма резултати", - "search.result.one": "1 резултат", - "search.result.other": "# резултата", - "search.result.more.one": "още 1 на тази страница", - "search.result.more.other": "още # на тази страница", - "search.result.term.missing": "Липсващо", - "select.language": "Избери език", - "select.version": "Избери версия", - "source": "Към хранилището", - "source.file.contributors": "Участници", - "source.file.date.created": "Създаден", - "source.file.date.updated": "Последна промяна", - "tabs": "Табове", - "toc": "Съдържание", - "top": "Върни се в началото" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/bn.html b/src/templates/partials/languages/bn.html deleted file mode 100644 index 0a3ee6d0..00000000 --- a/src/templates/partials/languages/bn.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Bengali (Bangla) --> -{% macro t(key) %}{{ { - "language": "bn", - "action.edit": "এই পেজ এডিট করুন", - "action.skip": "কনটেন্টে যান", - "action.view": "পেজের ভিউ", - "announce.dismiss": "আর কখনো দেখাবে না", - "blog.archive": "সংরক্ষণাগার", - "blog.categories": "বিভাগ", - "blog.categories.in": "বিভাগের মধ্যে", - "blog.continue": "পড়তে থাকুন", - "blog.draft": "খসড়া", - "blog.index": "ইনডেক্সে ফিরে যান", - "blog.meta": "মেটাডেটা", - "blog.references": "সম্পর্কিত লিংক", - "clipboard.copy": "ক্লিপবোর্ডে কপি করুন", - "clipboard.copied": "ক্লিপবোর্ডে কপি হয়েছে", - "consent.accept": "গ্রহণ", - "consent.manage": "সেটিংস ব্যবস্থাপনা", - "consent.reject": "প্রত্যাখ্যান", - "footer": "ফুটার", - "footer.next": "পরে", - "footer.previous": "পূর্ববর্তী", - "header": "হেডার", - "meta.comments": "মন্তব্য", - "meta.source": "উৎস", - "nav": "ন্যাভিগেশন", - "readtime.one": "১ মিনিট পড়া", - "readtime.other": "# মিনিট পড়া", - "rss.created": "আরএসএস ফিড", - "rss.updated": "আপডেট করা বিষয়বস্তুর আরএসএস ফিড", - "search": "অনুসন্ধান করুন", - "search.config.pipeline": " ", - "search.placeholder": "অনুসন্ধান করুন", - "search.share": "শেয়ার", - "search.reset": "রিসেট", - "search.result.initializer": "অনুসন্ধান শুরু করা হচ্ছে", - "search.result.placeholder": "সার্চ টাইপ করুন", - "search.result.none": "কিছু পাওয়া যায়নি", - "search.result.one": "১ টা ডকুমেন্ট", - "search.result.other": "# টা ডকুমেন্ট", - "search.result.more.one": "এই পৃষ্ঠায় আরও ১টি আছে", - "search.result.more.other": "এই পৃষ্ঠায় আরও #টি আছে", - "search.result.term.missing": "অনুপস্থিত", - "select.language": "ভাষা নির্বাচন করুণ", - "select.version": "সংস্করণ নির্বাচন করুণ", - "source": "রিপোজিটরিতে যান", - "source.file.contributors": "অবদানকারী", - "source.file.date.created": "তৈরি হয়েছে", - "source.file.date.updated": "শেষ আপডেট", - "tabs": "ট্যাব", - "toc": "সূচি তালিকা", - "top": "উপরে ফিরে যাও" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/ca.html b/src/templates/partials/languages/ca.html deleted file mode 100644 index 8fd2b03a..00000000 --- a/src/templates/partials/languages/ca.html +++ /dev/null @@ -1,75 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Catalan --> -{% macro t(key) %}{{ { - "language": "ca", - "action.edit": "Edita aquesta pàgina", - "action.skip": "Salta el contingut", - "action.view": "Visualitza el codi font", - "announce.dismiss": "No ho tornis a mostrar", - "blog.archive": "Arxiva", - "blog.categories": "Categories", - "blog.categories.in": "a", - "blog.continue": "Continua llegint", - "blog.draft": "Esborrany", - "blog.index": "Torna a l'índex", - "blog.meta": "Metadades", - "blog.references": "Enllaços relacionats", - "clipboard.copy": "Còpia al porta-retalls", - "clipboard.copied": "Copiat al porta-retalls", - "consent.accept": "Accepta", - "consent.manage": "Gestiona la configuració", - "consent.reject": "Rebutja", - "footer": "Peu de pàgina", - "footer.next": "Següent", - "footer.previous": "Anterior", - "header": "Capçalera", - "meta.comments": "Comentaris", - "meta.source": "Codi font", - "nav": "Navegació", - "readtime.one": "1 min de lectura", - "readtime.other": "# min de lectura", - "rss.created": "Canal RSS", - "rss.updated": "Canal RSS de contingut actualitzat", - "search": "Cerca", - "search.placeholder": "Cerca", - "search.share": "Comparteix", - "search.reset": "Neteja", - "search.result.initializer": "Inicialitzant cerca", - "search.result.placeholder": "Escriu per a començar a cercar", - "search.result.none": "Cap document coincideix", - "search.result.one": "1 document coincident", - "search.result.other": "# documents coincidents", - "search.result.more.one": "1 més en aquesta pàgina", - "search.result.more.other": "# més en aquesta pàgina", - "search.result.term.missing": "Desaparegut", - "select.language": "Selecciona la llengua", - "select.version": "Selecciona la versió", - "source": "Ves al repositori", - "source.file.contributors": "Col·laboradors", - "source.file.date.created": "Creada", - "source.file.date.updated": "Darrera actualització", - "tabs": "Pestanyes", - "toc": "Taula de continguts", - "top": "Torna a l'inici" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/cs.html b/src/templates/partials/languages/cs.html deleted file mode 100644 index fb955865..00000000 --- a/src/templates/partials/languages/cs.html +++ /dev/null @@ -1,75 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Czech --> -{% macro t(key) %}{{ { - "language": "cs", - "action.edit": "Upravit tuto stránku", - "action.skip": "Přeskočit obsah", - "action.view": "Zobrazit zdroj této stránky", - "announce.dismiss": "Již nezobrazovat", - "blog.archive": "Archiv", - "blog.categories": "Kategorie", - "blog.categories.in": "v", - "blog.continue": "Pokračovat ve čtení", - "blog.draft": "Návrh", - "blog.index": "Zpět na index", - "blog.meta": "Metadata", - "blog.references": "Související odkazy", - "clipboard.copy": "Kopírovat do schránky", - "clipboard.copied": "Zkopírováno do schránky", - "consent.accept": "Akceptovat", - "consent.manage": "Spravovat nastavení", - "consent.reject": "Odmítnout", - "footer": "Zápatí", - "footer.next": "Další", - "footer.previous": "Předchozí", - "header": "Záhlaví", - "meta.comments": "Komentáře", - "meta.source": "Zdroj", - "nav": "Navigace", - "readtime.one": "1 min čtení", - "readtime.other": "# min čtení", - "rss.created": "RSS kanál", - "rss.updated": "RSS zdroj aktualizovaného obsahu", - "search": "Vyhledávání", - "search.placeholder": "Hledat", - "search.share": "Sdílet", - "search.reset": "Vyčistit", - "search.result.initializer": "Inicializace vyhledávání", - "search.result.placeholder": "Pište co se má vyhledat", - "search.result.none": "Nenalezeny žádné dokumenty", - "search.result.one": "Nalezený dokument: 1", - "search.result.other": "Nalezené dokumenty: #", - "search.result.more.one": "1 další na této stránce", - "search.result.more.other": "# více na této stránce", - "search.result.term.missing": "Chybějící", - "select.language": "Zvolte jazyk", - "select.version": "Vyberte verzi", - "source": "Přejít do repozitáře", - "source.file.contributors": "Přispěvatelé", - "source.file.date.created": "Vytvořeno", - "source.file.date.updated": "Poslední aktualizace", - "tabs": "Karty", - "toc": "Obsah", - "top": "Zpět na začátek" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/da.html b/src/templates/partials/languages/da.html deleted file mode 100644 index 2f9da2db..00000000 --- a/src/templates/partials/languages/da.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Danish --> -{% macro t(key) %}{{ { - "language": "da", - "action.edit": "Redigér denne side", - "action.skip": "Gå til indholdet", - "action.view": "Vis kildetekst på denne side", - "announce.dismiss": "Vis ikke dette igen", - "blog.archive": "Arkiv", - "blog.categories": "Kategorier", - "blog.categories.in": "i", - "blog.continue": "Læs mere", - "blog.draft": "Udkast", - "blog.index": "Gå tilbage", - "blog.meta": "Metadata", - "blog.references": "Relateret indhold", - "clipboard.copy": "Kopiér til udklipsholderen", - "clipboard.copied": "Kopieret til udklipsholderen", - "consent.accept": "Accepter", - "consent.manage": "Administrer indstillinger", - "consent.reject": "Afvis", - "footer": "Sidefod", - "footer.next": "Næste", - "footer.previous": "Forrige", - "header": "Sidehoved", - "meta.comments": "Kommentarer", - "meta.source": "Kilde", - "nav": "Navigation", - "readtime.one": "1 minuts læsetid", - "readtime.other": "# minuts læstid", - "rss.created": "RSS feed", - "rss.updated": "RSS feed af opdateret indhold", - "search": "Søg", - "search.config.lang": "da", - "search.placeholder": "Søg", - "search.share": "Del", - "search.reset": "Nulstil søgning", - "search.result.initializer": "Start søgning", - "search.result.placeholder": "Indtast søgeord", - "search.result.none": "Ingen resultater fundet", - "search.result.one": "1 resultat", - "search.result.other": "# resultater", - "search.result.more.one": "1 resultat mere på denne side", - "search.result.more.other": "# resultater mere på denne side", - "search.result.term.missing": "Mangler", - "select.language": "Vælg sprog", - "select.version": "Vælg version", - "source": "Åbn arkiv", - "source.file.contributors": "Bidragydere", - "source.file.date.created": "Oprettet", - "source.file.date.updated": "Sidste ændring", - "tabs": "Faner", - "toc": "Indholdsfortegnelse", - "top": "Tilbage til start" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/de.html b/src/templates/partials/languages/de.html deleted file mode 100644 index bfd8b909..00000000 --- a/src/templates/partials/languages/de.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: German --> -{% macro t(key) %}{{ { - "language": "de", - "action.edit": "Seite editieren", - "action.skip": "Zum Inhalt", - "action.view": "Quellcode der Seite anzeigen", - "announce.dismiss": "Nicht mehr anzeigen", - "blog.archive": "Archiv", - "blog.categories": "Kategorien", - "blog.categories.in": "in", - "blog.continue": "Weiterlesen", - "blog.draft": "Entwurf", - "blog.index": "Zur Übersicht", - "blog.meta": "Metadaten", - "blog.references": "Weiterführende Links", - "clipboard.copy": "In Zwischenablage kopieren", - "clipboard.copied": "In Zwischenablage kopiert", - "consent.accept": "Akzeptieren", - "consent.manage": "Einstellungen", - "consent.reject": "Ablehnen", - "footer": "Fußzeile", - "footer.next": "Weiter", - "footer.previous": "Zurück", - "header": "Kopfzeile", - "meta.comments": "Kommentare", - "meta.source": "Quellcode", - "nav": "Navigation", - "readtime.one": "1 Min. Lesezeit", - "readtime.other": "# Min. Lesezeit", - "rss.created": "RSS Feed", - "rss.updated": "RSS Feed der aktualisierten Inhalte", - "search": "Suche", - "search.config.lang": "de", - "search.placeholder": "Suche", - "search.share": "Teilen", - "search.reset": "Zurücksetzen", - "search.result.initializer": "Suche wird initialisiert", - "search.result.placeholder": "Suchbegriff eingeben", - "search.result.none": "Keine Suchergebnisse", - "search.result.one": "1 Suchergebnis", - "search.result.other": "# Suchergebnisse", - "search.result.more.one": "1 weiteres Suchergebnis auf dieser Seite", - "search.result.more.other": "# weitere Suchergebnisse auf dieser Seite", - "search.result.term.missing": "Es fehlt", - "select.language": "Sprache wechseln", - "select.version": "Version auswählen", - "source": "Zum Repository", - "source.file.contributors": "Mitwirkende", - "source.file.date.created": "Erstellt", - "source.file.date.updated": "Letztes Update", - "tabs": "Hauptnavigation", - "toc": "Inhaltsverzeichnis", - "top": "Zurück zum Seitenanfang" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/el.html b/src/templates/partials/languages/el.html deleted file mode 100644 index 8dce1793..00000000 --- a/src/templates/partials/languages/el.html +++ /dev/null @@ -1,74 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Greek --> -{% macro t(key) %}{{ { - "language": "el", - "action.edit": "Επεξεργασία αυτής της σελίδας", - "action.skip": "Μετάβαση στο περιεχόμενο", - "action.view": "Προβολή πηγαίου κώδικα", - "announce.dismiss": "Μην το ξαναδείξετε αυτό", - "blog.archive": "Aρχείο", - "blog.categories": "Κατηγορίες", - "blog.categories.in": "Στο", - "blog.continue": "Περισσότερα", - "blog.draft": "Πρόχειρο", - "blog.index": "Eπιστροφή", - "blog.references": "Σχετικοί σύνδεσμοι", - "clipboard.copy": "Αντιγραφή στο πρόχειρο", - "clipboard.copied": "Αντιγράφηκε στο πρόχειρο", - "consent.accept": "Αποδοχή", - "consent.manage": "Περισσότερες επιλογές", - "consent.reject": "Απόρριψη", - "footer": "Υποσέλιδο", - "footer.next": "Επόμενο", - "footer.previous": "Προηγούμενο", - "header": "Κεφαλίδα", - "meta.comments": "Σχόλια", - "meta.source": "Πηγή", - "nav": "Πλοήγηση", - "readtime.one": "1 λεπτό διάβασμα", - "readtime.other": "# λεπτά διάβασμα", - "rss.created": "Ροές Δεδομένων RSS", - "rss.updated": "Ροές Δεδομένων RSS. Τελευταία νέα", - "search": "Αναζήτηση", - "search.placeholder": "Αναζήτηση", - "search.share": "Διαμοίραση", - "search.reset": "Καθαρισμός", - "search.result.initializer": "Αρχικοποίηση αναζήτησης", - "search.result.placeholder": "Πληκτρολογήστε για να αρχίσει η αναζήτηση", - "search.result.none": "δεν βρήκε κάποιο έγγραφο", - "search.result.one": "1 έγγραφο που ταιριάζει", - "search.result.other": "# έγγραφα που ταιριάζουν", - "search.result.more.one": "1 ακόμα σε αυτήν τη σελίδα", - "search.result.more.other": "# ακόμα σε αυτήν τη σελίδα", - "search.result.term.missing": "Λείπει", - "select.language": "Επιλογή γλώσσας", - "select.version": "Επιλογή έκδοσης", - "source": "Μετάβαση στο αποθετήριο", - "source.file.contributors": "Συνεισφέροντες", - "source.file.date.created": "Δημιουργήθηκε", - "source.file.date.updated": "τελευταία ενημέρωση", - "tabs": "Καρτέλες", - "toc": "Πίνακας περιεχομένων", - "top": "Επιστροφή στην αρχή" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/en.html b/src/templates/partials/languages/en.html deleted file mode 100644 index 0e6a73ac..00000000 --- a/src/templates/partials/languages/en.html +++ /dev/null @@ -1,79 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: English --> -{% macro t(key) %}{{ { - "language": "en", - "direction": "ltr", - "action.edit": "Edit this page", - "action.skip": "Skip to content", - "action.view": "View source of this page", - "announce.dismiss": "Don't show this again", - "blog.archive": "Archive", - "blog.categories": "Categories", - "blog.categories.in": "in", - "blog.continue": "Continue reading", - "blog.draft": "Draft", - "blog.index": "Back to index", - "blog.meta": "Metadata", - "blog.references": "Related links", - "clipboard.copy": "Copy to clipboard", - "clipboard.copied": "Copied to clipboard", - "consent.accept": "Accept", - "consent.manage": "Manage settings", - "consent.reject": "Reject", - "footer": "Footer", - "footer.next": "Next", - "footer.previous": "Previous", - "header": "Header", - "meta.comments": "Comments", - "meta.source": "Source", - "nav": "Navigation", - "readtime.one": "1 min read", - "readtime.other": "# min read", - "rss.created": "RSS feed", - "rss.updated": "RSS feed of updated content", - "search": "Search", - "search.config.lang": "en", - "search.config.pipeline": "stopWordFilter", - "search.config.separator": "[\\s\\-]+", - "search.placeholder": "Search", - "search.share": "Share", - "search.reset": "Clear", - "search.result.initializer": "Initializing search", - "search.result.placeholder": "Type to start searching", - "search.result.none": "No matching documents", - "search.result.one": "1 matching document", - "search.result.other": "# matching documents", - "search.result.more.one": "1 more on this page", - "search.result.more.other": "# more on this page", - "search.result.term.missing": "Missing", - "select.language": "Select language", - "select.version": "Select version", - "source": "Go to repository", - "source.file.contributors": "Contributors", - "source.file.date.created": "Created", - "source.file.date.updated": "Last update", - "tabs": "Tabs", - "toc": "Table of contents", - "top": "Back to top" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/eo.html b/src/templates/partials/languages/eo.html deleted file mode 100644 index cd3829a8..00000000 --- a/src/templates/partials/languages/eo.html +++ /dev/null @@ -1,49 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Esperanto --> -{% macro t(key) %}{{ { - "language": "eo", - "action.edit": "Redakti ĉi tiun paĝon", - "action.skip": "Saltu al enhavo", - "clipboard.copy": "Kopii al tondujo", - "clipboard.copied": "Kopiado al klipo", - "footer": "Piedlinio", - "footer.next": "Sekva", - "footer.previous": "Antaŭa", - "header": "Kaplinio", - "meta.comments": "Komentoj", - "meta.source": "Fontkodo", - "nav": "Navigado", - "search.config.lang": "es", - "search.placeholder": "Serĉo", - "search.reset": "Klara", - "search.result.placeholder": "Tajpu por komenci serĉadon", - "search.result.none": "Neniuj kongruaj dokumentoj", - "search.result.one": "1 kongrua dokumento", - "search.result.other": "# kongruaj dokumentoj", - "source": "Iru al deponejo", - "source.file.date.created": "Kreita", - "source.file.date.updated": "Lasta ĝisdatigo", - "tabs": "Langetoj", - "toc": "Enhavtabelo" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/es.html b/src/templates/partials/languages/es.html deleted file mode 100644 index bbbd9dc1..00000000 --- a/src/templates/partials/languages/es.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Spanish --> -{% macro t(key) %}{{ { - "language": "es", - "action.edit": "Editar esta página", - "action.skip": "Saltar a contenido", - "action.view": "Ver código fuente de esta página", - "announce.dismiss": "No mostrar esto de nuevo", - "blog.archive": "Archivo", - "blog.categories": "Categorías", - "blog.categories.in": "en", - "blog.continue": "Seguir leyendo", - "blog.draft": "Borrador", - "blog.index": "Regresar al índice", - "blog.meta": "Metadata", - "blog.references": "Enlaces relacionados", - "clipboard.copy": "Copiar al portapapeles", - "clipboard.copied": "Copiado al portapapeles", - "consent.accept": "Aceptar", - "consent.manage": "Gestionar cookies", - "consent.reject": "Rechazar", - "footer": "Pie", - "footer.next": "Siguiente", - "footer.previous": "Anterior", - "header": "Cabecera", - "meta.comments": "Comentarios", - "meta.source": "Fuente", - "nav": "Navegación", - "readtime.one": "1 minuto de lectura", - "readtime.other": "# minutos de lectura", - "rss.created": "Fuente RSS", - "rss.updated": "Fuente RSS de contenido actualizado", - "search": "Buscar", - "search.config.lang": "es", - "search.placeholder": "Búsqueda", - "search.share": "Compartir", - "search.reset": "Limpiar", - "search.result.initializer": "Inicializando búsqueda", - "search.result.placeholder": "Teclee para comenzar búsqueda", - "search.result.none": "No se encontraron documentos", - "search.result.one": "1 documento encontrado", - "search.result.other": "# documentos encontrados", - "search.result.more.one": "1 más en esta página", - "search.result.more.other": "# más en esta página", - "search.result.term.missing": "Falta", - "select.language": "Seleccionar idioma", - "select.version": "Seleccionar versión", - "source": "Ir al repositorio", - "source.file.contributors": "Contribuidores", - "source.file.date.created": "Creado", - "source.file.date.updated": "Última actualización", - "tabs": "Pestañas", - "toc": "Tabla de contenidos", - "top": "Volver al principio" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/et.html b/src/templates/partials/languages/et.html deleted file mode 100644 index 8add4225..00000000 --- a/src/templates/partials/languages/et.html +++ /dev/null @@ -1,43 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Estonian --> -{% macro t(key) %}{{ { - "language": "et", - "action.edit": "Muuda seda lehte", - "action.skip": "Keri sisuni", - "clipboard.copy": "Kopeeri lõikelauale", - "clipboard.copied": "Kopeeritud", - "footer.next": "Järgmine", - "footer.previous": "Eelmine", - "meta.comments": "Kommentaarid", - "meta.source": "Lähtekood", - "search.placeholder": "Otsi", - "search.result.placeholder": "Otsimiseks kirjuta siia", - "search.result.none": "Otsingule ei leitud ühtegi vastet", - "search.result.one": "Leiti üks tulemus", - "search.result.other": "Leiti # tulemust", - "source": "Ava repositooriumis", - "source.file.date.created": "Loodud", - "source.file.date.updated": "Viimane uuendus", - "toc": "Sisukord" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/eu.html b/src/templates/partials/languages/eu.html deleted file mode 100644 index 0e52f925..00000000 --- a/src/templates/partials/languages/eu.html +++ /dev/null @@ -1,75 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Basque --> -{% macro t(key) %}{{ { - "language": "eu", - "action.edit": "Editatu orri hau", - "action.skip": "Joan zuzenean edukira", - "action.view": "Ikusi orri honen iturburua", - "announce.dismiss": "Ez erakutsi hau berriro", - "blog.archive": "Artxiboa", - "blog.categories": "Kategoriak", - "blog.categories.in": "kategoria", - "blog.continue": "Jarraitu irakurtzen", - "blog.draft": "Zirriborroa", - "blog.index": "Itzuli aurkibidera", - "blog.meta": "Metadatuak", - "blog.references": "Erlazionatutako estekak", - "clipboard.copy": "Kopiatu arbelean", - "clipboard.copied": "Arbelean kopiatuta", - "consent.accept": "Onartu", - "consent.manage": "Kudeatu ezarpenak", - "consent.reject": "Ukatu", - "footer": "Orri-oina", - "footer.next": "Hurrengoa", - "footer.previous": "Aurrekoa", - "header": "Atalburua", - "meta.comments": "Iruzkinak", - "meta.source": "Iturburua", - "nav": "Nabigazioa", - "readtime.one": "Minutu batean irakurtzeko", - "readtime.other": "# minututan irakurtzeko", - "rss.created": "RSS jarioa", - "rss.updated": "Eduki eguneratuen RSS jarioa", - "search": "Bilatu", - "search.placeholder": "Bilatu", - "search.share": "Partekatu", - "search.reset": "Garbitu", - "search.result.initializer": "Bilaketa hasieratzen", - "search.result.placeholder": "Idatzi bilatzen hasteko", - "search.result.none": "Bat datorren dokumenturik ez", - "search.result.one": "Bat datorren dokumentu bat", - "search.result.other": "Bat datozen # dokumentu", - "search.result.more.one": "Bat gehiago orri honetan", - "search.result.more.other": "# gehiago orri honetan", - "search.result.term.missing": "Falta da", - "select.language": "Hautatu hizkuntza", - "select.version": "Hautatu bertsioa", - "source": "Joan biltegira", - "source.file.contributors": "Kolaboratzaileak", - "source.file.date.created": "Sortze data", - "source.file.date.updated": "Azken eguneratzea", - "tabs": "Fitxak", - "toc": "Edukiak", - "top": "Igo goraino" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/fa.html b/src/templates/partials/languages/fa.html deleted file mode 100644 index deaa8bca..00000000 --- a/src/templates/partials/languages/fa.html +++ /dev/null @@ -1,77 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Persian (Farsi) --> -{% macro t(key) %}{{ { - "language": "fa", - "direction": "rtl", - "action.edit": "این صفحه را ویرایش کنید", - "action.skip": "پرش به محتویات", - "action.view": "محتویات این صفحه را نشان بده", - "announce.dismiss": "این را دیگر نشان نده", - "blog.archive": "بایگانی", - "blog.categories": "دستهبندیها", - "blog.categories.in": "در", - "blog.continue": "ادامه به خواندن", - "blog.draft": "پیشنویس", - "blog.index": "برگشت به فهرست", - "blog.meta": "فراداده", - "blog.references": "پیوندهای مربوط", - "clipboard.copy": "کپی کردن", - "clipboard.copied": "کپی شد", - "consent.accept": "تایید", - "consent.manage": "مدیریت تنظیمات", - "consent.reject": "رد کردن", - "footer": "پاورقی", - "footer.next": "بعدی", - "footer.previous": "قبلی", - "header": "سرتیتر", - "meta.comments": "نظرات", - "meta.source": "منبع", - "nav": "هدایت", - "readtime.one": "1 دقیقه زمان خواندن", - "readtime.other": "# دقیقه زمان خواندن", - "rss.created": "خوراک آراساس", - "rss.updated": "خوراک آراساس محتویات بهروز شده", - "search": "جستجو", - "search.config.pipeline": " ", - "search.placeholder": "جستجو", - "search.share": "همرسانی", - "search.reset": "بازنشانی", - "search.result.initializer": "راهاندازی جستجو", - "search.result.placeholder": "برای شروع جستجو تایپ کنید", - "search.result.none": "سندی یافت نشد", - "search.result.one": "1 سند یافت شد", - "search.result.other": "# سند یافت شد", - "search.result.more.one": "1 مورد دیگر در این صفحه", - "search.result.more.other": "# مورد دیگر در این صفحه", - "search.result.term.missing": "موجود نیست", - "select.language": "انتخاب زبان", - "select.version": "انتخاب ویرایش", - "source": "رفتن به مخزن", - "source.file.contributors": "مشارکت کنندگان", - "source.file.date.created": "ایجاد شده", - "source.file.date.updated": "اخرین بروزرسانی", - "tabs": "زبانهها", - "toc": "فهرست موضوعات", - "top": "برگشت به بالا" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/fi.html b/src/templates/partials/languages/fi.html deleted file mode 100644 index 8ee09122..00000000 --- a/src/templates/partials/languages/fi.html +++ /dev/null @@ -1,44 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Finnish --> -{% macro t(key) %}{{ { - "language": "fi", - "action.edit": "Muokkaa tätä sivua", - "action.skip": "Hyppää sisältöön", - "clipboard.copy": "Kopioi leikepöydälle", - "clipboard.copied": "Kopioitu leikepöydälle", - "footer.next": "Seuraava", - "footer.previous": "Edellinen", - "meta.comments": "Kommentit", - "meta.source": "Lähdekodi", - "search.config.lang": "fi", - "search.placeholder": "Hae", - "search.result.placeholder": "Kirjoita aloittaaksesi haun", - "search.result.none": "Ei täsmääviä dokumentteja", - "search.result.one": "1 täsmäävä dokumentti", - "search.result.other": "# täsmäävää dokumenttia", - "source": "Mene repositoryyn", - "source.file.date.created": "Luotu", - "source.file.date.updated": "Viimeisin päivitys", - "toc": "Sisällysluettelo" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/fr.html b/src/templates/partials/languages/fr.html deleted file mode 100644 index 9d49535a..00000000 --- a/src/templates/partials/languages/fr.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: French --> -{% macro t(key) %}{{ { - "language": "fr", - "action.edit": "Editer cette page", - "action.skip": "Aller au contenu", - "action.view": "Consulter la source de cette page", - "announce.dismiss": "Ne plus montrer cela", - "blog.archive": "Archive", - "blog.categories": "Catégories", - "blog.categories.in": "dans", - "blog.continue": "Continuer à lire", - "blog.draft": "Brouillon", - "blog.index": "Retourner à l'index", - "blog.meta": "Metadonnées", - "blog.references": "Liens connexes", - "clipboard.copy": "Copier dans le presse-papier", - "clipboard.copied": "Copié dans le presse-papier", - "consent.accept": "Accepter", - "consent.manage": "Paramétrer vos choix", - "consent.reject": "Refuser", - "footer": "Pied de page", - "footer.next": "Suivant", - "footer.previous": "Précédent", - "header": "En-tête", - "meta.comments": "Commentaires", - "meta.source": "Source", - "nav": "Navigation", - "readtime.one": "1 min de lecture", - "readtime.other": "# min de lecture", - "rss.created": "Flux RSS", - "rss.updated": "Flux RSS du contenu mis à jour", - "search": "Recherche", - "search.config.lang": "fr", - "search.placeholder": "Rechercher", - "search.share": "Partager", - "search.reset": "Effacer", - "search.result.initializer": "Initialisation de la recherche", - "search.result.placeholder": "Taper pour démarrer la recherche", - "search.result.none": "Aucun document trouvé", - "search.result.one": "1 document trouvé", - "search.result.other": "# documents trouvés", - "search.result.more.one": "1 de plus sur cette page", - "search.result.more.other": "# de plus sur cette page", - "search.result.term.missing": "Non trouvé", - "select.language": "Sélectionner la langue", - "select.version": "Sélectionner la version", - "source": "Aller au dépôt", - "source.file.contributors": "Contributeurs", - "source.file.date.created": "Créé", - "source.file.date.updated": "Dernière mise à jour", - "tabs": "Onglets", - "toc": "Table des matières", - "top": "Retour en haut de la page" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/gl.html b/src/templates/partials/languages/gl.html deleted file mode 100644 index ecb54ffd..00000000 --- a/src/templates/partials/languages/gl.html +++ /dev/null @@ -1,56 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Galician --> -{% macro t(key) %}{{ { - "language": "gl", - "action.edit": "Editar esta páxina", - "action.skip": "Ir ao contido", - "clipboard.copy": "Copiar no cortapapeis", - "clipboard.copied": "Copiado no cortapapeis", - "footer": "Pé", - "footer.next": "Seguinte", - "footer.previous": "Anterior", - "header": "Cabeceira", - "meta.comments": "Comentarios", - "meta.source": "Fonte", - "nav": "Navegación", - "search.config.lang": "es", - "search.placeholder": "Procura", - "search.reset": "Limpar", - "search.result.initializer": "Inicializando procura", - "search.result.placeholder": "Insira un termo", - "search.result.none": "Sen resultados", - "search.result.one": "1 resultado atopado", - "search.result.other": "# resultados atopados", - "search.result.more.one": "1 máis nesta páxina", - "search.result.more.other": "# máis nesta páxina", - "search.result.term.missing": "Falta", - "select.language": "Seleccionar idioma", - "select.version": "Seleccionar version", - "source": "Ir ao repositorio", - "source.file.date.created": "Creada", - "source.file.date.updated": "Última actualización", - "tabs": "Pestanas", - "toc": "Táboa de contidos", - "top": "Volver ao principio" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/he.html b/src/templates/partials/languages/he.html deleted file mode 100644 index 128edab5..00000000 --- a/src/templates/partials/languages/he.html +++ /dev/null @@ -1,77 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Hebrew --> -{% macro t(key) %}{{ { - "language": "he", - "direction": "rtl", - "action.edit": "עריכת הדף הזה", - "action.skip": "לדלג לתוכן", - "action.view": "צפה במקור של דף זה", - "announce.dismiss": "לא להציג את זה שוב", - "blog.archive": "ארכיון", - "blog.categories": "קטגוריות", - "blog.categories.in": "בתוך", - "blog.continue": "המשך לקרוא", - "blog.draft": "טיוטה", - "blog.index": "חזרה לאינדקס", - "blog.meta": "מטא-נתונים", - "blog.references": "קישורים קשורים", - "clipboard.copy": "העתקה ללוח", - "clipboard.copied": "הועתק ללוח", - "consent.accept": "לקבל", - "consent.manage": "לנהל הגדרות", - "consent.reject": "לדחות", - "footer": "כותרת תחתונה", - "footer.next": "הבא", - "footer.previous": "הקודם", - "header": "כותרת עליונה", - "meta.comments": "הערות", - "meta.source": "מקור", - "nav": "ניווט", - "readtime.one": "קריאה 1 דקות", - "readtime.other": "# דקות קריאה", - "rss.created": "RSS הזנת", - "rss.updated": "הזנת RSS של תוכן מעודכן", - "search": "חיפוש", - "search.config.pipeline": " ", - "search.placeholder": "חיפוש", - "search.share": "שיתוף", - "search.reset": "ניקוי", - "search.result.initializer": "אתחול חיפוש", - "search.result.placeholder": "יש להקליד כדי להתחיל לחפש", - "search.result.none": "אין מסמכים תואמים", - "search.result.one": "מסמך1 תואם", - "search.result.other": "# מסמך תואם", - "search.result.more.one": "עוד אחד בדף הזה", - "search.result.more.other": "עוד # בדף הזה", - "search.result.term.missing": "חסר", - "select.language": "בחירת שפה", - "select.version": "בחירת גרסה", - "source": "לעבור אל המאגר", - "source.file.contributors": "תורמים", - "source.file.date.created": "נוצר", - "source.file.date.updated": "עדכון אחרון", - "tabs": "לשוניות", - "toc": "תוכן העניינים", - "top": "חזרה למעלה" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/hi.html b/src/templates/partials/languages/hi.html deleted file mode 100644 index 8c27c259..00000000 --- a/src/templates/partials/languages/hi.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Hindi --> -{% macro t(key) %}{{ { - "language": "hi", - "action.edit": "इस पृष्ठ को संपादित करें", - "action.skip": "विषय पर बढ़ें", - "action.view": "इस पृष्ठ का सूत्र देखें", - "announce.dismiss": "इसे पुनः न दिखायें", - "blog.archive": "पुरालेख", - "blog.categories": "वर्ग", - "blog.categories.in": "में", - "blog.continue": "पढ़ते रहिये", - "blog.draft": "मसौदा", - "blog.index": "सूचि को लौटें", - "blog.meta": "मेटाडेटा", - "blog.references": "सम्बंधित लिंक", - "clipboard.copy": "क्लिपबोर्ड पर कॉपी करें", - "clipboard.copied": "क्लिपबोर्ड पर कॉपी कर दिया गया", - "consent.accept": "स्वीकार करें", - "consent.manage": "सेटिंग्स मैनेज करें", - "consent.reject": "अस्वीकार करें", - "footer": "फुटर", - "footer.next": "आगामी", - "footer.previous": "पिछला", - "header": "शीर्षक", - "meta.comments": "टिप्पणियाँ", - "meta.source": "स्रोत", - "nav": "नैविगेशन", - "readtime.one": "1 मिनट पढ़ने को", - "readtime.other": "# मिनट पढ़ने को", - "rss.created": "RSS फीड", - "rss.updated": "नवीनतम विषयवस्तु का RSS feed", - "search": "खोजें", - "search.config.lang": "hi", - "search.placeholder": "खोज", - "search.share": "शेयर करें", - "search.reset": "हटा दें", - "search.result.initializer": "खोज शुरू करें", - "search.result.placeholder": "खोज शुरू करने के लिए टाइप करें", - "search.result.none": "कोई मिलान डॉक्यूमेंट नहीं", - "search.result.one": "1 मिलान डॉक्यूमेंट", - "search.result.other": "# मिलान डाक्यूमेंट्स", - "search.result.more.one": "1 और इस पृष्ठ पर", - "search.result.more.other": "# और इस पृष्ठ पर", - "search.result.term.missing": "ग़ायब", - "select.language": "भाषा चुनें", - "select.version": "वर्शन चुनें", - "source": "रिपॉजिटरी पर जाएं", - "source.file.contributors": "योगदाता", - "source.file.date.created": "बनाया था", - "source.file.date.updated": "आखिरी अपडेट", - "tabs": "टैब", - "toc": "विषय - सूची", - "top": "शीर्षभाग पर लौटें" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/hr.html b/src/templates/partials/languages/hr.html deleted file mode 100644 index 30afe6a9..00000000 --- a/src/templates/partials/languages/hr.html +++ /dev/null @@ -1,75 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Croatian --> -{% macro t(key) %}{{ { - "language": "hr", - "action.edit": "Uredi stranicu", - "action.skip": "Preskoči na sadržaj", - "action.view": "Pregledaj izvorni kod ove stranice", - "announce.dismiss": "Ne prikazuj ovo opet", - "blog.archive": "Arhiva", - "blog.categories": "Kategorije", - "blog.categories.in": "u", - "blog.continue": "Nastavi čitati", - "blog.draft": "Nacrt", - "blog.index": "Natrag na indeks", - "blog.meta": "Metapodaci", - "blog.references": "Srodne poveznice", - "clipboard.copy": "Kopiraj u međuspremnik", - "clipboard.copied": "Kopirano u međuspremnik", - "consent.accept": "Prihvati", - "consent.manage": "Upravljaj postavkama", - "consent.reject": "Odbij", - "footer": "Podnožje", - "footer.next": "Sljedeće", - "footer.previous": "Prethodno", - "header": "Zaglavlje", - "meta.comments": "Komentari", - "meta.source": "Izvor", - "nav": "Navigacija", - "readtime.one": "1 minuta čitanja", - "readtime.other": "# minut(a/e) čitanja", - "rss.created": "RSS izvor", - "rss.updated": "RSS izvor osvježenog sadržaja", - "search": "Pretraživanje", - "search.placeholder": "Pretraži", - "search.share": "Podijeli", - "search.reset": "Očisti", - "search.result.initializer": "Inicijaliziranje pretraživanja", - "search.result.placeholder": "Unesite pojam pretraživanja", - "search.result.none": "Ništa nije pronađeno", - "search.result.one": "1 rezultat pretraživanja", - "search.result.other": "# rezultat(a) pretraživanja", - "search.result.more.one": "1 rezultat na ovoj stranici", - "search.result.more.other": "# rezultat(a) na ovoj stranici", - "search.result.term.missing": "Nedostaje", - "select.language": "Odabir jezika", - "select.version": "Odabir verzije", - "source": "Idi u repozitorij", - "source.file.contributors": "Suradnici", - "source.file.date.created": "Stvaranje", - "source.file.date.updated": "Posljednje ažuriranje", - "tabs": "Kartice", - "toc": "Sadržaj", - "top": "Vrati se na vrh" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/hu.html b/src/templates/partials/languages/hu.html deleted file mode 100644 index 44798dd8..00000000 --- a/src/templates/partials/languages/hu.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Hungarian --> -{% macro t(key) %}{{ { - "language": "hu", - "action.edit": "Oldal szerkesztése", - "action.skip": "Kihagyás", - "action.view": "Oldal forrásának megtekintése", - "announce.dismiss": "Ne mutasd többet", - "blog.archive": "Archívum", - "blog.categories": "Kategóriák", - "blog.categories.in": "Kategória:", - "blog.continue": "Folytatás", - "blog.draft": "Piszkozat", - "blog.index": "Vissza a főoldalra", - "blog.meta": "Metaadat", - "blog.references": "Kapcsolódó linkek", - "clipboard.copy": "Másolás vágólapra", - "clipboard.copied": "Vágólapra másolva", - "consent.accept": "Elfogadás", - "consent.manage": "Beállítások", - "consent.reject": "Visszautasítás", - "footer": "Élőláb", - "footer.next": "Következő", - "footer.previous": "Előző", - "header": "Élőfej", - "meta.comments": "Hozzászólások", - "meta.source": "Forrás", - "nav": "Navigáció", - "readtime.one": "1 percnyi", - "readtime.other": "# percnyi", - "rss.created": "RSS feed", - "rss.updated": "Frissített tartalom RSS feedje", - "search": "Keresés", - "search.config.lang": "hu", - "search.placeholder": "Keresés", - "search.share": "Megosztás", - "search.reset": "Törlés", - "search.result.initializer": "Keresés inicializálása", - "search.result.placeholder": "Kereséshez írj ide valamit", - "search.result.none": "Nincs találat", - "search.result.one": "1 egyező dokumentum", - "search.result.other": "# egyező dokumentum", - "search.result.more.one": "1 további találat az oldalon", - "search.result.more.other": "# további találat az oldalon", - "search.result.term.missing": "Üres", - "select.language": "Nyelvváltás", - "select.version": "Verzióváltás", - "source": "Főoldalra ugrás", - "source.file.contributors": "Szerzők", - "source.file.date.created": "Létrehozva", - "source.file.date.updated": "Utolsó frissítés", - "tabs": "Lapok", - "toc": "Tartalomjegyzék", - "top": "Vissza a tetejére" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/hy.html b/src/templates/partials/languages/hy.html deleted file mode 100644 index e3418341..00000000 --- a/src/templates/partials/languages/hy.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Armenian --> -{% macro t(key) %}{{ { - "language": "hy", - "action.edit": "Խմբագրել այս էջը", - "action.skip": "Անցնել պարունակությանը", - "action.view": "Դիտել այս էջի սկզբնաղբյուրը", - "announce.dismiss": "Այլևս չցուցադրել", - "blog.archive": "Արխիվ", - "blog.categories": "Կատեգորիաներ", - "blog.categories.in": "in", - "blog.continue": "Շարունակել կարդալ", - "blog.draft": "Սևագիր", - "blog.index": "Հետ դեպի ինդեքս", - "blog.meta": "Մետատվյալներ", - "blog.references": "Առնչվող հղումներ", - "clipboard.copy": "Պատճենել", - "clipboard.copied": "Պատճենված է", - "consent.accept": "Ընդունել", - "consent.manage": "Կառավարել կարգավորումները", - "consent.reject": "Մերժել", - "footer": "Էջատակ", - "footer.next": "Հաջորդը", - "footer.previous": "Նախորդը", - "header": "Գլխագիր", - "meta.comments": "Մեկնաբանությունները", - "meta.source": "Աղբյուր", - "nav": "Տեղորոշում", - "readtime.one": "Ընթերցում՝ 1 րոպե", - "readtime.other": "Ընթերցում՝ # րոպե", - "rss.created": "RSS հոսք", - "rss.updated": "Արդիացված բովանդակության RSS հոսք", - "search": "Որոնում", - "search.config.pipeline": " ", - "search.placeholder": "Որոնում", - "search.share": "Կիսվել", - "search.reset": "Ջնջել", - "search.result.initializer": "Որոնում", - "search.result.placeholder": "Մուտքագրեք որոնելու համար", - "search.result.none": "Արդյունքներ չկան", - "search.result.one": "1 արդյունք", - "search.result.other": "# արդյունք", - "search.result.more.one": "ևս 1-ը այս էջում", - "search.result.more.other": "ևս #-ը այս էջում", - "search.result.term.missing": "Բացակայում է", - "select.language": "Ընտրել լեզուն", - "select.version": "Ընտրել տարբերակը", - "source": "Դեպի պահոց", - "source.file.contributors": "Հեղինակողներ", - "source.file.date.created": "Ստեղծված է", - "source.file.date.updated": "Վերջին թարմացումը", - "tabs": "Ներդիրներ", - "toc": "Բովանդակություն", - "top": "Վերադառնալ սկիզբ" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/id.html b/src/templates/partials/languages/id.html deleted file mode 100644 index c54229f0..00000000 --- a/src/templates/partials/languages/id.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Indonesian --> -{% macro t(key) %}{{ { - "language": "id", - "action.edit": "Ubah halaman ini", - "action.skip": "Lewati ke isi", - "action.view": "Lihat sumber halaman ini", - "announce.dismiss": "Jangan lihat ini lagi", - "blog.archive": "Arsip", - "blog.categories": "Kategori", - "blog.categories.in": "dalam", - "blog.continue": "Lanjut membaca", - "blog.draft": "Draf", - "blog.index": "Kembali ke indeks", - "blog.meta": "Metadata", - "blog.references": "Tautan yang berhubungan", - "clipboard.copy": "Salin ke clipboard", - "clipboard.copied": "Tersalin ke clipboard", - "consent.accept": "Terima", - "consent.manage": "Kelola pengaturan", - "consent.reject": "Tolak", - "footer": "Footer", - "footer.next": "Selanjutnya", - "footer.previous": "Sebelumnya", - "header": "Header", - "meta.comments": "Komentar", - "meta.source": "Sumber", - "nav": "Navigasi", - "readtime.one": "1 menit baca", - "readtime.other": "# menit baca", - "rss.created": "Umpan RSS", - "rss.updated": "Umpan RSS dari konten yang diperbarui", - "search": "Cari", - "search.config.pipeline": " ", - "search.placeholder": "Cari", - "search.share": "Bagikan", - "search.reset": "Kosongkan", - "search.result.initializer": "Mempersiapkan pencarian", - "search.result.placeholder": "Ketik untuk mulai pencarian", - "search.result.none": "Tidak ada dokumen yang sesuai", - "search.result.one": "1 dokumen ditemukan", - "search.result.other": "# dokumen ditemukan", - "search.result.more.one": "1 lagi di halaman ini", - "search.result.more.other": "# lagi di halaman ini", - "search.result.term.missing": "Tidak ada", - "select.language": "Pilih bahasa", - "select.version": "Pilih versi", - "source": "Ke repositori", - "source.file.contributors": "Kontributor", - "source.file.date.created": "Dibuat", - "source.file.date.updated": "Pembaruan terakhir", - "tabs": "Tab", - "toc": "Daftar isi", - "top": "Kembali ke atas" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/is.html b/src/templates/partials/languages/is.html deleted file mode 100644 index 5b9a47e8..00000000 --- a/src/templates/partials/languages/is.html +++ /dev/null @@ -1,75 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Icelandic --> -{% macro t(key) %}{{ { - "language": "is", - "action.edit": "Breyta þessari síðu", - "action.skip": "Hoppa yfir í efnið", - "action.view": "Skoða frumgögn þessarar síðu", - "announce.dismiss": "Ekki sýna þetta aftur", - "blog.archive": "Safn", - "blog.categories": "Flokkar", - "blog.categories.in": "í", - "blog.continue": "Lesa meira", - "blog.draft": "Uppkast", - "blog.index": "Til baka í yfirlit", - "blog.meta": "Lýsigögn", - "blog.references": "Þessu tengt", - "clipboard.copy": "Afrita á klemmuspjald", - "clipboard.copied": "Afritað á klemmuspjald", - "consent.accept": "Samþykkja", - "consent.manage": "Breyta stillingum", - "consent.reject": "Hafna", - "footer": "Síðufótur", - "footer.next": "Næsta", - "footer.previous": "Fyrri", - "header": "Haus", - "meta.comments": "Umræður", - "meta.source": "Frumgögn", - "nav": "Valmynd", - "readtime.one": "1 mín lestur", - "readtime.other": "# mín lestur", - "rss.created": "RSS veita", - "rss.updated": "RSS veita fyrir uppfært innihald", - "search": "Leita", - "search.placeholder": "Leita", - "search.share": "Deila", - "search.reset": "Hreinsa", - "search.result.initializer": "Ræsi leitarvél", - "search.result.placeholder": "Byrjaðu að skrifa til að hefja leit", - "search.result.none": "Engar síður fundust", - "search.result.one": "1 síða fannst", - "search.result.other": "# síður fundust", - "search.result.more.one": "1 til viðbótar á þessari síðu", - "search.result.more.other": "# til viðbótar á þessari síðu", - "search.result.term.missing": "Vantar", - "select.language": "Veldu tungumál", - "select.version": "Veldu útgáfu", - "source": "Fara í gagnageymslu", - "source.file.contributors": "Meðhöfundar", - "source.file.date.created": "Búið til", - "source.file.date.updated": "Síðast uppfært", - "tabs": "Flipar", - "toc": "Efnisyfirlit", - "top": "Fara aftur efst" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/it.html b/src/templates/partials/languages/it.html deleted file mode 100644 index 77956ee7..00000000 --- a/src/templates/partials/languages/it.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Italian --> -{% macro t(key) %}{{ { - "language": "it", - "action.edit": "Modifica", - "action.skip": "Vai al contenuto", - "action.view": "Vedi il sorgente di questa pagina", - "announce.dismiss": "Non mostrare più", - "blog.archive": "Archivio", - "blog.categories": "Categorie", - "blog.categories.in": "in", - "blog.continue": "Continua a leggere", - "blog.draft": "Bozza", - "blog.index": "Torna all'indice", - "blog.meta": "Metadati", - "blog.references": "Collegamenti", - "clipboard.copy": "Copia", - "clipboard.copied": "Copiato", - "consent.accept": "Accetta", - "consent.manage": "Gestisci le opzioni", - "consent.reject": "Rifiuta", - "footer": "Piede", - "footer.next": "Successivo", - "footer.previous": "Precedente", - "header": "Intestazione", - "meta.comments": "Commenti", - "meta.source": "Sorgente", - "nav": "Navigazione", - "readtime.one": "1 minuto di lettura", - "readtime.other": "# minuti di lettura", - "rss.created": "Feed RSS", - "rss.updated": "Contenuto aggiornato del feed RSS", - "search": "Cerca", - "search.config.lang": "it", - "search.placeholder": "Cerca", - "search.share": "Condividi", - "search.reset": "Cancella", - "search.result.initializer": "Inizializza la ricerca", - "search.result.placeholder": "Scrivi per iniziare a cercare", - "search.result.none": "Nessun documento trovato", - "search.result.one": "1 documento trovato", - "search.result.other": "# documenti trovati", - "search.result.more.one": "1 altro in questa pagina", - "search.result.more.other": "# altri in questa pagina", - "search.result.term.missing": "Non presente", - "select.language": "Seleziona la lingua", - "select.version": "Seleziona la versione", - "source": "Apri repository", - "source.file.contributors": "Contributori", - "source.file.date.created": "Creata", - "source.file.date.updated": "Ultimo aggiornamento", - "tabs": "Tabs", - "toc": "Indice", - "top": "Torna su" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/ja.html b/src/templates/partials/languages/ja.html deleted file mode 100644 index b4b4279d..00000000 --- a/src/templates/partials/languages/ja.html +++ /dev/null @@ -1,78 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Japanese --> -{% macro t(key) %}{{ { - "language": "ja", - "action.edit": "編集", - "action.skip": "コンテンツにスキップ", - "action.view": "このページの原文を表示", - "announce.dismiss": "非表示にします", - "blog.archive": "過去の投稿", - "blog.categories": "カテゴリー", - "blog.categories.in": "", - "blog.continue": "続きを読む", - "blog.draft": "下書き", - "blog.index": "ブログトップへ戻る", - "blog.meta": "メタデータ", - "blog.references": "関連リンク", - "clipboard.copy": "クリップボードへコピー", - "clipboard.copied": "コピーしました", - "consent.accept": "同意", - "consent.manage": "サイトの設定", - "consent.reject": "拒否", - "footer": "フッター", - "footer.next": "次", - "footer.previous": "前", - "header": "ヘッダー", - "meta.comments": "コメント", - "meta.source": "ソース", - "nav": "ナビゲーション", - "readtime.one": "このページは約1分で読めます", - "readtime.other": "このページは約#分で読めます", - "rss.created": "新しいページのRSSフィード", - "rss.updated": "更新されたページのRSSフィード", - "search": "検索", - "search.config.lang": "ja", - "search.config.pipeline": "stemmer", - "search.config.separator": "[\\s\\- 、。,.]+", - "search.placeholder": "検索", - "search.share": "共有", - "search.reset": "クリア", - "search.result.initializer": "検索を初期化", - "search.result.placeholder": "検索キーワードを入力してください", - "search.result.none": "何も見つかりませんでした", - "search.result.one": "1件見つかりました", - "search.result.other": "#件見つかりました", - "search.result.more.one": "このページ内にもう1件見つかりました", - "search.result.more.other": "このページ内にあと#件見つかりました", - "search.result.term.missing": "検索に含まれない", - "select.language": "言語切り替え", - "select.version": "バージョン切り替え", - "source": "リポジトリへ", - "source.file.contributors": "投稿者", - "source.file.date.created": "作成日", - "source.file.date.updated": "最終更新日", - "tabs": "タブ", - "toc": "目次", - "top": "ページトップへ戻る" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/ka.html b/src/templates/partials/languages/ka.html deleted file mode 100644 index edfd2e02..00000000 --- a/src/templates/partials/languages/ka.html +++ /dev/null @@ -1,49 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Georgian --> -{% macro t(key) %}{{ { - "language": "ka", - "action.edit": "გვერდის რედარქირება", - "action.skip": "კონტენტზე გადასვლა", - "clipboard.copy": "კოპირება", - "clipboard.copied": "კოპირებულია", - "footer.next": "შემდეგი", - "footer.previous": "წინა", - "meta.comments": "კომენტარები", - "meta.source": "წყარო", - "nav": "ნავიგაცია", - "search.config.pipeline": " ", - "search.placeholder": "ძებნა", - "search.reset": "გასუფთავება", - "search.result.placeholder": "ჩაწერე ძებნის დასაწყებად", - "search.result.none": "დოკუმენტი ვერ მოიძებნა", - "search.result.one": "მოიძებნა 1 დოკუმენტი", - "search.result.other": "მოიძებნა # დოკუმენტი", - "search.result.more.one": "კიდევ 1 ამ გვერდზე", - "search.result.more.other": "კიდევ # ამ გვერდზე", - "source": "საცავში გადასვლა", - "source.file.date.created": "შეიქმნა", - "source.file.date.updated": "ბოლო განახლება", - "tabs": "ტაბები", - "toc": "სარჩევი" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/kn.html b/src/templates/partials/languages/kn.html deleted file mode 100644 index bd0ff722..00000000 --- a/src/templates/partials/languages/kn.html +++ /dev/null @@ -1,75 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Kannada --> -{% macro t(key) %}{{ { - "language": "kn", - "action.edit": "ಈ ಪುಟವನ್ನು ತಿದ್ದುಪಡಿ ಮಾಡಿ", - "action.skip": "ವಿಷಯಕ್ಕೆ ತೆರಳಿ", - "action.view": "ಈ ಪುಟದ ಮೂಲವನ್ನು ವೀಕ್ಷಿಸಿ", - "announce.dismiss": "ಇದನ್ನು ಮತ್ತೊಮ್ಮೆ ತೋರಿಸಬೇಡಿ", - "blog.archive": "ಹಳೆಯ ಲೇಖನ", - "blog.categories": "ವರ್ಗಗಳು", - "blog.categories.in": "ರಲ್ಲಿ", - "blog.continue": "ಓದು ಮುಂದುವರೆಸಿ", - "blog.draft": "ಆರಂಭಿಕ ಬರವಣಿಗೆ", - "blog.index": "ಸೂಚ್ಯಂಕಕ್ಕೆ ಹಿಂತಿರುಗಿ", - "blog.meta": "ಮಾಹಿತಿಯ ಬಗ್ಗೆ ಮಾಹಿತಿ", - "blog.references": "ಸಂಬಂಧಿತ ಉಲ್ಲೇಖಗಳು", - "clipboard.copy": "ಇದನ್ನು ನಕಲಿಸಿ", - "clipboard.copied": "ಇದನ್ನು ನಕಲು ಮಾಡಿದೆ", - "consent.accept": "ನಾನು ಇದನ್ನು ಒಪ್ಪಿಕೊಳ್ಳುತ್ತೇನೆ", - "consent.manage": "ಸಂರಚನೆಯನ್ನು ನಿರ್ವಹಿಸಿ", - "consent.reject": "ನಾನು ಇದನ್ನು ತಿರಸ್ಕರಿಸುತ್ತೇನೆ", - "footer": "ಅಡಿಟಿಪ್ಪಣಿ", - "footer.next": "ಮುಂದಿನ ಸಂಚಿಕೆ", - "footer.previous": "ಹಿಂದಿನ ಸಂಚಿಕೆ", - "header": "ಮೇಲ್ಟಿಪ್ಪಣಿ", - "meta.comments": "ಪ್ರತಿಕ್ರಿಯೆಗಳು", - "meta.source": "ಮೂಲ", - "nav": "ಸಂಚರಣೆ", - "readtime.one": "ಓದಲು ೧ ನಿಮಿಷ ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ", - "readtime.other": "ಓದಲು # ನಿಮಿಷಗಳನ್ನು ತೆಗೆದುಕೊಳ್ಳುತ್ತದೆ", - "rss.created": "ಆರ್ಎಸ್ಎಸ್ ಸೇವೆ", - "rss.updated": "ಆರ್ಎಸ್ಎಸ್ ಸೇವೆಯಿಂದ ಇತ್ತೀಚಿನ ನವೀಕರಣ", - "search": "ಹುಡುಕಿ", - "search.placeholder": "ಹುಡುಕಿ", - "search.share": "ಹಂಚಿಕೊಳ್ಳಿ", - "search.reset": "ಅಳಿಸು", - "search.result.initializer": "ಹುಡುಕಾಟವನ್ನು ಪ್ರಾರಂಭಿಸಲಾಗುತ್ತಿದೆ", - "search.result.placeholder": "ಬರೆಯುವ ಮೂಲಕ ಹುಡುಕಲು ಪ್ರಾರಂಭಿಸಿ", - "search.result.none": "ಹೊಂದಾಣಿಕೆಯಾಗುವ ದಾಖಲೆಗಳಿಲ್ಲ", - "search.result.one": "೧ ಹೊಂದಾಣಿಕೆಯ ದಾಖಲೆಯಿದೆ", - "search.result.other": "# ಹೊಂದಾಣಿಕೆಯ ದಾಖಲೆಗಳಿವೆ", - "search.result.more.one": "ಈ ಪುಟದಲ್ಲಿ ಇನ್ನೂ ಒಂದು ಕಂಡುಬಂದಿದೆ", - "search.result.more.other": "ಈ ಪುಟದಲ್ಲಿ ಇನ್ನೂ # ಇವೆ", - "search.result.term.missing": "ಕಾಣೆಯಾಗಿದೆ", - "select.language": "ಭಾಷೆಯನ್ನು ಆಯ್ಕೆಮಾಡಿ", - "select.version": "ಆವೃತ್ತಿಯನ್ನು ಆಯ್ಕೆಮಾಡಿ", - "source": "ಭಂಡಾರಕ್ಕೆ ಹೋಗಿ", - "source.file.contributors": "ಕೊಡುಗೆದಾರರು", - "source.file.date.created": "ರಚಿಸಿದ ದಿನಾಂಕ", - "source.file.date.updated": "ಕೊನೆಯ ನವೀಕರಣ ದಿನಾಂಕ", - "tabs": "ವಿವಿಧ ಕಿಟಕಿಗಳು", - "toc": "ವಿಷಯಗಳ ಪಟ್ಟಿ", - "top": "ಮೇಲಕ್ಕೆ ಹಿಂತಿರುಗಿ" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/ko.html b/src/templates/partials/languages/ko.html deleted file mode 100644 index adadccb7..00000000 --- a/src/templates/partials/languages/ko.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Korean --> -{% macro t(key) %}{{ { - "language": "ko", - "action.edit": "이 페이지를 편집", - "action.skip": "콘텐츠로 이동", - "action.view": "페이지소스 보기", - "announce.dismiss": "다시 안보기", - "blog.archive": "아카이브", - "blog.categories": "카테고리", - "blog.categories.in": "카테고리", - "blog.continue": "계속 읽기", - "blog.draft": "임시 저장", - "blog.index": "Index로 돌아가기", - "blog.meta": "메타데이터", - "blog.references": "관련 링크", - "clipboard.copy": "클립보드로 복사", - "clipboard.copied": "클립보드에 복사됨", - "consent.accept": "동의 허락", - "consent.manage": "동의 허락 관리", - "consent.reject": "동의 거부", - "footer": "하단/푸터", - "footer.next": "다음", - "footer.previous": "이전", - "header": "상단/헤더", - "meta.comments": "댓글", - "meta.source": "출처", - "nav": "네비게이션", - "readtime.one": "읽는시간 1분", - "readtime.other": "읽는시간 #분", - "rss.created": "RSS 피드 생성완료", - "rss.updated": "RSS 피드 업데이트완료", - "search": "검색", - "search.config.pipeline": " ", - "search.placeholder": "검색", - "search.share": "공유", - "search.reset": "지우기", - "search.result.initializer": "검색 초기화", - "search.result.placeholder": "검색어를 입력하세요", - "search.result.none": "검색어와 일치하는 문서가 없습니다", - "search.result.one": "1개의 일치하는 문서", - "search.result.other": "#개의 일치하는 문서", - "search.result.more.one": "이 문서에서 1개의 검색 결과 더 보기", - "search.result.more.other": "이 문서에서 #개의 검색 결과 더 보기", - "search.result.term.missing": "포함되지 않은 검색어", - "select.language": "언어설정", - "select.version": "버전 선택", - "source": "저장소로 이동", - "source.file.contributors": "참여자들", - "source.file.date.created": "작성일", - "source.file.date.updated": "마지막 업데이트", - "tabs": "탭", - "toc": "목차", - "top": "맨위로" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/ku-IQ.html b/src/templates/partials/languages/ku-IQ.html deleted file mode 100644 index fe9dd1e7..00000000 --- a/src/templates/partials/languages/ku-IQ.html +++ /dev/null @@ -1,64 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Kurdish (Soranî) --> -{% macro t(key) %}{{ { - "language": "ku", - "direction": "rtl", - "action.edit": "دەستکاری ئەم پەڕە بکە", - "action.skip": "ئەم ناوەڕۆکە بپەڕێنە", - "action.view": "سەرچاوەی ئەم لاپەڕەیە نیشان بدە", - "announce.dismiss": "دووبارە ئەمە پیشان مەدە", - "clipboard.copy": "لەبەرگتنەوە بۆ کلیپبۆرد", - "clipboard.copied": "لەبەرگیرایەوە بۆ کلیپ بۆرد", - "consent.accept": "ڕازیبوون", - "consent.manage": "بەڕیوەبردنی ڕیکخستنەکان", - "consent.reject": "ڕەتکردنەوە", - "footer": "ژێرپەڕە", - "footer.next": "دواتر", - "footer.previous": "پێشتر", - "header": "ناونیشانی بەڕه", - "meta.comments": "لێدوانەکان", - "meta.source": "سەرجاوە", - "nav": "ڕێنیشاندەر", - "search": "گەڕان", - "search.config.pipeline": " ", - "search.placeholder": "گەڕان", - "search.share": "گەڕان", - "search.reset": "سڕینەوە", - "search.result.initializer": "ئامادەکردنی گەڕان", - "search.result.placeholder": "بنووسە بۆ دەستپێکردن بە گەڕان", - "search.result.none": "هیچ بەڵگەنامەیەکی هاوتا نیە", - "search.result.one": "١ بەڵگەنامەی هاوتا", - "search.result.other": "بەڵگەنامەی هاوتا #", - "search.result.more.one": "١ دانەی تر لەسەر ئەم پەڕەیە", - "search.result.more.other": "دانەی تر لەسەر ئەم پەڕەیە #", - "search.result.term.missing": "ونبوو", - "select.language": "زمان دیاریبکە", - "select.version": "وەشان دیاریبکە", - "source": "بڕۆ بۆ کۆگا", - "source.file.date.created": "دروسکت کرا", - "source.file.date.updated": "دوایین نوێکردنەوە", - "tabs": "تابەکان", - "toc": "خشتەی ناوەڕۆکەکان", - "top": "گەڕانەوە بۆ سەرەوە" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/lb.html b/src/templates/partials/languages/lb.html deleted file mode 100644 index f38c6568..00000000 --- a/src/templates/partials/languages/lb.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Luxembourgish --> -{% macro t(key) %}{{ { - "language": "lb", - "direction": "ltr", - "action.edit": "D'Säit beaarbechten", - "action.skip": "Zum Inhalt iwwersprangen", - "action.view": "Quellcode uweisen", - "announce.dismiss": "Net erëm uweisen", - "blog.archive": "Archiv", - "blog.categories": "Kategorien", - "blog.categories.in": "an", - "blog.continue": "Weider liesen", - "blog.draft": "Skizz", - "blog.index": "Zeréck zum Index", - "blog.meta": "Metadaten", - "blog.references": "Änlech Links", - "clipboard.copy": "Kopéieren", - "clipboard.copied": "Kopéiert", - "consent.accept": "Accept", - "consent.manage": "Astellungen beaarbechten", - "consent.reject": "Ofleenen", - "footer": "Footer", - "footer.next": "Weider", - "footer.previous": "Zeréck", - "header": "Header", - "meta.comments": "Kommentaren", - "meta.source": "Quell", - "nav": "Navigatioun", - "readtime.one": "1 min Liesedauer", - "readtime.other": "# min Liesedauer", - "rss.created": "RSS feed", - "rss.updated": "RSS feed vun aktualiséiertem Inhalt", - "search": "Sichen", - "search.placeholder": "Sichen", - "search.share": "Deelen", - "search.reset": "Läschen", - "search.result.initializer": "D'Sich gëtt initialiséiert", - "search.result.placeholder": "Schreif fir eppes ze sichen", - "search.result.none": "Keng zoutreffend Dokumenter", - "search.result.one": "1 zoutreffend Dokument", - "search.result.other": "# zoutreffend Dokumenter", - "search.result.more.one": "1 méi op dëser Säit", - "search.result.more.other": "# méi op dëser Säit", - "search.result.term.missing": "Feelend", - "select.language": "Sprooch auswielen", - "select.version": "Versioun auswielen", - "source": "Op den Repository goen", - "source.file.contributors": "Matwirkender", - "source.file.date.created": "Erstallt", - "source.file.date.updated": "Läscht update", - "tabs": "Tabs", - "toc": "Inhaltsverzeichnis", - "top": "Zeréck zum Ufank" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/lt.html b/src/templates/partials/languages/lt.html deleted file mode 100644 index 129505f5..00000000 --- a/src/templates/partials/languages/lt.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Lithuanian --> -{% macro t(key) %}{{ { - "language": "lt", - "action.edit": "Redaguoti šį puslapį", - "action.skip": "Pereiti prie turinio", - "action.view": "Žiūrėti puslapio šaltinius", - "announce.dismiss": "Daugiau neberodyti", - "blog.archive": "Archyvas", - "blog.categories": "Kategorijos", - "blog.categories.in": "į", - "blog.continue": "Skaityti toliau", - "blog.draft": "Ruošinys", - "blog.index": "Grįžti į indeksą", - "blog.meta": "Meta duomenys", - "blog.references": "Susieja saitai", - "clipboard.copy": "Kopijuoti į iškarpinę", - "clipboard.copied": "Nukopijuota į iškarpinę", - "consent.accept": "Sutikti", - "consent.manage": "Redaguoti nustatymus", - "consent.reject": "Atmesti", - "footer": "Poraštė", - "footer.next": "Sekantis", - "footer.previous": "Ankstesnis", - "header": "Antraštė", - "meta.comments": "Komentarai", - "meta.source": "Išeitinis kodas", - "nav": "Navigacija", - "readtime.one": "1 min skaitymo", - "readtime.other": "# min skaitymo", - "rss.created": "RSS šaltinis", - "rss.updated": "RSS šaltinis atnaujinimams", - "search": "Paieška", - "search.config.pipeline": " ", - "search.placeholder": "Paieška", - "search.share": "Dalintis", - "search.reset": "Išvalyti", - "search.result.initializer": "Paieškos inicijavimas", - "search.result.placeholder": "Įveskite norėdami pradėti paiešką", - "search.result.none": "Atitinkančių dokumentų nerasta", - "search.result.one": "1 atitinkantis dokumentas", - "search.result.other": "# atitinkantys dokumentai", - "search.result.more.one": "Dar 1 šiame puslapyje", - "search.result.more.other": "Dar # šiame puslapyje", - "search.result.term.missing": "Nerasta", - "select.language": "Pasirinkti kalbą", - "select.version": "Pasrinkti versiją", - "source": "Eiti į saugyklą", - "source.file.contributors": "Dalininkai", - "source.file.date.created": "Sukurta", - "source.file.date.updated": "Paskutinis atnaujinimas", - "tabs": "Skirtukai", - "toc": "Turinys", - "top": "Grįžti į viršų" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/lv.html b/src/templates/partials/languages/lv.html deleted file mode 100644 index 7bcd9ace..00000000 --- a/src/templates/partials/languages/lv.html +++ /dev/null @@ -1,55 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Latvian --> -{% macro t(key) %}{{ { - "language": "lv", - "action.edit": "Rediģēt šo lapu", - "action.skip": "Pāriet uz saturu", - "clipboard.copy": "Kopēt starpliktuvē", - "clipboard.copied": "Kopēts starpliktuvē", - "footer": "Kājene", - "footer.next": "Nākamais", - "footer.previous": "Iepriekšējais", - "header": "Galvene", - "meta.comments": "Komentārs", - "meta.source": "Avots", - "nav": "Navigācija", - "search.placeholder": "Meklēt", - "search.reset": "Notīrīt", - "search.result.initializer": "Notiek meklēšanas inicializācija", - "search.result.placeholder": "Ierakstiet, lai sāktu meklēšanu", - "search.result.none": "Nav atbilstošu dokumentu", - "search.result.one": "1 atbilstošs dokuments", - "search.result.other": "# atbilstoši dokumenti ", - "search.result.more.one": "1 šajā lapā", - "search.result.more.other": "# un vairāk šajā lapā", - "search.result.term.missing": "Trūkstošs", - "select.language": "Izvēlies valodu", - "select.version": "Izvēlies versiju", - "source": "Doties uz repozitoriju", - "source.file.date.created": "Izveidots", - "source.file.date.updated": "Pēdējoreiz atjaunots", - "tabs": "Cilnes", - "toc": "Satura rādītājs", - "top": "Atpakaļ uz augšu" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/mk.html b/src/templates/partials/languages/mk.html deleted file mode 100644 index e3dc114c..00000000 --- a/src/templates/partials/languages/mk.html +++ /dev/null @@ -1,56 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Macedonian --> -{% macro t(key) %}{{ { - "language": "mk", - "action.edit": "Уредете ја оваа страница", - "action.skip": "Прескокнете до содржината", - "clipboard.copy": "Копирај во таблата", - "clipboard.copied": "Копирано", - "footer": "Подножје", - "footer.next": "Следно", - "footer.previous": "Претходно", - "header": "Заглавје", - "meta.comments": "Коментари", - "meta.source": "Извор", - "nav": "Наслов за навигација", - "search.config.lang": "ru", - "search.placeholder": "Пребарување", - "search.reset": "Чисти", - "search.result.initializer": "Иницијализирање на пребарувањето", - "search.result.placeholder": "Напишете за да започнете со пребарување", - "search.result.none": "Нема соодветни документи", - "search.result.one": "1 документ што се совпаѓа", - "search.result.other": "# соодветни документи", - "search.result.more.one": "Уште 1 на оваа страница", - "search.result.more.other": "Уште # на оваа страница", - "search.result.term.missing": "Недостасува", - "select.language": "Изберете јазик", - "select.version": "Изберете верзија", - "source": "Одете до складиштето", - "source.file.date.created": "Создаден", - "source.file.date.updated": "Последно ажурирање", - "tabs": "Јазичиња", - "toc": "Содржина", - "top": "Вратете се на почетокот" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/mn.html b/src/templates/partials/languages/mn.html deleted file mode 100644 index de9002ab..00000000 --- a/src/templates/partials/languages/mn.html +++ /dev/null @@ -1,51 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Mongolian --> -{% macro t(key) %}{{ { - "language": "mn", - "action.edit": "Хуудас засварлах", - "action.skip": "Агуулгыг алгасах", - "clipboard.copy": "Хуулах", - "clipboard.copied": "Санах ойд хуулах", - "footer": "Хөл", - "footer.next": "Дараах", - "footer.previous": "Өмнөх", - "header": "Толгой", - "meta.comments": "Сэтгэгдэл", - "meta.source": "Эх үүсвэр", - "nav": "Чиглүүлэгч", - "search.config.lang": "ru", - "search.placeholder": "Хайлт", - "search.reset": "Цэвэрлэх", - "search.result.placeholder": "Хайлтын үгээ бичнэ үү", - "search.result.none": "Таарц илэрсэнгүй", - "search.result.one": "1 таарц илэрлээ", - "search.result.other": "# Тохирох баримт бичиг", - "search.result.more.one": "1 илүү хуудас байна", - "search.result.more.other": "# илүү хуудас байна", - "source": "Хадгалах сан руу очих", - "source.file.date.created": "Үүсгэсэн", - "source.file.date.updated": "Сүүлийн шинэчлэлт", - "tabs": "Табууд", - "toc": "Агуулга" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/ms.html b/src/templates/partials/languages/ms.html deleted file mode 100644 index 57b70fc7..00000000 --- a/src/templates/partials/languages/ms.html +++ /dev/null @@ -1,55 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Bahasa Malaysia --> -{% macro t(key) %}{{ { - "language": "ms", - "action.edit": "Edit halaman ini", - "action.skip": "Langkau tajuk talian", - "clipboard.copy": "Salin ke papan keratan", - "clipboard.copied": "Disalin ke papan keratan", - "footer": "Pengaki", - "footer.next" : "Seterusnya", - "footer.previous": "Sebelumnya", - "header": "Pengepala", - "meta.comments": "Komen", - "meta.source": "Sumber", - "nav": "Navigasi", - "search.placeholder": "Cari", - "search.reset": "Padam", - "search.result.initializer": "Siap carian", - "search.result.placeholder": "Taip untuk mula mencari", - "search.result.none": "Tiada dokumen yang sepadan", - "search.result.one": "1 dokumen yang sepadan", - "search.result.other": "# dokumen yang sepadan", - "search.result.more.one": "1 lagi di halaman ini", - "search.result.more.other": "# lagi di halaman ini", - "search.result.term.missing": "Hilang", - "select.language": "Pilih bahasa", - "select.version": "Pilih versi", - "source": "tajuk talian asal", - "source.file.date.created": "tarikh fil asal dicipta", - "source.file.date.updated": "Tarikh fil dikemas kini", - "tabs": "Tab", - "toc": "Jadual kandungan", - "top": "Kembali ke atas" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/my.html b/src/templates/partials/languages/my.html deleted file mode 100644 index 27ca3ad9..00000000 --- a/src/templates/partials/languages/my.html +++ /dev/null @@ -1,49 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Burmese --> -{% macro t(key) %}{{ { - "language": "my", - "action.edit": "ဤ စာမျက်နှာကို ပြင်ရန်", - "action.skip": "မာတိကာ သို့ သွားရန်", - "clipboard.copy": "ကလစ်ဘုတ် သို့ ကူးယူရန်", - "clipboard.copied": "ကလစ်ဘုတ် သို့ ကူယူပြီး", - "footer": "အောက်ခြေ", - "footer.next": "ရှေ့သို့", - "footer.previous": "နောက်သို့", - "header": "ခေါင်းပိုင်း", - "meta.comments": "မှတ်ချက်များ", - "meta.source": "ရင်းမြစ်", - "nav": "လမ်းညွှန်", - "search.config.pipeline": " ", - "search.placeholder": "ရှာရန်", - "search.reset": "ရှင်းလင်း", - "search.result.placeholder": "ရှာဖွေခြင်းစရန် စာရိုက်ပါ", - "search.result.none": "တူညီသော စာရွက်စာတမ်းများ မရှိပါ", - "search.result.one": "စာရွက်စာတမ်း ၁ ခု တူညီသည်", - "search.result.other": "စာရွက်စာတမ်း # ခု တူညီသည်", - "source": "repository သို့ သွားရန်", - "source.file.date.created": "နေပြည်တော်", - "source.file.date.updated": "နောက်ဆုံး ထုတ်ပြန်ချက်", - "tabs": "တက်များ", - "toc": "ပါဝင်အကြောင်းအရာများ" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/nb.html b/src/templates/partials/languages/nb.html deleted file mode 100644 index 6be63531..00000000 --- a/src/templates/partials/languages/nb.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Norwegian Bokmål --> -{% macro t(key) %}{{ { - "language": "nb", - "action.edit": "Rediger denne siden", - "action.skip": "Gå til innhold", - "action.view": "Vis kildekoden til denne siden", - "announce.dismiss": "Ikke vis dette igjen", - "blog.archive": "Arkiv", - "blog.categories": "Kategorier", - "blog.categories.in": "i", - "blog.continue": "Fortsett å lese", - "blog.draft": "Kladd", - "blog.index": "Tilbake til oversikt", - "blog.meta": "Metadata", - "blog.references": "Relaterte lenker", - "clipboard.copy": "Kopier til utklippstavlen", - "clipboard.copied": "Kopiert til utklippstavlen", - "consent.accept": "Akseptert", - "consent.manage": "Innstillinger", - "consent.reject": "Reject", - "footer": "Footer", - "footer.next": "Neste", - "footer.previous": "Forrige", - "header": "Header", - "meta.comments": "Kommentarer", - "meta.source": "Kilde", - "nav": "Navigasjon", - "readtime.one": "lesteid: 1 min", - "readtime.other": "lesetid: # min", - "rss.created": "RSS feed", - "rss.updated": "Oppdatert RSS feed", - "search": "Søk", - "search.config.lang": "no", - "search.placeholder": "Søk", - "search.share": "Del", - "search.reset": "Nullstill", - "search.result.initializer": "Starter søk", - "search.result.placeholder": "Skriv søkeord", - "search.result.none": "Ingen treff", - "search.result.one": "1 treff", - "search.result.other": "# treff", - "search.result.more.one": "1 til på denne siden", - "search.result.more.other": "# flere på denne siden", - "search.result.term.missing": "Mangler", - "select.language": "Velg språk", - "select.version": "Velg versjon", - "source": "Gå til kilde", - "source.file.contributors": "Bidragsytere", - "source.file.date.created": "Opprettet", - "source.file.date.updated": "Sist oppdatert", - "tabs": "Faner", - "toc": "Innholdsliste", - "top": "Tilbake til toppen" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/nl.html b/src/templates/partials/languages/nl.html deleted file mode 100644 index 0000fe60..00000000 --- a/src/templates/partials/languages/nl.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Dutch --> -{% macro t(key) %}{{ { - "language": "nl", - "action.edit": "Wijzig deze pagina", - "action.skip": "Ga naar inhoud", - "action.view": "Bron van deze pagina bekijken", - "announce.dismiss": "Niet meer laten zien", - "blog.archive": "Archief", - "blog.categories": "Categorieën", - "blog.categories.in": "in", - "blog.continue": "Doorgaan met lezen", - "blog.draft": "Concept", - "blog.index": "Terug naar de inhoudsopgave", - "blog.meta": "Metadata", - "blog.references": "Gerelateerde links", - "clipboard.copy": "Kopiëren naar klembord", - "clipboard.copied": "Gekopieerd naar klembord", - "consent.accept": "Accepteren", - "consent.manage": "Instellingen", - "consent.reject": "Afwijzen", - "footer": "Footer", - "footer.next": "Volgende", - "footer.previous": "Vorige", - "header": "Header", - "meta.comments": "Reacties", - "meta.source": "Bron", - "nav": "Navigatie", - "readtime.one": "1 min leestijd", - "readtime.other": "# min leestijd", - "rss.created": "RSS feed", - "rss.updated": "RSS feed met geüpdatet inhoud", - "search": "Zoeken", - "search.config.lang": "nl", - "search.placeholder": "Zoeken", - "search.share": "Delen", - "search.reset": "Leegmaken", - "search.result.initializer": "Zoeken initialiseren", - "search.result.placeholder": "Typ om te beginnen met zoeken", - "search.result.none": "Geen overeenkomende documenten", - "search.result.one": "1 overeenkomende document", - "search.result.other": "# overeenkomende documenten", - "search.result.more.one": "1 extra overeenkomst op deze pagina", - "search.result.more.other": "# extra overeenkomsten op deze pagina", - "search.result.term.missing": "Ontbreekt", - "select.language": "Selecteer taal", - "select.version": "Selecteer versie", - "source": "Ga naar repository", - "source.file.contributors": "Bijdragers", - "source.file.date.created": "Gecreëerd", - "source.file.date.updated": "Laatst geüpdatet", - "tabs": "Tabs", - "toc": "Inhoudsopgave", - "top": "Terug naar boven" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/nn.html b/src/templates/partials/languages/nn.html deleted file mode 100644 index 9478bdbe..00000000 --- a/src/templates/partials/languages/nn.html +++ /dev/null @@ -1,62 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Norwegian Nynorsk --> -{% macro t(key) %}{{ { - "language": "nn", - "action.edit": "Rediger denne sida", - "action.skip": "Gå til innhald", - "announce.dismiss": "Ikkje vis dette att", - "clipboard.copy": "Kopier til utklippstavla", - "clipboard.copied": "Kopiert til utklippstavla", - "consent.accept": "Akseptert", - "consent.manage": "Innstillinger", - "consent.reject": "Reject", - "footer": "Footer", - "footer.next": "Neste", - "footer.previous": "Førre", - "header": "Header", - "meta.comments": "Kommentarar", - "meta.source": "Kjelde", - "nav": "Navigasjon", - "search": "Søk", - "search.config.lang": "no", - "search.placeholder": "Søk", - "search.share": "Del", - "search.reset": "Nullstill", - "search.result.initializer": "Startar søk", - "search.result.placeholder": "Skriv søkeord", - "search.result.none": "Ingen treff", - "search.result.one": "1 treff", - "search.result.other": "# treff", - "search.result.more.one": "1 til på denne sida", - "search.result.more.other": "# fleire på denne sida", - "search.result.term.missing": "Manglar", - "select.language": "Vel språk", - "select.version": "Vel versjon", - "source": "Gå til kjelde", - "source.file.date.created": "Oppretta", - "source.file.date.updated": "Sist oppdatert", - "tabs": "Faner", - "toc": "Innhaldsliste", - "top": "Tilbake til toppen" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/pl.html b/src/templates/partials/languages/pl.html deleted file mode 100644 index 7817633a..00000000 --- a/src/templates/partials/languages/pl.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Polish --> -{% macro t(key) %}{{ { - "language": "pl", - "action.edit": "Edytuj tę stronę", - "action.skip": "Przejdź do treści", - "action.view": "Zobacz kod źródłowy tej strony", - "announce.dismiss": "Nie pokazuj tego ponownie", - "blog.archive": "Archiwum", - "blog.categories": "Kategorie", - "blog.categories.in": "", - "blog.continue": "Czytaj dalej", - "blog.draft": "Wersja robocza", - "blog.index": "Powrót do indeksu", - "blog.meta": "Metadane", - "blog.references": "Powiązane łącza", - "clipboard.copy": "Kopiuj do schowka", - "clipboard.copied": "Skopiowano do schowka", - "consent.accept": "Akceptuj", - "consent.manage": "Zarządzaj ustawieniami", - "consent.reject": "Odrzuć", - "footer": "Stopka", - "footer.next": "Następna strona", - "footer.previous": "Poprzednia strona", - "header": "Nagłówek", - "meta.comments": "Komentarze", - "meta.source": "Kod źródłowy", - "nav": "Nawigacja", - "readtime.one": "Czas czytania: 1 min", - "readtime.other": "Czas czytania: # min", - "rss.created": "Kanał RSS", - "rss.updated": "Kanał RSS zaktualizowanych treści", - "search": "Szukaj", - "search.config.pipeline": " ", - "search.placeholder": "Szukaj", - "search.share": "Udostępnij", - "search.reset": "Wyczyść", - "search.result.initializer": "Inicjowanie wyszukiwania", - "search.result.placeholder": "Zacznij pisać, aby szukać", - "search.result.none": "Brak wyników wyszukiwania", - "search.result.one": "Wyniki wyszukiwania: 1", - "search.result.other": "Wyniki wyszukiwania: #", - "search.result.more.one": "1 więcej na tej stronie", - "search.result.more.other": "# więcej na tej stronie", - "search.result.term.missing": "Brak", - "select.language": "Wybierz język", - "select.version": "Wybierz wersję", - "source": "Przejdź do repozytorium", - "source.file.contributors": "Kontrybutorzy", - "source.file.date.created": "Utworzony", - "source.file.date.updated": "Ostatnia aktualizacja", - "tabs": "Zakładki", - "toc": "Spis treści", - "top": "Powrót do góry" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/pt-BR.html b/src/templates/partials/languages/pt-BR.html deleted file mode 100644 index d934a9ac..00000000 --- a/src/templates/partials/languages/pt-BR.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Portuguese (Brasilian) --> -{% macro t(key) %}{{ { - "language": "pt", - "action.edit": "Editar esta página", - "action.skip": "Pular para conteúdo", - "action.view": "Exibir fonte desta página", - "announce.dismiss": "Não mostrar isso novamente", - "blog.archive": "Arquivo", - "blog.categories": "Categorias", - "blog.categories.in": "em", - "blog.continue": "Continuar leitura", - "blog.draft": "Rascunho", - "blog.index": "Voltar ao índice", - "blog.meta": "Metadados", - "blog.references": "Links relacionados", - "clipboard.copy": "Copiar para área de transferência", - "clipboard.copied": "Copiado para área de transferência", - "consent.accept": "Aceitar", - "consent.manage": "Gerenciar configurações", - "consent.reject": "Rejeitar", - "footer": "Rodapé", - "footer.next": "Próximo", - "footer.previous": "Anterior", - "header": "Cabeçalho", - "meta.comments": "Comentários", - "meta.source": "Origem", - "nav": "Navegação", - "readtime.one": "1 min de leitura", - "readtime.other": "# min de leitura", - "rss.created": "RSS feed", - "rss.updated": "RSS feed de conteúdo atualizado", - "search": "Pesquisar", - "search.config.lang": "pt", - "search.placeholder": "Buscar", - "search.share": "Compartilhar", - "search.reset": "Limpar", - "search.result.initializer": "Inicializando busca", - "search.result.placeholder": "Digite para iniciar a busca", - "search.result.none": "Nenhum documento encontrado", - "search.result.one": "1 documento encontrado", - "search.result.other": "# documentos encontrados", - "search.result.more.one": "mais 1 nesta página", - "search.result.more.other": "# mais nesta página", - "search.result.term.missing": "Ausente", - "select.language": "Selecione o idioma", - "select.version": "Selecione a versão", - "source": "Ir para repositório", - "source.file.contributors": "Contribuidores", - "source.file.date.created": "Criado em", - "source.file.date.updated": "Última atualização", - "tabs": "Abas", - "toc": "Índice", - "top": "Voltar para o topo" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/pt.html b/src/templates/partials/languages/pt.html deleted file mode 100644 index e5dee1cb..00000000 --- a/src/templates/partials/languages/pt.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Portuguese --> -{% macro t(key) %}{{ { - "language": "pt", - "action.edit": "Editar esta página", - "action.skip": "Ir para o conteúdo", - "action.view": "Ver fonte desta página", - "announce.dismiss": "Não mostrar novamente", - "blog.archive": "Arquivo", - "blog.categories": "Categorias", - "blog.categories.in": "em", - "blog.continue": "Continuar leitura", - "blog.draft": "Rascunho", - "blog.index": "Voltar ao índice", - "blog.meta": "Metadados", - "blog.references": "Ligações relacionadas", - "clipboard.copy": "Copiar para área de transferência", - "clipboard.copied": "Copiado para área de transferência", - "consent.accept": "Aceitar", - "consent.manage": "Gerir configurações", - "consent.reject": "Rejeitar", - "footer": "Rodapé", - "footer.next": "Próximo", - "footer.previous": "Anterior", - "header": "Cabeçalho", - "meta.comments": "Comentários", - "meta.source": "Fonte", - "nav": "Navegação", - "readtime.one": "1 min de leitura", - "readtime.other": "# min de leitura", - "rss.created": "canal RSS", - "rss.updated": "canal RSS com conteúdo atualizado", - "search": "Pesquisar", - "search.config.lang": "pt", - "search.placeholder": "Buscar", - "search.share": "Compartilhar", - "search.reset": "Limpar", - "search.result.initializer": "Inicializando a pesquisa", - "search.result.placeholder": "Digite para iniciar a busca", - "search.result.none": "Nenhum resultado encontrado", - "search.result.one": "1 resultado encontrado", - "search.result.other": "# resultados encontrados", - "search.result.more.one": "Mais 1 nesta página", - "search.result.more.other": "Mais # nesta página", - "search.result.term.missing": "Ausente", - "select.language": "Selecione o idioma", - "select.version": "Selecione a versão", - "source": "Ir ao repositório", - "source.file.contributors": "Colaboradores", - "source.file.date.created": "Criada", - "source.file.date.updated": "Última atualização", - "tabs": "Abas", - "toc": "Índice", - "top": "Voltar ao topo" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/ro.html b/src/templates/partials/languages/ro.html deleted file mode 100644 index 7bea9afb..00000000 --- a/src/templates/partials/languages/ro.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Romanian --> -{% macro t(key) %}{{ { - "language": "ro", - "action.edit": "Editeaza această pagină", - "action.skip": "Sari la conținut", - "action.view": "Vezi sursa acestei pagini", - "announce.dismiss": "Nu mai arăta asta", - "blog.archive": "Arhivează", - "blog.categories": "Categorii", - "blog.categories.in": "în", - "blog.continue": "Continuă să citești", - "blog.draft": "Ciornă", - "blog.index": "Înapoi la index", - "blog.meta": "Metadata", - "blog.references": "Link-uri relevante", - "clipboard.copy": "Copiază în clipboard", - "clipboard.copied": "Copiat în clipboard", - "consent.accept": "Accept", - "consent.manage": "Gestionați setările", - "consent.reject": "Refuz", - "footer": "Subsol", - "footer.next": "Următor", - "footer.previous": "Anterior", - "header": "Antet", - "meta.comments": "Comentarii", - "meta.source": "Sursă", - "nav": "Navigație", - "readtime.one": "1 minut de citit", - "readtime.other": "# minut de citit", - "rss.created": "Flux RSS", - "rss.updated": "Flux RSS cu conținut actualizat", - "search": "Caută", - "search.config.lang": "ro", - "search.placeholder": "Căutare", - "search.share": "Distribuie", - "search.reset": "Resetează", - "search.result.initializer": "Inițializare căutare", - "search.result.placeholder": "Tastează pentru a începe căutarea", - "search.result.none": "Nu a fost găsit niciun document", - "search.result.one": "1 document găsit", - "search.result.other": "# documente găsite", - "search.result.more.one": "Încă 1 pe această pagină", - "search.result.more.other": "Încă # pe această pagină", - "search.result.term.missing": "Lipsă", - "select.language": "Selectează limba", - "select.version": "Selectează versuine", - "source": "Accesează repository-ul", - "source.file.contributors": "Contribuitori", - "source.file.date.created": "Creată", - "source.file.date.updated": "Ultima actualizare", - "tabs": "File", - "toc": "Cuprins", - "top": "Înapoi sus" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/ru.html b/src/templates/partials/languages/ru.html deleted file mode 100644 index ddbd7b95..00000000 --- a/src/templates/partials/languages/ru.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Russian --> -{% macro t(key) %}{{ { - "language": "ru", - "action.edit": "Редактировать страницу", - "action.skip": "Перейти к содержанию", - "action.view": "Посмотреть исходный код страницы", - "announce.dismiss": "Больше не показывать", - "blog.archive": "Архив", - "blog.categories": "Категории", - "blog.categories.in": "В", - "blog.continue": "Читать", - "blog.draft": "Черновик", - "blog.index": "На главную", - "blog.meta": "Метаданные", - "blog.references": "Ссылки", - "clipboard.copy": "Копировать в буфер", - "clipboard.copied": "Скопировано в буфер", - "consent.accept": "Принять", - "consent.manage": "Управлять настройками", - "consent.reject": "Отклонить", - "footer": "Нижний колонтитул", - "footer.next": "Вперед", - "footer.previous": "Назад", - "header": "Верхний колонтитул", - "meta.comments": "Комментарии", - "meta.source": "Исходный код", - "nav": "Навигация", - "readtime.one": "Читать 1 минуту", - "readtime.other": "Читать # минут", - "rss.created": "RSS канал", - "rss.updated": "RSS канал с новым контентом", - "search": "Поиск", - "search.config.lang": "ru", - "search.placeholder": "Поиск", - "search.share": "Поделиться", - "search.reset": "Очистить", - "search.result.initializer": "Инициализация поиска", - "search.result.placeholder": "Начните печатать для поиска", - "search.result.none": "Совпадений не найдено", - "search.result.one": "Найдено 1 совпадение", - "search.result.other": "Найдено совпадений: #", - "search.result.more.one": "Ещё 1 на этой странице", - "search.result.more.other": "Ещё # на этой странице", - "search.result.term.missing": "Отсутствует", - "select.language": "Выберите язык", - "select.version": "Выберите версию", - "source": "Перейти к репозиторию", - "source.file.contributors": "Участники", - "source.file.date.created": "Дата создания", - "source.file.date.updated": "Последнее обновление", - "tabs": "Вкладки", - "toc": "Содержание", - "top": "К началу" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/sa.html b/src/templates/partials/languages/sa.html deleted file mode 100644 index 338e2b61..00000000 --- a/src/templates/partials/languages/sa.html +++ /dev/null @@ -1,75 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Sanskrit --> -{% macro t(key) %}{{ { - "language": "sa", - "action.edit": "एतत् पृष्ठं सम्पादयतु", - "action.skip": "सामग्रीं त्यजन्तु", - "action.view": "अस्य पृष्ठस्य स्रोतः पश्यन्तु", - "announce.dismiss": "एतत् पुनः न दर्शयतु", - "blog.archive": "लेखागार", - "blog.categories": "श्रेणियाँ", - "blog.categories.in": "इत्यस्मिन्", - "blog.continue": "पठनं निरन्तरं कुर्वन्तु", - "blog.draft": "प्रारूप", - "blog.index": "अनुक्रमणिकां प्रति पुनः आगच्छन्तु", - "blog.meta": "परिदत्तांश", - "blog.references": "सन्दर्भाः", - "clipboard.copy": "एतत् प्रतिलिख्यताम्", - "clipboard.copied": "प्रतिलिपितः भवति", - "consent.accept": "अहं तत् स्वीकुर्वन् अस्मि", - "consent.manage": "वविन्यासं प्रबन्धयन्तु", - "consent.reject": "अहं तत् निराकरोमि", - "footer": "पादलेखः", - "footer.next": "अग्रिमः", - "footer.previous": "पूर्वकृत", - "header": "शीर्षकम्", - "meta.comments": "विचाराः", - "meta.source": "स्रोतः", - "nav": "मार्गदर्शनम्", - "readtime.one": "१ निमेषं पठितुं", - "readtime.other": "# निमेषं पठितुं", - "rss.created": "आरएसएस सेवा", - "rss.updated": "आरएसएस सेवातः नवीनतमं अद्यतनम्", - "search": "अन्वेषण", - "search.placeholder": "अन्वेषण", - "search.share": "भजतु", - "search.reset": "तत् स्वच्छं कुर्वन्तु", - "search.result.initializer": "अन्वेषणस्य आरम्भः", - "search.result.placeholder": "अन्वेषणं आरभ्य लिखन्तु", - "search.result.none": "अभिलेखाः नास्ति", - "search.result.one": "१ अभिलेखः अस्ति", - "search.result.other": "# अभिलेखाः सन्ति", - "search.result.more.one": "अस्मिन् पृष्ठे १ अन्यः अस्ति", - "search.result.more.other": "अस्मिन् पृष्ठे # अन्ये सन्ति", - "search.result.term.missing": "शून्य", - "select.language": "भाषां चिनोतु", - "select.version": "संस्करणं चिनोतु", - "source": "भण्डारं गच्छन्तु", - "source.file.contributors": "अंशदाता", - "source.file.date.created": "ननिर्माणस्य तिथिः", - "source.file.date.updated": "परिवर्तनस्य तिथिः", - "tabs": "पट्टाः", - "toc": "सामग्रीसारणी", - "top": "पुनः उपरिभागं प्रति गच्छन्तु" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/sh.html b/src/templates/partials/languages/sh.html deleted file mode 100644 index 42a0d902..00000000 --- a/src/templates/partials/languages/sh.html +++ /dev/null @@ -1,70 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Serbo-Croatian --> -{% macro t(key) %}{{ { - "language": "sh", - "action.edit": "Ažuriraj stranicu", - "action.skip": "Idi na tekst", - "action.view": "Pogledaj izvorni kod ove stranice", - "announce.dismiss": "Nemoj mi ponovo pokazati ovo", - "blog.archive": "Arhiva", - "blog.categories": "Kategorije", - "blog.categories.in": "u", - "blog.continue": "Nastavi sa čitanjem", - "blog.meta": "Metapodaci", - "blog.references": "Povezani linkovi", - "clipboard.copy": "Kopiraj u klipbord", - "clipboard.copied": "Iskopirano u klipbord", - "consent.accept": "Prihvati", - "consent.manage": "Promeni podešavanja", - "consent.reject": "Odbij", - "footer": "Podnožje", - "footer.next": "Sledeće", - "footer.previous": "Prethodno", - "header": "Zaglavlje", - "meta.comments": "Komentari", - "meta.source": "Izvor", - "nav": "Navigacija", - "readtime.one": "1 minut čitanja", - "readtime.other": "# minuta čitanja", - "search": "Pretraga", - "search.placeholder": "Pretraga", - "search.share": "Deljenje", - "search.reset": "Očisti", - "search.result.initializer": "Inicijalizujem pretragu", - "search.result.placeholder": "Unesite pojam pretrage", - "search.result.none": "Ništa nije pronađeno", - "search.result.one": "1 rezultat pretrage", - "search.result.other": "# rezultata pretrage", - "search.result.more.one": "još 1 na ovoj strani", - "search.result.more.other": "još # na ovoj strani", - "search.result.term.missing": "Nedostaje", - "select.language": "Izaberi jezik", - "select.version": "Izaberi verziju", - "source": "Idi u repozitorijum", - "source.file.date.created": "Kreiran", - "source.file.date.updated": "Ažuriran", - "tabs": "Tabovi", - "toc": "Sadržaj", - "top": "Nazad na vrh" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/si.html b/src/templates/partials/languages/si.html deleted file mode 100644 index eb41309e..00000000 --- a/src/templates/partials/languages/si.html +++ /dev/null @@ -1,51 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Sinhalese --> -{% macro t(key) %}{{ { - "language": "si", - "action.edit": "පිටුව සංස්කරණය", - "action.skip": "අන්තර්ගතය වෙත යන්න", - "clipboard.copy": "කොපි කරන්න", - "clipboard.copied": "කොපි කළා", - "footer": "පාදම", - "footer.next": "මීළඟ", - "footer.previous": "පසුගිය", - "header": "ශීර්ෂය", - "meta.comments": "ප්රතිචාර", - "meta.source": "මූලාශ්රය", - "nav": "යාත්රණය", - "search.config.pipeline": " ", - "search.placeholder": "සොයන්න", - "search.reset": "මකන්න", - "search.result.placeholder": "සෙවීමට ටයිප් කරන්න", - "search.result.none": "කිසිවක් හමු නොවුණි", - "search.result.one": "1 ගැලපෙන ගොනුවක්", - "search.result.other": "ගැලපෙන ගොනු # ක්", - "search.result.more.one": "තව 1 ප්රතිඵලයක්", - "search.result.more.other": "තව ප්රතිඵල # ක්", - "source": "රිපොසිටරියට යන්න", - "source.file.date.created": "ٺاھيو ويو", - "source.file.date.updated": "අවසන් යාවත්කාලීන වීම", - "tabs": "ටැබ්ස්", - "toc": "පටුන" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/sk.html b/src/templates/partials/languages/sk.html deleted file mode 100644 index 701a5a53..00000000 --- a/src/templates/partials/languages/sk.html +++ /dev/null @@ -1,43 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Slovak --> -{% macro t(key) %}{{ { - "language": "sk", - "action.edit": "Upraviť túto stránku", - "action.skip": "Preskočiť na obsah", - "clipboard.copy": "Kopírovať do schránky", - "clipboard.copied": "Skopírované do schránky", - "footer.next": "Ďalej", - "footer.previous": "Späť", - "meta.comments": "Komentáre", - "meta.source": "Zdroj", - "search.placeholder": "Hľadať", - "search.result.placeholder": "Pre vyhľadávanie začni písať", - "search.result.none": "Žiadne vyhovujúce dokumenty", - "search.result.one": "Vyhovujúci dokument: 1", - "search.result.other": "Vyhovujúce dokumenty: #", - "source": "Zobraziť repozitár", - "source.file.date.created": "Vytvorené", - "source.file.date.updated": "Posledná aktualizácia", - "toc": "Obsah" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/sl.html b/src/templates/partials/languages/sl.html deleted file mode 100644 index a01f31d9..00000000 --- a/src/templates/partials/languages/sl.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Slovenian --> -{% macro t(key) %}{{ { - "language": "sl", - "action.edit": "Uredi stran", - "action.skip": "Skoči na vsebino", - "action.view": "Prikaži izvorno stran", - "announce.dismiss": "Ne prikaži več", - "blog.archive": "Arhiv", - "blog.categories": "Kategorije", - "blog.categories.in": "v", - "blog.continue": "Nadaljuj z branjem", - "blog.draft": "Osnutek", - "blog.index": "Nazaj na kazalo", - "blog.meta": "Metapodatki", - "blog.references": "Sorodne povezave", - "clipboard.copy": "Kopiraj v odložišče", - "clipboard.copied": "Kopirano v odložišče", - "consent.accept": "Sprejmi", - "consent.manage": "Uredi nastavitve", - "consent.reject": "Zavrni", - "footer": "Glava", - "footer.next": "Naslednja stran", - "footer.previous": "Prejšnja stran", - "header": "Noga", - "meta.comments": "Komentarji", - "meta.source": "Izvorna koda", - "nav": "Navigacija", - "readtime.one": "Čas branja: 1 min", - "readtime.other": "Čas branja: # min", - "rss.created": "RSS vir", - "rss.updated": "RSS vir posodobljene vsebine", - "search": "Iskanje", - "search.config.lang": "sl", - "search.placeholder": "Išči", - "search.share": "Deli", - "search.reset": "Počisti", - "search.result.initializer": "Inicializacija iskanja", - "search.result.placeholder": "Vpiši iskalni niz", - "search.result.none": "Ni zadetkov", - "search.result.one": "1 zadetek", - "search.result.other": "# zadetkov", - "search.result.more.one": "Še 1 na tej strani", - "search.result.more.other": "Še # na tej strani", - "search.result.term.missing": "Manjka", - "select.language": "Izberi jezik", - "select.version": "Izberi različico", - "source": "Pojdi na repozitorij", - "source.file.contributors": "Soavtorji", - "source.file.date.created": "Ustvarjeno", - "source.file.date.updated": "Zadnja posodobitev", - "tabs": "Zavihki", - "toc": "Kazalo", - "top": "Nazaj na vrh" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/sr.html b/src/templates/partials/languages/sr.html deleted file mode 100644 index 275ea126..00000000 --- a/src/templates/partials/languages/sr.html +++ /dev/null @@ -1,57 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Serbian --> -{% macro t(key) %}{{ { - "language": "sr", - "action.edit": "Ажурирај страницу", - "action.skip": "Иди на текст", - "clipboard.copy": "Копирај у клипборд", - "clipboard.copied": "Ископирано у клипборд", - "footer": "Подножје", - "footer.next": "Следеће", - "footer.previous": "Претходно", - "header": "Заглавље", - "meta.comments": "Коментари", - "meta.source": "Извор", - "nav": "Навигација", - "search": "Претрага", - "search.placeholder": "Претрага", - "search.share": "Дељење", - "search.reset": "Очисти", - "search.result.initializer": "Иницијализујем претрагу", - "search.result.placeholder": "Унесите појам претраге", - "search.result.none": "Ништа није пронађено", - "search.result.one": "1 резултат претраге", - "search.result.other": "# резултата претраге", - "search.result.more.one": "још 1 на овој страни", - "search.result.more.other": "још # на овој страни", - "search.result.term.missing": "Недостаје", - "select.language": "Изабери језик", - "select.version": "Изабери верзију", - "source": "Иди у репозиторијум", - "source.file.date.created": "Креиран", - "source.file.date.updated": "Ажуриран", - "tabs": "Табови", - "toc": "Садржај", - "top": "Назад на врх" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/sv.html b/src/templates/partials/languages/sv.html deleted file mode 100644 index 52f151d2..00000000 --- a/src/templates/partials/languages/sv.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Swedish --> -{% macro t(key) %}{{ { - "language": "sv", - "action.edit": "Redigera sidan", - "action.skip": "Gå till innehållet", - "action.view": "Visa källkoden för denna sida", - "announce.dismiss": "Visa inte igen", - "blog.archive": "Arkivera", - "blog.categories": "Kategorier", - "blog.categories.in": "i", - "blog.continue": "Fortsätt läsa", - "blog.draft": "Utkast", - "blog.index": "Tillbaka till index", - "blog.meta": "Metadata", - "blog.references": "Relaterade länkar", - "clipboard.copy": "Kopiera till urklipp", - "clipboard.copied": "Kopierat till urklipp", - "consent.accept": "Acceptera", - "consent.manage": "Hantera inställningar", - "consent.reject": "Acceptera inte", - "footer": "Sidfot", - "footer.next": "Nästa", - "footer.previous": "Föregående", - "header": "Sidhuvud", - "meta.comments": "Kommentarer", - "meta.source": "Källa", - "nav": "Navigation", - "readtime.one": "1 min lästid", - "readtime.other": "# min lästid", - "rss.created": "RSS-flöde", - "rss.updated": "RSS-flöde av uppdaterat innehåll", - "search": "Sök", - "search.config.lang": "sv", - "search.placeholder": "Sök", - "search.share": "Dela", - "search.reset": "Rensa", - "search.result.initializer": "Initialiserar sök", - "search.result.placeholder": "Skriv sökord", - "search.result.none": "Inga sökresultat", - "search.result.one": "1 sökresultat", - "search.result.other": "# sökresultat", - "search.result.more.one": "1 till på denna sida", - "search.result.more.other": "# till på denna sida", - "search.result.term.missing": "Saknas", - "select.language": "Välj språk", - "select.version": "Välj version", - "source": "Gå till datakatalog", - "source.file.contributors": "Författare", - "source.file.date.created": "Skapad", - "source.file.date.updated": "Senast uppdaterad", - "tabs": "Flikar", - "toc": "Innehållsförteckning", - "top": "Tillbaka till toppen" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/te.html b/src/templates/partials/languages/te.html deleted file mode 100644 index 7529a47c..00000000 --- a/src/templates/partials/languages/te.html +++ /dev/null @@ -1,75 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Telugu --> -{% macro t(key) %}{{ { - "language": "te", - "action.edit": "ఈ పేజీలో దిద్దుబాట్లు చేయండి", - "action.skip": "సమాచారానికి వెళ్లండి", - "action.view": "నేను ఈ పేజీ యొక్క మూలాన్ని చూడాలనుకుంటున్నాను", - "announce.dismiss": "దీన్ని మళ్లీ చూపవద్దు", - "blog.archive": "పాత వ్యాసం", - "blog.categories": "వర్గాలు", - "blog.categories.in": "లో", - "blog.continue": "చదవడం కొనసాగించండి", - "blog.draft": "ప్రారంభ రచన", - "blog.index": "సూచికకు తిరిగి వెళ్ళు", - "blog.meta": "సమాచారం గురించి సమాచారం", - "blog.references": "సంబంధిత సూచనలు", - "clipboard.copy": "దీనిని అనుకరించు", - "clipboard.copied": "దీనిని అతికించు", - "consent.accept": "నేను దీనిని అంగీకరిస్తున్నాను", - "consent.manage": "ఆకృతీకరణను నిర్వహించండి", - "consent.reject": "నేను దీనిని తిరస్కరిస్తున్నాను", - "footer": "అడిటిప్పణి", - "footer.next": "తదుపరి భాగం", - "footer.previous": "మునుపటి భాగం", - "header": "శీర్షిక విభాగం", - "meta.comments": "అభిప్రాయాలు", - "meta.source": "మూలం", - "nav": "మార్గదర్శక పట్టీ", - "readtime.one": "చదవడానికి ఒక నిమిషం పడుతుంది", - "readtime.other": "చదవడానికి # నిమిషాలు పడుతుంది", - "rss.created": "ఆర్ఎస్ఎస్ సేవ", - "rss.updated": "ఆర్ఎస్ఎస్ సేవ నుండి తాజా నవీకరణ", - "search": "వెతకండి", - "search.placeholder": "వెతకండి", - "search.share": "పంచుకోండి", - "search.reset": "తుడిచివేయు", - "search.result.initializer": "శోధనను ప్రారంభిస్తోంది", - "search.result.placeholder": "రాయడం ద్వారా వెతకడం ప్రారంభించండి", - "search.result.none": "సరిపోలే పత్రాలు లేవు", - "search.result.one": "ఒక సరిపోలే పత్రం", - "search.result.other": "# సరిపోలే పత్రాలు", - "search.result.more.one": "ఈ పేజీలో మరొకటి", - "search.result.more.other": "ఈ పేజీలో ఇంకా # ఉన్నాయి", - "search.result.term.missing": "తప్పిపోయింది", - "select.language": "భాషను ఎంచుకోండి", - "select.version": "సంస్కరణను ఎంచుకోండి", - "source": "భండారానికి వెళ్ళండి", - "source.file.contributors": "సహకారులు", - "source.file.date.created": "సృష్టించబడింది", - "source.file.date.updated": "చివరి నవీకరణ", - "tabs": "వివిధ కిటికీలు", - "toc": "విషయ సూచిక", - "top": "పైకి తిరిగి వెళ్ళు" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/th.html b/src/templates/partials/languages/th.html deleted file mode 100644 index c8104fc1..00000000 --- a/src/templates/partials/languages/th.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Thai --> -{% macro t(key) %}{{ { - "language": "th", - "action.edit": "แก้ไขหน้านี้", - "action.skip": "ข้ามไปที่เนื้อหา", - "action.view": "ดูแหล่งที่มาของหน้านี้", - "announce.dismiss": "อย่าแสดงสิ่งนี้อีก", - "blog.archive": "คลังเก็บเอกสาร", - "blog.categories": "หมวดหมู่", - "blog.categories.in": "ใย", - "blog.continue": "อ่านต่อไป", - "blog.draft": "ฉบับร่าง", - "blog.index": "กลับไปยังหน้าแรก", - "blog.meta": "คำอธิบายข้อมูล", - "blog.references": "ลิงก์ที่เกี่ยวข้อง", - "clipboard.copy": "คัดลอก", - "clipboard.copied": "คัดลอกแล้ว", - "consent.accept": "ยอมรับ", - "consent.manage": "จัดการการตั้งค่า", - "consent.reject": "ปฏิเสธ", - "footer": "ส่วนท้าย", - "footer.next": "ต่อไป", - "footer.previous": "ก่อนหน้า", - "header": "หัวข้อ", - "meta.comments": "ความคิดเห็น", - "meta.source": "แหล่งที่มา", - "nav": "ตัวนำทาง", - "readtime.one": "อ่าน 1 นาที", - "readtime.other": "อ่าน # นาที", - "rss.created": "ฟีด RSS", - "rss.updated": "ฟีด RSS ของเนื้อหาที่อัปเดต", - "search": "ค้นหา", - "search.config.lang": "th", - "search.placeholder": "ค้นหา", - "search.share": "แบ่งปัน", - "search.reset": "ล้าง", - "search.result.initializer": "กำลังเริ่มต้นการค้นหา", - "search.result.placeholder": "พิมพ์เพื่อเริ่มค้นหา", - "search.result.none": "ไม่พบเอกสารที่ตรงกัน", - "search.result.one": "พบเอกสารที่ตรงกัน", - "search.result.other": "พบ # เอกสารที่ตรงกัน", - "search.result.more.one": "อีกหนึ่งในหน้านี้", - "search.result.more.other": "# เพิ่มเติมในหน้านี้", - "search.result.term.missing": "ไม่พบ", - "select.language": "เลือกภาษา", - "select.version": "เลือกเวอร์ชัน", - "source": "ไปที่พื้นที่เก็บข้อมูล", - "source.file.contributors": "ผู้มีส่วนร่วม", - "source.file.date.created": "สร้าง", - "source.file.date.updated": "สร้าง", - "tabs": "แท็บ", - "toc": "สารบัญ", - "top": "กลับไปด้านบนสุด" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/tl.html b/src/templates/partials/languages/tl.html deleted file mode 100644 index 00c22c99..00000000 --- a/src/templates/partials/languages/tl.html +++ /dev/null @@ -1,57 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Tagalog --> -{% macro t(key) %}{{ { - "language": "tl", - "action.edit": "I-edit ang pahinang ito", - "action.skip": "I-skip tungo sa nilalaman", - "clipboard.copy": "Kopyahin sa clipboard", - "clipboard.copied": "Nakopya mula sa clipboard", - "footer": "Lagdang Pangwakas", - "footer.next": "Susunod", - "footer.previous": "Nakaraan", - "header": "Pamuhatan", - "meta.comments": "Mga Komento", - "meta.source": "Pinagmulan", - "nav": "Nabigasyon", - "search": "Hanapin", - "search.placeholder": "Hanapin", - "search.share": "Ibahagi", - "search.reset": "Tanggalin", - "search.result.initializer": "Sinisimulan ang paghahanap", - "search.result.placeholder": "Mag-type upang simulan ang paghahanap", - "search.result.none": "Walang nahanap na dokumento", - "search.result.one": "1 magkatugmang dokumento", - "search.result.other": "# magkatugmang mga dokumento", - "search.result.more.one": "1 meron sa pahina na ito", - "search.result.more.other": "# meron sa pahina na ito", - "search.result.term.missing": "Nawawala", - "select.language": "Pumili ng lenguwahe", - "select.version": "Pumili ng bersyon", - "source": "Pumunta sa repository", - "source.file.date.created": "Nagawa", - "source.file.date.updated": "Huling update", - "tabs": "Mga tala", - "toc": "Talaan ng nilalaman", - "top": "Bumalik sa taas" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/tr.html b/src/templates/partials/languages/tr.html deleted file mode 100644 index 860f8ed7..00000000 --- a/src/templates/partials/languages/tr.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Turkish --> -{% macro t(key) %}{{ { - "language": "tr", - "action.edit": "Düzenle", - "action.skip": "Ana içeriğe geç", - "action.view": "Sayfanın kaynağını görüntüle", - "announce.dismiss": "Bir daha gösterme", - "blog.archive": "Arşiv", - "blog.categories": "Kategoriler", - "blog.categories.in": "in", - "blog.continue": "Okumaya devam et", - "blog.draft": "Taslak", - "blog.index": "Dizine geri dön", - "blog.meta": "Metadata", - "blog.references": "İlgili bağlantılar", - "clipboard.copy": "Kopyala", - "clipboard.copied": "Kopyalandı", - "consent.accept": "Kabul et", - "consent.manage": "Ayarları yönet", - "consent.reject": "Reddet", - "footer": "Altbilgi", - "footer.next": "Sonraki", - "footer.previous": "Önceki", - "header": "Başlık", - "meta.comments": "Yorumlar", - "meta.source": "Kaynak", - "nav": "Navigasyon", - "readtime.one": "1 dakika okuma", - "readtime.other": "# dakika okuma", - "rss.created": "RSS beslemesi", - "rss.updated": "Güncellenmiş içeriğin RSS beslemesi", - "search": "Ara", - "search.config.lang": "tr", - "search.placeholder": "Ara", - "search.share": "Paylaş", - "search.reset": "Temizle", - "search.result.initializer": "Arama başlatılıyor", - "search.result.placeholder": "Aramaya başlamak için yazın", - "search.result.none": "Eşleşen doküman bulunamadı", - "search.result.one": "1 doküman bulundu", - "search.result.other": "# doküman bulundu", - "search.result.more.one": "Bu sayfada 1 tane daha", - "search.result.more.other": "Bu sayfada # tane daha", - "search.result.term.missing": "Eksik", - "select.language": "Dil seç", - "select.version": "Versiyon seç", - "source": "Depoya git", - "source.file.contributors": "Katkıda bulunanlar", - "source.file.date.created": "Oluşturuldu", - "source.file.date.updated": "Son Güncelleme", - "tabs": "Sekmeler", - "toc": "İçindekiler", - "top": "Başa dön" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/uk.html b/src/templates/partials/languages/uk.html deleted file mode 100644 index ca5c709c..00000000 --- a/src/templates/partials/languages/uk.html +++ /dev/null @@ -1,75 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Ukrainian --> -{% macro t(key) %}{{ { - "language": "uk", - "action.edit": "Редагувати сторінку", - "action.skip": "Перейти до змісту", - "action.view": "Переглянути вихідний код сторінки", - "announce.dismiss": "Більше не показувати", - "blog.archive": "Архівувати", - "blog.categories": "Категорії", - "blog.categories.in": "в", - "blog.continue": "Читати далі", - "blog.draft": "Чернетка", - "blog.index": "Повернутись на головну", - "blog.meta": "Метадані", - "blog.references": "Пов'язані посилання", - "clipboard.copy": "Скопіювати в буфер", - "clipboard.copied": "Скопійовано в буфер", - "consent.accept": "Прийняти", - "consent.manage": "Керувати налаштуваннями", - "consent.reject": "Відхилити", - "footer": "Футер", - "footer.next": "Вперед", - "footer.previous": "Назад", - "header": "Хедер", - "meta.comments": "Коментарі", - "meta.source": "Вихідний код", - "nav": "Навігація", - "readtime.one": "Час на прочитання: 1 хвилина", - "readtime.other": "Час на прочитання: # хвилин", - "rss.created": "RSS стрічка", - "rss.updated": "RSS стрічка оновленого контенту", - "search": "Шукати", - "search.placeholder": "Пошук", - "search.share": "Поділитись", - "search.reset": "Очистити", - "search.result.initializer": "Пошук розпочато", - "search.result.placeholder": "Розпочніть писати для пошуку", - "search.result.none": "Збігів не знайдено", - "search.result.one": "Знайдено 1 збіг", - "search.result.other": "Знайдено # збігів", - "search.result.more.one": "Ще 1 збіг на цій сторінці", - "search.result.more.other": "Ще # збігів на цій сторінці", - "search.result.term.missing": "Не знайдено запиту", - "select.language": "Обрати мову", - "select.version": "Обрати версію", - "source": "Перейти до вихідного коду", - "source.file.contributors": "Контриб'ютори", - "source.file.date.created": "Створено", - "source.file.date.updated": "Востаннє оновлено", - "tabs": "Вкладки", - "toc": "Зміст", - "top": "Повернутись нагору" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/ur.html b/src/templates/partials/languages/ur.html deleted file mode 100644 index 14a50588..00000000 --- a/src/templates/partials/languages/ur.html +++ /dev/null @@ -1,77 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Urdu --> -{% macro t(key) %}{{ { - "language": "ur", - "direction": "rtl", - "action.edit": "اس صفحے میں ترمیم کریں", - "action.skip": "براہِ راست مواد پر جائیں", - "action.view": "اس صفحہ کا ماخذ دیکھیں", - "announce.dismiss": "اسے دوبارہ مت دکھائیں", - "blog.archive": "محفوظ شدہ", - "blog.categories": "اقسام", - "blog.categories.in": "میں", - "blog.continue": "پڑھنا جاری رکھیے", - "blog.draft": "ڈرافٹ", - "blog.index": "واپس انڈیکس پر جائیں", - "blog.meta": "میٹا ڈیٹا", - "blog.references": "متعلقہ لنکس", - "clipboard.copy": "کلِپ بورڈ میں نقل کریں", - "clipboard.copied": "کلِپ بورڈ میں نقل کر دیا گیا", - "consent.accept": "قبول کریں", - "consent.manage": "سیٹینگ بدلیں", - "consent.reject": "رد کرنا", - "footer": "ذیلی تحریر", - "footer.next": "اگلا", - "footer.previous": "پچھلا", - "header": "سر تحریر", - "meta.comments": "تبصرے", - "meta.source": "ذریعہ", - "nav": "رہنمائی", - "readtime.one": "1 منٹ لگے گا", - "readtime.other": "# منٹ لگیں گے", - "rss.created": "RSS فیڈ", - "rss.updated": "تازہ ترین مواد کی RSS فیڈ", - "search": "تلاش", - "search.config.pipeline": " ", - "search.placeholder": "تلاش کریں", - "search.share": "اشتراک کریں", - "search.reset": "صاف کریں", - "search.result.initializer": "تلاش کا آغاز ہو رہا ہے", - "search.result.placeholder": "تلاش شروع کرنے کے لئے ٹائپ کریں", - "search.result.none": "کوئی ملتی جلتی دستاویزات نہیں", - "search.result.one": "۱ ملتی جلتی دستاویز", - "search.result.other": "# ملتی جلتی دستاویزات", - "search.result.more.one": "اِس صفحے پر مزید ۱", - "search.result.more.other": "اِس صفحے پر مزید #", - "search.result.term.missing": "گمشدہ", - "select.language": "زبان کا انتخاب کریں", - "select.version": "ورژن کا انتخاب کریں", - "source": "ریپازٹری پر جائیں", - "source.file.contributors": "تعاون کار", - "source.file.date.created": "تخلیق", - "source.file.date.updated": "آخری بار تجدید", - "tabs": "ٹیبز", - "toc": "فہرست", - "top": "واپس اوپر جائیں" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/uz.html b/src/templates/partials/languages/uz.html deleted file mode 100644 index d86f4db2..00000000 --- a/src/templates/partials/languages/uz.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Uzbek --> -{% macro t(key) %}{{ { - "language": "uz", - "action.edit": "Ushbu sahifani tahrirlash", - "action.skip": "Tarkibga o'tish", - "action.view": "Ushbu sahifaning manbasini ko'rish", - "announce.dismiss": "Buni boshqa ko'rsatma", - "blog.archive": "Arxiv", - "blog.categories": "Kategoriyalar", - "blog.categories.in": "ichida", - "blog.continue": "O'qishni davom ettiring", - "blog.draft": "Qoralama", - "blog.index": "Indeks sahifasiga qaytish", - "blog.meta": "Metama'lumot", - "blog.references": "Bog'liq havolalar", - "clipboard.copy": "Buferga nusxalash", - "clipboard.copied": "Buferga nusxalandi", - "consent.accept": "Qabul qilish", - "consent.manage": "Sozlamalarni boshqarish", - "consent.reject": "Rad etish", - "footer": "Pastgi qism", - "footer.next": "Keyingi sahifa", - "footer.previous": "Oldingi sahifa", - "header": "Sarlavha", - "meta.comments": "Izohlar", - "meta.source": "Manba", - "nav": "Navigatsiya", - "readtime.one": "1 daqiqa o'qish", - "readtime.other": "# daqiqa o'qish", - "rss.created": "RSS tasmasi", - "rss.updated": "Yangilangan kontentning RSS tasmasi", - "search": "Qidirish", - "search.config.lang": "tr", - "search.placeholder": "Qidirish", - "search.share": "Ulashish", - "search.reset": "Tozalash", - "search.result.initializer": "Qidiruv ishga tushirilmoqda", - "search.result.placeholder": "Qidiruvni boshlash uchun kiriting", - "search.result.none": "Mos natijalar yo'q", - "search.result.one": "1 ta mos natija", - "search.result.other": "# ta mos keladigan natijalar", - "search.result.more.one": "Ushbu sahifada yana 1 ta natija", - "search.result.more.other": "Bu sahifada yana # ta natija", - "search.result.term.missing": "To'ldirilmagan", - "select.language": "Tilni tanlang", - "select.version": "Versiyani tanlang", - "source": "Repozitoriyga o'tish", - "source.file.contributors": "Hissa qo'shuvchilar", - "source.file.date.created": "Yaratildi", - "source.file.date.updated": "Oxirgi yangilanish", - "tabs": "Yorliqlar", - "toc": "Mundarija", - "top": "Yuqoriga qaytish" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/vi.html b/src/templates/partials/languages/vi.html deleted file mode 100644 index b63a8d82..00000000 --- a/src/templates/partials/languages/vi.html +++ /dev/null @@ -1,76 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Vietnamese --> -{% macro t(key) %}{{ { - "language": "vi", - "action.edit": "Chỉnh sửa", - "action.skip": "Bỏ qua", - "action.view": "Xem mã nguồn của trang", - "announce.dismiss": "Không hiển thị lại", - "blog.archive": "Lưu trữ", - "blog.categories": "Mục", - "blog.categories.in": "Trong", - "blog.continue": "Tiếp tục đọc", - "blog.draft": "Bản nháp", - "blog.index": "Quay lại", - "blog.meta": "Metadata", - "blog.references": "Các liên kết liên quan", - "clipboard.copy": "Sao chép vào bộ nhớ tạm", - "clipboard.copied": "Đã sao chép", - "consent.accept": "Đồng ý", - "consent.manage": "Cài đặt", - "consent.reject": "Từ chối", - "footer": "Chân trang", - "footer.next": "Sau", - "footer.previous": "Trước", - "header": "Đầu trang", - "meta.comments": "Bình luận", - "meta.source": "Mã nguồn", - "nav": "Thanh điều hướng", - "readtime.one": "1 phút đọc", - "readtime.other": "# phút đọc", - "rss.created": "RSS feed", - "rss.updated": "RSS feed of updated content", - "search": "Tìm kiếm", - "search.config.lang": "vi", - "search.placeholder": "Tìm kiếm", - "search.share": "Chia sẻ", - "search.reset": "Xoá", - "search.result.initializer": "Initializing search", - "search.result.placeholder": "Nhập để bắt đầu tìm kiếm", - "search.result.none": "Không tìm thấy tài liệu liên quan", - "search.result.one": "1 tài liệu liên quan", - "search.result.other": "# tài liệu liên quan", - "search.result.more.one": "1 từ khác trong trang", - "search.result.more.other": "# từ khác trong trang", - "search.result.term.missing": "Không", - "select.language": "Chọn ngôn ngữ", - "select.version": "Chọn phiên bản", - "source": "Xem mã nguồn", - "source.file.contributors": "Contributors", - "source.file.date.created": "Tạo", - "source.file.date.updated": "Cập nhật lần cuối", - "tabs": "Tabs", - "toc": "Mục lục", - "top": "Trở lại mục lục" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/zh-Hant.html b/src/templates/partials/languages/zh-Hant.html deleted file mode 100644 index 578fc82a..00000000 --- a/src/templates/partials/languages/zh-Hant.html +++ /dev/null @@ -1,77 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Chinese (Traditional) --> -{% macro t(key) %}{{ { - "language": "zh-Hant", - "action.edit": "編輯此頁", - "action.skip": "跳轉至", - "action.view": "查看源代碼", - "announce.dismiss": "不再顯示此訊息", - "blog.archive": "存檔", - "blog.categories": "分類", - "blog.categories.in": "分類在", - "blog.continue": "繼續閲讀", - "blog.draft": "草稿", - "blog.index": "回到首頁", - "blog.meta": "元數據", - "blog.references": "相關鏈接", - "clipboard.copy": "拷貝", - "clipboard.copied": "已拷貝", - "consent.accept": "接受", - "consent.manage": "管理設置", - "consent.reject": "拒絕", - "footer": "頁脚", - "footer.next": "下一頁", - "footer.previous": "上一頁", - "header": "頁首", - "meta.comments": "評論", - "meta.source": "來源", - "search.config.pipeline": "stemmer", - "search.config.separator": "[\\s\\u200b\\u3000\\-、。,.?!;]+", - "nav": "導航", - "readtime.one": "需要 1 分鐘閲讀", - "readtime.other": "需要 # 分鐘閲讀", - "rss.created": "簡易資訊聚合", - "rss.updated": "更新之部分的簡易資訊聚合", - "search": "搜尋", - "search.placeholder": "搜尋", - "search.share": "分享", - "search.reset": "清空", - "search.result.initializer": "正在初始化搜尋引擎", - "search.result.placeholder": "鍵入以開始檢索", - "search.result.none": "沒有找到符合條件的結果", - "search.result.one": "找到 1 个符合條件的結果", - "search.result.other": "找到 # 個符合條件的結果", - "search.result.more.one": "此頁尚有 1 個符合的項目", - "search.result.more.other": "此頁尚有 # 個符合的項目", - "search.result.term.missing": "缺失", - "select.language": "選擇語言", - "select.version": "選擇版本", - "source": "前往倉庫", - "source.file.contributors": "貢獻者", - "source.file.date.created": "建立日期", - "source.file.date.updated": "最後更新", - "tabs": "標籤頁", - "toc": "目錄", - "top": "回到頂部" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/zh-TW.html b/src/templates/partials/languages/zh-TW.html deleted file mode 100644 index 405538f8..00000000 --- a/src/templates/partials/languages/zh-TW.html +++ /dev/null @@ -1,77 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Chinese (Taiwanese) --> -{% macro t(key) %}{{ { - "language": "zh-TW", - "action.edit": "編輯此頁", - "action.skip": "跳轉到", - "action.view": "查看此頁原始碼", - "announce.dismiss": "不再顯示此訊息", - "blog.archive": "封存", - "blog.categories": "分類", - "blog.categories.in": "於", - "blog.continue": "繼續閱讀", - "blog.draft": "草稿", - "blog.index": "回到主頁", - "blog.meta": "元數據", - "blog.references": "相關連結", - "clipboard.copy": "複製", - "clipboard.copied": "已複製", - "consent.accept": "同意", - "consent.manage": "管理設定", - "consent.reject": "拒絕", - "footer": "頁腳", - "footer.next": "下一頁", - "footer.previous": "上一頁", - "header": "頁首", - "meta.comments": "留言", - "meta.source": "來源", - "nav": "導覽列", - "readtime.one": "需要 1 分鐘閱讀時間", - "readtime.other": "需要 # 分鐘閱讀時間", - "rss.created": "RSS 訂閱", - "rss.updated": "RSS 訂閱內容已更新", - "search": "搜尋", - "search.config.pipeline": "stemmer", - "search.config.separator": "[\\s\\u200b\\u3000\\-、。,.?!;]+", - "search.placeholder": "搜尋", - "search.share": "分享", - "search.reset": "清除", - "search.result.initializer": "正在初始化搜尋引擎", - "search.result.placeholder": "打字進行搜尋", - "search.result.none": "沒有符合的項目", - "search.result.one": "找到 1 個符合的項目", - "search.result.other": "找到 # 個符合的項目", - "search.result.more.one": "此頁尚有 1 個符合的項目", - "search.result.more.other": "此頁尚有 # 個符合的項目", - "search.result.term.missing": "缺少字詞", - "select.language": "選擇語言", - "select.version": "選擇版本", - "source": "前往倉庫", - "source.file.contributors": "貢獻者", - "source.file.date.created": "建立日期", - "source.file.date.updated": "最後更新", - "tabs": "標籤", - "toc": "目錄", - "top": "回到頂端" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/languages/zh.html b/src/templates/partials/languages/zh.html deleted file mode 100644 index 49f233a4..00000000 --- a/src/templates/partials/languages/zh.html +++ /dev/null @@ -1,77 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Translations: Chinese (Simplified) --> -{% macro t(key) %}{{ { - "language": "zh", - "action.edit": "编辑此页", - "action.skip": "跳转至", - "action.view": "查看本页的源代码", - "announce.dismiss": "不再显示此消息", - "blog.archive": "归档", - "blog.categories": "分类", - "blog.categories.in": "分类于", - "blog.continue": "继续阅读", - "blog.draft": "草稿", - "blog.index": "回到主页", - "blog.meta": "元数据", - "blog.references": "相关链接", - "clipboard.copy": "复制", - "clipboard.copied": "已复制", - "consent.accept": "同意", - "consent.manage": "管理设定", - "consent.reject": "拒绝", - "footer": "页脚", - "footer.next": "下一页", - "footer.previous": "上一页", - "header": "页眉", - "meta.comments": "评论", - "meta.source": "来源", - "nav": "导航栏", - "readtime.one": "需要 1 分钟阅读时间", - "readtime.other": "需要 # 分钟阅读时间", - "rss.created": "RSS 订阅", - "rss.updated": "已更新内容的 RSS 订阅", - "search": "查找", - "search.config.pipeline": "stemmer", - "search.config.separator": "[\\s\\u200b\\u3000\\-、。,.?!;]+", - "search.placeholder": "搜索", - "search.share": "分享", - "search.reset": "清空当前内容", - "search.result.initializer": "正在初始化搜索引擎", - "search.result.placeholder": "键入以开始搜索", - "search.result.none": "没有找到符合条件的结果", - "search.result.one": "找到 1 个符合条件的结果", - "search.result.other": "# 个符合条件的结果", - "search.result.more.one": "在该页上还有 1 个符合条件的结果", - "search.result.more.other": "在该页上还有 # 个符合条件的结果", - "search.result.term.missing": "缺少", - "select.language": "选择当前语言", - "select.version": "选择当前版本", - "source": "前往仓库", - "source.file.contributors": "贡献者", - "source.file.date.created": "创建日期", - "source.file.date.updated": "最后更新", - "tabs": "标签", - "toc": "目录", - "top": "回到页面顶部" -}[key] }}{% endmacro %} diff --git a/src/templates/partials/logo.html b/src/templates/partials/logo.html deleted file mode 100644 index 05832c71..00000000 --- a/src/templates/partials/logo.html +++ /dev/null @@ -1,29 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Logo --> -{% if config.theme.logo %} - <img src="{{ config.theme.logo | url }}" alt="logo" /> -{% else %} - {% set icon = config.theme.icon.logo or "material/library" %} - {% include ".icons/" ~ icon ~ ".svg" %} -{% endif %} diff --git a/src/templates/partials/nav-item.html b/src/templates/partials/nav-item.html deleted file mode 100644 index 24d74a1a..00000000 --- a/src/templates/partials/nav-item.html +++ /dev/null @@ -1,249 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Render navigation link status --> -{% macro render_status(nav_item, type) %} - {% set class = "md-status md-status--" ~ type %} - - <!-- Render icon with title (or tooltip), if given --> - {% if config.extra.status and config.extra.status[type] %} - <span - class="{{ class }}" - title="{{ config.extra.status[type] }}" - > - </span> - - <!-- Render icon only --> - {% else %} - <span class="{{ class }}"></span> - {% endif %} -{% endmacro %} - -<!-- Render navigation link content --> -{% macro render_content(nav_item, ref = nav_item) %} - - <!-- Navigation link icon --> - {% if nav_item.is_page and nav_item.meta.icon %} - {% include ".icons/" ~ nav_item.meta.icon ~ ".svg" %} - {% endif %} - - <!-- Navigation link title --> - <span class="md-ellipsis"> - {{ ref.title }} - </span> - - <!-- Navigation link status --> - {% if nav_item.is_page and nav_item.meta.status %} - {{ render_status(nav_item, nav_item.meta.status) }} - {% endif %} -{% endmacro %} - -<!-- Render navigation item (pruned) --> -{% macro render_pruned(nav_item, ref = nav_item) %} - {% set first = nav_item.children | first %} - - <!-- Recurse, if the first item has further nested items --> - {% if first and first.children %} - {{ render_pruned(first, ref) }} - - <!-- Navigation link --> - {% else %} - <a href="{{ first.url | url }}" class="md-nav__link"> - {{ render_content(ref) }} - - <!-- Only render toggle if there's at least one nested item --> - {% if nav_item.children | length > 0 %} - <span class="md-nav__icon md-icon"></span> - {% endif %} - </a> - {% endif %} -{% endmacro %} - -<!-- Render navigation item --> -{% macro render(nav_item, path, level) %} - - <!-- Determine classes --> - {% set class = "md-nav__item" %} - {% if nav_item.active %} - {% set class = class ~ " md-nav__item--active" %} - {% endif %} - - <!-- Navigation item with nested items --> - {% if nav_item.children %} - - <!-- Determine all nested items that are index pages --> - {% set indexes = [] %} - {% if "navigation.indexes" in features %} - {% for nav_item in nav_item.children %} - {% if nav_item.is_index and not index is defined %} - {% set _ = indexes.append(nav_item) %} - {% endif %} - {% endfor %} - {% endif %} - - <!-- Determine whether to render item as a section --> - {% set tabs = "navigation.tabs" in features %} - {% set sections = "navigation.sections" in features %} - {% if tabs and level == 1 or sections and tabs >= level - 1 %} - {% set class = class ~ " md-nav__item--section" %} - {% set is_section = true %} - - <!-- Determine whether to prune inactive item --> - {% elif not nav_item.active and "navigation.prune" in features %} - {% set class = class ~ " md-nav__item--pruned" %} - {% set is_pruned = true %} - {% endif %} - - <!-- Nested navigation item --> - <li class="{{ class }} md-nav__item--nested"> - {% if not is_pruned %} - {% set checked = "checked" if nav_item.active %} - - <!-- Determine checked and indeterminate state --> - {% set is_expanded = "navigation.expand" in features %} - {% if is_expanded and not checked %} - {% set indeterminate = "md-toggle--indeterminate" %} - {% endif %} - - <!-- Active checkbox expands items contained within nested section --> - <input - class="md-nav__toggle md-toggle {{ indeterminate }}" - type="checkbox" - id="{{ path }}" - {{ checked }} - /> - - <!-- Toggle to expand nested items --> - {% if not indexes %} - {% set tabindex = "0" if not is_section %} - <label - class="md-nav__link" - for="{{ path }}" - id="{{ path }}_label" - tabindex="{{ tabindex }}" - > - {{ render_content(nav_item) }} - <span class="md-nav__icon md-icon"></span> - </label> - - <!-- Toggle to expand nested items with link to index page --> - {% else %} - {% set index = indexes | first %} - {% set class = "md-nav__link--active" if index == page %} - <div class="md-nav__link md-nav__container"> - <a - href="{{ index.url | url }}" - class="md-nav__link {{ class }}" - > - {{ render_content(index, nav_item) }} - </a> - - <!-- Only render toggle if there's at least one more page --> - {% if nav_item.children | length > 1 %} - {% set tabindex = "0" if not is_section %} - <label - class="md-nav__link {{ class }}" - for="{{ path }}" - id="{{ path }}_label" - tabindex="{{ tabindex }}" - > - <span class="md-nav__icon md-icon"></span> - </label> - {% endif %} - </div> - {% endif %} - - <!-- Nested navigation --> - <nav - class="md-nav" - data-md-level="{{ level }}" - aria-labelledby="{{ path }}_label" - aria-expanded="{{ nav_item.active | tojson }}" - > - <label class="md-nav__title" for="{{ path }}"> - <span class="md-nav__icon md-icon"></span> - {{ nav_item.title }} - </label> - <ul class="md-nav__list" data-md-scrollfix> - - <!-- Nested navigation item --> - {% for nav_item in nav_item.children %} - {% if not indexes or nav_item != indexes | first %} - {{ render(nav_item, path ~ "_" ~ loop.index, level + 1) }} - {% endif %} - {% endfor %} - </ul> - </nav> - - <!-- Pruned navigation item --> - {% else %} - {{ render_pruned(nav_item) }} - {% endif %} - </li> - - <!-- Currently active page --> - {% elif nav_item == page %} - <li class="{{ class }}"> - {% set toc = page.toc %} - - <!-- State toggle --> - <input - class="md-nav__toggle md-toggle" - type="checkbox" - id="__toc" - /> - - <!-- Hack: see partials/toc.html for more information --> - {% set first = toc | first %} - {% if first and first.level == 1 %} - {% set toc = first.children %} - {% endif %} - - <!-- Navigation link to table of contents --> - {% if toc %} - <label class="md-nav__link md-nav__link--active" for="__toc"> - {{ render_content(nav_item) }} - <span class="md-nav__icon md-icon"></span> - </label> - {% endif %} - <a - href="{{ nav_item.url | url }}" - class="md-nav__link md-nav__link--active" - > - {{ render_content(nav_item) }} - </a> - - <!-- Table of contents --> - {% if toc %} - {% include "partials/toc.html" %} - {% endif %} - </li> - - <!-- Navigation item --> - {% else %} - <li class="{{ class }}"> - <a href="{{ nav_item.url | url }}" class="md-nav__link"> - {{ render_content(nav_item) }} - </a> - </li> - {% endif %} -{% endmacro %} diff --git a/src/templates/partials/nav.html b/src/templates/partials/nav.html deleted file mode 100644 index c41fe694..00000000 --- a/src/templates/partials/nav.html +++ /dev/null @@ -1,69 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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 "partials/nav-item.html" as item with context %} - -<!-- Determine classes --> -{% set class = "md-nav md-nav--primary" %} -{% if "navigation.tabs" in features %} - {% set class = class ~ " md-nav--lifted" %} -{% endif %} -{% if "toc.integrate" in features %} - {% set class = class ~ " md-nav--integrated" %} -{% endif %} - -<!-- Navigation --> -<nav - class="{{ class }}" - aria-label="{{ lang.t('nav') }}" - data-md-level="0" -> - - <!-- Site title --> - <label class="md-nav__title" for="__drawer"> - <a - href="{{ config.extra.homepage | d(nav.homepage.url, true) | url }}" - title="{{ config.site_name | e }}" - class="md-nav__button md-logo" - aria-label="{{ config.site_name }}" - data-md-component="logo" - > - {% include "partials/logo.html" %} - </a> - {{ config.site_name }} - </label> - - <!-- Repository information --> - {% if config.repo_url %} - <div class="md-nav__source"> - {% include "partials/source.html" %} - </div> - {% endif %} - - <!-- Navigation list --> - <ul class="md-nav__list" data-md-scrollfix> - {% for nav_item in nav %} - {% set path = "__nav_" ~ loop.index %} - {{ item.render(nav_item, path, 1) }} - {% endfor %} - </ul> -</nav> diff --git a/src/templates/partials/pagination.html b/src/templates/partials/pagination.html deleted file mode 100644 index 046ecbe9..00000000 --- a/src/templates/partials/pagination.html +++ /dev/null @@ -1,42 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Pagination icons --> -{% import ".icons/material/chevron-double-left.svg" as icon_first %} -{% import ".icons/material/chevron-left.svg" as icon_previous %} -{% import ".icons/material/chevron-right.svg" as icon_next %} -{% import ".icons/material/chevron-double-right.svg" as icon_last %} - -<!-- Pagination --> -<nav class="md-pagination"> - {{ - pagination({ - "link_attr": { "class": "md-pagination__link" }, - "curpage_attr": { "class": "md-pagination__current" }, - "dotdot_attr": { "class": "md-pagination__dots" }, - "symbol_first": icon_first, - "symbol_previous": icon_previous, - "symbol_next": icon_next, - "symbol_last": icon_last - }) - }} -</nav> diff --git a/src/templates/partials/palette.html b/src/templates/partials/palette.html deleted file mode 100644 index ccb8db0a..00000000 --- a/src/templates/partials/palette.html +++ /dev/null @@ -1,55 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Color palette toggle --> -<form class="md-header__option" data-md-component="palette"> - {% for option in config.theme.palette %} - {% set scheme = option.scheme | d("default", true) %} - {% set primary = option.primary | d("indigo", true) %} - {% set accent = option.accent | d("indigo", true) %} - <input - class="md-option" - data-md-color-media="{{ option.media }}" - data-md-color-scheme="{{ scheme | replace(' ', '-') }}" - data-md-color-primary="{{ primary | replace(' ', '-') }}" - data-md-color-accent="{{ accent | replace(' ', '-') }}" - {% if option.toggle %} - aria-label="{{ option.toggle.name }}" - {% else %} - aria-hidden="true" - {% endif %} - type="radio" - name="__palette" - id="__palette_{{ loop.index }}" - /> - {% if option.toggle %} - <label - class="md-header__button md-icon" - title="{{ option.toggle.name }}" - for="__palette_{{ loop.index0 or loop.length }}" - hidden - > - {% include ".icons/" ~ option.toggle.icon ~ ".svg" %} - </label> - {% endif %} - {% endfor %} -</form> diff --git a/src/templates/partials/post.html b/src/templates/partials/post.html deleted file mode 100644 index c7233051..00000000 --- a/src/templates/partials/post.html +++ /dev/null @@ -1,99 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Post excerpt --> -<article class="md-post md-post--excerpt"> - <header class="md-post__header"> - - <!-- Post authors --> - {% if post.authors %} - <nav class="md-post__authors md-typeset"> - {% for author in post.authors %} - <span class="md-author"> - <img src="{{ author.avatar }}" alt="{{ author.name }}" /> - </span> - {% endfor %} - </nav> - {% endif %} - - <!-- Post metadata --> - <div class="md-post__meta md-meta"> - <ul class="md-meta__list"> - - <!-- Post date --> - <li class="md-meta__item"> - <time datetime="{{ post.config.date.created }}"> - {{- post.config.date.created | date -}} - </time> - {#- Collapse whitespace -#} - </li> - - <!-- Post categories --> - {% if post.categories %} - <li class="md-meta__item"> - {{ lang.t("blog.categories.in") }} - {% for category in post.categories %} - <a - href="{{ category.url | url }}" - class="md-meta__link" - > - {{- category.title -}} - </a> - {%- if loop.revindex > 1 %}, {% endif -%} - {% endfor -%} - </li> - {% endif %} - - <!-- Post readtime --> - {% if post.config.readtime %} - {% set time = post.config.readtime %} - <li class="md-meta__item"> - {% if time == 1 %} - {{ lang.t("readtime.one") }} - {% else %} - {{ lang.t("readtime.other") | replace("#", time) }} - {% endif %} - </li> - {% endif %} - </ul> - - <!-- Draft marker --> - {% if post.config.draft %} - <span class="md-draft"> - {{ lang.t("blog.draft") }} - </span> - {% endif %} - </div> - </header> - - <!-- Post content --> - <div class="md-post__content md-typeset"> - {{ post.content }} - - <!-- Continue reading link --> - <nav class="md-post__action"> - <a href="{{ post.url | url }}"> - {{ lang.t("blog.continue") }} - </a> - </nav> - </div> -</article> diff --git a/src/templates/partials/progress.html b/src/templates/partials/progress.html deleted file mode 100644 index f5d13d10..00000000 --- a/src/templates/partials/progress.html +++ /dev/null @@ -1,24 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Progress indicator --> -<div class="md-progress" data-md-component="progress" role="progressbar"></div> diff --git a/src/templates/partials/search.html b/src/templates/partials/search.html deleted file mode 100644 index 1854a7d3..00000000 --- a/src/templates/partials/search.html +++ /dev/null @@ -1,109 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Search interface --> -<div class="md-search" data-md-component="search" role="dialog"> - <label class="md-search__overlay" for="__search"></label> - <div class="md-search__inner" role="search"> - <form class="md-search__form" name="search"> - - <!-- Search input --> - <input - type="text" - class="md-search__input" - name="query" - aria-label="{{ lang.t('search.placeholder') }}" - placeholder="{{ lang.t('search.placeholder') }}" - autocapitalize="off" - autocorrect="off" - autocomplete="off" - spellcheck="false" - data-md-component="search-query" - required - /> - - <!-- Button to open search --> - <label class="md-search__icon md-icon" for="__search"> - {% set icon = config.theme.icon.search or "material/magnify" %} - {% include ".icons/" ~ icon ~ ".svg" %} - {% set icon = config.theme.icon.previous or "material/arrow-left" %} - {% include ".icons/" ~ icon ~ ".svg" %} - </label> - - <!-- Search options --> - <nav - class="md-search__options" - aria-label="{{ lang.t('search') }}" - > - - <!-- Button to share search --> - {% if "search.share" in features %} - <a - href="javascript:void(0)" - class="md-search__icon md-icon" - title="{{ lang.t('search.share') }}" - aria-label="{{ lang.t('search.share') }}" - data-clipboard - data-clipboard-text="" - data-md-component="search-share" - tabindex="-1" - > - {% set icon = config.theme.icon.share or "material/share-variant" %} - {% include ".icons/" ~ icon ~ ".svg" %} - </a> - {% endif %} - - <!-- Button to reset search --> - <button - type="reset" - class="md-search__icon md-icon" - title="{{ lang.t('search.reset') }}" - aria-label="{{ lang.t('search.reset') }}" - tabindex="-1" - > - {% set icon = config.theme.icon.close or "material/close" %} - {% include ".icons/" ~ icon ~ ".svg" %} - </button> - </nav> - - <!-- Search suggestions --> - {% if "search.suggest" in features %} - <div - class="md-search__suggest" - data-md-component="search-suggest" - ></div> - {% endif %} - </form> - <div class="md-search__output"> - <div class="md-search__scrollwrap" data-md-scrollfix> - - <!-- Search results --> - <div class="md-search-result" data-md-component="search-result"> - <div class="md-search-result__meta"> - {{ lang.t("search.result.initializer") }} - </div> - <ol class="md-search-result__list" role="presentation"></ol> - </div> - </div> - </div> - </div> -</div> diff --git a/src/templates/partials/social.html b/src/templates/partials/social.html deleted file mode 100644 index 5d2c4017..00000000 --- a/src/templates/partials/social.html +++ /dev/null @@ -1,48 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Social links --> -<div class="md-social"> - {% for social in config.extra.social %} - - <!-- Automatically set rel=me for Mastodon --> - {% set rel = "noopener" %} - {% if "mastodon" in social.icon %} - {% set rel = rel ~ " me" %} - {% endif %} - - <!-- Compute title and render link --> - {% set title = social.name %} - {% if not title and "//" in social.link %} - {% set _, url = social.link.split("//") %} - {% set title = url.split("/")[0] %} - {% endif %} - <a - href="{{ social.link }}" - target="_blank" rel="{{ rel }}" - title="{{ title | e }}" - class="md-social__link" - > - {% include ".icons/" ~ social.icon ~ ".svg" %} - </a> - {% endfor %} -</div> diff --git a/src/templates/partials/source-file.html b/src/templates/partials/source-file.html deleted file mode 100644 index 928e35de..00000000 --- a/src/templates/partials/source-file.html +++ /dev/null @@ -1,44 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Source file information --> -<hr /> -<div class="md-source-file"> - <small> - - <!-- mkdocs-git-revision-date-localized-plugin --> - {% if page.meta.git_revision_date_localized %} - {{ lang.t("source.file.date.updated") }}: - {{ page.meta.git_revision_date_localized }} - {% if page.meta.git_creation_date_localized %} - <br /> - {{ lang.t("source.file.date.created") }}: - {{ page.meta.git_creation_date_localized }} - {% endif %} - - <!-- mkdocs-git-revision-date-plugin --> - {% elif page.meta.revision_date %} - {{ lang.t("source.file.date.updated") }}: - {{ page.meta.revision_date }} - {% endif %} - </small> -</div> diff --git a/src/templates/partials/source.html b/src/templates/partials/source.html deleted file mode 100644 index f4aac3e6..00000000 --- a/src/templates/partials/source.html +++ /dev/null @@ -1,37 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Repository information --> -<a - href="{{ config.repo_url }}" - title="{{ lang.t('source') }}" - class="md-source" - data-md-component="source" -> - <div class="md-source__icon md-icon"> - {% set icon = config.theme.icon.repo or "fontawesome/brands/git-alt" %} - {% include ".icons/" ~ icon ~ ".svg" %} - </div> - <div class="md-source__repository"> - {{ config.repo_name }} - </div> -</a> diff --git a/src/templates/partials/tabs-item.html b/src/templates/partials/tabs-item.html deleted file mode 100644 index 7a12a742..00000000 --- a/src/templates/partials/tabs-item.html +++ /dev/null @@ -1,71 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Render navigation link content --> -{% macro render_content(nav_item, ref = nav_item) %} - - <!-- Navigation link icon --> - {% if nav_item == ref or "navigation.indexes" in features %} - {% if nav_item.is_index and nav_item.meta.icon %} - {% include ".icons/" ~ nav_item.meta.icon ~ ".svg" %} - {% endif %} - {% endif %} - - <!-- Navigation link title --> - {{ ref.title }} -{% endmacro %} - -<!-- Render navigation item --> -{% macro render(nav_item, ref = nav_item) %} - - <!-- Determine classes --> - {% set class = "md-tabs__item" %} - {% if ref.active %} - {% set class = class ~ " md-tabs__item--active" %} - {% endif %} - - <!-- Navigation item with nested items --> - {% if nav_item.children %} - {% set first = nav_item.children | first %} - - <!-- Recurse, if the first item has further nested items --> - {% if first.children %} - {{ render(first, ref) }} - - <!-- Nested navigation item --> - {% else %} - <li class="{{ class }}"> - <a href="{{ first.url | url }}" class="md-tabs__link"> - {{ render_content(first, ref) }} - </a> - </li> - {% endif %} - - <!-- Navigation item --> - {% else %} - <li class="{{ class }}"> - <a href="{{ nav_item.url | url }}" class="md-tabs__link"> - {{ render_content(nav_item) }} - </a> - </li> - {% endif %} -{% endmacro %} diff --git a/src/templates/partials/tabs.html b/src/templates/partials/tabs.html deleted file mode 100644 index 0ea590cf..00000000 --- a/src/templates/partials/tabs.html +++ /dev/null @@ -1,38 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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 "partials/tabs-item.html" as item with context %} - -<!-- Navigation tabs --> -<nav - class="md-tabs" - aria-label="{{ lang.t('tabs') }}" - data-md-component="tabs" -> - <div class="md-grid"> - <ul class="md-tabs__list"> - {% for nav_item in nav %} - {{ item.render(nav_item) }} - {% endfor %} - </ul> - </div> -</nav> diff --git a/src/templates/partials/tags.html b/src/templates/partials/tags.html deleted file mode 100644 index b3dea295..00000000 --- a/src/templates/partials/tags.html +++ /dev/null @@ -1,52 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Determine whether to show tags --> -{% if page.meta and page.meta.hide %} - {% set hidden = "hidden" if "tags" in page.meta.hide %} -{% endif %} - -<!-- Tags --> -<nav class="md-tags" {{ hidden }}> - {% for tag in tags %} - {% set icon = "" %} - {% if config.extra.tags %} - {% set icon = " md-tag-icon" %} - {% if tag.type %} - {% set icon = icon ~ " md-tag--" ~ tag.type %} - {% endif %} - {% endif %} - - <!-- Render tag with link --> - {% if tag.url %} - <a href="{{ tag.url | url }}" class="md-tag{{ icon }}"> - {{- tag.name -}} - </a> - - <!-- Render tag without link --> - {% else %} - <span class="md-tag{{ icon }}"> - {{- tag.name -}} - </span> - {% endif %} - {% endfor %} -</nav> diff --git a/src/templates/partials/toc-item.html b/src/templates/partials/toc-item.html deleted file mode 100644 index 1af82c56..00000000 --- a/src/templates/partials/toc-item.html +++ /dev/null @@ -1,39 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Table of contents item --> -<li class="md-nav__item"> - <a href="{{ toc_item.url }}" class="md-nav__link"> - {{ toc_item.title }} - </a> - - <!-- Table of contents list --> - {% if toc_item.children %} - <nav class="md-nav" aria-label="{{ toc_item.title | striptags }}"> - <ul class="md-nav__list"> - {% for toc_item in toc_item.children %} - {% include "partials/toc-item.html" %} - {% endfor %} - </ul> - </nav> - {% endif %} -</li> diff --git a/src/templates/partials/toc.html b/src/templates/partials/toc.html deleted file mode 100644 index cb50b257..00000000 --- a/src/templates/partials/toc.html +++ /dev/null @@ -1,56 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Determine title --> -{% set title = lang.t("toc") %} -{% if config.mdx_configs.toc and config.mdx_configs.toc.title %} - {% set title = config.mdx_configs.toc.title %} -{% endif %} - -<!-- Table of contents --> -<nav class="md-nav md-nav--secondary" aria-label="{{ title }}"> - {% set toc = page.toc %} - - <!-- - Check whether the content starts with a level 1 headline. If it does, the - top-level anchor must be skipped, since it would be redundant to the link - to the current page that is located just above the anchor. Therefore we - directly continue with the children of the anchor. - --> - {% set first = toc | first %} - {% if first and first.level == 1 %} - {% set toc = first.children %} - {% endif %} - - <!-- Table of contents title and list --> - {% if toc %} - <label class="md-nav__title" for="__toc"> - <span class="md-nav__icon md-icon"></span> - {{ title }} - </label> - <ul class="md-nav__list" data-md-component="toc" data-md-scrollfix> - {% for toc_item in toc %} - {% include "partials/toc-item.html" %} - {% endfor %} - </ul> - {% endif %} -</nav> diff --git a/src/templates/partials/top.html b/src/templates/partials/top.html deleted file mode 100644 index 737e6248..00000000 --- a/src/templates/partials/top.html +++ /dev/null @@ -1,28 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!-- Progress indicator --> -<button type="button" class="md-top md-icon" data-md-component="top" hidden> - {% set icon = config.theme.icon.top or "material/arrow-up" %} - {% include ".icons/" ~ icon ~ ".svg" %} - {{ lang.t("top") }} -</button> diff --git a/src/templates/redirect.html b/src/templates/redirect.html deleted file mode 100644 index 80869c4f..00000000 --- a/src/templates/redirect.html +++ /dev/null @@ -1,41 +0,0 @@ -<!-- - Copyright (c) 2016-2023 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. ---> - -<!doctype html> -<html> - <head> - <meta charset="utf-8" /> - <meta name="viewport" content="width=device-width,initial-scale=1" /> - <title>{{ config.site_name }}</title> - <noscript> - <meta http-equiv="refresh" content="0;url={{ page.meta.location }}" /> - </noscript> - <script> - window.location.replace([ - "{{ page.meta.location }}", - window.location.search, - window.location.hash - ].join("")) - </script> - </head> - <body></body> -</html> diff --git a/src/test.py b/src/test.py deleted file mode 100644 index 349b1bfd..00000000 --- a/src/test.py +++ /dev/null @@ -1,4 +0,0 @@ -import infini - -client = infini.Cli() -client.parse_args() |
