@orz/ui-mermaid 0.0.0-stage → 0.0.0
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/LICENSE +29 -0
- package/README.md +84 -2
- package/dist/content.d.ts +8 -0
- package/dist/content.d.ts.map +1 -0
- package/dist/content.js +45 -0
- package/dist/content.js.map +1 -0
- package/dist/index.d.ts +3 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/mermaid-block.d.ts +20 -0
- package/dist/mermaid-block.d.ts.map +1 -0
- package/dist/mermaid-block.js +91 -0
- package/dist/mermaid-block.js.map +1 -0
- package/dist/render.d.ts +30 -0
- package/dist/render.d.ts.map +1 -0
- package/dist/render.js +99 -0
- package/dist/render.js.map +1 -0
- package/package.json +53 -3
- package/styles.css +22 -0
package/LICENSE
ADDED
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
BSD 3-Clause License
|
|
2
|
+
|
|
3
|
+
Copyright 2026 the orzui team
|
|
4
|
+
Copyright 2026 the todou team
|
|
5
|
+
|
|
6
|
+
Redistribution and use in source and binary forms, with or without
|
|
7
|
+
modification, are permitted provided that the following conditions are met:
|
|
8
|
+
|
|
9
|
+
1. Redistributions of source code must retain the above copyright notice, this
|
|
10
|
+
list of conditions and the following disclaimer.
|
|
11
|
+
|
|
12
|
+
2. Redistributions in binary form must reproduce the above copyright notice,
|
|
13
|
+
this list of conditions and the following disclaimer in the documentation
|
|
14
|
+
and/or other materials provided with the distribution.
|
|
15
|
+
|
|
16
|
+
3. Neither the name of the copyright holder nor the names of its
|
|
17
|
+
contributors may be used to endorse or promote products derived from
|
|
18
|
+
this software without specific prior written permission.
|
|
19
|
+
|
|
20
|
+
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
|
21
|
+
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
|
22
|
+
IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
|
23
|
+
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
|
24
|
+
FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
|
25
|
+
DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
|
26
|
+
SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
|
27
|
+
CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
|
28
|
+
OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
|
29
|
+
OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
package/README.md
CHANGED
|
@@ -1,3 +1,85 @@
|
|
|
1
|
-
#
|
|
1
|
+
# @orz/ui-mermaid
|
|
2
2
|
|
|
3
|
-
|
|
3
|
+
[Mermaid](https://www.npmjs.com/package/mermaid) diagrams drawn in the active `@orz/ui` theme. The
|
|
4
|
+
package contributes a renderer to `@orz/ui-content`'s registry, so a ```` ```mermaid ```` fence in
|
|
5
|
+
`@orz/ui-markdown` and a `.mmd` file in a viewer both become diagrams without importing this package
|
|
6
|
+
from either.
|
|
7
|
+
|
|
8
|
+
## Install
|
|
9
|
+
|
|
10
|
+
```bash
|
|
11
|
+
pnpm add @orz/ui-mermaid @orz/ui-content @orz/ui react
|
|
12
|
+
```
|
|
13
|
+
|
|
14
|
+
`mermaid` is a regular dependency: installing this package is the whole setup.
|
|
15
|
+
`@orz/ui-content` is a peer dependency so that the app and every content package share one registry.
|
|
16
|
+
|
|
17
|
+
## CSS
|
|
18
|
+
|
|
19
|
+
```css
|
|
20
|
+
@import "tailwindcss";
|
|
21
|
+
@import "@orz/ui/styles.css";
|
|
22
|
+
@import "@orz/ui-mermaid/styles.css";
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
Import it after `@orz/ui/styles.css`. It holds the diagram's fit rule: a diagram shrinks to its
|
|
26
|
+
column down to 75% of its natural width, then scrolls, and is never enlarged. Like `@orz/ui`'s
|
|
27
|
+
stylesheet, it registers `@source "./dist"` on its own.
|
|
28
|
+
|
|
29
|
+
## `mermaidContent`
|
|
30
|
+
|
|
31
|
+
```tsx
|
|
32
|
+
import { ContentRenderers } from "@orz/ui-content";
|
|
33
|
+
import { mermaidContent } from "@orz/ui-mermaid";
|
|
34
|
+
|
|
35
|
+
const RENDERERS = [mermaidContent, markdownContent(), codeContent];
|
|
36
|
+
|
|
37
|
+
<ContentRenderers renderers={RENDERERS}>{app}</ContentRenderers>;
|
|
38
|
+
```
|
|
39
|
+
|
|
40
|
+
It accepts inline sources whose `lang` is `mermaid` (any case), which is what a markdown fence
|
|
41
|
+
becomes, and files named `*.mmd` or `*.mermaid`, in either placement. Register it before any
|
|
42
|
+
renderer that takes every inline source, such as a code renderer, since the first renderer that
|
|
43
|
+
accepts wins.
|
|
44
|
+
|
|
45
|
+
The source shows until the first render lands, in place of a diagram that does not parse (with a
|
|
46
|
+
one-line summary of the parser's message under it), and behind the Source toggle. That source view
|
|
47
|
+
is `Next`: the renderers registered after this one draw it, so it is highlighted when a code
|
|
48
|
+
renderer is registered and a plain `<pre><code>` when none is. A file is loaded once: the source view gets its text as an inline
|
|
49
|
+
source tagged `mermaid`. A file that fails to load shows the message and a Retry button.
|
|
50
|
+
|
|
51
|
+
## `MermaidBlock`
|
|
52
|
+
|
|
53
|
+
For a surface that draws a diagram outside the registry:
|
|
54
|
+
|
|
55
|
+
```tsx
|
|
56
|
+
import { MermaidBlock } from "@orz/ui-mermaid";
|
|
57
|
+
|
|
58
|
+
<MermaidBlock source={text} />
|
|
59
|
+
<MermaidBlock source={text} sourceView={<MySourceView text={text} />} className="my-4" />
|
|
60
|
+
```
|
|
61
|
+
|
|
62
|
+
`sourceView` defaults to a plain `<pre><code>`.
|
|
63
|
+
|
|
64
|
+
## Theme
|
|
65
|
+
|
|
66
|
+
A diagram is drawn in the theme tokens in effect on its element (`--background`, `--foreground`,
|
|
67
|
+
`--muted`, `--muted-foreground`, `--border`), so every `@orz/ui` theme gets its own colours with no
|
|
68
|
+
table to maintain. The palette is baked into the SVG, so the diagram is drawn again whenever
|
|
69
|
+
`@orz/ui`'s `useTheme()` reports a new theme, color scheme or variant. Outside a `ThemeProvider` a diagram keeps the colours
|
|
70
|
+
present when it was drawn and does not follow a later switch.
|
|
71
|
+
|
|
72
|
+
## Loading
|
|
73
|
+
|
|
74
|
+
mermaid is only reached through `import("mermaid")`, so a bundler splits it into chunks of its own,
|
|
75
|
+
fetched the first time a page holds a diagram. A chunk that fails to load leaves the diagram on its
|
|
76
|
+
source, and the next render tries the import again; whether that refetches is the browser's call,
|
|
77
|
+
since some cache a failed module fetch for the life of the page. Labels go through mermaid's
|
|
78
|
+
`securityLevel: "strict"`, which sanitises them: markup survives, scripts and handlers do not.
|
|
79
|
+
|
|
80
|
+
## Entry points
|
|
81
|
+
|
|
82
|
+
| Import | Contents |
|
|
83
|
+
|---|---|
|
|
84
|
+
| `@orz/ui-mermaid` | `mermaidContent`, `MermaidBlock` |
|
|
85
|
+
| `@orz/ui-mermaid/styles.css` | the `.mermaid-diagram` fit rule |
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
import { type ContentRenderer } from "@orz/ui-content";
|
|
2
|
+
/**
|
|
3
|
+
* The registry entry for mermaid: a source tagged `mermaid` (a fenced block) and a `.mmd` or
|
|
4
|
+
* `.mermaid` file, in either placement. Register it before any renderer that takes every inline
|
|
5
|
+
* source, such as a code renderer, which then draws the diagram's source view through `Next`.
|
|
6
|
+
*/
|
|
7
|
+
export declare const mermaidContent: ContentRenderer;
|
|
8
|
+
//# sourceMappingURL=content.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.d.ts","sourceRoot":"","sources":["../src/content.tsx"],"names":[],"mappings":"AACA,OAAO,EAGL,KAAK,eAAe,EAGrB,MAAM,iBAAiB,CAAC;AAmEzB;;;;GAIG;AACH,eAAO,MAAM,cAAc,EAAE,eAK5B,CAAC"}
|
package/dist/content.js
ADDED
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from "@orz/ui/components/button";
|
|
3
|
+
import { ContentFallback, useSourceText, } from "@orz/ui-content";
|
|
4
|
+
import { MermaidBlock } from "./mermaid-block.js";
|
|
5
|
+
function isMermaid(source) {
|
|
6
|
+
if (source.kind === "inline")
|
|
7
|
+
return source.lang?.toLowerCase() === "mermaid";
|
|
8
|
+
return /\.(mmd|mermaid)$/i.test(source.name);
|
|
9
|
+
}
|
|
10
|
+
function MermaidFile({ source, placement, className, Next }) {
|
|
11
|
+
const text = useSourceText(source);
|
|
12
|
+
if (text.status === "loading") {
|
|
13
|
+
return (_jsx(ContentFallback, { source: source, placement: placement, className: className }));
|
|
14
|
+
}
|
|
15
|
+
if (text.status === "error") {
|
|
16
|
+
return (_jsxs("div", { className: className, children: [_jsx(ContentFallback, { source: source, placement: placement }), " ", _jsx("span", { children: text.error.message }), " ", _jsx(Button, { size: "xs", variant: "outline", onClick: text.retry, children: "Retry" })] }));
|
|
17
|
+
}
|
|
18
|
+
// Handed on as inline text, not as the file: the code renderer below would
|
|
19
|
+
// load the file a second time, while the diagram is still rendering. Inline
|
|
20
|
+
// text is spelled as a fence's contents, without the file's final newline,
|
|
21
|
+
// which a code view would draw as an empty last line.
|
|
22
|
+
return (_jsx(MermaidBlock, { source: text.text, className: className, sourceView: _jsx(Next, { source: {
|
|
23
|
+
kind: "inline",
|
|
24
|
+
text: text.text.replace(/\r?\n$/, ""),
|
|
25
|
+
lang: "mermaid",
|
|
26
|
+
}, placement: placement }) }));
|
|
27
|
+
}
|
|
28
|
+
function Mermaid(props) {
|
|
29
|
+
const { source, placement, className, Next } = props;
|
|
30
|
+
if (source.kind === "file")
|
|
31
|
+
return _jsx(MermaidFile, { ...props });
|
|
32
|
+
return (_jsx(MermaidBlock, { source: source.text, className: className, sourceView: _jsx(Next, { source: source, placement: placement }) }));
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* The registry entry for mermaid: a source tagged `mermaid` (a fenced block) and a `.mmd` or
|
|
36
|
+
* `.mermaid` file, in either placement. Register it before any renderer that takes every inline
|
|
37
|
+
* source, such as a code renderer, which then draws the diagram's source view through `Next`.
|
|
38
|
+
*/
|
|
39
|
+
export const mermaidContent = {
|
|
40
|
+
name: "mermaid",
|
|
41
|
+
accepts: isMermaid,
|
|
42
|
+
display: "block",
|
|
43
|
+
Component: Mermaid,
|
|
44
|
+
};
|
|
45
|
+
//# sourceMappingURL=content.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"content.js","sourceRoot":"","sources":["../src/content.tsx"],"names":[],"mappings":";AAAA,OAAO,EAAE,MAAM,EAAE,MAAM,2BAA2B,CAAC;AACnD,OAAO,EACL,eAAe,EAIf,aAAa,GACd,MAAM,iBAAiB,CAAC;AAEzB,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAqB,CAAC;AAInD,SAAS,SAAS,CAAC,MAAqB;IACtC,IAAI,MAAM,CAAC,IAAI,KAAK,QAAQ;QAAE,OAAO,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,KAAK,SAAS,CAAC;IAC9E,OAAO,mBAAmB,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;AAC/C,CAAC;AAED,SAAS,WAAW,CAAC,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAgB;IACvE,MAAM,IAAI,GAAG,aAAa,CAAC,MAAM,CAAC,CAAC;IACnC,IAAI,IAAI,CAAC,MAAM,KAAK,SAAS,EAAE,CAAC;QAC9B,OAAO,CACL,KAAC,eAAe,IACd,MAAM,EAAE,MAAM,EACd,SAAS,EAAE,SAAS,EACpB,SAAS,EAAE,SAAS,GACpB,CACH,CAAC;IACJ,CAAC;IACD,IAAI,IAAI,CAAC,MAAM,KAAK,OAAO,EAAE,CAAC;QAC5B,OAAO,CACL,eAAK,SAAS,EAAE,SAAS,aACvB,KAAC,eAAe,IAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAI,EAAC,GAAG,EAC7D,yBAAO,IAAI,CAAC,KAAK,CAAC,OAAO,GAAQ,EAAC,GAAG,EACrC,KAAC,MAAM,IAAC,IAAI,EAAC,IAAI,EAAC,OAAO,EAAC,SAAS,EAAC,OAAO,EAAE,IAAI,CAAC,KAAK,sBAE9C,IACL,CACP,CAAC;IACJ,CAAC;IACD,2EAA2E;IAC3E,4EAA4E;IAC5E,2EAA2E;IAC3E,sDAAsD;IACtD,OAAO,CACL,KAAC,YAAY,IACX,MAAM,EAAE,IAAI,CAAC,IAAI,EACjB,SAAS,EAAE,SAAS,EACpB,UAAU,EACR,KAAC,IAAI,IACH,MAAM,EAAE;gBACN,IAAI,EAAE,QAAQ;gBACd,IAAI,EAAE,IAAI,CAAC,IAAI,CAAC,OAAO,CAAC,QAAQ,EAAE,EAAE,CAAC;gBACrC,IAAI,EAAE,SAAS;aAChB,EACD,SAAS,EAAE,SAAS,GACpB,GAEJ,CACH,CAAC;AACJ,CAAC;AAED,SAAS,OAAO,CAAC,KAAmB;IAClC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,EAAE,IAAI,EAAE,GAAG,KAAK,CAAC;IACrD,IAAI,MAAM,CAAC,IAAI,KAAK,MAAM;QAAE,OAAO,KAAC,WAAW,OAAK,KAAK,GAAI,CAAC;IAC9D,OAAO,CACL,KAAC,YAAY,IACX,MAAM,EAAE,MAAM,CAAC,IAAI,EACnB,SAAS,EAAE,SAAS,EACpB,UAAU,EAAE,KAAC,IAAI,IAAC,MAAM,EAAE,MAAM,EAAE,SAAS,EAAE,SAAS,GAAI,GAC1D,CACH,CAAC;AACJ,CAAC;AAED;;;;GAIG;AACH,MAAM,CAAC,MAAM,cAAc,GAAoB;IAC7C,IAAI,EAAE,SAAS;IACf,OAAO,EAAE,SAAS;IAClB,OAAO,EAAE,OAAO;IAChB,SAAS,EAAE,OAAO;CACnB,CAAC"}
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,eAAe,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,qBAAqB,CAAC"}
|
package/dist/index.js
ADDED
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,MAAM,cAAe,CAAC;AAC/C,OAAO,EAAE,YAAY,EAAE,MAAM,oBAAqB,CAAC"}
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { type ReactNode } from "react";
|
|
2
|
+
/**
|
|
3
|
+
* Mermaid source drawn as its diagram (T-523). `sourceView` shows until the
|
|
4
|
+
* first render lands — the renderer is a lazy chunk — and stays one click
|
|
5
|
+
* away afterwards. A diagram that does not parse keeps its source on screen
|
|
6
|
+
* with the parser's complaint under it.
|
|
7
|
+
*
|
|
8
|
+
* The colors are the theme tokens in effect on this element. The diagram is
|
|
9
|
+
* drawn again whenever `useTheme()` reports a new theme, color scheme or
|
|
10
|
+
* variant; outside a ThemeProvider it keeps the colors present when it was
|
|
11
|
+
* drawn.
|
|
12
|
+
*/
|
|
13
|
+
export declare function MermaidBlock({ source, sourceView, className, }: {
|
|
14
|
+
source: string;
|
|
15
|
+
/** Shown in place of the diagram. Default: a plain `<pre><code>`. */
|
|
16
|
+
sourceView?: ReactNode;
|
|
17
|
+
/** On the outer element, which also carries the probe the palette is read from. */
|
|
18
|
+
className?: string;
|
|
19
|
+
}): import("react").JSX.Element;
|
|
20
|
+
//# sourceMappingURL=mermaid-block.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mermaid-block.d.ts","sourceRoot":"","sources":["../src/mermaid-block.tsx"],"names":[],"mappings":"AAGA,OAAO,EAEL,KAAK,SAAS,EAIf,MAAM,OAAO,CAAC;AAsDf;;;;;;;;;;GAUG;AACH,wBAAgB,YAAY,CAAC,EAC3B,MAAM,EACN,UAAU,EACV,SAAS,GACV,EAAE;IACD,MAAM,EAAE,MAAM,CAAC;IACf,qEAAqE;IACrE,UAAU,CAAC,EAAE,SAAS,CAAC;IACvB,mFAAmF;IACnF,SAAS,CAAC,EAAE,MAAM,CAAC;CACpB,+BAyEA"}
|
|
@@ -0,0 +1,91 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { Button } from "@orz/ui/components/button";
|
|
3
|
+
import { cn } from "@orz/ui/lib/utils";
|
|
4
|
+
import { useTheme } from "@orz/ui/theme";
|
|
5
|
+
import { useEffect, useRef, useState, } from "react";
|
|
6
|
+
import { errorSummary, renderDiagram, } from "./render.js";
|
|
7
|
+
let canvas;
|
|
8
|
+
/**
|
|
9
|
+
* Any CSS color → `#rrggbb`, composited over `under` so translucent tokens
|
|
10
|
+
* (the dark themes' borders) come out as the color they actually paint.
|
|
11
|
+
*/
|
|
12
|
+
function toHex(color, under) {
|
|
13
|
+
canvas ??= document.createElement("canvas").getContext("2d", {
|
|
14
|
+
willReadFrequently: true,
|
|
15
|
+
});
|
|
16
|
+
if (canvas == null)
|
|
17
|
+
return color;
|
|
18
|
+
canvas.clearRect(0, 0, 1, 1);
|
|
19
|
+
canvas.fillStyle = under;
|
|
20
|
+
canvas.fillRect(0, 0, 1, 1);
|
|
21
|
+
canvas.fillStyle = color;
|
|
22
|
+
canvas.fillRect(0, 0, 1, 1);
|
|
23
|
+
const [r = 0, g = 0, b = 0] = canvas.getImageData(0, 0, 1, 1).data;
|
|
24
|
+
return `#${[r, g, b].map((v) => v.toString(16).padStart(2, "0")).join("")}`;
|
|
25
|
+
}
|
|
26
|
+
/** WCAG relative luminance of a `#rrggbb` color. */
|
|
27
|
+
function luminance(hex) {
|
|
28
|
+
const [r = 0, g = 0, b = 0] = [1, 3, 5].map((at) => {
|
|
29
|
+
const c = Number.parseInt(hex.slice(at, at + 2), 16) / 255;
|
|
30
|
+
return c <= 0.04045 ? c / 12.92 : ((c + 0.055) / 1.055) ** 2.4;
|
|
31
|
+
});
|
|
32
|
+
return 0.2126 * r + 0.7152 * g + 0.0722 * b;
|
|
33
|
+
}
|
|
34
|
+
function readPalette(el) {
|
|
35
|
+
const style = getComputedStyle(el);
|
|
36
|
+
const token = (name) => style.getPropertyValue(name).trim();
|
|
37
|
+
const background = toHex(token("--background") || "#fff", "#fff");
|
|
38
|
+
const hex = (name) => toHex(token(name), background);
|
|
39
|
+
return {
|
|
40
|
+
// Read off the painted background rather than `.dark` on <html>: the
|
|
41
|
+
// theme root can be any element, and there may be no ThemeProvider at all.
|
|
42
|
+
dark: luminance(background) < 0.5,
|
|
43
|
+
background,
|
|
44
|
+
foreground: hex("--foreground"),
|
|
45
|
+
muted: hex("--muted"),
|
|
46
|
+
mutedForeground: hex("--muted-foreground"),
|
|
47
|
+
border: hex("--border"),
|
|
48
|
+
};
|
|
49
|
+
}
|
|
50
|
+
/**
|
|
51
|
+
* Mermaid source drawn as its diagram (T-523). `sourceView` shows until the
|
|
52
|
+
* first render lands — the renderer is a lazy chunk — and stays one click
|
|
53
|
+
* away afterwards. A diagram that does not parse keeps its source on screen
|
|
54
|
+
* with the parser's complaint under it.
|
|
55
|
+
*
|
|
56
|
+
* The colors are the theme tokens in effect on this element. The diagram is
|
|
57
|
+
* drawn again whenever `useTheme()` reports a new theme, color scheme or
|
|
58
|
+
* variant; outside a ThemeProvider it keeps the colors present when it was
|
|
59
|
+
* drawn.
|
|
60
|
+
*/
|
|
61
|
+
export function MermaidBlock({ source, sourceView, className, }) {
|
|
62
|
+
const { theme, colorScheme, variant } = useTheme();
|
|
63
|
+
const probe = useRef(null);
|
|
64
|
+
const [result, setResult] = useState(null);
|
|
65
|
+
const [showSource, setShowSource] = useState(false);
|
|
66
|
+
useEffect(() => {
|
|
67
|
+
// Read only as a trigger: the colors come off the computed style below,
|
|
68
|
+
// which the store has already switched by the time it notifies.
|
|
69
|
+
void [theme, colorScheme, variant];
|
|
70
|
+
const el = probe.current;
|
|
71
|
+
if (el === null)
|
|
72
|
+
return;
|
|
73
|
+
let live = true;
|
|
74
|
+
renderDiagram(source, readPalette(el), getComputedStyle(el).fontFamily).then((next) => {
|
|
75
|
+
if (live)
|
|
76
|
+
setResult(next);
|
|
77
|
+
});
|
|
78
|
+
return () => {
|
|
79
|
+
live = false;
|
|
80
|
+
};
|
|
81
|
+
}, [source, theme, colorScheme, variant]);
|
|
82
|
+
const diagram = result?.ok === true ? result : null;
|
|
83
|
+
const sourceShown = sourceView ?? (_jsx("pre", { children: _jsx("code", { children: source }) }));
|
|
84
|
+
return (_jsxs("div", { ref: probe, className: cn(diagram === null ? undefined : "relative pt-7", className), children: [diagram !== null && !showSource ? (_jsx("div", { className: "mermaid-diagram overflow-x-auto", style: { "--diagram-width": `${diagram.width}px` },
|
|
85
|
+
// mermaid's own output under securityLevel "strict", which runs
|
|
86
|
+
// labels through DOMPurify: markup survives, scripts and handlers
|
|
87
|
+
// do not.
|
|
88
|
+
// biome-ignore lint/security/noDangerouslySetInnerHtml: sanitized by mermaid, see above
|
|
89
|
+
dangerouslySetInnerHTML: { __html: diagram.svg } })) : (sourceShown), result?.ok === false && (_jsx("p", { className: "mt-1 truncate text-destructive text-xs", title: result.error, children: errorSummary(result.error) })), diagram !== null && (_jsx(Button, { type: "button", size: "xs", variant: "ghost", className: "absolute top-0 right-0", "aria-pressed": showSource, onClick: () => setShowSource((shown) => !shown), children: showSource ? "Diagram" : "Source" }))] }));
|
|
90
|
+
}
|
|
91
|
+
//# sourceMappingURL=mermaid-block.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"mermaid-block.js","sourceRoot":"","sources":["../src/mermaid-block.tsx"],"names":[],"mappings":"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"}
|
package/dist/render.d.ts
ADDED
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Colors a diagram is drawn in, already resolved to `#rrggbb`: mermaid's
|
|
3
|
+
* color math (khroma) cannot parse the app's oklch() custom properties.
|
|
4
|
+
*/
|
|
5
|
+
export type DiagramPalette = {
|
|
6
|
+
dark: boolean;
|
|
7
|
+
background: string;
|
|
8
|
+
foreground: string;
|
|
9
|
+
muted: string;
|
|
10
|
+
mutedForeground: string;
|
|
11
|
+
border: string;
|
|
12
|
+
};
|
|
13
|
+
export type DiagramResult = {
|
|
14
|
+
ok: true;
|
|
15
|
+
svg: string;
|
|
16
|
+
width: number;
|
|
17
|
+
} | {
|
|
18
|
+
ok: false;
|
|
19
|
+
error: string;
|
|
20
|
+
};
|
|
21
|
+
export declare function renderDiagram(source: string, palette: DiagramPalette, fontFamily: string): Promise<DiagramResult>;
|
|
22
|
+
/** The diagram's natural width, which the fit rule in styles.css scales from. */
|
|
23
|
+
export declare function viewBoxWidth(svg: string): number;
|
|
24
|
+
/**
|
|
25
|
+
* mermaid's parse errors quote the offending line and draw a caret under it,
|
|
26
|
+
* which only lines up in the monospace block the error came from. One line
|
|
27
|
+
* is what fits under the source: where it failed, and what it got there.
|
|
28
|
+
*/
|
|
29
|
+
export declare function errorSummary(message: string): string;
|
|
30
|
+
//# sourceMappingURL=render.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.d.ts","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"AAAA;;;GAGG;AACH,MAAM,MAAM,cAAc,GAAG;IAC3B,IAAI,EAAE,OAAO,CAAC;IACd,UAAU,EAAE,MAAM,CAAC;IACnB,UAAU,EAAE,MAAM,CAAC;IACnB,KAAK,EAAE,MAAM,CAAC;IACd,eAAe,EAAE,MAAM,CAAC;IACxB,MAAM,EAAE,MAAM,CAAC;CAChB,CAAC;AAEF,MAAM,MAAM,aAAa,GACrB;IAAE,EAAE,EAAE,IAAI,CAAC;IAAC,GAAG,EAAE,MAAM,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,GACxC;IAAE,EAAE,EAAE,KAAK,CAAC;IAAC,KAAK,EAAE,MAAM,CAAA;CAAE,CAAC;AAkBjC,wBAAgB,aAAa,CAC3B,MAAM,EAAE,MAAM,EACd,OAAO,EAAE,cAAc,EACvB,UAAU,EAAE,MAAM,GACjB,OAAO,CAAC,aAAa,CAAC,CAqCxB;AA2BD,iFAAiF;AACjF,wBAAgB,YAAY,CAAC,GAAG,EAAE,MAAM,GAAG,MAAM,CAGhD;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,OAAO,EAAE,MAAM,GAAG,MAAM,CAUpD"}
|
package/dist/render.js
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
// mermaid is heavy (T-523); it is only ever reached through this dynamic
|
|
2
|
+
// import, so its chunks are fetched the first time a page actually holds a
|
|
3
|
+
// diagram.
|
|
4
|
+
let loaded;
|
|
5
|
+
function loadMermaid() {
|
|
6
|
+
loaded ??= import("mermaid").then((m) => m.default);
|
|
7
|
+
return loaded;
|
|
8
|
+
}
|
|
9
|
+
// `initialize` is global state, so a render for one palette must not
|
|
10
|
+
// interleave with a render for another: every call waits for the last.
|
|
11
|
+
let queue = Promise.resolve();
|
|
12
|
+
let sequence = 0;
|
|
13
|
+
export function renderDiagram(source, palette, fontFamily) {
|
|
14
|
+
const run = queue.then(async () => {
|
|
15
|
+
try {
|
|
16
|
+
let mermaid;
|
|
17
|
+
try {
|
|
18
|
+
mermaid = await loadMermaid();
|
|
19
|
+
}
|
|
20
|
+
catch (error) {
|
|
21
|
+
// A chunk that failed once (a dropped connection) would stay rejected
|
|
22
|
+
// in the memo and leave every later diagram on its source for the
|
|
23
|
+
// life of the page: forget it so the next render imports again.
|
|
24
|
+
// Whether that refetches is the browser's call; some still cache a
|
|
25
|
+
// failed module fetch.
|
|
26
|
+
loaded = undefined;
|
|
27
|
+
throw error;
|
|
28
|
+
}
|
|
29
|
+
mermaid.initialize({
|
|
30
|
+
startOnLoad: false,
|
|
31
|
+
securityLevel: "strict",
|
|
32
|
+
layout: "elk",
|
|
33
|
+
theme: "base",
|
|
34
|
+
fontFamily,
|
|
35
|
+
themeVariables: themeVariables(palette, fontFamily),
|
|
36
|
+
});
|
|
37
|
+
// parse() first: it throws the readable error without touching the
|
|
38
|
+
// DOM, where a failing render() can leave its scratch node behind.
|
|
39
|
+
await mermaid.parse(source);
|
|
40
|
+
const { svg } = await mermaid.render(`mermaid-${++sequence}`, source);
|
|
41
|
+
return { ok: true, svg, width: viewBoxWidth(svg) };
|
|
42
|
+
}
|
|
43
|
+
catch (error) {
|
|
44
|
+
return {
|
|
45
|
+
ok: false,
|
|
46
|
+
error: error instanceof Error ? error.message : String(error),
|
|
47
|
+
};
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
queue = run.catch(() => undefined);
|
|
51
|
+
return run;
|
|
52
|
+
}
|
|
53
|
+
function themeVariables(p, fontFamily) {
|
|
54
|
+
return {
|
|
55
|
+
darkMode: p.dark,
|
|
56
|
+
fontFamily,
|
|
57
|
+
background: p.background,
|
|
58
|
+
primaryColor: p.muted,
|
|
59
|
+
primaryTextColor: p.foreground,
|
|
60
|
+
primaryBorderColor: p.mutedForeground,
|
|
61
|
+
secondaryColor: p.muted,
|
|
62
|
+
tertiaryColor: p.background,
|
|
63
|
+
mainBkg: p.muted,
|
|
64
|
+
nodeBorder: p.mutedForeground,
|
|
65
|
+
textColor: p.foreground,
|
|
66
|
+
nodeTextColor: p.foreground,
|
|
67
|
+
lineColor: p.mutedForeground,
|
|
68
|
+
clusterBkg: p.background,
|
|
69
|
+
clusterBorder: p.border,
|
|
70
|
+
edgeLabelBackground: p.background,
|
|
71
|
+
titleColor: p.foreground,
|
|
72
|
+
noteBkgColor: p.muted,
|
|
73
|
+
noteTextColor: p.foreground,
|
|
74
|
+
noteBorderColor: p.border,
|
|
75
|
+
};
|
|
76
|
+
}
|
|
77
|
+
/** The diagram's natural width, which the fit rule in styles.css scales from. */
|
|
78
|
+
export function viewBoxWidth(svg) {
|
|
79
|
+
const match = /viewBox="[-\d.]+[\s,]+[-\d.]+[\s,]+([\d.]+)/.exec(svg);
|
|
80
|
+
return match ? Number(match[1]) : 0;
|
|
81
|
+
}
|
|
82
|
+
/**
|
|
83
|
+
* mermaid's parse errors quote the offending line and draw a caret under it,
|
|
84
|
+
* which only lines up in the monospace block the error came from. One line
|
|
85
|
+
* is what fits under the source: where it failed, and what it got there.
|
|
86
|
+
*/
|
|
87
|
+
export function errorSummary(message) {
|
|
88
|
+
const lines = message
|
|
89
|
+
.split("\n")
|
|
90
|
+
.map((line) => line.trim())
|
|
91
|
+
.filter(Boolean);
|
|
92
|
+
if (lines.length <= 1)
|
|
93
|
+
return lines[0] ?? "";
|
|
94
|
+
const got = lines.at(-1) ?? "";
|
|
95
|
+
return /^Parse error/.test(lines[0] ?? "") && /got /.test(got)
|
|
96
|
+
? `${lines[0]} ${got}`
|
|
97
|
+
: (lines[0] ?? "");
|
|
98
|
+
}
|
|
99
|
+
//# sourceMappingURL=render.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"render.js","sourceRoot":"","sources":["../src/render.ts"],"names":[],"mappings":"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"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,56 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@orz/ui-mermaid",
|
|
3
|
-
"version": "0.0.0
|
|
4
|
-
"
|
|
5
|
-
"
|
|
3
|
+
"version": "0.0.0",
|
|
4
|
+
"description": "Mermaid diagrams drawn in the active @orz/ui theme, contributed to the @orz/ui-content registry",
|
|
5
|
+
"license": "BSD-3-Clause",
|
|
6
|
+
"repository": {
|
|
7
|
+
"type": "git",
|
|
8
|
+
"url": "git+https://github.com/orzFly/ui.git",
|
|
9
|
+
"directory": "packages/ui-mermaid"
|
|
10
|
+
},
|
|
11
|
+
"type": "module",
|
|
12
|
+
"sideEffects": [
|
|
13
|
+
"**/*.css"
|
|
14
|
+
],
|
|
15
|
+
"exports": {
|
|
16
|
+
".": {
|
|
17
|
+
"@orz/source": "./src/index.ts",
|
|
18
|
+
"types": "./dist/index.d.ts",
|
|
19
|
+
"default": "./dist/index.js"
|
|
20
|
+
},
|
|
21
|
+
"./styles.css": "./styles.css"
|
|
22
|
+
},
|
|
23
|
+
"files": [
|
|
24
|
+
"dist",
|
|
25
|
+
"styles.css"
|
|
26
|
+
],
|
|
27
|
+
"publishConfig": {
|
|
28
|
+
"access": "public"
|
|
29
|
+
},
|
|
30
|
+
"peerDependencies": {
|
|
31
|
+
"react": "^19",
|
|
32
|
+
"@orz/ui": "^0.0.0",
|
|
33
|
+
"@orz/ui-content": "^0.0.0"
|
|
34
|
+
},
|
|
35
|
+
"dependencies": {
|
|
36
|
+
"mermaid": "^12.2.0"
|
|
37
|
+
},
|
|
38
|
+
"devDependencies": {
|
|
39
|
+
"@testing-library/react": "^16.3.2",
|
|
40
|
+
"@types/react": "^19.2.18",
|
|
41
|
+
"@types/react-dom": "^19.2.4",
|
|
42
|
+
"happy-dom": "^21.0.3",
|
|
43
|
+
"radix-ui": "^1.6.7",
|
|
44
|
+
"react": "^19.2.8",
|
|
45
|
+
"react-dom": "^19.2.8",
|
|
46
|
+
"vitest": "^5.0.5",
|
|
47
|
+
"@orz/ui-content": "0.0.0",
|
|
48
|
+
"@orz/themes": "0.0.0",
|
|
49
|
+
"@orz/ui": "0.0.0"
|
|
50
|
+
},
|
|
51
|
+
"scripts": {
|
|
52
|
+
"build": "tsc -p tsconfig.build.json",
|
|
53
|
+
"typecheck": "tsc --noEmit",
|
|
54
|
+
"test": "vitest run"
|
|
55
|
+
}
|
|
6
56
|
}
|
package/styles.css
ADDED
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
/* Tailwind resolves an imported file's @source against that file, so a
|
|
2
|
+
consumer importing this stylesheet scans the classes in the package's
|
|
3
|
+
shipped JS without writing an @source of its own. */
|
|
4
|
+
@source "./dist";
|
|
5
|
+
|
|
6
|
+
@layer components {
|
|
7
|
+
/* A diagram shrinks to the column, but never below 75% of its natural
|
|
8
|
+
width — past that its labels stop being readable, so it scrolls instead
|
|
9
|
+
(T-523). Never enlarged. `!important` beats the width attribute and the
|
|
10
|
+
inline max-width mermaid writes onto its own <svg>. */
|
|
11
|
+
/* biome-ignore-start lint/complexity/noImportantStyles: mermaid's inline style, see above */
|
|
12
|
+
.mermaid-diagram > svg {
|
|
13
|
+
display: block;
|
|
14
|
+
width: min(
|
|
15
|
+
var(--diagram-width),
|
|
16
|
+
max(100%, calc(var(--diagram-width) * 0.75))
|
|
17
|
+
) !important;
|
|
18
|
+
max-width: none !important;
|
|
19
|
+
height: auto;
|
|
20
|
+
}
|
|
21
|
+
/* biome-ignore-end lint/complexity/noImportantStyles: mermaid's inline style, see above */
|
|
22
|
+
}
|