fix: improve zenuml print rendering, sizing, and syntax resilience

This commit is contained in:
MrCoder
2026-04-22 21:30:02 +10:00
parent 2fe6e55d1a
commit 45a9498175
6 changed files with 298 additions and 164 deletions
+10
View File
@@ -0,0 +1,10 @@
---
'mermaid': patch
'@mermaid-js/mermaid-zenuml': patch
---
fix: update @zenuml/core to v3.46.11 with native SVG renderer
- Fix vertical lifelines disappearing when printing (#6004)
- Fix SVG dimensions exceeding container boundaries (#7266)
- Fix invalid ZenUML syntax freezing the editor (#7154)
+1 -1
View File
@@ -33,7 +33,7 @@
],
"license": "MIT",
"dependencies": {
"@zenuml/core": "^3.41.6"
"@zenuml/core": "^3.47.0"
},
"devDependencies": {
"mermaid": "workspace:^"
+18
View File
@@ -0,0 +1,18 @@
// Override @zenuml/core types for nodenext module resolution.
// The package lacks "type": "module" so TS treats it as CJS,
// rejecting named imports. This declaration fixes that.
declare module '@zenuml/core' {
export interface RenderOptions {
theme?: 'theme-default' | 'theme-mermaid';
}
export interface RenderResult {
svg: string;
innerSvg: string;
width: number;
height: number;
viewBox: string;
}
export function renderToSvg(code: string, options?: RenderOptions): RenderResult;
}
@@ -0,0 +1,98 @@
import { vi } from 'vitest';
import { calculateSvgSizeAttrs } from './zenumlRenderer.js';
vi.mock('@zenuml/core', () => ({
renderToSvg: vi.fn((code: string) => ({
innerSvg: `<text>${code.trim()}</text>`,
width: 400,
height: 300,
viewBox: '0 0 400 300',
})),
}));
vi.mock('./mermaidUtils.js', () => ({
log: { info: vi.fn(), error: vi.fn(), debug: vi.fn(), warn: vi.fn() },
getConfig: vi.fn(() => ({
securityLevel: 'loose',
sequence: { useMaxWidth: true },
})),
}));
describe('calculateSvgSizeAttrs', function () {
it('should return responsive width when useMaxWidth is true', function () {
const attrs = calculateSvgSizeAttrs(133, 392, true);
expect(attrs.get('width')).toEqual('100%');
expect(attrs.get('style')).toEqual('max-width: 133px;');
expect(attrs.has('height')).toBe(false);
});
it('should return absolute dimensions when useMaxWidth is false', function () {
const attrs = calculateSvgSizeAttrs(133, 392, false);
expect(attrs.get('width')).toEqual('133');
expect(attrs.get('height')).toEqual('392');
expect(attrs.has('style')).toBe(false);
});
});
describe('draw', () => {
beforeEach(() => {
vi.clearAllMocks();
document.body.innerHTML = '';
});
it('should render SVG content into the target element', async () => {
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.id = 'test-id';
document.body.appendChild(svg);
const { draw } = await import('./zenumlRenderer.js');
await draw('zenuml\n Alice->Bob: hello', 'test-id');
expect(svg.innerHTML).toContain('Alice-');
expect(svg.getAttribute('viewBox')).toBe('0 0 400 300');
expect(svg.getAttribute('width')).toBe('100%');
expect(svg.getAttribute('style')).toBe('max-width: 400px;');
});
it('should set absolute dimensions when useMaxWidth is false', async () => {
const { getConfig } = await import('./mermaidUtils.js');
vi.mocked(getConfig).mockReturnValue({
securityLevel: 'loose',
sequence: { useMaxWidth: false },
});
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.id = 'test-abs';
document.body.appendChild(svg);
const { draw } = await import('./zenumlRenderer.js');
await draw('zenuml\n A->B: msg', 'test-abs');
expect(svg.getAttribute('width')).toBe('400');
expect(svg.getAttribute('height')).toBe('300');
});
it('should handle missing SVG element gracefully', async () => {
const { draw } = await import('./zenumlRenderer.js');
const { log } = await import('./mermaidUtils.js');
await draw('zenuml\n A->B: msg', 'nonexistent');
expect(log.error).toHaveBeenCalledWith('Cannot find svg element');
});
it('should strip the zenuml prefix before rendering', async () => {
const { renderToSvg } = await import('@zenuml/core');
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
svg.id = 'test-strip';
document.body.appendChild(svg);
const { draw } = await import('./zenumlRenderer.js');
await draw('zenuml\n Alice->Bob: hello', 'test-strip');
expect(renderToSvg).toHaveBeenCalledWith('\n Alice->Bob: hello');
});
});
+68 -47
View File
@@ -1,65 +1,86 @@
import { renderToSvg } from '@zenuml/core';
import { getConfig, log } from './mermaidUtils.js';
import ZenUml from '@zenuml/core';
const regexp = /^\s*zenuml/;
// Create a Zen UML container outside the svg first for rendering, otherwise the Zen UML diagram cannot be rendered properly
function createTemporaryZenumlContainer(id: string) {
const container = document.createElement('div');
container.id = `container-${id}`;
container.style.display = 'flex';
container.innerHTML = `<div id="zenUMLApp-${id}"></div>`;
const app = container.querySelector(`#zenUMLApp-${id}`)!;
return { container, app };
}
export const calculateSvgSizeAttrs = (
width: number,
height: number,
useMaxWidth: boolean
): Map<string, string> => {
const attrs = new Map<string, string>();
// Create a foreignObject to wrap the Zen UML container in the svg
function createForeignObject(id: string) {
const foreignObject = document.createElementNS('http://www.w3.org/2000/svg', 'foreignObject');
foreignObject.setAttribute('x', '0');
foreignObject.setAttribute('y', '0');
foreignObject.setAttribute('width', '100%');
foreignObject.setAttribute('height', '100%');
const { container, app } = createTemporaryZenumlContainer(id);
foreignObject.appendChild(container);
return { foreignObject, container, app };
}
if (useMaxWidth) {
attrs.set('width', '100%');
attrs.set('style', `max-width: ${width}px;`);
} else {
attrs.set('width', String(width));
attrs.set('height', String(height));
}
return attrs;
};
/**
* Draws a Zen UML in the tag with id: id based on the graph definition in text.
* Resolves the root document and SVG element, handling sandbox mode.
* Follows the same pattern as mermaid's selectSvgElement utility.
*/
const selectSvgElement = (id: string): SVGSVGElement | null => {
const { securityLevel } = getConfig();
let root: Document = document;
if (securityLevel === 'sandbox') {
const sandboxElement = document.querySelector<HTMLIFrameElement>(`#i${id}`);
root = sandboxElement?.contentDocument ?? document;
}
return root.querySelector<SVGSVGElement>(`#${id}`);
};
const configureSvgSize = (
svgEl: SVGSVGElement,
width: number,
height: number,
useMaxWidth: boolean
) => {
const attrs = calculateSvgSizeAttrs(width, height, useMaxWidth);
svgEl.removeAttribute('height');
svgEl.style.removeProperty('max-width');
for (const [attr, value] of attrs) {
svgEl.setAttribute(attr, value);
}
};
/**
* Draws a ZenUML diagram in the SVG element with id: id based on the
* graph definition in text, using native SVG rendering.
*
* @param text - The text of the diagram
* @param id - The id of the diagram which will be used as a DOM element id¨
* @param id - The id of the diagram which will be used as a DOM element id
*/
export const draw = async function (text: string, id: string) {
log.info('draw with Zen UML renderer', ZenUml);
export const draw = function (text: string, id: string): Promise<void> {
log.info('draw with ZenUML native SVG renderer');
text = text.replace(regexp, '');
const { securityLevel } = getConfig();
// Handle root and Document for when rendering in sandbox mode
let sandboxElement: HTMLIFrameElement | null = null;
if (securityLevel === 'sandbox') {
sandboxElement = document.getElementById('i' + id) as HTMLIFrameElement;
const code = text.replace(regexp, '');
const config = getConfig();
const useMaxWidth = config.sequence?.useMaxWidth ?? true;
const svgEl = selectSvgElement(id);
if (!svgEl) {
log.error('Cannot find svg element');
return Promise.resolve();
}
const root = securityLevel === 'sandbox' ? sandboxElement?.contentWindow?.document : document;
const result = renderToSvg(code);
const svgContainer = root?.querySelector(`svg#${id}`);
configureSvgSize(svgEl, result.width, result.height, useMaxWidth);
svgEl.setAttribute('viewBox', result.viewBox);
svgEl.innerHTML = result.innerSvg;
if (!root || !svgContainer) {
log.error('Cannot find root or svgContainer');
return;
}
const { foreignObject, container, app } = createForeignObject(id);
svgContainer.appendChild(foreignObject);
const zenuml = new ZenUml(app);
// default is a theme name. More themes to be added and will be configurable in the future
await zenuml.render(text, { theme: 'default', mode: 'static' });
const { width, height } = window.getComputedStyle(container);
log.debug('zenuml diagram size', width, height);
svgContainer.setAttribute('style', `width: ${width}; height: ${height};`);
return Promise.resolve();
};
export default {
+103 -116
View File
@@ -474,8 +474,8 @@ importers:
packages/mermaid-zenuml:
dependencies:
'@zenuml/core':
specifier: ^3.41.6
version: 3.41.6(@babel/core@7.29.0)(@babel/template@7.28.6)
specifier: ^3.47.0
version: 3.47.2(@babel/core@7.29.0)(@babel/template@7.28.6)
devDependencies:
mermaid:
specifier: workspace:^
@@ -2469,8 +2469,8 @@ packages:
'@hapi/topo@6.0.2':
resolution: {integrity: sha512-KR3rD5inZbGMrHmgPxsJ9dbi6zEK+C3ZwUwTa+eMwWLz7oijWUTWD2pMSNNYJAU6Qq+65NkxXjqHr/7LM2Xkqg==}
'@headlessui/react@2.2.8':
resolution: {integrity: sha512-vkiZulDC0lFeTrZTbA4tHvhZHvkUb2PFh5xJ1BvWAZdRK0fayMKO1QEO4inWkXxK1i0I1rcwwu1d6mo0K7Pcbw==}
'@headlessui/react@2.2.10':
resolution: {integrity: sha512-5pVLNK9wlpxTUTy9GpgbX/SdcRh+HBnPktjM2wbiLTH4p+2EPHBO1aoSryUCuKUIItdDWO9ITlhUL8UnUN/oIA==}
engines: {node: '>=10'}
peerDependencies:
react: ^18 || ^19 || ^19.0.0-rc
@@ -4040,8 +4040,8 @@ packages:
'@xtuc/long@4.2.2':
resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==}
'@zenuml/core@3.41.6':
resolution: {integrity: sha512-j+yHQb7W9I8ytyvbx+Wht66lsBqcWdbaBpyhOwVsny8m3ohVKNQhayJ7rANHKo6DAtdPnCexzOuttKciySnztA==}
'@zenuml/core@3.47.2':
resolution: {integrity: sha512-aDw1/H06L8HitKYeZoXtw7/HmfVcVHIzdHyoC+6TBYfy6BgfHbfY52a3ONi6/NwMLh6LQZ7IWruWUmlcbi8vNQ==}
engines: {node: '>=20'}
JSONSelect@0.4.0:
@@ -4769,8 +4769,8 @@ packages:
resolution: {integrity: sha512-9vEt7gE16EW7Eu7pvZnR0abW9z6ufzhXxGXZEVU9IqPdlsUiMwJeJfRtq0zePUmnbHGT9zajca7mX8zgoayo4A==}
engines: {node: '>=12.20'}
color-string@2.1.2:
resolution: {integrity: sha512-RxmjYxbWemV9gKu4zPgiZagUxbH3RQpEIO77XoSSX0ivgABDZ+h8Zuash/EMFLTI4N9QgFPOJ6JQpPZKFxa+dA==}
color-string@2.1.4:
resolution: {integrity: sha512-Bb6Cq8oq0IjDOe8wJmi4JeNn763Xs9cfrBcaylK1tPypWzyoy2G3l90v9k64kjphl/ZJjPIShFztenRomi8WTg==}
engines: {node: '>=18'}
colorette@2.0.20:
@@ -6544,8 +6544,8 @@ packages:
resolution: {integrity: sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==}
engines: {node: '>= 4'}
immer@10.1.3:
resolution: {integrity: sha512-tmjF/k8QDKydUlm3mZU+tjM6zeq9/fFpPqH9SzWmBnVVKsPBg/V66qsMwb3/Bo90cgUN+ghdVBess+hPsxUyRw==}
immer@10.2.0:
resolution: {integrity: sha512-d/+XTN3zfODyjr89gM3mPq1WNX2B8pYsu7eORitdwyA2sBubnTl3laYlBk4sXY5FUa5qTZGBDPJICVbvqzjlbw==}
import-fresh@3.3.1:
resolution: {integrity: sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==}
@@ -7077,8 +7077,8 @@ packages:
resolution: {integrity: sha512-IiQpRyypSnLisQf3PwuN2eIHAsAIGZIrLZkd4zdvIar2bDyhM91ubRjy8a3eYablXsh9BeI/c7dmPYHca5qtoA==}
engines: {node: '>= 20'}
jotai@2.14.0:
resolution: {integrity: sha512-JQkNkTnqjk1BlSUjHfXi+pGG/573bVN104gp6CymhrWDseZGDReTNniWrLhJ+zXbM6pH+82+UNJ2vwYQUkQMWQ==}
jotai@2.19.1:
resolution: {integrity: sha512-sqm9lVZiqBHZH8aSRk32DSiZDHY3yUIlulXYn9GQj7/LvoUdYXSMti7ZPJGo+6zjzKFt5a25k/I6iBCi43PJcw==}
engines: {node: '>=12.20.0'}
peerDependencies:
'@babel/core': '>=7.0.0'
@@ -8456,16 +8456,9 @@ packages:
quote-unquote@1.0.0:
resolution: {integrity: sha512-twwRO/ilhlG/FIgYeKGFqyHhoEhqgnKVkcmqMKi2r524gz3ZbDTcyFt38E9xjJI2vT+KbRNHVbnJ/e0I25Azwg==}
radash@12.1.1:
resolution: {integrity: sha512-h36JMxKRqrAxVD8201FrCpyeNuUY9Y5zZwujr20fFO77tpUtGa6EZzfKw/3WaiBX95fq7+MpsuMLNdSnORAwSA==}
engines: {node: '>=14.18.0'}
railroad-diagrams@1.0.0:
resolution: {integrity: sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==}
ramda@0.28.0:
resolution: {integrity: sha512-9QnLuG/kPVgWvMQ4aODhsBUFKOUmnbUnsSXACv+NCQZcHbeb+v8Lodp8OVxtRULN1/xOyYLLaL6npE6dMq5QTA==}
ramda@0.29.1:
resolution: {integrity: sha512-OfxIeWzd4xdUNxlWhgFazxsA/nl3mS4/jGZI5n00uWOoSSFRhC1b6gl6xvmzUamgmqELraWp0J/qqVlXYPDPyA==}
@@ -8488,16 +8481,16 @@ packages:
resolution: {integrity: sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==}
hasBin: true
react-dom@19.1.1:
resolution: {integrity: sha512-Dlq/5LAZgF0Gaz6yiqZCf6VCcZs1ghAJyrsu84Q/GT0gV+mCxbfmKNoGRKBYMJ8IEdGPqu49YWXD02GCknEDkw==}
react-dom@19.2.5:
resolution: {integrity: sha512-J5bAZz+DXMMwW/wV3xzKke59Af6CHY7G4uYLN1OvBcKEsWOs4pQExj86BBKamxl/Ik5bx9whOrvBlSDfWzgSag==}
peerDependencies:
react: ^19.1.1
react: ^19.2.5
react-is@18.3.1:
resolution: {integrity: sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==}
react@19.1.1:
resolution: {integrity: sha512-w8nqGImo45dmMIfljjMwOGtbmC/mk4CMYhWIicdSflH91J9TyCyczcPFXJzrZ/ZXcgGRFeP6BU0BEJTw6tZdfQ==}
react@19.2.5:
resolution: {integrity: sha512-llUJLzz1zTUBrskt2pwZgLq59AemifIftw4aB7JxOqf1HY2FDaGDxgwpAPVzHU1kdWabH7FauP4i1oEeer2WCA==}
engines: {node: '>=0.10.0'}
read-cache@1.0.0:
@@ -8785,8 +8778,8 @@ packages:
resolution: {integrity: sha512-xAg7SOnEhrm5zI3puOOKyy1OMcMlIJZYNJY7xLBwSze0UjhPLnWfj2GF2EpT0jmzaJKIWKHLsaSSajf35bcYnA==}
engines: {node: '>=v12.22.7'}
scheduler@0.26.0:
resolution: {integrity: sha512-NlHwttCI/l5gCPR3D1nNXtWABUmBwvZpEQiD4IXSbIDq8BzLIK/7Ir5gTFSGZDUu37K5cMNp0hFtzO38sC7gWA==}
scheduler@0.27.0:
resolution: {integrity: sha512-eNv+WrVbKu1f3vbYJT/xtiF5syA5HPIMtf9IgY/nKg0sWqzAUEvqY/xm7OcZc/qafLx/iO9FgOmeSAp4v5ti/Q==}
schema-utils@4.3.2:
resolution: {integrity: sha512-Gn/JaSk/Mt9gYubxTtSn/QCV4em9mpAPiR1rqy/Ocu19u/G9J5WWdNoUT4SiV6mFC3y6cxyFcFwdzPM3FgxGAQ==}
@@ -9255,11 +9248,11 @@ packages:
tabbable@6.2.0:
resolution: {integrity: sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew==}
tailwind-merge@3.3.1:
resolution: {integrity: sha512-gBXpgUm/3rp1lMZZrM/w7D8GKqshif0zAymAhbCyIt8KMe+0v9DQ7cdYLR4FHH/cKpdTXb+A/tKKU3eolfsI+g==}
tailwind-merge@3.5.0:
resolution: {integrity: sha512-I8K9wewnVDkL1NTGoqWmVEIlUcB9gFriAEkXkfCjX5ib8ezGxtR3xD7iZIxrfArjEsH7F1CHD4RFUtxefdqV/A==}
tailwindcss@3.4.17:
resolution: {integrity: sha512-w33E2aCvSDP0tW9RZuNXadXlkHXqFzSkQew/aIa2i/Sj8fThxwovwlXHSPXTbAHwEIhBFXAedUhP2tueAKP8Og==}
tailwindcss@3.4.19:
resolution: {integrity: sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==}
engines: {node: '>=14.0.0'}
hasBin: true
@@ -12097,7 +12090,7 @@ snapshots:
babel-loader: 10.0.0(@babel/core@7.29.0)(webpack@5.101.3(esbuild@0.25.12))
bluebird: 3.7.1
debug: 4.4.0
lodash: 4.17.21
lodash: 4.18.1
semver: 7.7.3
webpack: 5.101.3(esbuild@0.25.12)
transitivePeerDependencies:
@@ -12472,26 +12465,26 @@ snapshots:
'@floating-ui/core': 1.7.3
'@floating-ui/utils': 0.2.10
'@floating-ui/react-dom@2.1.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
'@floating-ui/react-dom@2.1.6(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies:
'@floating-ui/dom': 1.7.4
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
react: 19.2.5
react-dom: 19.2.5(react@19.2.5)
'@floating-ui/react@0.26.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
'@floating-ui/react@0.26.28(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies:
'@floating-ui/react-dom': 2.1.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@floating-ui/react-dom': 2.1.6(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@floating-ui/utils': 0.2.10
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
react: 19.2.5
react-dom: 19.2.5(react@19.2.5)
tabbable: 6.2.0
'@floating-ui/react@0.27.16(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
'@floating-ui/react@0.27.16(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies:
'@floating-ui/react-dom': 2.1.6(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@floating-ui/react-dom': 2.1.6(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@floating-ui/utils': 0.2.10
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
react: 19.2.5
react-dom: 19.2.5(react@19.2.5)
tabbable: 6.2.0
'@floating-ui/utils@0.2.10': {}
@@ -12520,19 +12513,19 @@ snapshots:
dependencies:
'@hapi/hoek': 11.0.7
'@headlessui/react@2.2.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
'@headlessui/react@2.2.10(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies:
'@floating-ui/react': 0.26.28(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@react-aria/focus': 3.21.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@react-aria/interactions': 3.25.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@tanstack/react-virtual': 3.13.12(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
use-sync-external-store: 1.5.0(react@19.1.1)
'@floating-ui/react': 0.26.28(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@react-aria/focus': 3.21.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@react-aria/interactions': 3.25.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@tanstack/react-virtual': 3.13.12(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
react: 19.2.5
react-dom: 19.2.5(react@19.2.5)
use-sync-external-store: 1.5.0(react@19.2.5)
'@headlessui/tailwindcss@0.2.2(tailwindcss@3.4.17)':
'@headlessui/tailwindcss@0.2.2(tailwindcss@3.4.19)':
dependencies:
tailwindcss: 3.4.17
tailwindcss: 3.4.19
'@humanfs/core@0.19.1': {}
@@ -12954,54 +12947,54 @@ snapshots:
dependencies:
quansync: 0.2.11
'@react-aria/focus@3.21.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
'@react-aria/focus@3.21.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies:
'@react-aria/interactions': 3.25.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@react-aria/utils': 3.30.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@react-types/shared': 3.32.0(react@19.1.1)
'@react-aria/interactions': 3.25.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@react-aria/utils': 3.30.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@react-types/shared': 3.32.0(react@19.2.5)
'@swc/helpers': 0.5.17
clsx: 2.1.1
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
react: 19.2.5
react-dom: 19.2.5(react@19.2.5)
'@react-aria/interactions@3.25.5(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
'@react-aria/interactions@3.25.5(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies:
'@react-aria/ssr': 3.9.10(react@19.1.1)
'@react-aria/utils': 3.30.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@react-aria/ssr': 3.9.10(react@19.2.5)
'@react-aria/utils': 3.30.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@react-stately/flags': 3.1.2
'@react-types/shared': 3.32.0(react@19.1.1)
'@react-types/shared': 3.32.0(react@19.2.5)
'@swc/helpers': 0.5.17
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
react: 19.2.5
react-dom: 19.2.5(react@19.2.5)
'@react-aria/ssr@3.9.10(react@19.1.1)':
'@react-aria/ssr@3.9.10(react@19.2.5)':
dependencies:
'@swc/helpers': 0.5.17
react: 19.1.1
react: 19.2.5
'@react-aria/utils@3.30.1(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
'@react-aria/utils@3.30.1(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies:
'@react-aria/ssr': 3.9.10(react@19.1.1)
'@react-aria/ssr': 3.9.10(react@19.2.5)
'@react-stately/flags': 3.1.2
'@react-stately/utils': 3.10.8(react@19.1.1)
'@react-types/shared': 3.32.0(react@19.1.1)
'@react-stately/utils': 3.10.8(react@19.2.5)
'@react-types/shared': 3.32.0(react@19.2.5)
'@swc/helpers': 0.5.17
clsx: 2.1.1
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
react: 19.2.5
react-dom: 19.2.5(react@19.2.5)
'@react-stately/flags@3.1.2':
dependencies:
'@swc/helpers': 0.5.17
'@react-stately/utils@3.10.8(react@19.1.1)':
'@react-stately/utils@3.10.8(react@19.2.5)':
dependencies:
'@swc/helpers': 0.5.17
react: 19.1.1
react: 19.2.5
'@react-types/shared@3.32.0(react@19.1.1)':
'@react-types/shared@3.32.0(react@19.2.5)':
dependencies:
react: 19.1.1
react: 19.2.5
'@rolldown/pluginutils@1.0.0-beta.50': {}
@@ -13238,11 +13231,11 @@ snapshots:
dependencies:
defer-to-connect: 2.0.1
'@tanstack/react-virtual@3.13.12(react-dom@19.1.1(react@19.1.1))(react@19.1.1)':
'@tanstack/react-virtual@3.13.12(react-dom@19.2.5(react@19.2.5))(react@19.2.5)':
dependencies:
'@tanstack/virtual-core': 3.13.12
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
react: 19.2.5
react-dom: 19.2.5(react@19.2.5)
'@tanstack/virtual-core@3.13.12': {}
@@ -14358,30 +14351,28 @@ snapshots:
'@xtuc/long@4.2.2': {}
'@zenuml/core@3.41.6(@babel/core@7.29.0)(@babel/template@7.28.6)':
'@zenuml/core@3.47.2(@babel/core@7.29.0)(@babel/template@7.28.6)':
dependencies:
'@floating-ui/react': 0.27.16(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@headlessui/react': 2.2.8(react-dom@19.1.1(react@19.1.1))(react@19.1.1)
'@headlessui/tailwindcss': 0.2.2(tailwindcss@3.4.17)
'@floating-ui/react': 0.27.16(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@headlessui/react': 2.2.10(react-dom@19.2.5(react@19.2.5))(react@19.2.5)
'@headlessui/tailwindcss': 0.2.2(tailwindcss@3.4.19)
antlr4: 4.11.0
class-variance-authority: 0.7.1
clsx: 2.1.1
color-string: 2.1.2
color-string: 2.1.4
dompurify: 3.4.0
highlight.js: 10.7.3
html-to-image: 1.11.13
immer: 10.1.3
jotai: 2.14.0(@babel/core@7.29.0)(@babel/template@7.28.6)(react@19.1.1)
lodash: 4.17.21
immer: 10.2.0
jotai: 2.19.1(@babel/core@7.29.0)(@babel/template@7.28.6)(react@19.2.5)
lodash: 4.18.1
marked: 4.3.0
pako: 2.1.0
pino: 8.21.0
radash: 12.1.1
ramda: 0.28.0
react: 19.1.1
react-dom: 19.1.1(react@19.1.1)
tailwind-merge: 3.3.1
tailwindcss: 3.4.17
react: 19.2.5
react-dom: 19.2.5(react@19.2.5)
tailwind-merge: 3.5.0
tailwindcss: 3.4.19
transitivePeerDependencies:
- '@babel/core'
- '@babel/template'
@@ -15158,7 +15149,7 @@ snapshots:
color-name@2.0.2: {}
color-string@2.1.2:
color-string@2.1.4:
dependencies:
color-name: 2.0.2
@@ -16745,7 +16736,7 @@ snapshots:
enhanced-resolve: 5.18.3
module-definition: 6.0.1
module-lookup-amd: 9.0.5
resolve: 1.22.10
resolve: 1.22.12
resolve-dependency-path: 4.0.1
sass-lookup: 6.1.0
stylus-lookup: 6.1.0
@@ -17364,7 +17355,7 @@ snapshots:
ignore@7.0.5: {}
immer@10.1.3: {}
immer@10.2.0: {}
import-fresh@3.3.1:
dependencies:
@@ -17837,7 +17828,7 @@ snapshots:
get-stdin: 5.0.1
glur: 1.1.2
jest: 30.1.3(@types/node@22.19.1)
lodash: 4.17.21
lodash: 4.18.1
mkdirp: 0.5.6
pixelmatch: 5.3.0
pngjs: 3.4.0
@@ -18068,11 +18059,11 @@ snapshots:
'@hapi/topo': 6.0.2
'@standard-schema/spec': 1.0.0
jotai@2.14.0(@babel/core@7.29.0)(@babel/template@7.28.6)(react@19.1.1):
jotai@2.19.1(@babel/core@7.29.0)(@babel/template@7.28.6)(react@19.2.5):
optionalDependencies:
'@babel/core': 7.29.0
'@babel/template': 7.28.6
react: 19.1.1
react: 19.2.5
jpeg-js@0.4.4: {}
@@ -19465,7 +19456,7 @@ snapshots:
postcss: 8.5.8
postcss-value-parser: 4.2.0
read-cache: 1.0.0
resolve: 1.22.10
resolve: 1.22.12
postcss-js@4.0.1(postcss@8.5.8):
dependencies:
@@ -19622,12 +19613,8 @@ snapshots:
quote-unquote@1.0.0: {}
radash@12.1.1: {}
railroad-diagrams@1.0.0: {}
ramda@0.28.0: {}
ramda@0.29.1: {}
randombytes@2.1.0:
@@ -19657,14 +19644,14 @@ snapshots:
minimist: 1.2.8
strip-json-comments: 2.0.1
react-dom@19.1.1(react@19.1.1):
react-dom@19.2.5(react@19.2.5):
dependencies:
react: 19.1.1
scheduler: 0.26.0
react: 19.2.5
scheduler: 0.27.0
react-is@18.3.1: {}
react@19.1.1: {}
react@19.2.5: {}
read-cache@1.0.0:
dependencies:
@@ -20022,7 +20009,7 @@ snapshots:
dependencies:
xmlchars: 2.2.0
scheduler@0.26.0: {}
scheduler@0.27.0: {}
schema-utils@4.3.2:
dependencies:
@@ -20612,9 +20599,9 @@ snapshots:
tabbable@6.2.0: {}
tailwind-merge@3.3.1: {}
tailwind-merge@3.5.0: {}
tailwindcss@3.4.17:
tailwindcss@3.4.19:
dependencies:
'@alloc/quick-lru': 5.2.0
arg: 5.0.2
@@ -20636,7 +20623,7 @@ snapshots:
postcss-load-config: 4.0.2(postcss@8.5.8)
postcss-nested: 6.2.0(postcss@8.5.8)
postcss-selector-parser: 6.1.2
resolve: 1.22.10
resolve: 1.22.12
sucrase: 3.35.0
transitivePeerDependencies:
- ts-node
@@ -20662,7 +20649,7 @@ snapshots:
dependencies:
'@babel/runtime': 7.28.4
bluebird: 3.7.2
lodash: 4.17.21
lodash: 4.18.1
shell-quote: 1.8.3
source-map-support: 0.5.21
which: 2.0.2
@@ -21159,9 +21146,9 @@ snapshots:
dependencies:
punycode: 2.3.1
use-sync-external-store@1.5.0(react@19.1.1):
use-sync-external-store@1.5.0(react@19.2.5):
dependencies:
react: 19.1.1
react: 19.2.5
util-deprecate@1.0.2: {}
@@ -21492,7 +21479,7 @@ snapshots:
dependencies:
axios: 1.13.2(debug@4.4.3)
joi: 18.0.1
lodash: 4.17.21
lodash: 4.18.1
minimist: 1.2.8
rxjs: 7.8.2
transitivePeerDependencies: