@matfsw/docusaurus-plantuml-plugin 1.0.3 → 1.1.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/CHANGELOG.md +77 -1
- package/README.md +264 -49
- package/dist/assets.js +25 -8
- package/dist/constants.d.ts +12 -1
- package/dist/constants.js +12 -1
- package/dist/index.cjs +116 -17
- package/dist/index.d.cts +41 -1
- package/dist/options.d.ts +42 -1
- package/dist/options.js +105 -8
- package/dist/runtime/assetLoader.d.ts +13 -3
- package/dist/runtime/assetLoader.js +68 -8
- package/dist/runtime/cache.d.ts +21 -0
- package/dist/runtime/cache.js +12 -0
- package/dist/runtime/errors.d.ts +16 -1
- package/dist/runtime/errors.js +32 -0
- package/dist/runtime/graphvizRenderer.d.ts +24 -0
- package/dist/runtime/graphvizRenderer.js +95 -0
- package/dist/runtime/types.d.ts +41 -0
- package/dist/theme/MDXComponents/Code/index.d.ts +8 -3
- package/dist/theme/MDXComponents/Code/index.js +31 -8
- package/dist/theme/PlantUmlDiagram/index.d.ts +16 -4
- package/dist/theme/PlantUmlDiagram/index.js +49 -12
- package/dist/theme/PlantUmlDiagram/styles.module.css +31 -0
- package/dist/theme/codeBlockMeta.d.ts +9 -0
- package/dist/theme/codeBlockMeta.js +21 -0
- package/dist/theme/usePlantUmlConfig.d.ts +1 -1
- package/dist/theme/usePlantUmlConfig.js +20 -1
- package/package.json +1 -1
package/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,81 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.1.0]
|
|
11
|
+
|
|
12
|
+
### Added
|
|
13
|
+
|
|
14
|
+
- **Graphviz/DOT diagrams.** `dot`, `graphviz` and `gv` fences are now laid out by Graphviz in
|
|
15
|
+
the reader's browser and replaced with SVG, exactly as `plantuml` fences already were. Zoom
|
|
16
|
+
and pan, lazy rendering, caching, sanitization, the accessible markup and the error panel are
|
|
17
|
+
all shared with the PlantUML path.
|
|
18
|
+
|
|
19
|
+
**This costs no additional bytes.** `@plantuml/core` already bundles `viz-global.js` — Viz.js
|
|
20
|
+
containing Graphviz — because PlantUML needs it for its own layout, and the plugin has been
|
|
21
|
+
emitting and loading it since `0.1.0`. Rendering DOT reuses that engine rather than adding a
|
|
22
|
+
dependency. See [ADR 0004](docs/adr/0004-graphviz-engine-reuse.md).
|
|
23
|
+
|
|
24
|
+
- A `graphviz` option group: `enabled`, `languages`, `engine`, `allowEngineOverride`,
|
|
25
|
+
`maxSourceBytes` and `transparentBackground`. Unknown keys inside it are rejected at build
|
|
26
|
+
time, like unknown keys at the top level.
|
|
27
|
+
|
|
28
|
+
- Per-fence layout engine selection with `engine=neato` (or `circo`, `fdp`, `twopi`, `sfdp`,
|
|
29
|
+
`osage`, `patchwork`, `nop`, `nop1`, `nop2`, `dot`) in the fence metastring. Disable with
|
|
30
|
+
`graphviz.allowEngineOverride: false`.
|
|
31
|
+
|
|
32
|
+
- Two `data-*` attributes on the diagram `<figure>`: `data-diagram-engine`
|
|
33
|
+
(`plantuml` | `graphviz`) and `data-diagram-layout` (the Graphviz layout engine, absent on
|
|
34
|
+
PlantUML diagrams). Both are part of the documented public surface.
|
|
35
|
+
|
|
36
|
+
- `GraphvizOptions`, `ResolvedGraphvizOptions`, `GraphvizEngine`, `GRAPHVIZ_ENGINES` and
|
|
37
|
+
`DEFAULT_GRAPHVIZ_OPTIONS` are exported from the package root.
|
|
38
|
+
|
|
39
|
+
### Changed
|
|
40
|
+
|
|
41
|
+
- **`dot`, `graphviz` and `gv` fences now render as diagrams instead of as code blocks.** This
|
|
42
|
+
is the one behaviour change in this release. If you have such fences that are meant to stay
|
|
43
|
+
code, set `graphviz: {enabled: false}` or narrow `graphviz.languages`.
|
|
44
|
+
|
|
45
|
+
- **The two runtimes are now loaded independently.** `viz-global.js` (~1.4 MB) and
|
|
46
|
+
`plantuml.js` (~6.8 MB) previously shared one loader promise, so any diagram fetched both.
|
|
47
|
+
They are now separate singletons, and a page with only DOT diagrams never downloads the
|
|
48
|
+
PlantUML engine. Nothing changes for a PlantUML-only page: the same two files load in the
|
|
49
|
+
same order from the same single `<script>` tag.
|
|
50
|
+
|
|
51
|
+
- The build now fails with an actionable message if the installed `@plantuml/core` is missing
|
|
52
|
+
either runtime file, rather than letting a broken install reach a reader's browser as a
|
|
53
|
+
runtime load failure.
|
|
54
|
+
|
|
55
|
+
- Progress text, the default accessible label and the error heading name the engine that is
|
|
56
|
+
actually involved — "Loading Graphviz runtime…", "Graphviz diagram", "Error: Graphviz diagram
|
|
57
|
+
could not be rendered".
|
|
58
|
+
|
|
59
|
+
- The missing-plugin-data error panel now says "Diagram plugin data is missing" rather than
|
|
60
|
+
"PlantUML plugin data is missing", since it applies to both engines.
|
|
61
|
+
|
|
62
|
+
### Notes
|
|
63
|
+
|
|
64
|
+
- **Invalid DOT is reported with Graphviz's own diagnostic, including the line number** — for
|
|
65
|
+
example `syntax error in line 3 near '}'`. PlantUML reports invalid diagrams by rendering an
|
|
66
|
+
error picture, which the plugin has to detect heuristically
|
|
67
|
+
([ADR 0002](docs/adr/0002-render-to-string.md)); Graphviz returns structured errors, so the
|
|
68
|
+
reader is told exactly what is wrong and where.
|
|
69
|
+
|
|
70
|
+
- **Graphviz diagrams are not re-rendered on a colour-mode toggle.** Graphviz has no dark
|
|
71
|
+
theme, so rather than laying the graph out twice, the plugin renders on a transparent
|
|
72
|
+
background and retargets Graphviz's default black strokes, fills and text at the page's text
|
|
73
|
+
colour in CSS. Colours set in the DOT source always win, in both modes. As a result the
|
|
74
|
+
colour mode is absent from the Graphviz cache key and a theme toggle does not disturb a
|
|
75
|
+
reader's zoom.
|
|
76
|
+
|
|
77
|
+
- **`graphviz.maxSourceBytes` defaults to 100 000.** Graphviz lays out synchronously: a
|
|
78
|
+
300-edge graph renders in ~26 ms, but a 3 000-edge graph takes ~2.25 s and visibly freezes the
|
|
79
|
+
page. Oversized sources are refused with an explanatory panel, before the engine is even
|
|
80
|
+
downloaded.
|
|
81
|
+
|
|
82
|
+
- Rendering remains 100% same-origin and client-side. No CDN, no rendering service, no
|
|
83
|
+
`unsafe-eval`, and no Graphviz installation on the build machine or the reader's.
|
|
84
|
+
|
|
10
85
|
## [1.0.3]
|
|
11
86
|
|
|
12
87
|
### Security
|
|
@@ -126,7 +201,8 @@ Initial release.
|
|
|
126
201
|
opt-out.
|
|
127
202
|
- Plugin option validation that rejects unknown keys and out-of-range values at build time.
|
|
128
203
|
|
|
129
|
-
[Unreleased]: https://github.com/matf/docusaurus-plantuml-plugin/compare/v1.0
|
|
204
|
+
[Unreleased]: https://github.com/matf/docusaurus-plantuml-plugin/compare/v1.1.0...HEAD
|
|
205
|
+
[1.1.0]: https://github.com/matf/docusaurus-plantuml-plugin/compare/v1.0.3...v1.1.0
|
|
130
206
|
[1.0.3]: https://github.com/matf/docusaurus-plantuml-plugin/compare/v1.0.2...v1.0.3
|
|
131
207
|
[1.0.2]: https://github.com/matf/docusaurus-plantuml-plugin/compare/v1.0.1...v1.0.2
|
|
132
208
|
[1.0.1]: https://github.com/matf/docusaurus-plantuml-plugin/compare/v1.0.0...v1.0.1
|
package/README.md
CHANGED
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
# @matfsw/docusaurus-plantuml-plugin
|
|
2
2
|
|
|
3
|
-
Render PlantUML diagrams in Docusaurus 3 entirely in the browser — no
|
|
4
|
-
server, no Kroki, no CDN.
|
|
3
|
+
Render **PlantUML** and **Graphviz/DOT** diagrams in Docusaurus 3 entirely in the browser — no
|
|
4
|
+
Java, no PlantUML server, no Graphviz install, no Kroki, no CDN.
|
|
5
5
|
|
|
6
6
|
**→ [Live demo](https://matf.github.io/docusaurus-plantuml-demo)** — every diagram on that site
|
|
7
7
|
is rendered by your own browser.
|
|
8
8
|
|
|
9
|
+
> **The package name says PlantUML, and it renders Graphviz too.** Graphviz support was added
|
|
10
|
+
> in 1.1.0; the name is kept for the sake of everyone who already depends on it. See
|
|
11
|
+
> [Graphviz diagrams](#graphviz-dot-diagrams).
|
|
12
|
+
|
|
9
13
|
Write a `plantuml` fence in any `.md` or `.mdx` file and the code block is replaced, in the
|
|
10
14
|
reader's browser, with an SVG rendered by the official [`@plantuml/core`][plantuml-core]
|
|
11
15
|
package:
|
|
@@ -25,9 +29,20 @@ Browser --> User: Signed in
|
|
|
25
29
|
```
|
|
26
30
|
````
|
|
27
31
|
|
|
32
|
+
…and a `dot` fence is replaced with an SVG laid out by Graphviz:
|
|
33
|
+
|
|
34
|
+
````markdown
|
|
35
|
+
```dot title="Build pipeline"
|
|
36
|
+
digraph {
|
|
37
|
+
rankdir=LR;
|
|
38
|
+
src -> build -> test -> deploy;
|
|
39
|
+
}
|
|
40
|
+
```
|
|
41
|
+
````
|
|
42
|
+
|
|
28
43
|
**Rendering is 100% same-origin and client-side. Your diagram source never leaves the
|
|
29
44
|
browser.** It is not sent to plantuml.com, to a Kroki instance, or to any other service, and
|
|
30
|
-
the
|
|
45
|
+
the engines themselves are served from your own site's `baseUrl`.
|
|
31
46
|
|
|
32
47
|
## Status and compatibility
|
|
33
48
|
|
|
@@ -134,6 +149,15 @@ const config: Config = {
|
|
|
134
149
|
showSourceOnError: true,
|
|
135
150
|
renderTimeoutMs: 20_000,
|
|
136
151
|
cacheMaxEntries: 50,
|
|
152
|
+
zoom: true,
|
|
153
|
+
graphviz: {
|
|
154
|
+
enabled: true,
|
|
155
|
+
languages: ['dot', 'graphviz', 'gv'],
|
|
156
|
+
engine: 'dot',
|
|
157
|
+
allowEngineOverride: true,
|
|
158
|
+
maxSourceBytes: 100_000,
|
|
159
|
+
transparentBackground: true,
|
|
160
|
+
},
|
|
137
161
|
} satisfies PlantUmlPluginOptions,
|
|
138
162
|
],
|
|
139
163
|
],
|
|
@@ -185,14 +209,20 @@ Alice -> Bob : puml alias in MDX
|
|
|
185
209
|
|
|
186
210
|
### Supported fence aliases
|
|
187
211
|
|
|
188
|
-
By default the plugin claims
|
|
212
|
+
By default the plugin claims five fence languages across two engines:
|
|
213
|
+
|
|
214
|
+
| Engine | Default languages | Option |
|
|
215
|
+
| -------- | ----------------------- | -------------------- |
|
|
216
|
+
| PlantUML | `plantuml`, `puml` | `languages` |
|
|
217
|
+
| Graphviz | `dot`, `graphviz`, `gv` | `graphviz.languages` |
|
|
189
218
|
|
|
190
|
-
- `
|
|
191
|
-
|
|
219
|
+
Matching is **case-insensitive**, so ` ```PlantUML `, ` ```PUML `, ` ```DOT ` and ` ```dot `
|
|
220
|
+
are all recognised. Change either set with its option; entries are normalised to lower case,
|
|
221
|
+
must be non-empty, must not repeat, and the two sets must not overlap.
|
|
192
222
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
223
|
+
> **Upgrading from 1.0.x:** `dot`, `graphviz` and `gv` fences were previously rendered as
|
|
224
|
+
> ordinary code blocks and are now rendered as diagrams. If you have such fences that are meant
|
|
225
|
+
> to stay code, set `graphviz: {enabled: false}`, or narrow `graphviz.languages`.
|
|
196
226
|
|
|
197
227
|
Everything else — inline code, ordinary fenced blocks in any other language, and code blocks
|
|
198
228
|
authored as JSX children — is delegated to the original Docusaurus `Code` component with its
|
|
@@ -212,8 +242,14 @@ props untouched. Existing code-block behaviour (highlighting, line numbers, titl
|
|
|
212
242
|
| `renderTimeoutMs` | `number` | `20000` | Abort a single render (and the runtime load) after this many milliseconds. Integer, `100`–`600000`. |
|
|
213
243
|
| `cacheMaxEntries` | `number` | `50` | Upper bound on cached SVG entries. Positive integer. |
|
|
214
244
|
| `zoom` | `boolean` | `true` | Let readers zoom and pan diagrams. Adds a control toolbar and a focusable viewport. Override per fence with `zoom=false`. |
|
|
245
|
+
| `graphviz` | `object` | see below | Graphviz/DOT support. See [Graphviz options](#graphviz-options). |
|
|
215
246
|
| `id` | `string` | `'default'` | Docusaurus plugin instance id; only relevant if you register the plugin more than once. |
|
|
216
247
|
|
|
248
|
+
Every option above except `graphviz` applies to **both** engines: `lazy`, `cache`,
|
|
249
|
+
`sanitizeSvg`, `showSourceOnError`, `renderTimeoutMs`, `cacheMaxEntries` and `zoom` behave
|
|
250
|
+
identically for a `dot` fence and a `plantuml` fence. `theme` is the exception — see
|
|
251
|
+
[Light and dark mode](#light-and-dark-mode).
|
|
252
|
+
|
|
217
253
|
Options are validated during the Docusaurus configuration phase, before anything is built.
|
|
218
254
|
**Unknown keys are rejected** rather than ignored, because a typo in `docusaurus.config.ts`
|
|
219
255
|
would otherwise silently disable the option you meant to set:
|
|
@@ -221,15 +257,133 @@ would otherwise silently disable the option you meant to set:
|
|
|
221
257
|
```text
|
|
222
258
|
[docusaurus-plugin-plantuml-client] Unknown option 'sanitiseSvg'. Supported options:
|
|
223
259
|
'languages', 'theme', 'lazy', 'cache', 'sanitizeSvg', 'showSourceOnError',
|
|
224
|
-
'renderTimeoutMs', 'cacheMaxEntries', 'zoom'.
|
|
260
|
+
'renderTimeoutMs', 'cacheMaxEntries', 'zoom', 'graphviz'.
|
|
225
261
|
```
|
|
226
262
|
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
263
|
+
The same is true one level deeper, so `graphviz: {enigne: 'neato'}` fails the build rather than
|
|
264
|
+
quietly doing nothing.
|
|
265
|
+
|
|
266
|
+
`PlantUmlPluginOptions`, `ResolvedPlantUmlOptions`, `GraphvizOptions`,
|
|
267
|
+
`ResolvedGraphvizOptions`, `GraphvizEngine`, `GRAPHVIZ_ENGINES`, `CacheMode`, `DiagramTheme`,
|
|
268
|
+
`DEFAULT_OPTIONS`, `DEFAULT_GRAPHVIZ_OPTIONS`, `resolveOptions` and `PlantUmlOptionsError` are
|
|
269
|
+
exported from the package root. The renderer, queue and cache internals are deliberately not
|
|
270
|
+
exported.
|
|
271
|
+
|
|
272
|
+
## Graphviz (DOT) diagrams
|
|
273
|
+
|
|
274
|
+
`dot`, `graphviz` and `gv` fences are laid out by [Graphviz][graphviz] compiled to WebAssembly,
|
|
275
|
+
in the reader's browser, exactly like PlantUML fences:
|
|
276
|
+
|
|
277
|
+
````markdown
|
|
278
|
+
```dot title="Build pipeline"
|
|
279
|
+
digraph {
|
|
280
|
+
rankdir=LR;
|
|
281
|
+
node [shape=box, style=rounded];
|
|
282
|
+
src -> build -> test -> deploy;
|
|
283
|
+
}
|
|
284
|
+
```
|
|
285
|
+
````
|
|
286
|
+
|
|
287
|
+
### It costs no extra bytes
|
|
288
|
+
|
|
289
|
+
This is the part worth knowing: **the plugin already shipped Graphviz before it could render
|
|
290
|
+
DOT.** `@plantuml/core` bundles `viz-global.js` — Viz.js containing Graphviz — because PlantUML
|
|
291
|
+
needs it for its own layout, and the plugin has been emitting and loading it since 0.1.0.
|
|
292
|
+
Rendering DOT reuses that engine, so a site that already renders PlantUML pays **zero
|
|
293
|
+
additional bytes** for Graphviz support. See
|
|
294
|
+
[ADR 0004](docs/adr/0004-graphviz-engine-reuse.md).
|
|
295
|
+
|
|
296
|
+
The reverse also holds: a page containing only DOT diagrams loads only `viz-global.js`
|
|
297
|
+
(~1.4 MB) and never fetches the ~6.8 MB PlantUML engine.
|
|
298
|
+
|
|
299
|
+
### Choosing a layout engine
|
|
300
|
+
|
|
301
|
+
Graphviz ships eleven layout engines. The default is `dot`; any fence can pick another with
|
|
302
|
+
`engine=`:
|
|
303
|
+
|
|
304
|
+
````markdown
|
|
305
|
+
```dot title="Undirected mesh" engine=neato
|
|
306
|
+
graph { a -- b -- c -- a }
|
|
307
|
+
```
|
|
308
|
+
````
|
|
309
|
+
|
|
310
|
+
Available engines: `circo`, `dot`, `fdp`, `neato`, `nop`, `nop1`, `nop2`, `osage`,
|
|
311
|
+
`patchwork`, `sfdp`, `twopi`. An unknown name fails with the supported set spelled out. Set
|
|
312
|
+
`graphviz.allowEngineOverride: false` to ignore the fence flag and pin every diagram to the
|
|
313
|
+
configured engine.
|
|
314
|
+
|
|
315
|
+
### Colours and dark mode
|
|
316
|
+
|
|
317
|
+
Graphviz has no dark theme — it draws black on white regardless of the page. Rather than
|
|
318
|
+
re-rendering the graph for each colour mode, the plugin retargets Graphviz's _defaults_ at the
|
|
319
|
+
page's text colour in CSS, and renders on a transparent background.
|
|
320
|
+
|
|
321
|
+
**Colours set in the DOT source always win.** The rules only match elements Graphviz coloured
|
|
322
|
+
with its own black default (`stroke="black"`, `fill="black"`, and `<text>` with no `fill`), so
|
|
323
|
+
`color=red`, `fillcolor=lightblue` and friends are emitted and displayed exactly as authored,
|
|
324
|
+
in both modes.
|
|
325
|
+
|
|
326
|
+
Because nothing is re-rendered, toggling the theme on a page of DOT diagrams costs no layout
|
|
327
|
+
work at all and does not disturb a reader's zoom.
|
|
328
|
+
|
|
329
|
+
### Error reporting
|
|
330
|
+
|
|
331
|
+
Graphviz returns structured diagnostics, so an invalid diagram is reported with the engine's
|
|
332
|
+
own message including the offending line:
|
|
333
|
+
|
|
334
|
+
```text
|
|
335
|
+
Error: Graphviz diagram could not be rendered
|
|
336
|
+
syntax error in line 3 near '}'
|
|
337
|
+
```
|
|
338
|
+
|
|
339
|
+
### Graphviz options
|
|
340
|
+
|
|
341
|
+
```ts
|
|
342
|
+
graphviz: {
|
|
343
|
+
enabled: true, // intercept DOT fences at all
|
|
344
|
+
languages: ['dot', 'graphviz', 'gv'], // fence languages, matched case-insensitively
|
|
345
|
+
engine: 'dot', // default layout engine
|
|
346
|
+
allowEngineOverride: true, // permit `engine=neato` on a fence
|
|
347
|
+
maxSourceBytes: 100_000, // refuse larger sources; see below
|
|
348
|
+
transparentBackground: true, // omit Graphviz's opaque white background
|
|
349
|
+
}
|
|
350
|
+
```
|
|
351
|
+
|
|
352
|
+
| Option | Type | Default | Description |
|
|
353
|
+
| ----------------------- | ---------- | --------------------------- | --------------------------------------------------------------------------------------- |
|
|
354
|
+
| `enabled` | `boolean` | `true` | Intercept DOT fences. `false` leaves them as ordinary, highlighted code blocks. |
|
|
355
|
+
| `languages` | `string[]` | `['dot', 'graphviz', 'gv']` | Fence languages treated as Graphviz. Must not overlap the top-level `languages`. |
|
|
356
|
+
| `engine` | `string` | `'dot'` | Default layout engine, one of the eleven listed above. |
|
|
357
|
+
| `allowEngineOverride` | `boolean` | `true` | Whether a fence may select its own engine with `engine=`. |
|
|
358
|
+
| `maxSourceBytes` | `number` | `100000` | Refuse sources larger than this many UTF-8 bytes, showing an explanatory panel instead. |
|
|
359
|
+
| `transparentBackground` | `boolean` | `true` | Render with `bgcolor=transparent` so the page background shows through. |
|
|
360
|
+
|
|
361
|
+
A language claimed by both engines fails the build, because a fence has exactly one language
|
|
362
|
+
and the result would otherwise depend on evaluation order:
|
|
363
|
+
|
|
364
|
+
```text
|
|
365
|
+
[docusaurus-plugin-plantuml-client] options.graphviz.languages and options.languages both
|
|
366
|
+
claim 'dot'. A fence language can only belong to one engine.
|
|
367
|
+
```
|
|
368
|
+
|
|
369
|
+
### Why `maxSourceBytes` exists
|
|
370
|
+
|
|
371
|
+
Graphviz lays out **synchronously**, so an enormous graph blocks the main thread rather than
|
|
372
|
+
merely taking a while. Measured on the bundled engine: a 300-edge graph renders in ~26 ms
|
|
373
|
+
(imperceptible), while a 3 000-edge graph takes ~2.25 s — a visible freeze. The default limit
|
|
374
|
+
turns that freeze into a contained error panel. Raise it if you genuinely have diagrams that
|
|
375
|
+
large, and expect the page to stall while they render.
|
|
376
|
+
|
|
377
|
+
The check happens **before** the engine is downloaded, so refusing an oversized diagram is
|
|
378
|
+
free.
|
|
230
379
|
|
|
231
380
|
## Light and dark mode
|
|
232
381
|
|
|
382
|
+
The two engines handle this differently, because PlantUML has a real dark theme and Graphviz
|
|
383
|
+
does not.
|
|
384
|
+
|
|
385
|
+
### PlantUML — re-rendered
|
|
386
|
+
|
|
233
387
|
With `theme: 'auto'` (the default), the diagram follows the site's colour mode through
|
|
234
388
|
Docusaurus' own `useColorMode()` hook. Toggling the site theme re-renders every visible
|
|
235
389
|
diagram with the engine's `{dark}` flag flipped, which changes PlantUML's own fill and stroke
|
|
@@ -241,7 +395,20 @@ and the engine itself is loaded once per page regardless of how often you toggle
|
|
|
241
395
|
Set `theme: 'light'` or `theme: 'dark'` to pin the diagram palette independently of the site
|
|
242
396
|
theme.
|
|
243
397
|
|
|
244
|
-
|
|
398
|
+
### Graphviz — restyled, not re-rendered
|
|
399
|
+
|
|
400
|
+
Graphviz draws black on white and has no dark palette to ask for, so the plugin adapts its
|
|
401
|
+
_defaults_ with CSS instead of rendering the graph twice. A colour-mode toggle therefore costs
|
|
402
|
+
no layout work for DOT diagrams, does not reset the reader's zoom, and needs no second cache
|
|
403
|
+
entry. The `theme` option does not apply to them.
|
|
404
|
+
|
|
405
|
+
See [Colours and dark mode](#colours-and-dark-mode) for exactly which elements are adapted and
|
|
406
|
+
why authored colours are never touched.
|
|
407
|
+
|
|
408
|
+
### Both
|
|
409
|
+
|
|
410
|
+
The current mode is exposed on the wrapper as `data-plantuml-theme="light|dark"` for every
|
|
411
|
+
diagram, whichever engine produced it.
|
|
245
412
|
|
|
246
413
|
## Zoom and pan
|
|
247
414
|
|
|
@@ -444,13 +611,20 @@ transform layer, and a control group is added beside it:
|
|
|
444
611
|
These attributes are part of the public surface; write your own end-to-end tests against
|
|
445
612
|
them.
|
|
446
613
|
|
|
447
|
-
| Attribute | Values
|
|
448
|
-
| --------------------------- |
|
|
449
|
-
| `data-plantuml-diagram` | the fence language that matched, e.g. `plantuml
|
|
450
|
-
| `data-
|
|
451
|
-
| `data-
|
|
452
|
-
| `data-plantuml-
|
|
453
|
-
| `data-plantuml-
|
|
614
|
+
| Attribute | Values |
|
|
615
|
+
| --------------------------- | --------------------------------------------------------------- |
|
|
616
|
+
| `data-plantuml-diagram` | the fence language that matched, e.g. `plantuml`, `puml`, `dot` |
|
|
617
|
+
| `data-diagram-engine` | `plantuml` \| `graphviz` |
|
|
618
|
+
| `data-diagram-layout` | Graphviz layout engine, e.g. `dot`; absent on PlantUML diagrams |
|
|
619
|
+
| `data-plantuml-status` | `idle` \| `loading` \| `rendering` \| `ready` \| `error` |
|
|
620
|
+
| `data-plantuml-theme` | `light` \| `dark` |
|
|
621
|
+
| `data-plantuml-interactive` | `true`, on the `<figure>`, only when zoom is enabled |
|
|
622
|
+
| `data-plantuml-zoom` | current scale on the viewport, e.g. `1`, `2.5` |
|
|
623
|
+
|
|
624
|
+
The `data-plantuml-*` prefix is historical: it predates Graphviz support and is applied to
|
|
625
|
+
every diagram this plugin renders, whatever the engine. It was kept rather than renamed so that
|
|
626
|
+
existing author CSS and end-to-end tests keep working. Select on `data-diagram-engine` when the
|
|
627
|
+
two engines need different styling.
|
|
454
628
|
|
|
455
629
|
## SVG sanitization and security model
|
|
456
630
|
|
|
@@ -494,25 +668,32 @@ to plantuml.com or anywhere else, and none can be configured.
|
|
|
494
668
|
A failed diagram produces a contained error panel. It never crashes the page, never blocks
|
|
495
669
|
the render queue, and never silently disappears.
|
|
496
670
|
|
|
497
|
-
The panel shows a heading (`⚠ Error: PlantUML diagram could not be rendered
|
|
498
|
-
|
|
499
|
-
element. The
|
|
671
|
+
The panel shows a heading naming the engine (`⚠ Error: PlantUML diagram could not be rendered`,
|
|
672
|
+
or `⚠ Error: Graphviz diagram could not be rendered`), the message, and — unless
|
|
673
|
+
`showSourceOnError: false` — the original source in a collapsed `<details>` element. The
|
|
674
|
+
wrapper carries `data-plantuml-status="error"`.
|
|
500
675
|
|
|
501
676
|
Failures are classified internally as one of:
|
|
502
677
|
|
|
503
|
-
| Kind
|
|
504
|
-
|
|
|
505
|
-
| `load`
|
|
506
|
-
| `engine`
|
|
507
|
-
| `diagram`
|
|
508
|
-
| `
|
|
509
|
-
| `
|
|
510
|
-
| `
|
|
511
|
-
|
|
512
|
-
|
|
513
|
-
|
|
514
|
-
|
|
515
|
-
|
|
678
|
+
| Kind | Cause |
|
|
679
|
+
| ----------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
|
|
680
|
+
| `load` | `viz-global.js` or `plantuml.js` could not be fetched, timed out, or was not the expected module (usually a proxy or service worker returning the wrong file). |
|
|
681
|
+
| `engine` | The engine threw, or its output could not be used at all. |
|
|
682
|
+
| `diagram` | The source is not valid PlantUML. |
|
|
683
|
+
| `syntax` | The source is not valid DOT. Carries Graphviz's own diagnostic, including the line number. |
|
|
684
|
+
| `too-large` | A DOT source exceeded `graphviz.maxSourceBytes`. |
|
|
685
|
+
| `timeout` | One render exceeded `renderTimeoutMs`. |
|
|
686
|
+
| `config` | The plugin's global data is missing, or a fence named a layout engine this Graphviz build does not have. |
|
|
687
|
+
| `aborted` | The component unmounted or re-rendered; not surfaced to the reader. |
|
|
688
|
+
|
|
689
|
+
The two engines report invalid source very differently:
|
|
690
|
+
|
|
691
|
+
- **Invalid PlantUML is not reported through the engine's error callback.** The engine renders
|
|
692
|
+
an "error picture" and reports success, so the rendered SVG is inspected for error markers
|
|
693
|
+
before it is trusted. See [ADR 0002](docs/adr/0002-render-to-string.md) for the exact
|
|
694
|
+
detection rules.
|
|
695
|
+
- **Invalid DOT is reported as structured data**, so the panel shows Graphviz's own message
|
|
696
|
+
verbatim — `syntax error in line 3 near '}'` — with no heuristics involved.
|
|
516
697
|
|
|
517
698
|
## `baseUrl` support
|
|
518
699
|
|
|
@@ -556,13 +737,13 @@ exactly as it did before installation.
|
|
|
556
737
|
|
|
557
738
|
## Bundle-size implications
|
|
558
739
|
|
|
559
|
-
The
|
|
740
|
+
The runtimes are large:
|
|
560
741
|
|
|
561
|
-
| File | Size (uncompressed) |
|
|
562
|
-
| --------------- | ------------------- |
|
|
563
|
-
| `plantuml.js` | ≈ 6.8 MB |
|
|
564
|
-
| `viz-global.js` | ≈ 1.4 MB |
|
|
565
|
-
| **Total** | **≈ 8.2 MB** |
|
|
742
|
+
| File | Size (uncompressed) | Needed for |
|
|
743
|
+
| --------------- | ------------------- | ------------------------------------- |
|
|
744
|
+
| `plantuml.js` | ≈ 6.8 MB | PlantUML fences only |
|
|
745
|
+
| `viz-global.js` | ≈ 1.4 MB | DOT fences, and PlantUML's own layout |
|
|
746
|
+
| **Total** | **≈ 8.2 MB** | |
|
|
566
747
|
|
|
567
748
|
Crucially, **none of that is in your site's initial bundle**. The files are emitted as static
|
|
568
749
|
assets, not imported into the webpack graph (the dynamic import is marked `webpackIgnore`), so:
|
|
@@ -570,9 +751,15 @@ assets, not imported into the webpack graph (the dynamic import is marked `webpa
|
|
|
570
751
|
- Pages with no diagram never request them.
|
|
571
752
|
- Pages with diagrams request them once, on first render — and with `lazy: true`, only when a
|
|
572
753
|
diagram nears the viewport.
|
|
754
|
+
- **Each runtime is requested only if a diagram actually needs it.** A page with only DOT
|
|
755
|
+
diagrams fetches `viz-global.js` and never the 6.8 MB PlantUML engine; a page with PlantUML
|
|
756
|
+
diagrams fetches both, because PlantUML needs Graphviz for its own layout.
|
|
573
757
|
- The files are served from your origin with your own cache headers, and are re-fetched only
|
|
574
758
|
when the engine version changes.
|
|
575
759
|
|
|
760
|
+
**Adding Graphviz support to a site that already renders PlantUML costs nothing**, because
|
|
761
|
+
`viz-global.js` was already being emitted and loaded.
|
|
762
|
+
|
|
576
763
|
The published npm package itself is small (the compiled plugin and theme components only);
|
|
577
764
|
the 8 MB comes from the `@plantuml/core` dependency and lands in your build output, not in
|
|
578
765
|
your JavaScript bundle. Budget for roughly 8 MB of extra static assets per deployed site.
|
|
@@ -668,6 +855,15 @@ Four layers, all deterministic and none of them calling an external PlantUML ser
|
|
|
668
855
|
layer: focal-point and clamping geometry as pure functions, the wheel policy (plain wheel
|
|
669
856
|
ignored, Ctrl honoured, Cmd ignored), keyboard handling, both reset triggers, and listener
|
|
670
857
|
teardown.
|
|
858
|
+
For Graphviz specifically: the nested option group and its validation including the
|
|
859
|
+
both-engines-claim-one-language check, `engine=` metastring parsing, the separate cache-key
|
|
860
|
+
namespace and its deliberate omission of the colour mode, structured error formatting and
|
|
861
|
+
line-number extraction, the `window.Viz` API assertion, the loader split (a DOT-only page
|
|
862
|
+
never importing the PlantUML module), the source-size guard measuring UTF-8 bytes before
|
|
863
|
+
loading anything, engine reuse across renders and across syntax errors, that a colour-mode
|
|
864
|
+
toggle re-renders a PlantUML diagram but not a Graphviz one, and that DOMPurify strips
|
|
865
|
+
`javascript:` from DOT's `URL=` links while preserving the colour attributes the dark-mode
|
|
866
|
+
CSS selects on.
|
|
671
867
|
Docusaurus `@theme/*` and `@docusaurus/*` aliases only exist inside a real Docusaurus
|
|
672
868
|
webpack build, so the Vitest config points them at local stubs.
|
|
673
869
|
2. **Package verification** (`npm run pack:check`). Runs `npm pack --dry-run --json`, prints
|
|
@@ -691,12 +887,20 @@ Four layers, all deterministic and none of them calling an external PlantUML ser
|
|
|
691
887
|
loaded at most once when diagrams are present, that every asset URL carries the configured
|
|
692
888
|
`baseUrl`, that no request goes to an external host, and that the build hydrates without
|
|
693
889
|
React mismatch warnings.
|
|
890
|
+
The Graphviz suite adds: DOT fences rendering to real SVG with the expected node labels, a
|
|
891
|
+
DOT-only page fetching `viz-global.js` once and `plantuml.js` never, both engines rendering
|
|
892
|
+
on one page with one download each, `engine=neato` and `engine=circo` producing distinct
|
|
893
|
+
layouts, the Graphviz diagnostic and its line number appearing in the error panel while the
|
|
894
|
+
rest of the page still renders, default colours changing with the colour mode while authored
|
|
895
|
+
colours do not, a `javascript:` URL never surviving into a link, zoom working the same as it
|
|
896
|
+
does for PlantUML, and a client-side navigation not re-downloading the engine.
|
|
694
897
|
|
|
695
898
|
The example site under `examples/docusaurus/` is the fixture: it deploys under
|
|
696
899
|
`baseUrl: '/plantuml-test/'` and contains a sequence diagram, a Graphviz-dependent class
|
|
697
900
|
diagram, a component diagram, several diagrams on one page, `.md` and `.mdx` documents, a
|
|
698
|
-
`puml` alias, title metadata, an invalid diagram, an ordinary TypeScript block,
|
|
699
|
-
|
|
901
|
+
`puml` alias, title metadata, an invalid diagram, an ordinary TypeScript block, a page with no
|
|
902
|
+
diagram at all, a Graphviz page exercising several layout engines and authored colours, and a
|
|
903
|
+
DOT-only page that proves the PlantUML engine is never fetched for it.
|
|
700
904
|
|
|
701
905
|
## Release process
|
|
702
906
|
|
|
@@ -778,9 +982,15 @@ package.
|
|
|
778
982
|
- **Diagrams are not rendered during static-site generation.** The HTML Docusaurus emits
|
|
779
983
|
contains the deferred placeholder and the `<noscript>` source. Search engines that do not
|
|
780
984
|
execute JavaScript will not see the diagram image.
|
|
781
|
-
- **One diagram renders at a time.** The engine has module-level shared
|
|
782
|
-
many large diagrams renders them sequentially. This is a correctness
|
|
783
|
-
tuning knob.
|
|
985
|
+
- **One PlantUML diagram renders at a time.** The PlantUML engine has module-level shared
|
|
986
|
+
state, so a page with many large diagrams renders them sequentially. This is a correctness
|
|
987
|
+
requirement, not a tuning knob. Graphviz has no such constraint and is not queued.
|
|
988
|
+
- **Graphviz rendering blocks the main thread.** Viz.js lays out synchronously. A 300-edge
|
|
989
|
+
graph takes ~26 ms, but a 3 000-edge graph takes ~2.25 s and visibly freezes the page;
|
|
990
|
+
`graphviz.maxSourceBytes` is the guard. Rendering in a Web Worker would remove the ceiling
|
|
991
|
+
and is a possible future enhancement.
|
|
992
|
+
- **`theme` does not apply to Graphviz diagrams.** Graphviz has no dark palette; its colours
|
|
993
|
+
are adapted with CSS instead. See [Light and dark mode](#light-and-dark-mode).
|
|
784
994
|
- **`renderTimeoutMs` covers both loading and rendering.** On a very slow connection, the
|
|
785
995
|
8 MB download is subject to the same budget as a render.
|
|
786
996
|
- **Consuming the plugin through a `file:` link needs a webpack tweak.** See the entry in
|
|
@@ -917,11 +1127,15 @@ Then rebuild. If it persists, remove `node_modules/.cache` and `.docusaurus/` by
|
|
|
917
1127
|
## Further reading
|
|
918
1128
|
|
|
919
1129
|
- [`docs/architecture.md`](docs/architecture.md) — SSR boundary, asset loading, render queue,
|
|
920
|
-
caching, sanitization, dark
|
|
1130
|
+
caching, sanitization, and how each engine handles dark mode.
|
|
921
1131
|
- [`docs/adr/0001-theme-init-alias.md`](docs/adr/0001-theme-init-alias.md) — why the plugin
|
|
922
1132
|
wraps `@theme-init/`, not `@theme-original/`.
|
|
923
1133
|
- [`docs/adr/0002-render-to-string.md`](docs/adr/0002-render-to-string.md) — why the string
|
|
924
1134
|
API is used instead of the DOM `render()` API, and how invalid diagrams are detected.
|
|
1135
|
+
- [`docs/adr/0003-zoom-container-transform.md`](docs/adr/0003-zoom-container-transform.md) —
|
|
1136
|
+
why zoom transforms a wrapper rather than the SVG.
|
|
1137
|
+
- [`docs/adr/0004-graphviz-engine-reuse.md`](docs/adr/0004-graphviz-engine-reuse.md) — why DOT
|
|
1138
|
+
is rendered with the Graphviz already inside `@plantuml/core`, and what that couples us to.
|
|
925
1139
|
- [`CONTRIBUTING.md`](CONTRIBUTING.md)
|
|
926
1140
|
- [`SECURITY.md`](SECURITY.md)
|
|
927
1141
|
|
|
@@ -930,4 +1144,5 @@ Then rebuild. If it persists, remove `node_modules/.cache` and `.docusaurus/` by
|
|
|
930
1144
|
MIT. See [LICENSE](LICENSE).
|
|
931
1145
|
|
|
932
1146
|
[plantuml-core]: https://www.npmjs.com/package/@plantuml/core
|
|
1147
|
+
[graphviz]: https://graphviz.org/
|
|
933
1148
|
[dompurify]: https://github.com/cure53/DOMPurify
|
package/dist/assets.js
CHANGED
|
@@ -21,12 +21,29 @@ export function locatePlantUmlCore() {
|
|
|
21
21
|
const packageDir = path.dirname(packageJsonPath);
|
|
22
22
|
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
|
23
23
|
const version = typeof packageJson.version === 'string' ? packageJson.version : '0.0.0';
|
|
24
|
-
|
|
25
|
-
packageDir,
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
24
|
+
const files = [
|
|
25
|
+
path.join(packageDir, VIZ_SCRIPT_FILENAME),
|
|
26
|
+
path.join(packageDir, PLANTUML_MODULE_FILENAME),
|
|
27
|
+
];
|
|
28
|
+
files.forEach((file) => assertRuntimeFile(file, version));
|
|
29
|
+
return { packageDir, version, files };
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* Fails the build if a runtime asset is missing from the installed `@plantuml/core`.
|
|
33
|
+
*
|
|
34
|
+
* `viz-global.js` matters twice over: PlantUML needs it for layout, and it *is* the Graphviz
|
|
35
|
+
* engine this plugin renders DOT fences with. It is a declared `exports` entry of
|
|
36
|
+
* `@plantuml/core`, not a private file — but it is still shipped at PlantUML's discretion, so a
|
|
37
|
+
* routine dependency bump that dropped or renamed it would otherwise reach a reader's browser
|
|
38
|
+
* as a runtime load failure. Checking here turns that into a failed build with a name attached.
|
|
39
|
+
*
|
|
40
|
+
* See `docs/adr/0004-graphviz-engine-reuse.md`.
|
|
41
|
+
*/
|
|
42
|
+
function assertRuntimeFile(file, version) {
|
|
43
|
+
if (fs.existsSync(file))
|
|
44
|
+
return;
|
|
45
|
+
throw new Error(`[${PLUGIN_NAME}] '@plantuml/core@${version}' does not contain '${path.basename(file)}', ` +
|
|
46
|
+
'which this plugin serves as a runtime asset. This means the installed version of ' +
|
|
47
|
+
'@plantuml/core is not one this plugin supports. Pin a supported version, or open an ' +
|
|
48
|
+
'issue if the package has genuinely changed its layout.');
|
|
32
49
|
}
|
package/dist/constants.d.ts
CHANGED
|
@@ -14,9 +14,20 @@ export declare const PLUGIN_NAME = "docusaurus-plugin-plantuml-client";
|
|
|
14
14
|
export declare function assetsDirForVersion(coreVersion: string): string;
|
|
15
15
|
export declare const VIZ_SCRIPT_FILENAME = "viz-global.js";
|
|
16
16
|
export declare const PLANTUML_MODULE_FILENAME = "plantuml.js";
|
|
17
|
-
/**
|
|
17
|
+
/**
|
|
18
|
+
* `data-*` attribute names, kept in one place because tests and docs depend on them.
|
|
19
|
+
*
|
|
20
|
+
* The `data-plantuml-*` prefix is historical: it predates Graphviz support and is applied to
|
|
21
|
+
* every diagram this plugin renders, whatever the engine. Renaming it would break author CSS
|
|
22
|
+
* for no functional gain, so {@link DATA_ATTR.engine} was added alongside it instead —
|
|
23
|
+
* that is the attribute to select on when the two engines need different styling.
|
|
24
|
+
*/
|
|
18
25
|
export declare const DATA_ATTR: {
|
|
19
26
|
readonly diagram: "data-plantuml-diagram";
|
|
27
|
+
/** `"plantuml"` or `"graphviz"` — which engine produced this figure. */
|
|
28
|
+
readonly engine: "data-diagram-engine";
|
|
29
|
+
/** Graphviz layout engine (`dot`, `neato`, …). Absent on PlantUML figures. */
|
|
30
|
+
readonly layout: "data-diagram-layout";
|
|
20
31
|
readonly status: "data-plantuml-status";
|
|
21
32
|
readonly theme: "data-plantuml-theme";
|
|
22
33
|
/** `"true"` on the figure when the diagram is zoomable. */
|
package/dist/constants.js
CHANGED
|
@@ -16,9 +16,20 @@ export function assetsDirForVersion(coreVersion) {
|
|
|
16
16
|
}
|
|
17
17
|
export const VIZ_SCRIPT_FILENAME = 'viz-global.js';
|
|
18
18
|
export const PLANTUML_MODULE_FILENAME = 'plantuml.js';
|
|
19
|
-
/**
|
|
19
|
+
/**
|
|
20
|
+
* `data-*` attribute names, kept in one place because tests and docs depend on them.
|
|
21
|
+
*
|
|
22
|
+
* The `data-plantuml-*` prefix is historical: it predates Graphviz support and is applied to
|
|
23
|
+
* every diagram this plugin renders, whatever the engine. Renaming it would break author CSS
|
|
24
|
+
* for no functional gain, so {@link DATA_ATTR.engine} was added alongside it instead —
|
|
25
|
+
* that is the attribute to select on when the two engines need different styling.
|
|
26
|
+
*/
|
|
20
27
|
export const DATA_ATTR = {
|
|
21
28
|
diagram: 'data-plantuml-diagram',
|
|
29
|
+
/** `"plantuml"` or `"graphviz"` — which engine produced this figure. */
|
|
30
|
+
engine: 'data-diagram-engine',
|
|
31
|
+
/** Graphviz layout engine (`dot`, `neato`, …). Absent on PlantUML figures. */
|
|
32
|
+
layout: 'data-diagram-layout',
|
|
22
33
|
status: 'data-plantuml-status',
|
|
23
34
|
theme: 'data-plantuml-theme',
|
|
24
35
|
/** `"true"` on the figure when the diagram is zoomable. */
|