aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/src/templates/assets/javascripts/components/content
diff options
context:
space:
mode:
author简律纯 <i@jyunko.cn>2023-12-15 09:11:47 +0800
committer简律纯 <i@jyunko.cn>2023-12-15 09:11:47 +0800
commitbe8de118db913711eb72ae5187d26e54a0055727 (patch)
tree96cd6c012dafa3f4015e54edef90df5eaaab0ddb /src/templates/assets/javascripts/components/content
parent9b2d27ba1d91a0d5531bc9c0d52c3887a2dfb2aa (diff)
downloadinfini-be8de118db913711eb72ae5187d26e54a0055727.tar.gz
infini-be8de118db913711eb72ae5187d26e54a0055727.zip
refactor(docs): optmst `docs` dir & `deps`
Diffstat (limited to 'src/templates/assets/javascripts/components/content')
-rw-r--r--src/templates/assets/javascripts/components/content/_/index.ts125
-rw-r--r--src/templates/assets/javascripts/components/content/annotation/_/index.ts272
-rw-r--r--src/templates/assets/javascripts/components/content/annotation/block/index.ts88
-rw-r--r--src/templates/assets/javascripts/components/content/annotation/index.ts25
-rw-r--r--src/templates/assets/javascripts/components/content/annotation/list/index.ts209
-rw-r--r--src/templates/assets/javascripts/components/content/code/_/index.ts238
-rw-r--r--src/templates/assets/javascripts/components/content/code/index.ts23
-rw-r--r--src/templates/assets/javascripts/components/content/details/index.ts138
-rw-r--r--src/templates/assets/javascripts/components/content/index.ts28
-rw-r--r--src/templates/assets/javascripts/components/content/mermaid/index.css430
-rw-r--r--src/templates/assets/javascripts/components/content/mermaid/index.ts133
-rw-r--r--src/templates/assets/javascripts/components/content/table/index.ts70
-rw-r--r--src/templates/assets/javascripts/components/content/tabs/index.ts265
13 files changed, 0 insertions, 2044 deletions
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)
- )
-}