@matfsw/docusaurus-plantuml-plugin 1.3.0 → 1.3.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/CHANGELOG.md
CHANGED
|
@@ -7,6 +7,39 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
7
7
|
|
|
8
8
|
## [Unreleased]
|
|
9
9
|
|
|
10
|
+
## [1.3.1]
|
|
11
|
+
|
|
12
|
+
### Fixed
|
|
13
|
+
|
|
14
|
+
- **The toolbar's controls are drawn rather than typed** ([#21]). `⛶` U+26F6 SQUARE FOUR
|
|
15
|
+
CORNERS, the maximize icon, has no glyph in any font that ships with a stock Linux desktop,
|
|
16
|
+
so that control rendered as an empty box for an entire platform's readers — on the demo site
|
|
17
|
+
included. The other four only worked because DejaVu Sans happens to be installed, which a
|
|
18
|
+
minimal container image or a locked-down desktop does not promise, so all of them are now
|
|
19
|
+
inline SVG and the plugin depends on no font at all.
|
|
20
|
+
|
|
21
|
+
The source toggle's `</>` went the same way. It is ASCII and never had the glyph problem, but
|
|
22
|
+
left as text it would have been the one control still drawn in the page font, at a different
|
|
23
|
+
weight and optical size from its neighbours.
|
|
24
|
+
|
|
25
|
+
Nothing about the accessible surface changes: every button keeps its `aria-label`,
|
|
26
|
+
`aria-pressed`, `aria-expanded` and `aria-controls`, and the icons are `aria-hidden`. The
|
|
27
|
+
icons inherit `currentColor` and `1em`, so both colour modes and reader font scaling behave
|
|
28
|
+
exactly as before, with no CSS change. The `Copy` text button and the `⚠` error glyph are
|
|
29
|
+
unchanged.
|
|
30
|
+
|
|
31
|
+
If you worked around this with a `font-family` override on `[class*='toolbarButton']`, it is
|
|
32
|
+
now a harmless no-op and can be removed.
|
|
33
|
+
|
|
34
|
+
### Changed
|
|
35
|
+
|
|
36
|
+
- The example site records why its `onBrokenMarkdownLinks` stays at the top level rather than
|
|
37
|
+
moving to `markdown.hooks`, where Docusaurus 3.9 put it: 3.5's `markdown` schema rejects the
|
|
38
|
+
key outright, and CI builds that fixture against 3.5.2 — the oldest release this plugin's
|
|
39
|
+
peer range claims.
|
|
40
|
+
|
|
41
|
+
[#21]: https://github.com/matf/docusaurus-plantuml-plugin/issues/21
|
|
42
|
+
|
|
10
43
|
## [1.3.0]
|
|
11
44
|
|
|
12
45
|
### Added
|
|
@@ -347,7 +380,8 @@ Initial release.
|
|
|
347
380
|
opt-out.
|
|
348
381
|
- Plugin option validation that rejects unknown keys and out-of-range values at build time.
|
|
349
382
|
|
|
350
|
-
[Unreleased]: https://github.com/matf/docusaurus-plantuml-plugin/compare/v1.3.
|
|
383
|
+
[Unreleased]: https://github.com/matf/docusaurus-plantuml-plugin/compare/v1.3.1...HEAD
|
|
384
|
+
[1.3.1]: https://github.com/matf/docusaurus-plantuml-plugin/compare/v1.3.0...v1.3.1
|
|
351
385
|
[1.3.0]: https://github.com/matf/docusaurus-plantuml-plugin/compare/v1.2.0...v1.3.0
|
|
352
386
|
[1.2.0]: https://github.com/matf/docusaurus-plantuml-plugin/compare/v1.1.2...v1.2.0
|
|
353
387
|
[1.1.2]: https://github.com/matf/docusaurus-plantuml-plugin/compare/v1.1.1...v1.1.2
|
package/README.md
CHANGED
|
@@ -898,6 +898,12 @@ The runtime requires:
|
|
|
898
898
|
- `ResizeObserver` — optional; without it zoom still works, but the view is not re-clamped when
|
|
899
899
|
the column is resized
|
|
900
900
|
|
|
901
|
+
It requires **no particular fonts**. The toolbar's controls are inline SVG rather than symbol
|
|
902
|
+
characters, which they were until 1.3.1: `⛶` U+26F6 (maximize) has no glyph in any font a stock
|
|
903
|
+
Linux desktop ships, so it rendered as an empty box for those readers, and the rest only worked
|
|
904
|
+
where DejaVu Sans happened to be installed. The icons inherit `currentColor` and `1em`, so they
|
|
905
|
+
follow the colour mode and the reader's font size the way the characters did.
|
|
906
|
+
|
|
901
907
|
That is modern evergreen Chrome, Edge, Firefox and Safari. Internet Explorer is not
|
|
902
908
|
supported and will not be.
|
|
903
909
|
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The toolbar's icons, drawn rather than typed.
|
|
3
|
+
*
|
|
4
|
+
* These were symbol characters until 1.3.1, and one of them was invisible to a large group of
|
|
5
|
+
* readers: `⛶` U+26F6 SQUARE FOUR CORNERS has no glyph in any font that ships with a stock
|
|
6
|
+
* Linux desktop, so the maximize control rendered as a tofu box — on the demo site included.
|
|
7
|
+
* The other four only worked because DejaVu Sans happens to be installed, which a minimal
|
|
8
|
+
* container image or a locked-down corporate desktop does not promise. See issue #21.
|
|
9
|
+
*
|
|
10
|
+
* Two details keep the existing styling working with no CSS change at all:
|
|
11
|
+
*
|
|
12
|
+
* - `currentColor` inherits `.toolbarButton`'s `color: var(--ifm-font-color-base)`, so both
|
|
13
|
+
* colour modes keep working exactly as they did.
|
|
14
|
+
* - `1em` inherits its `font-size: 1rem`, so the icons size with the button — and with a
|
|
15
|
+
* reader who has scaled their font up — the way the characters used to.
|
|
16
|
+
*
|
|
17
|
+
* Every icon is `aria-hidden`: each `<button>` already carries an `aria-label`, which is the
|
|
18
|
+
* accessible name. Nothing here is announced.
|
|
19
|
+
*/
|
|
20
|
+
import type { ReactElement } from 'react';
|
|
21
|
+
/** Replaces `−` U+2212. */
|
|
22
|
+
export declare function ZoomOutIcon(): ReactElement;
|
|
23
|
+
/** Replaces `+`. */
|
|
24
|
+
export declare function ZoomInIcon(): ReactElement;
|
|
25
|
+
/** Replaces `⟲` U+27F2: a circular arrow, open at the top right where the arrowhead sits. */
|
|
26
|
+
export declare function ResetZoomIcon(): ReactElement;
|
|
27
|
+
/** Replaces `⛶` U+26F6, the character that had no glyph. */
|
|
28
|
+
export declare function MaximizeIcon(): ReactElement;
|
|
29
|
+
/** Replaces `✕` U+2715, shown in place of maximize while the diagram fills the viewport. */
|
|
30
|
+
export declare function CloseIcon(): ReactElement;
|
|
31
|
+
/**
|
|
32
|
+
* Replaces the literal `</>` of the source toggle.
|
|
33
|
+
*
|
|
34
|
+
* ASCII, so it never had the glyph problem — but left as text it would be the one control in
|
|
35
|
+
* the row still drawn in the page font, at a different weight and optical size from its
|
|
36
|
+
* neighbours, and moving with the reader's font settings while they stayed put.
|
|
37
|
+
*/
|
|
38
|
+
export declare function SourceIcon(): ReactElement;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
const iconProps = {
|
|
3
|
+
viewBox: '0 0 16 16',
|
|
4
|
+
width: '1em',
|
|
5
|
+
height: '1em',
|
|
6
|
+
fill: 'none',
|
|
7
|
+
stroke: 'currentColor',
|
|
8
|
+
strokeWidth: 1.5,
|
|
9
|
+
strokeLinecap: 'round',
|
|
10
|
+
strokeLinejoin: 'round',
|
|
11
|
+
'aria-hidden': true,
|
|
12
|
+
// Keeps the SVG out of the tab order in browsers that made it focusable by default.
|
|
13
|
+
focusable: false,
|
|
14
|
+
};
|
|
15
|
+
/** Replaces `−` U+2212. */
|
|
16
|
+
export function ZoomOutIcon() {
|
|
17
|
+
return (_jsx("svg", { ...iconProps, children: _jsx("path", { d: "M3 8h10" }) }));
|
|
18
|
+
}
|
|
19
|
+
/** Replaces `+`. */
|
|
20
|
+
export function ZoomInIcon() {
|
|
21
|
+
return (_jsx("svg", { ...iconProps, children: _jsx("path", { d: "M8 3v10M3 8h10" }) }));
|
|
22
|
+
}
|
|
23
|
+
/** Replaces `⟲` U+27F2: a circular arrow, open at the top right where the arrowhead sits. */
|
|
24
|
+
export function ResetZoomIcon() {
|
|
25
|
+
return (_jsxs("svg", { ...iconProps, children: [_jsx("path", { d: "M13 8A5 5 0 1 1 11.4 4.3" }), _jsx("path", { d: "M13 2v3h-3" })] }));
|
|
26
|
+
}
|
|
27
|
+
/** Replaces `⛶` U+26F6, the character that had no glyph. */
|
|
28
|
+
export function MaximizeIcon() {
|
|
29
|
+
return (_jsx("svg", { ...iconProps, children: _jsx("path", { d: "M2 6V2h4M14 6V2h-4M2 10v4h4M14 10v4h-4" }) }));
|
|
30
|
+
}
|
|
31
|
+
/** Replaces `✕` U+2715, shown in place of maximize while the diagram fills the viewport. */
|
|
32
|
+
export function CloseIcon() {
|
|
33
|
+
return (_jsx("svg", { ...iconProps, children: _jsx("path", { d: "M4 4l8 8M12 4l-8 8" }) }));
|
|
34
|
+
}
|
|
35
|
+
/**
|
|
36
|
+
* Replaces the literal `</>` of the source toggle.
|
|
37
|
+
*
|
|
38
|
+
* ASCII, so it never had the glyph problem — but left as text it would be the one control in
|
|
39
|
+
* the row still drawn in the page font, at a different weight and optical size from its
|
|
40
|
+
* neighbours, and moving with the reader's font settings while they stayed put.
|
|
41
|
+
*/
|
|
42
|
+
export function SourceIcon() {
|
|
43
|
+
return (_jsx("svg", { ...iconProps, children: _jsx("path", { d: "M6 4L2 8l4 4M10 4l4 4-4 4" }) }));
|
|
44
|
+
}
|
|
@@ -7,6 +7,7 @@ import { PlantUmlError } from '../../runtime/errors.js';
|
|
|
7
7
|
import { renderGraphvizDiagram } from '../../runtime/graphvizRenderer.js';
|
|
8
8
|
import { renderDiagram } from '../../runtime/renderer.js';
|
|
9
9
|
import { usePlantUmlConfig } from '../usePlantUmlConfig.js';
|
|
10
|
+
import { CloseIcon, MaximizeIcon, ResetZoomIcon, SourceIcon, ZoomInIcon, ZoomOutIcon, } from './icons.js';
|
|
10
11
|
import { useZoomPan } from './useZoomPan.js';
|
|
11
12
|
import styles from './styles.module.css';
|
|
12
13
|
/**
|
|
@@ -206,7 +207,7 @@ export default function PlantUmlDiagram({ source, title, language, engine = 'pla
|
|
|
206
207
|
// Sanitized above unless `sanitizeSvg: false` was explicitly opted into.
|
|
207
208
|
dangerouslySetInnerHTML: { __html: state.svg } }));
|
|
208
209
|
const copyControl = sourceAvailable && sourceOpen && state.status === 'ready' && (_jsx("button", { type: "button", className: `${styles.toolbarButton} ${styles.toolbarTextButton}`, "aria-label": `Copy ${engineName} source to clipboard`, onClick: copySource, children: "Copy" }));
|
|
209
|
-
const sourceToggle = sourceAvailable && (_jsx("button", { type: "button", className: styles.toolbarButton, "aria-label": sourceOpen ? 'Hide diagram source' : 'Show diagram source', "aria-expanded": sourceOpen, "aria-controls": sourcePanelId, onClick: () => setSourceOpen((open) => !open), children: _jsx(
|
|
210
|
+
const sourceToggle = sourceAvailable && (_jsx("button", { type: "button", className: styles.toolbarButton, "aria-label": sourceOpen ? 'Hide diagram source' : 'Show diagram source', "aria-expanded": sourceOpen, "aria-controls": sourcePanelId, onClick: () => setSourceOpen((open) => !open), children: _jsx(SourceIcon, {}) }));
|
|
210
211
|
/**
|
|
211
212
|
* The source *replaces the diagram in its own frame* rather than appearing beneath it.
|
|
212
213
|
*
|
|
@@ -224,7 +225,7 @@ export default function PlantUmlDiagram({ source, title, language, engine = 'pla
|
|
|
224
225
|
[DATA_ATTR.theme]: dark ? 'dark' : 'light',
|
|
225
226
|
...(interactive ? { [DATA_ATTR.interactive]: 'true' } : {}),
|
|
226
227
|
...(zoom.maximized ? { [DATA_ATTR.maximized]: 'true' } : {}),
|
|
227
|
-
...(sourceOpen ? { [DATA_ATTR.sourceOpen]: 'true' } : {}), children: [state.status === 'ready' && state.svg !== null && !interactive && canvas, state.status === 'ready' && state.svg !== null && !interactive && sourceView, state.status === 'ready' && state.svg !== null && !interactive && sourceAvailable && (_jsxs("div", { className: styles.plainToolbar, role: "group", "aria-label": `${label} source controls`, children: [sourceToggle, copyControl] })), state.status === 'ready' && state.svg !== null && interactive && (_jsxs("div", { ref: zoom.stageRef, className: zoom.maximized ? `${styles.stage} ${styles.maximized}` : styles.stage, children: [_jsxs("div", { className: styles.stageBody, children: [_jsx("div", { ref: zoom.viewportRef, className: sourceOpen ? `${styles.viewport} ${styles.invisibleView}` : styles.viewport, tabIndex: sourceOpen ? -1 : 0, "aria-describedby": hintId, "aria-keyshortcuts": "Plus Minus 0 ArrowUp ArrowDown ArrowLeft ArrowRight", onKeyDown: zoom.onKeyDown, [DATA_ATTR.zoom]: '1', children: _jsx("div", { ref: zoom.layerRef, className: styles.layer, children: canvas }) }), sourceView] }), _jsxs("div", { className: styles.toolbar, role: "group", "aria-label": `${label} zoom controls`, children: [!sourceOpen && (_jsx("button", { type: "button", className: styles.toolbarButton, "aria-label": "Zoom out", onClick: zoom.zoomOut, children: _jsx(
|
|
228
|
+
...(sourceOpen ? { [DATA_ATTR.sourceOpen]: 'true' } : {}), children: [state.status === 'ready' && state.svg !== null && !interactive && canvas, state.status === 'ready' && state.svg !== null && !interactive && sourceView, state.status === 'ready' && state.svg !== null && !interactive && sourceAvailable && (_jsxs("div", { className: styles.plainToolbar, role: "group", "aria-label": `${label} source controls`, children: [sourceToggle, copyControl] })), state.status === 'ready' && state.svg !== null && interactive && (_jsxs("div", { ref: zoom.stageRef, className: zoom.maximized ? `${styles.stage} ${styles.maximized}` : styles.stage, children: [_jsxs("div", { className: styles.stageBody, children: [_jsx("div", { ref: zoom.viewportRef, className: sourceOpen ? `${styles.viewport} ${styles.invisibleView}` : styles.viewport, tabIndex: sourceOpen ? -1 : 0, "aria-describedby": hintId, "aria-keyshortcuts": "Plus Minus 0 ArrowUp ArrowDown ArrowLeft ArrowRight", onKeyDown: zoom.onKeyDown, [DATA_ATTR.zoom]: '1', children: _jsx("div", { ref: zoom.layerRef, className: styles.layer, children: canvas }) }), sourceView] }), _jsxs("div", { className: styles.toolbar, role: "group", "aria-label": `${label} zoom controls`, children: [!sourceOpen && (_jsx("button", { type: "button", className: styles.toolbarButton, "aria-label": "Zoom out", onClick: zoom.zoomOut, children: _jsx(ZoomOutIcon, {}) })), !sourceOpen && (_jsx("button", { type: "button", className: styles.toolbarButton, "aria-label": "Zoom in", onClick: zoom.zoomIn, children: _jsx(ZoomInIcon, {}) })), !sourceOpen && (_jsx("button", { type: "button", className: styles.toolbarButton, "aria-label": "Reset zoom", onClick: zoom.reset, children: _jsx(ResetZoomIcon, {}) })), _jsx("button", { type: "button", className: styles.toolbarButton, "aria-label": "Maximize diagram", "aria-pressed": zoom.maximized, onClick: zoom.toggleMaximize, children: zoom.maximized ? _jsx(CloseIcon, {}) : _jsx(MaximizeIcon, {}) }), sourceToggle, copyControl, _jsx("span", { ref: zoom.readoutRef, className: sourceOpen ? `${styles.readout} ${styles.hiddenView}` : styles.readout, "aria-hidden": "true", children: "100%" })] })] })), state.status === 'ready' && state.svg !== null && interactive && (_jsx("p", { id: hintId, className: styles.visuallyHidden, children: "Zoomable diagram. Use the zoom controls, or press plus and minus to zoom, the arrow keys to pan, and zero to reset." })), state.status !== 'ready' && state.status !== 'error' && (
|
|
228
229
|
// `aria-busy` on the figure already conveys progress; announcing every phase change
|
|
229
230
|
// would make a page with several diagrams unusable with a screen reader.
|
|
230
231
|
_jsxs("div", { className: styles.placeholder, children: [_jsx("span", { className: styles.spinner, "aria-hidden": "true" }), _jsxs("span", { children: [state.status === 'loading' ? `Loading ${engineName} runtime…` : null, state.status === 'rendering' ? `Rendering ${label}…` : null, state.status === 'idle' ? `${label} (waiting to render)` : null] })] })), state.status === 'error' && (_jsxs("div", { className: styles.error, role: "alert", children: [_jsxs("p", { className: styles.errorHeading, children: [_jsx("span", { className: styles.errorIcon, "aria-hidden": "true", children: "\u26A0" }), _jsxs("span", { children: ["Error: ", engineName, " diagram could not be rendered"] })] }), _jsx("pre", { className: styles.errorMessage, children: state.error }), config?.options.showSourceOnError !== false && (_jsxs("details", { className: styles.errorDetails, children: [_jsx("summary", { children: "Show diagram source" }), _jsx("pre", { className: styles.source, children: source })] }))] })), title !== undefined && _jsx("figcaption", { className: styles.caption, children: title }), _jsx("noscript", { dangerouslySetInnerHTML: {
|
package/package.json
CHANGED