duckfn-docs-kit 0.3.0 → 0.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/AGENTS.md +326 -234
- package/README.md +10 -6
- package/dist/IconButton.d.ts +22 -0
- package/dist/codemirror.d.ts +29 -0
- package/dist/download.d.ts +51 -0
- package/dist/index.d.ts +28 -7
- package/dist/index.js +2 -2
- package/dist/mermaid/DfkMermaid.d.ts +25 -0
- package/dist/mermaid/config.d.ts +48 -0
- package/dist/mermaid/remark.d.ts +40 -0
- package/dist/mermaid/remark.js +32 -0
- package/dist/mermaid/render.d.ts +92 -0
- package/dist/mermaid/styles.d.ts +6 -0
- package/dist/panzoom-view.d.ts +17 -0
- package/dist/{register-CALCwFBv.js → register-wdwf0LC4.js} +1365 -738
- package/dist/remark.d.ts +1 -1
- package/dist/source-dialog.d.ts +35 -0
- package/dist/sql/PreviewTabs.d.ts +39 -23
- package/dist/sql/SvgViewer.d.ts +53 -0
- package/dist/sql/client.js +1 -1
- package/dist/sql/harness.js +1 -1
- package/dist/sql/remark.d.ts +6 -1
- package/dist/sql/renderers.d.ts +9 -0
- package/package.json +6 -2
- package/src/IconButton.ts +50 -0
- package/src/codemirror.ts +97 -0
- package/src/download.ts +169 -0
- package/src/index.ts +31 -7
- package/src/mermaid/DfkMermaid.css +326 -0
- package/src/mermaid/DfkMermaid.ts +411 -0
- package/src/mermaid/config.ts +74 -0
- package/src/mermaid/remark.ts +98 -0
- package/src/mermaid/render.ts +172 -0
- package/src/mermaid/styles.ts +24 -0
- package/src/panzoom-view.ts +235 -0
- package/src/register.ts +3 -0
- package/src/remark.ts +1 -1
- package/src/source-dialog.ts +126 -0
- package/src/sql/DfkSql.css +13 -10
- package/src/sql/DfkSql.ts +60 -51
- package/src/sql/PreviewTabs.ts +98 -52
- package/src/sql/SvgViewer.ts +155 -0
- package/src/sql/remark.ts +6 -1
- package/src/sql/renderers.ts +433 -159
- package/src/sql/sql.css +189 -19
- package/dist/sql/editor.d.ts +0 -16
- package/src/sql/editor.ts +0 -75
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* A compact icon-only button with a hover/focus tooltip, built once and then
|
|
3
|
+
* mutated. Shared by `<dfk-sql>`'s code-block cluster and `<dfk-mermaid>`'s
|
|
4
|
+
* diagram cluster: both want the same "floating icon row over content" idiom,
|
|
5
|
+
* and neither wants a second implementation of it.
|
|
6
|
+
*
|
|
7
|
+
* The tooltip is also the accessible name — an icon-only control has no text to
|
|
8
|
+
* fall back on. The two class names are written by this module and styled in
|
|
9
|
+
* *each* consumer's shadow-root CSS; that duplication is unavoidable (a shadow
|
|
10
|
+
* boundary stops one sheet from reaching the other tree), so the rules carry the
|
|
11
|
+
* same names and are kept in sync by hand.
|
|
12
|
+
*/
|
|
13
|
+
export declare class IconButton {
|
|
14
|
+
#private;
|
|
15
|
+
readonly root: HTMLButtonElement;
|
|
16
|
+
constructor(icon: string, onClick: () => void);
|
|
17
|
+
setIcon(icon: string): void;
|
|
18
|
+
setLabel(text: string): void;
|
|
19
|
+
/** Marks a toggle as currently on (e.g. the SQL block's wrap toggle). */
|
|
20
|
+
setOn(on: boolean): void;
|
|
21
|
+
setDisabled(disabled: boolean): void;
|
|
22
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The CodeMirror 6 editor behind the kit's editable content: the code view of a
|
|
3
|
+
* runnable SQL block (`<dfk-sql>`) and the diagram-source dialog of a
|
|
4
|
+
* `<dfk-mermaid>`. One implementation, two languages — the SQL block asks for
|
|
5
|
+
* highlighting, the diagram editor takes the plain-text default.
|
|
6
|
+
*
|
|
7
|
+
* Every CodeMirror module arrives through a dynamic `import()` inside
|
|
8
|
+
* {@link mountCodeEditor}: a page full of blocks pays nothing for the editor on
|
|
9
|
+
* its critical path, and Docusaurus' Node prerender never evaluates any of it.
|
|
10
|
+
*
|
|
11
|
+
* This is browser-only code: `document` is touched only through the container
|
|
12
|
+
* the caller hands over, and everything else is behind the `import()`s.
|
|
13
|
+
*/
|
|
14
|
+
export interface CodeEditor {
|
|
15
|
+
getValue(): string;
|
|
16
|
+
setValue(value: string): void;
|
|
17
|
+
/** Soft-wraps long lines, or stops wrapping them (the block's wrap toggle). */
|
|
18
|
+
setWrap(wrapped: boolean): void;
|
|
19
|
+
destroy(): void;
|
|
20
|
+
}
|
|
21
|
+
export interface CodeEditorOptions {
|
|
22
|
+
/**
|
|
23
|
+
* Highlight the document as SQL. Omitted, the editor is plain text — which is
|
|
24
|
+
* what a mermaid diagram gets: there is no first-party CodeMirror language for
|
|
25
|
+
* it, and a docs reader is editing prose-shaped source, not writing SQL.
|
|
26
|
+
*/
|
|
27
|
+
language?: 'sql';
|
|
28
|
+
}
|
|
29
|
+
export declare function mountCodeEditor(container: HTMLElement, value: string, onChange: (value: string) => void, options?: CodeEditorOptions): Promise<CodeEditor>;
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Saving something the kit rendered to a file: the payload shape, the click that
|
|
3
|
+
* performs the save, and how the file is named.
|
|
4
|
+
*
|
|
5
|
+
* Shared by `<dfk-mermaid>` (a downloaded diagram) and the SQL result chrome (a
|
|
6
|
+
* downloaded result of any kind), so a docs page has one definition of "what a
|
|
7
|
+
* download is" rather than one per component.
|
|
8
|
+
*
|
|
9
|
+
* This is browser-only code.
|
|
10
|
+
*/
|
|
11
|
+
/** One file's worth of text, ready to save. */
|
|
12
|
+
export interface DownloadPayload {
|
|
13
|
+
/** The file name, extension included. */
|
|
14
|
+
name: string;
|
|
15
|
+
/** The blob's MIME type. */
|
|
16
|
+
mime: string;
|
|
17
|
+
/** The file's contents — text for every format the kit produces. */
|
|
18
|
+
text: string;
|
|
19
|
+
}
|
|
20
|
+
/**
|
|
21
|
+
* Saves a payload through a temporary object URL.
|
|
22
|
+
*
|
|
23
|
+
* The anchor is in the document for the click — some browsers ignore a detached
|
|
24
|
+
* one — and the URL is revoked on the next tick, once the download has been
|
|
25
|
+
* handed to the browser.
|
|
26
|
+
*/
|
|
27
|
+
export declare function saveDownload(payload: DownloadPayload): void;
|
|
28
|
+
/**
|
|
29
|
+
* What a downloaded figure is called.
|
|
30
|
+
*
|
|
31
|
+
* The name is derived from the page, not from the figure: a diagram or an SVG
|
|
32
|
+
* result has no name of its own, and the reader downloading one is after "the
|
|
33
|
+
* figure from that section", not `diagram.svg`.
|
|
34
|
+
*
|
|
35
|
+
* Three sources, most specific first, each falling back to the next:
|
|
36
|
+
*
|
|
37
|
+
* 1. **The figure's own title** — mermaid's frontmatter (`---\ntitle: …\n---`,
|
|
38
|
+
* which mermaid itself draws above the diagram); only read when `options.source`
|
|
39
|
+
* is given.
|
|
40
|
+
* 2. **The nearest heading above it** — the section the figure belongs to, which
|
|
41
|
+
* on a docs page is what a reader would call it.
|
|
42
|
+
* 3. **The document title** — the browser tab's title, for a figure that sits
|
|
43
|
+
* above every heading on its page.
|
|
44
|
+
*
|
|
45
|
+
* Nothing found → `options.fallback` (or {@link DEFAULT_BASE}), with `extension`
|
|
46
|
+
* appended either way.
|
|
47
|
+
*/
|
|
48
|
+
export declare function sectionFileName(element: Element, extension: string, options?: {
|
|
49
|
+
source?: string;
|
|
50
|
+
fallback?: string;
|
|
51
|
+
}): string;
|
package/dist/index.d.ts
CHANGED
|
@@ -1,6 +1,11 @@
|
|
|
1
1
|
import type { HTMLAttributes } from 'react';
|
|
2
|
+
import { DfkFeatures } from './home/DfkFeatures';
|
|
3
|
+
import { DfkHero } from './home/DfkHero';
|
|
4
|
+
import { DfkMermaid } from './mermaid/DfkMermaid';
|
|
5
|
+
import { DfkNextSteps } from './home/DfkNextSteps';
|
|
6
|
+
import { DfkSql } from './sql/DfkSql';
|
|
2
7
|
/**
|
|
3
|
-
* Browser entry for duckfn-docs-kit: the
|
|
8
|
+
* Browser entry for duckfn-docs-kit: the custom elements it registers and the
|
|
4
9
|
* value types their `set*` methods accept.
|
|
5
10
|
*
|
|
6
11
|
* The components are retained-mode (build once, then mutate held nodes) and
|
|
@@ -12,17 +17,16 @@ import type { HTMLAttributes } from 'react';
|
|
|
12
17
|
* web component, which `registerDfkElements()` registers as a side effect, so
|
|
13
18
|
* this package ships no icon data.
|
|
14
19
|
*
|
|
15
|
-
* `TocToggle` and the remark
|
|
16
|
-
* (`duckfn-docs-kit/toc-toggle/TocToggle`, `duckfn-docs-kit/remark
|
|
20
|
+
* `TocToggle` and the remark plugins keep their own subpaths
|
|
21
|
+
* (`duckfn-docs-kit/toc-toggle/TocToggle`, `duckfn-docs-kit/remark`,
|
|
22
|
+
* `duckfn-docs-kit/sql/remark`, `duckfn-docs-kit/mermaid/remark`) instead of
|
|
17
23
|
* being merged here: a Docusaurus config file must never pull browser code into
|
|
18
24
|
* Node, and a site that only wants the TOC collapse button should not pay for
|
|
19
25
|
* the bundled `iconify-icon`.
|
|
20
26
|
*/
|
|
21
|
-
export { DfkFeatures
|
|
22
|
-
export { DfkHero } from './home/DfkHero';
|
|
23
|
-
export { DfkNextSteps } from './home/DfkNextSteps';
|
|
24
|
-
export { DfkSql } from './sql/DfkSql';
|
|
27
|
+
export { DfkFeatures, DfkHero, DfkMermaid, DfkNextSteps, DfkSql };
|
|
25
28
|
export { registerDfkElements } from './register';
|
|
29
|
+
export type { DfkMermaidConfig, DfkMermaidConfigInput } from './mermaid/config';
|
|
26
30
|
export type { RunnableSqlConfig } from './sql/remark';
|
|
27
31
|
export type { FeatureItem, HeroAction, HeroBadge, HeroLink, NextStepItem, } from './types';
|
|
28
32
|
/**
|
|
@@ -38,6 +42,22 @@ export type { FeatureItem, HeroAction, HeroBadge, HeroLink, NextStepItem, } from
|
|
|
38
42
|
* from the declaration file.
|
|
39
43
|
*/
|
|
40
44
|
export type DfkElementProps = HTMLAttributes<HTMLElement>;
|
|
45
|
+
/**
|
|
46
|
+
* The kit's tags in the DOM's own tag map, so `document.createElement('dfk-sql')`
|
|
47
|
+
* (and the kit's `el()` helper) is typed as the class it upgrades to. Without
|
|
48
|
+
* this, every place that builds a `dfk-*` element from scratch — `sql/renderers.ts`
|
|
49
|
+
* building a `<dfk-mermaid>` for a `mermaid` result, `docs/src/pages/index.tsx`
|
|
50
|
+
* mounting the home elements — would have to cast the result.
|
|
51
|
+
*/
|
|
52
|
+
declare global {
|
|
53
|
+
interface HTMLElementTagNameMap {
|
|
54
|
+
'dfk-hero': DfkHero;
|
|
55
|
+
'dfk-features': DfkFeatures;
|
|
56
|
+
'dfk-next-steps': DfkNextSteps;
|
|
57
|
+
'dfk-sql': DfkSql;
|
|
58
|
+
'dfk-mermaid': DfkMermaid;
|
|
59
|
+
}
|
|
60
|
+
}
|
|
41
61
|
declare module 'react' {
|
|
42
62
|
namespace JSX {
|
|
43
63
|
interface IntrinsicElements {
|
|
@@ -45,6 +65,7 @@ declare module 'react' {
|
|
|
45
65
|
'dfk-features': DfkElementProps;
|
|
46
66
|
'dfk-next-steps': DfkElementProps;
|
|
47
67
|
'dfk-sql': DfkElementProps;
|
|
68
|
+
'dfk-mermaid': DfkElementProps;
|
|
48
69
|
}
|
|
49
70
|
}
|
|
50
71
|
}
|
package/dist/index.js
CHANGED
|
@@ -1,2 +1,2 @@
|
|
|
1
|
-
import { a as e, i as t, n, r,
|
|
2
|
-
export {
|
|
1
|
+
import { a as e, i as t, n, o as r, r as i, t as a } from "./register-wdwf0LC4.js";
|
|
2
|
+
export { r as DfkFeatures, e as DfkHero, t as DfkMermaid, i as DfkNextSteps, n as DfkSql, a as registerDfkElements };
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
import { HTMLElementBase } from '../dom';
|
|
2
|
+
import { type DownloadPayload } from '../download';
|
|
3
|
+
export declare class DfkMermaid extends HTMLElementBase {
|
|
4
|
+
#private;
|
|
5
|
+
constructor();
|
|
6
|
+
/**
|
|
7
|
+
* The zoom/source controls an embedded diagram offers, for the host to place in
|
|
8
|
+
* its own chrome. Empty (and unused) when standalone — the element keeps them.
|
|
9
|
+
*/
|
|
10
|
+
get actions(): HTMLElement;
|
|
11
|
+
connectedCallback(): void;
|
|
12
|
+
disconnectedCallback(): void;
|
|
13
|
+
/**
|
|
14
|
+
* Turns zoom/pan on or off for an embedded diagram. The host calls this with its
|
|
15
|
+
* own fullscreen state: an embedded diagram zooms exactly where its result area
|
|
16
|
+
* is expanded, and fills that area while it is.
|
|
17
|
+
*/
|
|
18
|
+
setFullscreen(value: boolean): void;
|
|
19
|
+
/**
|
|
20
|
+
* The file this diagram would be saved as, or `null` while nothing is rendered.
|
|
21
|
+
* An embedded diagram hands this to the result chrome's download button, which
|
|
22
|
+
* is why the element does not save it itself.
|
|
23
|
+
*/
|
|
24
|
+
downloadPayload(): DownloadPayload | null;
|
|
25
|
+
}
|
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The mermaid look and palette, shared by the Node-side remark plugin (which
|
|
3
|
+
* stamps it onto every `<dfk-mermaid>` it emits) and the browser element (whose
|
|
4
|
+
* fallback when no config travels with the element).
|
|
5
|
+
*
|
|
6
|
+
* Pure data with no imports, like `sql/runtimeConfig.ts`: both sides have to
|
|
7
|
+
* agree on the shape, and neither may drag the other into its bundle — the
|
|
8
|
+
* remark plugin runs in Docusaurus' Node build, the element in the browser.
|
|
9
|
+
*
|
|
10
|
+
* Why the config travels per element instead of living in the component: the
|
|
11
|
+
* palette is the one part of a diagram that is *site-specific*. Passing it
|
|
12
|
+
* through the site's `docusaurus.config.ts` (as an option of `remarkMermaid`)
|
|
13
|
+
* keeps that choice where the rest of the site's theme is decided, and keeps a
|
|
14
|
+
* downstream docs site from having to fork the kit to change two colour names.
|
|
15
|
+
*/
|
|
16
|
+
/** The two colour modes a diagram is rendered for. */
|
|
17
|
+
export type MermaidColorMode = 'light' | 'dark';
|
|
18
|
+
/** A partial config, as a site writes it. */
|
|
19
|
+
export interface DfkMermaidConfigInput {
|
|
20
|
+
/** Mermaid theme name per colour mode; missing sides fall back to the default. */
|
|
21
|
+
theme?: Partial<Record<MermaidColorMode, string>>;
|
|
22
|
+
/** Extra mermaid options, spread into `initialize()` after `theme`. */
|
|
23
|
+
options?: Record<string, unknown>;
|
|
24
|
+
}
|
|
25
|
+
/** A resolved config: both themes present, options ready to spread. */
|
|
26
|
+
export interface DfkMermaidConfig {
|
|
27
|
+
theme: Record<MermaidColorMode, string>;
|
|
28
|
+
options: Record<string, unknown>;
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* The kit's default: the `neo` look (mermaid's flatter, rounder chrome) with the
|
|
32
|
+
* redux palette — `redux-color` in light mode, `redux-dark-color` in dark.
|
|
33
|
+
*
|
|
34
|
+
* `look` has no per-mode counterpart in mermaid, so it belongs in `options`;
|
|
35
|
+
* `theme` is the per-mode one. Both are easy to get wrong *silently*: mermaid
|
|
36
|
+
* ignores an unrecognised value and falls back, so a change is verified in a
|
|
37
|
+
* browser, not by a build.
|
|
38
|
+
*/
|
|
39
|
+
export declare const DEFAULT_MERMAID_CONFIG: DfkMermaidConfig;
|
|
40
|
+
/** Merges a site's overrides over {@link DEFAULT_MERMAID_CONFIG}. */
|
|
41
|
+
export declare function resolveMermaidConfig(input?: DfkMermaidConfigInput | null): DfkMermaidConfig;
|
|
42
|
+
/**
|
|
43
|
+
* Parses the `config` attribute the remark plugin writes. Anything unreadable
|
|
44
|
+
* falls back to the default rather than failing a diagram, and only the two
|
|
45
|
+
* known keys are read — the attribute is content, not a channel for arbitrary
|
|
46
|
+
* configuration.
|
|
47
|
+
*/
|
|
48
|
+
export declare function parseMermaidConfig(raw: string | null | undefined): DfkMermaidConfig;
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import type { Plugin } from 'unified';
|
|
2
|
+
import type { DfkMermaidConfigInput } from './config';
|
|
3
|
+
/**
|
|
4
|
+
* Turns a ```mermaid fence into a `<dfk-mermaid>` custom element, so the docs
|
|
5
|
+
* site renders diagrams through this kit instead of through
|
|
6
|
+
* `@docusaurus/theme-mermaid`.
|
|
7
|
+
*
|
|
8
|
+
* That theme's React component cannot avoid the two upstream defects
|
|
9
|
+
* `./render.ts` documents — it colours by `useColorMode()`, which lags behind on
|
|
10
|
+
* the first client render, so a dark-mode first load paints a light diagram and
|
|
11
|
+
* then a dark one (the flash, and occasionally an empty SVG), and mermaid's
|
|
12
|
+
* mutable singleton renders two diagrams at once. Doing the render in a custom
|
|
13
|
+
* element instead puts both fixes in one place that every duckfn-family docs site
|
|
14
|
+
* shares, and lets the runnable-SQL `mermaid` output reuse the same renderer.
|
|
15
|
+
*
|
|
16
|
+
* The source travels as the `source` attribute and the palette as the `config`
|
|
17
|
+
* one (see `./config`): React 19 reconciles string props onto a custom element as
|
|
18
|
+
* attributes, so both survive prerendering and hydration. The element has no
|
|
19
|
+
* children — the diagram is built in its shadow root, so there is no prerendered
|
|
20
|
+
* markup to hide (contrast `sql/remark.ts`, whose code node is the fallback the
|
|
21
|
+
* editor replaces).
|
|
22
|
+
*
|
|
23
|
+
* This is Node-side build code: it must not touch `window` / `document`, and it
|
|
24
|
+
* must not import any browser module (type-only imports are fine).
|
|
25
|
+
*/
|
|
26
|
+
/** The custom element the plugin emits; must match `register.ts`. */
|
|
27
|
+
export declare const DFK_MERMAID_TAG = "dfk-mermaid";
|
|
28
|
+
export interface RemarkMermaidOptions {
|
|
29
|
+
/**
|
|
30
|
+
* Overrides for the kit's default look and palette, merged by the element (see
|
|
31
|
+
* `resolveMermaidConfig`). This is where a site picks its mermaid colours — the
|
|
32
|
+
* one part of a diagram that is site-specific — so no docs site has to fork the
|
|
33
|
+
* kit to change two theme names.
|
|
34
|
+
*
|
|
35
|
+
* Omitted, no `config` attribute is written at all and every element falls back
|
|
36
|
+
* to the kit's default (`DEFAULT_MERMAID_CONFIG` in `./config`).
|
|
37
|
+
*/
|
|
38
|
+
config?: DfkMermaidConfigInput;
|
|
39
|
+
}
|
|
40
|
+
export declare const remarkMermaid: Plugin<[RemarkMermaidOptions?]>;
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
//#region src/mermaid/remark.ts
|
|
2
|
+
var e = "dfk-mermaid", t = (e = {}) => (t) => {
|
|
3
|
+
let r = e.config === void 0 ? null : JSON.stringify(e.config), i = (e) => {
|
|
4
|
+
if (typeof e != "object" || !e) return;
|
|
5
|
+
let t = e;
|
|
6
|
+
Array.isArray(t.children) && (t.children = t.children.map((e) => {
|
|
7
|
+
if (typeof e != "object" || !e) return e;
|
|
8
|
+
let t = e;
|
|
9
|
+
return t.type === "code" && t.lang === "mermaid" ? n(t, r) : (i(t), t);
|
|
10
|
+
}));
|
|
11
|
+
};
|
|
12
|
+
i(t);
|
|
13
|
+
};
|
|
14
|
+
function n(t, n) {
|
|
15
|
+
let r = [{
|
|
16
|
+
type: "mdxJsxAttribute",
|
|
17
|
+
name: "source",
|
|
18
|
+
value: String(t.value ?? "")
|
|
19
|
+
}];
|
|
20
|
+
return n !== null && r.push({
|
|
21
|
+
type: "mdxJsxAttribute",
|
|
22
|
+
name: "config",
|
|
23
|
+
value: n
|
|
24
|
+
}), {
|
|
25
|
+
type: "mdxJsxFlowElement",
|
|
26
|
+
name: e,
|
|
27
|
+
attributes: r,
|
|
28
|
+
children: []
|
|
29
|
+
};
|
|
30
|
+
}
|
|
31
|
+
//#endregion
|
|
32
|
+
export { e as DFK_MERMAID_TAG, t as remarkMermaid };
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The one place the kit talks to mermaid: the load, the render queue, the config
|
|
3
|
+
* the renderer is initialised with, and the two document-level facts a diagram
|
|
4
|
+
* needs (which colour mode the page is in, and how a rendered SVG gets into a
|
|
5
|
+
* shadow tree).
|
|
6
|
+
*
|
|
7
|
+
* Two upstream problems are solved here, and neither can be fixed from a site's
|
|
8
|
+
* `docusaurus.config.ts` or from the diagram source:
|
|
9
|
+
*
|
|
10
|
+
* 1. **The flash on a dark-mode first load, and the blank diagram.** Docusaurus'
|
|
11
|
+
* `useColorMode()` deliberately lags behind on the first client render (its
|
|
12
|
+
* state is initialised in an effect, to avoid hydration mismatches), so a
|
|
13
|
+
* theme-aware renderer paints once with the light palette and then again with
|
|
14
|
+
* the dark one: the light one lands on screen briefly (the flash), and the two
|
|
15
|
+
* overlap inside mermaid's mutable singleton, which can resolve with an empty
|
|
16
|
+
* SVG (an empty container, no error — facebook/docusaurus#8357). This module
|
|
17
|
+
* reads `<html data-theme>` instead: the attribute the inline script in
|
|
18
|
+
* `<head>` writes *before* the first paint, and the one the page CSS keys off.
|
|
19
|
+
* Nothing is rendered until it is known, so each diagram is rendered exactly
|
|
20
|
+
* once per mode, in the mode the page is really in.
|
|
21
|
+
* 2. **Concurrent renders.** Mermaid is a mutable singleton that cannot render
|
|
22
|
+
* two diagrams at once (`mermaid.initialize()` sets one global config, and the
|
|
23
|
+
* renderer mutates it as it goes): docusaurus#8357 asks to "render them
|
|
24
|
+
* sequentially one after the other", pointing at mermaid-js/mermaid#3577.
|
|
25
|
+
* Every render therefore goes through a single queue.
|
|
26
|
+
*
|
|
27
|
+
* This is browser-only code: `mermaid` and every DOM API are reached lazily, so
|
|
28
|
+
* Docusaurus' Node prerender can import the module graph without evaluating any
|
|
29
|
+
* of it.
|
|
30
|
+
*/
|
|
31
|
+
import type { DfkMermaidConfig, MermaidColorMode } from './config';
|
|
32
|
+
/** How a diagram is rendered: its source, its config, and its colour mode. */
|
|
33
|
+
export interface MermaidRenderRequest {
|
|
34
|
+
source: string;
|
|
35
|
+
config: DfkMermaidConfig;
|
|
36
|
+
colorMode: MermaidColorMode;
|
|
37
|
+
}
|
|
38
|
+
/** A rendered diagram: the SVG markup, plus mermaid's bind hook for click handlers. */
|
|
39
|
+
export interface MermaidRenderOutput {
|
|
40
|
+
svg: string;
|
|
41
|
+
bind?(container: Element): void;
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Renders one diagram, through the page-wide queue. Each render re-initialises
|
|
45
|
+
* mermaid with this diagram's config first: mermaid has two config levels and the
|
|
46
|
+
* site-wide one can only be set through `initialize()`.
|
|
47
|
+
*/
|
|
48
|
+
export declare function renderMermaid({ source, config, colorMode, }: MermaidRenderRequest): Promise<MermaidRenderOutput>;
|
|
49
|
+
/** The colour mode the page is actually in, read from the pre-paint attribute. */
|
|
50
|
+
export declare function documentColorMode(): MermaidColorMode;
|
|
51
|
+
/**
|
|
52
|
+
* Calls `listener` whenever the page's colour mode changes, and returns the
|
|
53
|
+
* unsubscribe. The `<head>` script only *writes* the attribute on load, so a
|
|
54
|
+
* mode switch made later has to be observed — that is how a diagram follows the
|
|
55
|
+
* theme toggle.
|
|
56
|
+
*/
|
|
57
|
+
export declare function watchColorMode(listener: () => void): () => void;
|
|
58
|
+
/**
|
|
59
|
+
* Turns mermaid's SVG markup into a node a shadow tree can host.
|
|
60
|
+
*
|
|
61
|
+
* Mermaid serialises through `innerHTML`, so its output is *HTML*, not strict
|
|
62
|
+
* XML: an HTML label can carry a bare `<br>`, which `image/svg+xml` would reject.
|
|
63
|
+
* Parsing as `text/html` and taking the `<svg>` element gives the right
|
|
64
|
+
* namespace for free (the HTML parser enters foreign content for `<svg>`) and
|
|
65
|
+
* keeps markup out of `innerHTML`, which the kit's conventions rule out.
|
|
66
|
+
*
|
|
67
|
+
* Returns `null` when there is no `<svg>` to be found, so the caller can show an
|
|
68
|
+
* error instead of an empty box.
|
|
69
|
+
*/
|
|
70
|
+
export declare function parseMermaidSvg(owner: Document, svg: string): SVGElement | null;
|
|
71
|
+
/**
|
|
72
|
+
* Serialises a rendered diagram into standalone SVG markup.
|
|
73
|
+
*
|
|
74
|
+
* Mermaid hands its SVG back as an **HTML** string (it stringifies a detached
|
|
75
|
+
* element through `innerHTML`), and HTML serialisation writes a void element
|
|
76
|
+
* without a closing slash: a `<br/>` the author put inside a label comes back as
|
|
77
|
+
* `<br>`. That is fine where it lands — the page's HTML parser reads it, and
|
|
78
|
+
* `parseMermaidSvg()` parses it the same way — but it is fatal for a *file*: a
|
|
79
|
+
* browser opening an `.svg` parses XML, and `<br>` inside a `<p>` there is
|
|
80
|
+
* `Opening and ending tag mismatch: br … and p`, with the drawing cut off at the
|
|
81
|
+
* first error.
|
|
82
|
+
*
|
|
83
|
+
* Re-serialising the live node with `XMLSerializer` fixes both halves at once:
|
|
84
|
+
* XML serialisation closes every element, and it emits the namespace declarations
|
|
85
|
+
* a standalone document needs (`xmlns` on the `<svg>`, and one on any
|
|
86
|
+
* `foreignObject` subtree, whose XHTML content inherits its namespace from the
|
|
87
|
+
* page rather than carrying it as an attribute).
|
|
88
|
+
*
|
|
89
|
+
* This is why the element keeps the rendered `<svg>` node for the download
|
|
90
|
+
* instead of mermaid's own string: only the node can be re-serialised.
|
|
91
|
+
*/
|
|
92
|
+
export declare function serializeMermaidSvg(svg: SVGElement): string;
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export declare class PanZoomView {
|
|
2
|
+
#private;
|
|
3
|
+
constructor(viewport: HTMLElement, content: HTMLElement);
|
|
4
|
+
/** Whether the figure is enlarged past its fit-to-box size. */
|
|
5
|
+
get zoomed(): boolean;
|
|
6
|
+
/** Replaces the figure on screen and returns the view to fit. */
|
|
7
|
+
setContent(node: Node | null): void;
|
|
8
|
+
/**
|
|
9
|
+
* Turns wheel zoom and dragging on or off. Activating loads panzoom on first
|
|
10
|
+
* use (a figure nobody zooms never pays for the chunk); deactivating leaves the
|
|
11
|
+
* view at fit, so the figure a reader returns to is the whole one.
|
|
12
|
+
*/
|
|
13
|
+
setActive(active: boolean): void;
|
|
14
|
+
reset(): void;
|
|
15
|
+
/** Releases the panzoom instance and returns the viewport to its idle state. */
|
|
16
|
+
destroy(): void;
|
|
17
|
+
}
|