feat(ui): @plannotator/ui 0.40.0 with Mermaid 12, lazy loading, and theme-aware diagrams; core 0.25.3 (#1557)
* chore(ui): mermaid 12.0.0 (exact), ELK layout by default
Bump @plannotator/ui's mermaid dependency from ^11.17.2 to an exact 12.0.0
and regenerate bun.lock. Mermaid 12 lays flowchart, state, class, ER and
requirement diagrams out with ELK by default (elkjs is now bundled in
mermaid itself), targets Safari 17.4+ / ES2024, and drops the legacy
flowchart/class/state diagram ids. We take 12's defaults rather than
pinning the 11 ones. No API or type changes were needed: MERMAID_CONFIG
(securityLevel 'strict') and the theme mapping apply unchanged, every
generated SVG id keeps its 11.x shape, and the katex import Mermaid makes
for $$ labels is the same call (the math-slot bridge is untouched).
The visual-explainer skill's render gate now expects Mermaid 12.
* feat(editor): load the Mermaid runtime lazily on the first diagram
Drop the eager registration import (@plannotator/ui/utils/mermaid-eager)
from the plan editor entry. Since Mermaid 12 the runtime plus ELK is about
1.8 MB larger, so a plan with no diagram must not pay for it: the block now
resolves the runtime through utils/mermaid's own import('mermaid') on the
first MermaidBlock render. In the chunked share-portal build that moves
mermaid.core (~640 KB) out of the entry chunk; the single-file builds still
inline it through inlineDynamicImports, so nothing changes there except
Mermaid 12's own size.
MermaidBlock shows the source fence under a role=status "Rendering
diagram" line until the first render lands, never the error panel, and
applyMermaidTheme is keyed on the runtime object so the lazily loaded
runtime is themed on its first render like an eagerly registered one.
mermaid-eager stays exported for hosts that want startup registration.
tests/entry-assets.test.ts now asserts the eager Mermaid marker is absent
from both app bundles; DiagramBlock.lazyRetry.test.tsx pins the pending
state.
* docs(ui): HANDOFF 0.40.0 section for Mermaid 12 and the lazy runtime
Add the "Mermaid 12 (0.40.0)" section hosts need to adopt the bump: ELK
layout by default and the other 12 changes we take, the concrete SVG id
patterns (unchanged 11 -> 12, per family), the g.edgePaths declaration-order
change and the select-by-id rule, the Safari 17.4+ / ES2024 floor, the
lazy-load contract (the plan editor no longer imports mermaid-eager; how a
host keeps startup registration; the pending state; measured chunk and
single-file sizes), the theming contract with and without tokens, the 0.40
contrast re-sweep (104 combinations, 0 failures), and the publish order
core 0.25.3 -> ui 0.40.0. Retitle the theme and element-context sections
to 0.40.0, fold the two unreleased publishing bullets into the current
pair, and update the 0.32.0 lazy-renderer text, README and AGENTS for the
new policy.
* chore(core): bump @plannotator/core to 0.25.3
Carries the #1549 html-anchor element-context exports (parseHtmlElementContext,
MAX_ELEMENT_CONTEXT_BYTES, MAX_PAGE_URL_LENGTH) that @plannotator/ui 0.40.0
imports. Publish this before ui 0.40.0.
* chore(ui): bump @plannotator/ui to 0.40.0 on core 0.25.3
Mermaid 12.0.0 (exact), lazy runtime loading in the plan editor, the
theme-aware diagram mapping from #1556, and the #1549 element-context host
seam. Pins @plannotator/core 0.25.3 exactly; bun.lock records both
workspace versions. Publish core 0.25.3 first, then this.
* chore: pin lodash-es 4.18.1 over chevrotain's vulnerable exact pin
Mermaid 12 pulls chevrotain 11.1.2 (via langium), which pins lodash-es
exactly 4.17.23 (CVE-2026-4800 high, CVE-2026-2950 medium), so the
workspace resolved a second, vulnerable copy beside the 4.18.1 that
dagre-d3-es already resolves. A root "overrides" entry forces every
lodash-es range to 4.18.1 (published 2026-04-01, past the 7-day gate);
bun.lock now records a single lodash-es@4.18.1. chevrotain still parses
every diagram grammar under it: all 15 eval diagrams render with zero
errors in the built plan editor, typecheck, the ui utils and MermaidBlock
tests, and the package smoke pass, and the built bundles are byte-for-byte
the same size. M
Michael Ramos committed
2a51b26e1bfa394207b26f08371795465fd3e18f
Parent: a42aefc
Committed by GitHub <noreply@github.com>
on 9/17/2026, 8:13:08 AM