mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-10-13 19:19:37 +02:00
Tidy-tree POC
This commit is contained in:
@@ -105,6 +105,29 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
|
<pre id="diagram4" class="mermaid">
|
||||||
|
---
|
||||||
|
config:
|
||||||
|
layout: tidy-tree
|
||||||
|
---
|
||||||
|
mindmap
|
||||||
|
root((mindmap))
|
||||||
|
Origins
|
||||||
|
Tools
|
||||||
|
Pen and paper
|
||||||
|
Mermaid
|
||||||
|
</pre>
|
||||||
|
<pre id="diagram4" class="mermaid">
|
||||||
|
---
|
||||||
|
config:
|
||||||
|
layout: elk
|
||||||
|
---
|
||||||
|
flowchart TB
|
||||||
|
A --> n0["1"]
|
||||||
|
A --> n1["2"]
|
||||||
|
A --> n2["3"]
|
||||||
|
A --> n3["4"]
|
||||||
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid2">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
@@ -127,10 +150,8 @@
|
|||||||
Tools
|
Tools
|
||||||
Pen and paper
|
Pen and paper
|
||||||
Mermaid
|
Mermaid
|
||||||
|
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: cose-bilkent
|
layout: cose-bilkent
|
||||||
@@ -138,23 +159,67 @@
|
|||||||
mindmap
|
mindmap
|
||||||
root((mindmap))
|
root((mindmap))
|
||||||
Origins
|
Origins
|
||||||
Europe
|
Long history
|
||||||
Asia
|
::icon(fa fa-book)
|
||||||
East
|
Popularisation
|
||||||
West
|
British popular psychology author Tony Buzan
|
||||||
|
Research
|
||||||
|
On effectiveness<br/>and features
|
||||||
|
On Automatic creation
|
||||||
|
Uses
|
||||||
|
Creative techniques
|
||||||
|
Strategic planning
|
||||||
|
Argument mapping
|
||||||
|
Tools
|
||||||
|
Pen and paper
|
||||||
|
Mermaid
|
||||||
|
</pre>
|
||||||
|
<pre id="diagram4" class="mermaid2">
|
||||||
|
---
|
||||||
|
config:
|
||||||
|
layout: elk
|
||||||
|
---
|
||||||
|
mindmap
|
||||||
|
root((mindmap))
|
||||||
|
Origins
|
||||||
|
Long history
|
||||||
|
::icon(fa fa-book)
|
||||||
|
Popularisation
|
||||||
|
British popular psychology author Tony Buzan
|
||||||
|
Research
|
||||||
|
On effectiveness<br/>and features
|
||||||
|
On Automatic creation
|
||||||
|
Uses
|
||||||
|
Creative techniques
|
||||||
|
Strategic planning
|
||||||
|
Argument mapping
|
||||||
|
Tools
|
||||||
|
Pen and paper
|
||||||
|
Mermaid
|
||||||
|
</pre>
|
||||||
|
<pre id="diagram4" class="mermaid2">
|
||||||
|
---
|
||||||
|
config:
|
||||||
|
layout: cose-bilkent
|
||||||
|
---
|
||||||
|
flowchart LR
|
||||||
|
root{mindmap} --- Origins --- Europe
|
||||||
|
Origins --> Asia
|
||||||
|
root --- Background --- Rich
|
||||||
|
Background --- Poor
|
||||||
|
subgraph apa
|
||||||
Background
|
Background
|
||||||
Rich
|
|
||||||
Poor
|
Poor
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: cose-bilkent
|
layout: elk
|
||||||
---
|
---
|
||||||
flowchart LR
|
flowchart LR
|
||||||
root{mindmap} --- Origins --- Europe
|
root{mindmap} --- Origins --- Europe
|
||||||
@@ -269,7 +334,7 @@ config:
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
@@ -282,7 +347,7 @@ config:
|
|||||||
D-->I
|
D-->I
|
||||||
D-->I
|
D-->I
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
@@ -321,7 +386,7 @@ flowchart LR
|
|||||||
n8@{ shape: rect}
|
n8@{ shape: rect}
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
@@ -337,7 +402,7 @@ flowchart LR
|
|||||||
|
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
@@ -346,7 +411,7 @@ flowchart LR
|
|||||||
A{A} --> B & C
|
A{A} --> B & C
|
||||||
</pre
|
</pre
|
||||||
>
|
>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
layout: elk
|
layout: elk
|
||||||
@@ -376,7 +441,7 @@ flowchart LR
|
|||||||
|
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
kanban:
|
kanban:
|
||||||
@@ -395,81 +460,81 @@ kanban
|
|||||||
task3[💻 Develop login feature]@{ ticket: 103 }
|
task3[💻 Develop login feature]@{ ticket: 103 }
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
flowchart LR
|
flowchart LR
|
||||||
nA[Default] --> A@{ icon: 'fa:bell', form: 'rounded' }
|
nA[Default] --> A@{ icon: 'fa:bell', form: 'rounded' }
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
flowchart LR
|
flowchart LR
|
||||||
nA[Style] --> A@{ icon: 'fa:bell', form: 'rounded' }
|
nA[Style] --> A@{ icon: 'fa:bell', form: 'rounded' }
|
||||||
style A fill:#f9f,stroke:#333,stroke-width:4px
|
style A fill:#f9f,stroke:#333,stroke-width:4px
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
flowchart LR
|
flowchart LR
|
||||||
nA[Class] --> A@{ icon: 'fa:bell', form: 'rounded' }
|
nA[Class] --> A@{ icon: 'fa:bell', form: 'rounded' }
|
||||||
A:::AClass
|
A:::AClass
|
||||||
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
|
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
flowchart LR
|
flowchart LR
|
||||||
nA[Class] --> A@{ icon: 'logos:aws', form: 'rounded' }
|
nA[Class] --> A@{ icon: 'logos:aws', form: 'rounded' }
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
flowchart LR
|
flowchart LR
|
||||||
nA[Default] --> A@{ icon: 'fa:bell', form: 'square' }
|
nA[Default] --> A@{ icon: 'fa:bell', form: 'square' }
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
flowchart LR
|
flowchart LR
|
||||||
nA[Style] --> A@{ icon: 'fa:bell', form: 'square' }
|
nA[Style] --> A@{ icon: 'fa:bell', form: 'square' }
|
||||||
style A fill:#f9f,stroke:#333,stroke-width:4px
|
style A fill:#f9f,stroke:#333,stroke-width:4px
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
flowchart LR
|
flowchart LR
|
||||||
nA[Class] --> A@{ icon: 'fa:bell', form: 'square' }
|
nA[Class] --> A@{ icon: 'fa:bell', form: 'square' }
|
||||||
A:::AClass
|
A:::AClass
|
||||||
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
|
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
flowchart LR
|
flowchart LR
|
||||||
nA[Class] --> A@{ icon: 'logos:aws', form: 'square' }
|
nA[Class] --> A@{ icon: 'logos:aws', form: 'square' }
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
flowchart LR
|
flowchart LR
|
||||||
nA[Default] --> A@{ icon: 'fa:bell', form: 'circle' }
|
nA[Default] --> A@{ icon: 'fa:bell', form: 'circle' }
|
||||||
|
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
flowchart LR
|
flowchart LR
|
||||||
nA[Style] --> A@{ icon: 'fa:bell', form: 'circle' }
|
nA[Style] --> A@{ icon: 'fa:bell', form: 'circle' }
|
||||||
style A fill:#f9f,stroke:#333,stroke-width:4px
|
style A fill:#f9f,stroke:#333,stroke-width:4px
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
flowchart LR
|
flowchart LR
|
||||||
nA[Class] --> A@{ icon: 'fa:bell', form: 'circle' }
|
nA[Class] --> A@{ icon: 'fa:bell', form: 'circle' }
|
||||||
A:::AClass
|
A:::AClass
|
||||||
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
|
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
flowchart LR
|
flowchart LR
|
||||||
nA[Class] --> A@{ icon: 'logos:aws', form: 'circle' }
|
nA[Class] --> A@{ icon: 'logos:aws', form: 'circle' }
|
||||||
A:::AClass
|
A:::AClass
|
||||||
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
|
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
flowchart LR
|
flowchart LR
|
||||||
nA[Style] --> A@{ icon: 'logos:aws', form: 'circle' }
|
nA[Style] --> A@{ icon: 'logos:aws', form: 'circle' }
|
||||||
style A fill:#f9f,stroke:#333,stroke-width:4px
|
style A fill:#f9f,stroke:#333,stroke-width:4px
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
kanban
|
kanban
|
||||||
id2[In progress]
|
id2[In progress]
|
||||||
docs[Create Blog about the new diagram]@{ priority: 'Very Low', ticket: MC-2037, assigned: 'knsv' }
|
docs[Create Blog about the new diagram]@{ priority: 'Very Low', ticket: MC-2037, assigned: 'knsv' }
|
||||||
</pre>
|
</pre>
|
||||||
<pre id="diagram4" class="mermaid">
|
<pre id="diagram4" class="mermaid2">
|
||||||
---
|
---
|
||||||
config:
|
config:
|
||||||
kanban:
|
kanban:
|
||||||
|
@@ -83,6 +83,7 @@
|
|||||||
"khroma": "^2.1.0",
|
"khroma": "^2.1.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"marked": "^15.0.7",
|
"marked": "^15.0.7",
|
||||||
|
"non-layered-tidy-tree-layout": "^2.0.2",
|
||||||
"roughjs": "^4.6.6",
|
"roughjs": "^4.6.6",
|
||||||
"stylis": "^4.3.6",
|
"stylis": "^4.3.6",
|
||||||
"ts-dedent": "^2.2.0",
|
"ts-dedent": "^2.2.0",
|
||||||
|
@@ -0,0 +1,281 @@
|
|||||||
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||||
|
import {
|
||||||
|
addNodes,
|
||||||
|
addEdges,
|
||||||
|
extractPositionedNodes,
|
||||||
|
extractPositionedEdges,
|
||||||
|
} from './cytoscape-setup.js';
|
||||||
|
import type { Node, Edge } from '../../types.js';
|
||||||
|
|
||||||
|
// Mock cytoscape
|
||||||
|
const mockCy = {
|
||||||
|
add: vi.fn(),
|
||||||
|
nodes: vi.fn(),
|
||||||
|
edges: vi.fn(),
|
||||||
|
};
|
||||||
|
|
||||||
|
vi.mock('cytoscape', () => {
|
||||||
|
const mockCytoscape = vi.fn(() => mockCy) as any;
|
||||||
|
mockCytoscape.use = vi.fn();
|
||||||
|
return {
|
||||||
|
default: mockCytoscape,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
vi.mock('cytoscape-cose-bilkent', () => ({
|
||||||
|
default: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('d3', () => ({
|
||||||
|
select: vi.fn(() => ({
|
||||||
|
append: vi.fn(() => ({
|
||||||
|
attr: vi.fn(() => ({
|
||||||
|
attr: vi.fn(() => ({
|
||||||
|
remove: vi.fn(),
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
|
||||||
|
describe('Cytoscape Setup', () => {
|
||||||
|
let mockNodes: Node[];
|
||||||
|
let mockEdges: Edge[];
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
vi.clearAllMocks();
|
||||||
|
|
||||||
|
mockNodes = [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
label: 'Root',
|
||||||
|
isGroup: false,
|
||||||
|
shape: 'rect',
|
||||||
|
width: 100,
|
||||||
|
height: 50,
|
||||||
|
padding: 10,
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
cssClasses: '',
|
||||||
|
cssStyles: [],
|
||||||
|
look: 'default',
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
label: 'Child 1',
|
||||||
|
isGroup: false,
|
||||||
|
shape: 'rect',
|
||||||
|
width: 80,
|
||||||
|
height: 40,
|
||||||
|
padding: 10,
|
||||||
|
x: 150,
|
||||||
|
y: 150,
|
||||||
|
cssClasses: '',
|
||||||
|
cssStyles: [],
|
||||||
|
look: 'default',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
mockEdges = [
|
||||||
|
{
|
||||||
|
id: '1_2',
|
||||||
|
start: '1',
|
||||||
|
end: '2',
|
||||||
|
type: 'edge',
|
||||||
|
classes: '',
|
||||||
|
style: [],
|
||||||
|
animate: false,
|
||||||
|
arrowTypeEnd: 'arrow_point',
|
||||||
|
arrowTypeStart: 'none',
|
||||||
|
},
|
||||||
|
];
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('addNodes', () => {
|
||||||
|
it('should add nodes to cytoscape', () => {
|
||||||
|
addNodes([mockNodes[0]], mockCy as unknown as any);
|
||||||
|
|
||||||
|
expect(mockCy.add).toHaveBeenCalledWith({
|
||||||
|
group: 'nodes',
|
||||||
|
data: {
|
||||||
|
id: '1',
|
||||||
|
labelText: 'Root',
|
||||||
|
height: 50,
|
||||||
|
width: 100,
|
||||||
|
padding: 10,
|
||||||
|
isGroup: false,
|
||||||
|
shape: 'rect',
|
||||||
|
cssClasses: '',
|
||||||
|
cssStyles: [],
|
||||||
|
look: 'default',
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should add multiple nodes to cytoscape', () => {
|
||||||
|
addNodes(mockNodes, mockCy as unknown as any);
|
||||||
|
|
||||||
|
expect(mockCy.add).toHaveBeenCalledTimes(2);
|
||||||
|
|
||||||
|
expect(mockCy.add).toHaveBeenCalledWith({
|
||||||
|
group: 'nodes',
|
||||||
|
data: {
|
||||||
|
id: '1',
|
||||||
|
labelText: 'Root',
|
||||||
|
height: 50,
|
||||||
|
width: 100,
|
||||||
|
padding: 10,
|
||||||
|
isGroup: false,
|
||||||
|
shape: 'rect',
|
||||||
|
cssClasses: '',
|
||||||
|
cssStyles: [],
|
||||||
|
look: 'default',
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
expect(mockCy.add).toHaveBeenCalledWith({
|
||||||
|
group: 'nodes',
|
||||||
|
data: {
|
||||||
|
id: '2',
|
||||||
|
labelText: 'Child 1',
|
||||||
|
height: 40,
|
||||||
|
width: 80,
|
||||||
|
padding: 10,
|
||||||
|
isGroup: false,
|
||||||
|
shape: 'rect',
|
||||||
|
cssClasses: '',
|
||||||
|
cssStyles: [],
|
||||||
|
look: 'default',
|
||||||
|
},
|
||||||
|
position: {
|
||||||
|
x: 150,
|
||||||
|
y: 150,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('addEdges', () => {
|
||||||
|
it('should add edges to cytoscape', () => {
|
||||||
|
addEdges(mockEdges, mockCy as unknown as any);
|
||||||
|
|
||||||
|
expect(mockCy.add).toHaveBeenCalledWith({
|
||||||
|
group: 'edges',
|
||||||
|
data: {
|
||||||
|
id: '1_2',
|
||||||
|
source: '1',
|
||||||
|
target: '2',
|
||||||
|
type: 'edge',
|
||||||
|
classes: '',
|
||||||
|
style: [],
|
||||||
|
animate: false,
|
||||||
|
arrowTypeEnd: 'arrow_point',
|
||||||
|
arrowTypeStart: 'none',
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('extractPositionedNodes', () => {
|
||||||
|
it('should extract positioned nodes from cytoscape', () => {
|
||||||
|
const mockCytoscapeNodes = [
|
||||||
|
{
|
||||||
|
data: () => ({
|
||||||
|
id: '1',
|
||||||
|
labelText: 'Root',
|
||||||
|
width: 100,
|
||||||
|
height: 50,
|
||||||
|
padding: 10,
|
||||||
|
isGroup: false,
|
||||||
|
shape: 'rect',
|
||||||
|
}),
|
||||||
|
position: () => ({ x: 100, y: 100 }),
|
||||||
|
},
|
||||||
|
{
|
||||||
|
data: () => ({
|
||||||
|
id: '2',
|
||||||
|
labelText: 'Child 1',
|
||||||
|
width: 80,
|
||||||
|
height: 40,
|
||||||
|
padding: 10,
|
||||||
|
isGroup: false,
|
||||||
|
shape: 'rect',
|
||||||
|
}),
|
||||||
|
position: () => ({ x: 150, y: 150 }),
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
mockCy.nodes.mockReturnValue({
|
||||||
|
map: (fn: unknown) => mockCytoscapeNodes.map(fn as any),
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = extractPositionedNodes(mockCy as unknown as any);
|
||||||
|
|
||||||
|
expect(result).toHaveLength(2);
|
||||||
|
expect(result[0]).toEqual({
|
||||||
|
id: '1',
|
||||||
|
x: 100,
|
||||||
|
y: 100,
|
||||||
|
labelText: 'Root',
|
||||||
|
width: 100,
|
||||||
|
height: 50,
|
||||||
|
padding: 10,
|
||||||
|
isGroup: false,
|
||||||
|
shape: 'rect',
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('extractPositionedEdges', () => {
|
||||||
|
it('should extract positioned edges from cytoscape', () => {
|
||||||
|
const mockCytoscapeEdges = [
|
||||||
|
{
|
||||||
|
data: () => ({
|
||||||
|
id: '1_2',
|
||||||
|
source: '1',
|
||||||
|
target: '2',
|
||||||
|
type: 'edge',
|
||||||
|
}),
|
||||||
|
_private: {
|
||||||
|
rscratch: {
|
||||||
|
startX: 100,
|
||||||
|
startY: 100,
|
||||||
|
midX: 125,
|
||||||
|
midY: 125,
|
||||||
|
endX: 150,
|
||||||
|
endY: 150,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
mockCy.edges.mockReturnValue({
|
||||||
|
map: (fn: unknown) => mockCytoscapeEdges.map(fn as any),
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = extractPositionedEdges(mockCy as unknown as any);
|
||||||
|
|
||||||
|
expect(result).toHaveLength(1);
|
||||||
|
expect(result[0]).toEqual({
|
||||||
|
id: '1_2',
|
||||||
|
source: '1',
|
||||||
|
target: '2',
|
||||||
|
type: 'edge',
|
||||||
|
startX: 100,
|
||||||
|
startY: 100,
|
||||||
|
midX: 125,
|
||||||
|
midY: 125,
|
||||||
|
endX: 150,
|
||||||
|
endY: 150,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,207 @@
|
|||||||
|
import cytoscape from 'cytoscape';
|
||||||
|
import coseBilkent from 'cytoscape-cose-bilkent';
|
||||||
|
import { select } from 'd3';
|
||||||
|
import { log } from '../../../logger.js';
|
||||||
|
import type { LayoutData, Node, Edge } from '../../types.js';
|
||||||
|
import type { CytoscapeLayoutConfig, PositionedNode, PositionedEdge } from './types.js';
|
||||||
|
|
||||||
|
// Inject the layout algorithm into cytoscape
|
||||||
|
cytoscape.use(coseBilkent);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Declare module augmentation for cytoscape edge types
|
||||||
|
*/
|
||||||
|
declare module 'cytoscape' {
|
||||||
|
interface EdgeSingular {
|
||||||
|
_private: {
|
||||||
|
bodyBounds: unknown;
|
||||||
|
rscratch: {
|
||||||
|
startX: number;
|
||||||
|
startY: number;
|
||||||
|
midX: number;
|
||||||
|
midY: number;
|
||||||
|
endX: number;
|
||||||
|
endY: number;
|
||||||
|
};
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add nodes to cytoscape instance from provided node array
|
||||||
|
* This function processes only the nodes provided in the data structure
|
||||||
|
* @param nodes - Array of nodes to add
|
||||||
|
* @param cy - The cytoscape instance
|
||||||
|
*/
|
||||||
|
export function addNodes(nodes: Node[], cy: cytoscape.Core): void {
|
||||||
|
nodes.forEach((node) => {
|
||||||
|
const nodeData: Record<string, unknown> = {
|
||||||
|
id: node.id,
|
||||||
|
labelText: node.label,
|
||||||
|
height: node.height,
|
||||||
|
width: node.width,
|
||||||
|
padding: node.padding ?? 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add any additional properties from the node
|
||||||
|
Object.keys(node).forEach((key) => {
|
||||||
|
if (!['id', 'label', 'height', 'width', 'padding', 'x', 'y'].includes(key)) {
|
||||||
|
nodeData[key] = (node as unknown as Record<string, unknown>)[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.add({
|
||||||
|
group: 'nodes',
|
||||||
|
data: nodeData,
|
||||||
|
position: {
|
||||||
|
x: node.x ?? 0,
|
||||||
|
y: node.y ?? 0,
|
||||||
|
},
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add edges to cytoscape instance from provided edge array
|
||||||
|
* This function processes only the edges provided in the data structure
|
||||||
|
* @param edges - Array of edges to add
|
||||||
|
* @param cy - The cytoscape instance
|
||||||
|
*/
|
||||||
|
export function addEdges(edges: Edge[], cy: cytoscape.Core): void {
|
||||||
|
edges.forEach((edge) => {
|
||||||
|
const edgeData: Record<string, unknown> = {
|
||||||
|
id: edge.id,
|
||||||
|
source: edge.start,
|
||||||
|
target: edge.end,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add any additional properties from the edge
|
||||||
|
Object.keys(edge).forEach((key) => {
|
||||||
|
if (!['id', 'start', 'end'].includes(key)) {
|
||||||
|
edgeData[key] = (edge as unknown as Record<string, unknown>)[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
cy.add({
|
||||||
|
group: 'edges',
|
||||||
|
data: edgeData,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Create and configure cytoscape instance
|
||||||
|
* @param data - Layout data containing nodes and edges
|
||||||
|
* @returns Promise resolving to configured cytoscape instance
|
||||||
|
*/
|
||||||
|
export function createCytoscapeInstance(data: LayoutData): Promise<cytoscape.Core> {
|
||||||
|
return new Promise((resolve) => {
|
||||||
|
// Add temporary render element
|
||||||
|
const renderEl = select('body').append('div').attr('id', 'cy').attr('style', 'display:none');
|
||||||
|
|
||||||
|
const cy = cytoscape({
|
||||||
|
container: document.getElementById('cy'), // container to render in
|
||||||
|
style: [
|
||||||
|
{
|
||||||
|
selector: 'edge',
|
||||||
|
style: {
|
||||||
|
'curve-style': 'bezier',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
// Remove element after layout
|
||||||
|
renderEl.remove();
|
||||||
|
|
||||||
|
// Add all nodes and edges to cytoscape using the generic functions
|
||||||
|
addNodes(data.nodes, cy);
|
||||||
|
addEdges(data.edges, cy);
|
||||||
|
|
||||||
|
// Make cytoscape care about the dimensions of the nodes
|
||||||
|
cy.nodes().forEach(function (n) {
|
||||||
|
n.layoutDimensions = () => {
|
||||||
|
const nodeData = n.data();
|
||||||
|
return { w: nodeData.width, h: nodeData.height };
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
// Configure and run the cose-bilkent layout
|
||||||
|
const layoutConfig: CytoscapeLayoutConfig = {
|
||||||
|
name: 'cose-bilkent',
|
||||||
|
// @ts-ignore Types for cose-bilkent are not correct?
|
||||||
|
quality: 'proof',
|
||||||
|
styleEnabled: false,
|
||||||
|
animate: false,
|
||||||
|
};
|
||||||
|
|
||||||
|
cy.layout(layoutConfig).run();
|
||||||
|
|
||||||
|
cy.ready((e) => {
|
||||||
|
log.info('Cytoscape ready', e);
|
||||||
|
resolve(cy);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract positioned nodes from cytoscape instance
|
||||||
|
* @param cy - The cytoscape instance after layout
|
||||||
|
* @returns Array of positioned nodes
|
||||||
|
*/
|
||||||
|
export function extractPositionedNodes(cy: cytoscape.Core): PositionedNode[] {
|
||||||
|
return cy.nodes().map((node) => {
|
||||||
|
const data = node.data();
|
||||||
|
const position = node.position();
|
||||||
|
|
||||||
|
// Create a positioned node with all original data plus position
|
||||||
|
const positionedNode: PositionedNode = {
|
||||||
|
id: data.id,
|
||||||
|
x: position.x,
|
||||||
|
y: position.y,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add all other properties from the original data
|
||||||
|
Object.keys(data).forEach((key) => {
|
||||||
|
if (key !== 'id') {
|
||||||
|
positionedNode[key] = data[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return positionedNode;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extract positioned edges from cytoscape instance
|
||||||
|
* @param cy - The cytoscape instance after layout
|
||||||
|
* @returns Array of positioned edges
|
||||||
|
*/
|
||||||
|
export function extractPositionedEdges(cy: cytoscape.Core): PositionedEdge[] {
|
||||||
|
return cy.edges().map((edge) => {
|
||||||
|
const data = edge.data();
|
||||||
|
const rscratch = edge._private.rscratch;
|
||||||
|
|
||||||
|
// Create a positioned edge with all original data plus position
|
||||||
|
const positionedEdge: PositionedEdge = {
|
||||||
|
id: data.id,
|
||||||
|
source: data.source,
|
||||||
|
target: data.target,
|
||||||
|
startX: rscratch.startX,
|
||||||
|
startY: rscratch.startY,
|
||||||
|
midX: rscratch.midX,
|
||||||
|
midY: rscratch.midY,
|
||||||
|
endX: rscratch.endX,
|
||||||
|
endY: rscratch.endY,
|
||||||
|
};
|
||||||
|
|
||||||
|
// Add all other properties from the original data
|
||||||
|
Object.keys(data).forEach((key) => {
|
||||||
|
if (!['id', 'source', 'target'].includes(key)) {
|
||||||
|
positionedEdge[key] = data[key];
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return positionedEdge;
|
||||||
|
});
|
||||||
|
}
|
@@ -0,0 +1,25 @@
|
|||||||
|
import { render as renderWithCoseBilkent } from './render.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cose-Bilkent Layout Algorithm for Generic Diagrams
|
||||||
|
*
|
||||||
|
* This module provides a layout algorithm implementation using Cytoscape
|
||||||
|
* with the cose-bilkent algorithm for positioning nodes and edges.
|
||||||
|
*
|
||||||
|
* The algorithm follows the unified rendering pattern and can be used
|
||||||
|
* by any diagram type that provides compatible LayoutData.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render function for the cose-bilkent layout algorithm
|
||||||
|
*
|
||||||
|
* This function follows the unified rendering pattern used by all layout algorithms.
|
||||||
|
* It takes LayoutData, inserts nodes into DOM, runs the cose-bilkent layout algorithm,
|
||||||
|
* and renders the positioned elements to the SVG.
|
||||||
|
*
|
||||||
|
* @param layoutData - Layout data containing nodes, edges, and configuration
|
||||||
|
* @param svg - SVG element to render to
|
||||||
|
* @param helpers - Internal helper functions for rendering
|
||||||
|
* @param options - Rendering options
|
||||||
|
*/
|
||||||
|
export const render = renderWithCoseBilkent;
|
@@ -0,0 +1,250 @@
|
|||||||
|
import { describe, it, expect, beforeEach, vi } from 'vitest';
|
||||||
|
|
||||||
|
// Mock cytoscape and cytoscape-cose-bilkent before importing the modules
|
||||||
|
vi.mock('cytoscape', () => {
|
||||||
|
const mockCy = {
|
||||||
|
add: vi.fn(),
|
||||||
|
nodes: vi.fn(() => ({
|
||||||
|
forEach: vi.fn(),
|
||||||
|
map: vi.fn((fn) => [
|
||||||
|
fn({
|
||||||
|
data: () => ({
|
||||||
|
id: '1',
|
||||||
|
nodeId: '1',
|
||||||
|
labelText: 'Root',
|
||||||
|
level: 0,
|
||||||
|
type: 0,
|
||||||
|
width: 100,
|
||||||
|
height: 50,
|
||||||
|
padding: 10,
|
||||||
|
}),
|
||||||
|
position: () => ({ x: 100, y: 100 }),
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
})),
|
||||||
|
edges: vi.fn(() => ({
|
||||||
|
map: vi.fn((fn) => [
|
||||||
|
fn({
|
||||||
|
data: () => ({
|
||||||
|
id: '1_2',
|
||||||
|
source: '1',
|
||||||
|
target: '2',
|
||||||
|
depth: 0,
|
||||||
|
}),
|
||||||
|
_private: {
|
||||||
|
rscratch: {
|
||||||
|
startX: 100,
|
||||||
|
startY: 100,
|
||||||
|
midX: 150,
|
||||||
|
midY: 150,
|
||||||
|
endX: 200,
|
||||||
|
endY: 200,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}),
|
||||||
|
]),
|
||||||
|
})),
|
||||||
|
layout: vi.fn(() => ({
|
||||||
|
run: vi.fn(),
|
||||||
|
})),
|
||||||
|
ready: vi.fn((callback) => callback({})),
|
||||||
|
};
|
||||||
|
|
||||||
|
const mockCytoscape = vi.fn(() => mockCy);
|
||||||
|
mockCytoscape.use = vi.fn();
|
||||||
|
|
||||||
|
return {
|
||||||
|
default: mockCytoscape,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
vi.mock('cytoscape-cose-bilkent', () => ({
|
||||||
|
default: vi.fn(),
|
||||||
|
}));
|
||||||
|
|
||||||
|
vi.mock('d3', () => ({
|
||||||
|
select: vi.fn(() => ({
|
||||||
|
append: vi.fn(() => ({
|
||||||
|
attr: vi.fn(() => ({
|
||||||
|
attr: vi.fn(() => ({
|
||||||
|
remove: vi.fn(),
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
})),
|
||||||
|
}));
|
||||||
|
|
||||||
|
// Import modules after mocks
|
||||||
|
import { layout, validateLayoutData } from './index.js';
|
||||||
|
import type { MindmapLayoutData, LayoutResult } from './types.js';
|
||||||
|
import type { MindmapNode } from '../../../diagrams/mindmap/mindmapTypes.js';
|
||||||
|
import type { MermaidConfig } from '../../../config.type.js';
|
||||||
|
|
||||||
|
describe('Cose-Bilkent Layout Algorithm', () => {
|
||||||
|
let mockConfig: MermaidConfig;
|
||||||
|
let mockRootNode: MindmapNode;
|
||||||
|
let mockLayoutData: MindmapLayoutData;
|
||||||
|
|
||||||
|
beforeEach(() => {
|
||||||
|
mockConfig = {
|
||||||
|
mindmap: {
|
||||||
|
layoutAlgorithm: 'cose-bilkent',
|
||||||
|
padding: 10,
|
||||||
|
maxNodeWidth: 200,
|
||||||
|
useMaxWidth: true,
|
||||||
|
},
|
||||||
|
} as MermaidConfig;
|
||||||
|
|
||||||
|
mockRootNode = {
|
||||||
|
id: 1,
|
||||||
|
nodeId: '1',
|
||||||
|
level: 0,
|
||||||
|
descr: 'Root',
|
||||||
|
type: 0,
|
||||||
|
width: 100,
|
||||||
|
height: 50,
|
||||||
|
padding: 10,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
children: [
|
||||||
|
{
|
||||||
|
id: 2,
|
||||||
|
nodeId: '2',
|
||||||
|
level: 1,
|
||||||
|
descr: 'Child 1',
|
||||||
|
type: 0,
|
||||||
|
width: 80,
|
||||||
|
height: 40,
|
||||||
|
padding: 10,
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
} as MindmapNode;
|
||||||
|
|
||||||
|
mockLayoutData = {
|
||||||
|
nodes: [
|
||||||
|
{
|
||||||
|
id: '1',
|
||||||
|
nodeId: '1',
|
||||||
|
level: 0,
|
||||||
|
descr: 'Root',
|
||||||
|
type: 0,
|
||||||
|
width: 100,
|
||||||
|
height: 50,
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
id: '2',
|
||||||
|
nodeId: '2',
|
||||||
|
level: 1,
|
||||||
|
descr: 'Child 1',
|
||||||
|
type: 0,
|
||||||
|
width: 80,
|
||||||
|
height: 40,
|
||||||
|
padding: 10,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
edges: [
|
||||||
|
{
|
||||||
|
id: '1_2',
|
||||||
|
source: '1',
|
||||||
|
target: '2',
|
||||||
|
depth: 0,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
config: mockConfig,
|
||||||
|
rootNode: mockRootNode,
|
||||||
|
};
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('validateLayoutData', () => {
|
||||||
|
it('should validate correct layout data', () => {
|
||||||
|
expect(() => validateLayoutData(mockLayoutData)).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error for missing data', () => {
|
||||||
|
expect(() => validateLayoutData(null as any)).toThrow('Layout data is required');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error for missing root node', () => {
|
||||||
|
const invalidData = { ...mockLayoutData, rootNode: null as any };
|
||||||
|
expect(() => validateLayoutData(invalidData)).toThrow('Root node is required');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error for missing config', () => {
|
||||||
|
const invalidData = { ...mockLayoutData, config: null as any };
|
||||||
|
expect(() => validateLayoutData(invalidData)).toThrow('Configuration is required');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error for invalid nodes array', () => {
|
||||||
|
const invalidData = { ...mockLayoutData, nodes: null as any };
|
||||||
|
expect(() => validateLayoutData(invalidData)).toThrow('Nodes array is required');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error for invalid edges array', () => {
|
||||||
|
const invalidData = { ...mockLayoutData, edges: null as any };
|
||||||
|
expect(() => validateLayoutData(invalidData)).toThrow('Edges array is required');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('layout function', () => {
|
||||||
|
it('should execute layout algorithm successfully', async () => {
|
||||||
|
const result: LayoutResult = await layout(mockLayoutData, mockConfig);
|
||||||
|
|
||||||
|
expect(result).toBeDefined();
|
||||||
|
expect(result.nodes).toBeDefined();
|
||||||
|
expect(result.edges).toBeDefined();
|
||||||
|
expect(Array.isArray(result.nodes)).toBe(true);
|
||||||
|
expect(Array.isArray(result.edges)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return positioned nodes with coordinates', async () => {
|
||||||
|
const result: LayoutResult = await layout(mockLayoutData, mockConfig);
|
||||||
|
|
||||||
|
expect(result.nodes.length).toBeGreaterThan(0);
|
||||||
|
result.nodes.forEach((node) => {
|
||||||
|
expect(node.x).toBeDefined();
|
||||||
|
expect(node.y).toBeDefined();
|
||||||
|
expect(typeof node.x).toBe('number');
|
||||||
|
expect(typeof node.y).toBe('number');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should return positioned edges with coordinates', async () => {
|
||||||
|
const result: LayoutResult = await layout(mockLayoutData, mockConfig);
|
||||||
|
|
||||||
|
expect(result.edges.length).toBeGreaterThan(0);
|
||||||
|
result.edges.forEach((edge) => {
|
||||||
|
expect(edge.startX).toBeDefined();
|
||||||
|
expect(edge.startY).toBeDefined();
|
||||||
|
expect(edge.midX).toBeDefined();
|
||||||
|
expect(edge.midY).toBeDefined();
|
||||||
|
expect(edge.endX).toBeDefined();
|
||||||
|
expect(edge.endY).toBeDefined();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle empty mindmap data gracefully', async () => {
|
||||||
|
const emptyData: MindmapLayoutData = {
|
||||||
|
nodes: [],
|
||||||
|
edges: [],
|
||||||
|
config: mockConfig,
|
||||||
|
rootNode: mockRootNode,
|
||||||
|
};
|
||||||
|
|
||||||
|
const result: LayoutResult = await layout(emptyData, mockConfig);
|
||||||
|
expect(result).toBeDefined();
|
||||||
|
expect(result.nodes).toBeDefined();
|
||||||
|
expect(result.edges).toBeDefined();
|
||||||
|
expect(Array.isArray(result.nodes)).toBe(true);
|
||||||
|
expect(Array.isArray(result.edges)).toBe(true);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw error for invalid data', async () => {
|
||||||
|
const invalidData = { ...mockLayoutData, rootNode: null as any };
|
||||||
|
|
||||||
|
await expect(layout(invalidData, mockConfig)).rejects.toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
@@ -0,0 +1,79 @@
|
|||||||
|
import type { MermaidConfig } from '../../../config.type.js';
|
||||||
|
import { log } from '../../../logger.js';
|
||||||
|
import type { LayoutData } from '../../types.js';
|
||||||
|
import type { LayoutResult } from './types.js';
|
||||||
|
import {
|
||||||
|
createCytoscapeInstance,
|
||||||
|
extractPositionedNodes,
|
||||||
|
extractPositionedEdges,
|
||||||
|
} from './cytoscape-setup.js';
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Execute the cose-bilkent layout algorithm on generic layout data
|
||||||
|
*
|
||||||
|
* This function takes layout data and uses Cytoscape with the cose-bilkent
|
||||||
|
* algorithm to calculate optimal node positions and edge paths.
|
||||||
|
*
|
||||||
|
* @param data - The layout data containing nodes, edges, and configuration
|
||||||
|
* @param config - Mermaid configuration object
|
||||||
|
* @returns Promise resolving to layout result with positioned nodes and edges
|
||||||
|
*/
|
||||||
|
export async function executeCoseBilkentLayout(
|
||||||
|
data: LayoutData,
|
||||||
|
_config: MermaidConfig
|
||||||
|
): Promise<LayoutResult> {
|
||||||
|
log.debug('Starting cose-bilkent layout algorithm');
|
||||||
|
|
||||||
|
try {
|
||||||
|
// Validate input data
|
||||||
|
if (!data.nodes || !Array.isArray(data.nodes)) {
|
||||||
|
throw new Error('No nodes found in layout data');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.edges || !Array.isArray(data.edges)) {
|
||||||
|
throw new Error('No edges found in layout data');
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create and configure cytoscape instance
|
||||||
|
const cy = await createCytoscapeInstance(data);
|
||||||
|
|
||||||
|
// Extract positioned nodes and edges after layout
|
||||||
|
const positionedNodes = extractPositionedNodes(cy);
|
||||||
|
const positionedEdges = extractPositionedEdges(cy);
|
||||||
|
|
||||||
|
log.debug(`Layout completed: ${positionedNodes.length} nodes, ${positionedEdges.length} edges`);
|
||||||
|
|
||||||
|
return {
|
||||||
|
nodes: positionedNodes,
|
||||||
|
edges: positionedEdges,
|
||||||
|
};
|
||||||
|
} catch (error) {
|
||||||
|
log.error('Error in cose-bilkent layout algorithm:', error);
|
||||||
|
throw error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate layout data structure
|
||||||
|
* @param data - The data to validate
|
||||||
|
* @returns True if data is valid, throws error otherwise
|
||||||
|
*/
|
||||||
|
export function validateLayoutData(data: LayoutData): boolean {
|
||||||
|
if (!data) {
|
||||||
|
throw new Error('Layout data is required');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!data.config) {
|
||||||
|
throw new Error('Configuration is required in layout data');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(data.nodes)) {
|
||||||
|
throw new Error('Nodes array is required in layout data');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!Array.isArray(data.edges)) {
|
||||||
|
throw new Error('Edges array is required in layout data');
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
@@ -0,0 +1,183 @@
|
|||||||
|
import type { InternalHelpers, LayoutData, RenderOptions, SVG, SVGGroup } from 'mermaid';
|
||||||
|
import { executeCoseBilkentLayout } from './layout.js';
|
||||||
|
|
||||||
|
type Node = LayoutData['nodes'][number];
|
||||||
|
|
||||||
|
interface NodeWithPosition extends Node {
|
||||||
|
x?: number;
|
||||||
|
y?: number;
|
||||||
|
domId?: SVGGroup;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Render function for cose-bilkent layout algorithm
|
||||||
|
*
|
||||||
|
* This follows the same pattern as ELK and dagre renderers:
|
||||||
|
* 1. Insert nodes into DOM to get their actual dimensions
|
||||||
|
* 2. Run the layout algorithm to calculate positions
|
||||||
|
* 3. Position the nodes and edges based on layout results
|
||||||
|
*/
|
||||||
|
export const render = async (
|
||||||
|
data4Layout: LayoutData,
|
||||||
|
svg: SVG,
|
||||||
|
{
|
||||||
|
insertCluster,
|
||||||
|
insertEdge,
|
||||||
|
insertEdgeLabel,
|
||||||
|
insertMarkers,
|
||||||
|
insertNode,
|
||||||
|
log,
|
||||||
|
positionEdgeLabel,
|
||||||
|
}: InternalHelpers,
|
||||||
|
{ algorithm }: RenderOptions
|
||||||
|
) => {
|
||||||
|
const nodeDb: Record<string, NodeWithPosition> = {};
|
||||||
|
const clusterDb: Record<string, any> = {};
|
||||||
|
|
||||||
|
// Insert markers for edges
|
||||||
|
const element = svg.select('g');
|
||||||
|
insertMarkers(element, data4Layout.markers, data4Layout.type, data4Layout.diagramId);
|
||||||
|
|
||||||
|
// Create container groups
|
||||||
|
const subGraphsEl = element.insert('g').attr('class', 'subgraphs');
|
||||||
|
const edgePaths = element.insert('g').attr('class', 'edgePaths');
|
||||||
|
const edgeLabels = element.insert('g').attr('class', 'edgeLabels');
|
||||||
|
const nodes = element.insert('g').attr('class', 'nodes');
|
||||||
|
|
||||||
|
// Step 1: Insert nodes into DOM to get their actual dimensions
|
||||||
|
log.debug('Inserting nodes into DOM for dimension calculation');
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
data4Layout.nodes.map(async (node) => {
|
||||||
|
if (node.isGroup) {
|
||||||
|
// Handle subgraphs/clusters
|
||||||
|
const clusterNode: NodeWithPosition = { ...node };
|
||||||
|
clusterDb[node.id] = clusterNode;
|
||||||
|
nodeDb[node.id] = clusterNode;
|
||||||
|
|
||||||
|
// Insert cluster to get dimensions
|
||||||
|
await insertCluster(subGraphsEl, node);
|
||||||
|
} else {
|
||||||
|
// Handle regular nodes
|
||||||
|
const nodeWithPosition: NodeWithPosition = { ...node };
|
||||||
|
nodeDb[node.id] = nodeWithPosition;
|
||||||
|
|
||||||
|
// Insert node to get actual dimensions
|
||||||
|
const nodeEl = await insertNode(nodes, node, {
|
||||||
|
config: data4Layout.config,
|
||||||
|
dir: data4Layout.direction || 'TB',
|
||||||
|
});
|
||||||
|
|
||||||
|
// Get the actual bounding box after insertion
|
||||||
|
const boundingBox = nodeEl.node()!.getBBox();
|
||||||
|
nodeWithPosition.width = boundingBox.width;
|
||||||
|
nodeWithPosition.height = boundingBox.height;
|
||||||
|
nodeWithPosition.domId = nodeEl;
|
||||||
|
|
||||||
|
log.debug(`Node ${node.id} dimensions: ${boundingBox.width}x${boundingBox.height}`);
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
// Step 2: Run the cose-bilkent layout algorithm
|
||||||
|
log.debug('Running cose-bilkent layout algorithm');
|
||||||
|
|
||||||
|
// Update the layout data with actual dimensions
|
||||||
|
const updatedLayoutData = {
|
||||||
|
...data4Layout,
|
||||||
|
nodes: data4Layout.nodes.map((node) => {
|
||||||
|
const nodeWithDimensions = nodeDb[node.id];
|
||||||
|
return {
|
||||||
|
...node,
|
||||||
|
width: nodeWithDimensions.width,
|
||||||
|
height: nodeWithDimensions.height,
|
||||||
|
};
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
const layoutResult = await executeCoseBilkentLayout(updatedLayoutData, data4Layout.config);
|
||||||
|
|
||||||
|
// Step 3: Position the nodes based on layout results
|
||||||
|
log.debug('Positioning nodes based on layout results');
|
||||||
|
|
||||||
|
layoutResult.nodes.forEach((positionedNode) => {
|
||||||
|
const node = nodeDb[positionedNode.id];
|
||||||
|
if (node && node.domId) {
|
||||||
|
// Position the node at the calculated coordinates
|
||||||
|
// The positionedNode.x/y represents the center of the node, so use directly
|
||||||
|
node.domId.attr('transform', `translate(${positionedNode.x}, ${positionedNode.y})`);
|
||||||
|
|
||||||
|
// Store the final position
|
||||||
|
node.x = positionedNode.x;
|
||||||
|
node.y = positionedNode.y;
|
||||||
|
|
||||||
|
log.debug(`Positioned node ${node.id} at center (${positionedNode.x}, ${positionedNode.y})`);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Step 4: Insert and position edges
|
||||||
|
log.debug('Inserting and positioning edges');
|
||||||
|
|
||||||
|
await Promise.all(
|
||||||
|
data4Layout.edges.map(async (edge) => {
|
||||||
|
// Insert edge label first
|
||||||
|
const edgeLabel = await insertEdgeLabel(edgeLabels, edge);
|
||||||
|
|
||||||
|
// Get start and end nodes
|
||||||
|
const startNode = nodeDb[edge.start];
|
||||||
|
const endNode = nodeDb[edge.end];
|
||||||
|
|
||||||
|
if (startNode && endNode) {
|
||||||
|
// Find the positioned edge data
|
||||||
|
const positionedEdge = layoutResult.edges.find((e) => e.id === edge.id);
|
||||||
|
|
||||||
|
if (positionedEdge) {
|
||||||
|
// Create edge path with positioned coordinates
|
||||||
|
const edgeWithPath = {
|
||||||
|
...edge,
|
||||||
|
points: [
|
||||||
|
{ x: positionedEdge.startX, y: positionedEdge.startY },
|
||||||
|
{ x: positionedEdge.endX, y: positionedEdge.endY },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
// Insert the edge path
|
||||||
|
const paths = insertEdge(
|
||||||
|
edgePaths,
|
||||||
|
edgeWithPath,
|
||||||
|
clusterDb,
|
||||||
|
data4Layout.type,
|
||||||
|
startNode,
|
||||||
|
endNode,
|
||||||
|
data4Layout.diagramId
|
||||||
|
);
|
||||||
|
|
||||||
|
// Position the edge label
|
||||||
|
positionEdgeLabel(edgeWithPath, paths);
|
||||||
|
} else {
|
||||||
|
// Fallback: create a simple straight line between nodes
|
||||||
|
const edgeWithPath = {
|
||||||
|
...edge,
|
||||||
|
points: [
|
||||||
|
{ x: startNode.x || 0, y: startNode.y || 0 },
|
||||||
|
{ x: endNode.x || 0, y: endNode.y || 0 },
|
||||||
|
],
|
||||||
|
};
|
||||||
|
|
||||||
|
const paths = insertEdge(
|
||||||
|
edgePaths,
|
||||||
|
edgeWithPath,
|
||||||
|
clusterDb,
|
||||||
|
data4Layout.type,
|
||||||
|
startNode,
|
||||||
|
endNode,
|
||||||
|
data4Layout.diagramId
|
||||||
|
);
|
||||||
|
positionEdgeLabel(edgeWithPath, paths);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
);
|
||||||
|
|
||||||
|
log.debug('Cose-bilkent rendering completed');
|
||||||
|
};
|
@@ -0,0 +1,43 @@
|
|||||||
|
/**
|
||||||
|
* Positioned node after layout calculation
|
||||||
|
*/
|
||||||
|
export interface PositionedNode {
|
||||||
|
id: string;
|
||||||
|
x: number;
|
||||||
|
y: number;
|
||||||
|
[key: string]: unknown; // Allow additional properties
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Positioned edge after layout calculation
|
||||||
|
*/
|
||||||
|
export interface PositionedEdge {
|
||||||
|
id: string;
|
||||||
|
source: string;
|
||||||
|
target: string;
|
||||||
|
startX: number;
|
||||||
|
startY: number;
|
||||||
|
midX: number;
|
||||||
|
midY: number;
|
||||||
|
endX: number;
|
||||||
|
endY: number;
|
||||||
|
[key: string]: unknown; // Allow additional properties
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Result of layout algorithm execution
|
||||||
|
*/
|
||||||
|
export interface LayoutResult {
|
||||||
|
nodes: PositionedNode[];
|
||||||
|
edges: PositionedEdge[];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Cytoscape layout configuration
|
||||||
|
*/
|
||||||
|
export interface CytoscapeLayoutConfig {
|
||||||
|
name: 'cose-bilkent';
|
||||||
|
quality: 'proof';
|
||||||
|
styleEnabled: boolean;
|
||||||
|
animate: boolean;
|
||||||
|
}
|
@@ -43,6 +43,10 @@ const registerDefaultLayoutLoaders = () => {
|
|||||||
name: 'cose-bilkent',
|
name: 'cose-bilkent',
|
||||||
loader: async () => await import('./layout-algorithms/cose-bilkent/index.js'),
|
loader: async () => await import('./layout-algorithms/cose-bilkent/index.js'),
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
name: 'tidy-tree',
|
||||||
|
loader: async () => await import('./layout-algorithms/tidy-tree/index.js'),
|
||||||
|
},
|
||||||
]);
|
]);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
309
pnpm-lock.yaml
generated
309
pnpm-lock.yaml
generated
@@ -265,6 +265,9 @@ importers:
|
|||||||
marked:
|
marked:
|
||||||
specifier: ^15.0.7
|
specifier: ^15.0.7
|
||||||
version: 15.0.7
|
version: 15.0.7
|
||||||
|
non-layered-tidy-tree-layout:
|
||||||
|
specifier: ^2.0.2
|
||||||
|
version: 2.0.2
|
||||||
roughjs:
|
roughjs:
|
||||||
specifier: ^4.6.6
|
specifier: ^4.6.6
|
||||||
version: 4.6.6(patch_hash=3543d47108cb41b68ec6a671c0e1f9d0cfe2ce524fea5b0992511ae84c3c6b64)
|
version: 4.6.6(patch_hash=3543d47108cb41b68ec6a671c0e1f9d0cfe2ce524fea5b0992511ae84c3c6b64)
|
||||||
@@ -508,6 +511,67 @@ importers:
|
|||||||
specifier: ^7.3.0
|
specifier: ^7.3.0
|
||||||
version: 7.3.0
|
version: 7.3.0
|
||||||
|
|
||||||
|
packages/mermaid/src/vitepress:
|
||||||
|
dependencies:
|
||||||
|
'@mdi/font':
|
||||||
|
specifier: ^7.4.47
|
||||||
|
version: 7.4.47
|
||||||
|
'@vueuse/core':
|
||||||
|
specifier: ^12.7.0
|
||||||
|
version: 12.7.0(typescript@5.7.3)
|
||||||
|
font-awesome:
|
||||||
|
specifier: ^4.7.0
|
||||||
|
version: 4.7.0
|
||||||
|
jiti:
|
||||||
|
specifier: ^2.4.2
|
||||||
|
version: 2.4.2
|
||||||
|
mermaid:
|
||||||
|
specifier: workspace:^
|
||||||
|
version: link:../..
|
||||||
|
vue:
|
||||||
|
specifier: ^3.4.38
|
||||||
|
version: 3.5.13(typescript@5.7.3)
|
||||||
|
devDependencies:
|
||||||
|
'@iconify-json/carbon':
|
||||||
|
specifier: ^1.1.37
|
||||||
|
version: 1.2.1
|
||||||
|
'@unocss/reset':
|
||||||
|
specifier: ^66.0.0
|
||||||
|
version: 66.0.0
|
||||||
|
'@vite-pwa/vitepress':
|
||||||
|
specifier: ^0.5.3
|
||||||
|
version: 0.5.4(vite-plugin-pwa@0.21.2(vite@6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0))
|
||||||
|
'@vitejs/plugin-vue':
|
||||||
|
specifier: ^5.0.5
|
||||||
|
version: 5.2.1(vite@6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(vue@3.5.13(typescript@5.7.3))
|
||||||
|
fast-glob:
|
||||||
|
specifier: ^3.3.3
|
||||||
|
version: 3.3.3
|
||||||
|
https-localhost:
|
||||||
|
specifier: ^4.7.1
|
||||||
|
version: 4.7.1
|
||||||
|
pathe:
|
||||||
|
specifier: ^2.0.3
|
||||||
|
version: 2.0.3
|
||||||
|
unocss:
|
||||||
|
specifier: ^66.0.0
|
||||||
|
version: 66.0.0(postcss@8.5.3)(vite@6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(vue@3.5.13(typescript@5.7.3))
|
||||||
|
unplugin-vue-components:
|
||||||
|
specifier: ^28.4.0
|
||||||
|
version: 28.4.0(@babel/parser@7.27.2)(vue@3.5.13(typescript@5.7.3))
|
||||||
|
vite:
|
||||||
|
specifier: ^6.1.1
|
||||||
|
version: 6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
|
||||||
|
vite-plugin-pwa:
|
||||||
|
specifier: ^0.21.1
|
||||||
|
version: 0.21.2(vite@6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0)
|
||||||
|
vitepress:
|
||||||
|
specifier: 1.6.3
|
||||||
|
version: 1.6.3(@algolia/client-search@5.20.3)(@types/node@22.13.5)(axios@1.8.4)(postcss@8.5.3)(search-insights@2.17.2)(terser@5.39.0)(typescript@5.7.3)
|
||||||
|
workbox-window:
|
||||||
|
specifier: ^7.3.0
|
||||||
|
version: 7.3.0
|
||||||
|
|
||||||
packages/parser:
|
packages/parser:
|
||||||
dependencies:
|
dependencies:
|
||||||
langium:
|
langium:
|
||||||
@@ -912,10 +976,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==}
|
resolution: {integrity: sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
|
|
||||||
'@babel/helper-string-parser@7.25.9':
|
|
||||||
resolution: {integrity: sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==}
|
|
||||||
engines: {node: '>=6.9.0'}
|
|
||||||
|
|
||||||
'@babel/helper-string-parser@7.27.1':
|
'@babel/helper-string-parser@7.27.1':
|
||||||
resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
|
resolution: {integrity: sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==}
|
||||||
engines: {node: '>=6.9.0'}
|
engines: {node: '>=6.9.0'}
|
||||||
@@ -3627,6 +3687,15 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0
|
vite: ^2.9.0 || ^3.0.0-0 || ^4.0.0 || ^5.0.0-0 || ^6.0.0-0
|
||||||
|
|
||||||
|
'@vite-pwa/vitepress@0.5.4':
|
||||||
|
resolution: {integrity: sha512-g57qwG983WTyQNLnOcDVPQEIeN+QDgK/HdqghmygiUFp3a/MzVvmLXC/EVnPAXxWa8W2g9pZ9lE3EiDGs2HjsA==}
|
||||||
|
peerDependencies:
|
||||||
|
'@vite-pwa/assets-generator': ^0.2.6
|
||||||
|
vite-plugin-pwa: '>=0.21.2 <1'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@vite-pwa/assets-generator':
|
||||||
|
optional: true
|
||||||
|
|
||||||
'@vite-pwa/vitepress@1.0.0':
|
'@vite-pwa/vitepress@1.0.0':
|
||||||
resolution: {integrity: sha512-i5RFah4urA6tZycYlGyBslVx8cVzbZBcARJLDg5rWMfAkRmyLtpRU6usGfVOwyN9kjJ2Bkm+gBHXF1hhr7HptQ==}
|
resolution: {integrity: sha512-i5RFah4urA6tZycYlGyBslVx8cVzbZBcARJLDg5rWMfAkRmyLtpRU6usGfVOwyN9kjJ2Bkm+gBHXF1hhr7HptQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -4372,10 +4441,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==}
|
resolution: {integrity: sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
|
|
||||||
call-bound@1.0.3:
|
|
||||||
resolution: {integrity: sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
call-bound@1.0.4:
|
call-bound@1.0.4:
|
||||||
resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
|
resolution: {integrity: sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -6082,10 +6147,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==}
|
resolution: {integrity: sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==}
|
||||||
engines: {node: '>=18'}
|
engines: {node: '>=18'}
|
||||||
|
|
||||||
get-intrinsic@1.2.7:
|
|
||||||
resolution: {integrity: sha512-VW6Pxhsrk0KAOqs3WEd0klDiF/+V7gQOpAvY1jVU/LHmaD/kQO4523aiJuikX/QAKYiW6x8Jh+RJej1almdtCA==}
|
|
||||||
engines: {node: '>= 0.4'}
|
|
||||||
|
|
||||||
get-intrinsic@1.3.0:
|
get-intrinsic@1.3.0:
|
||||||
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
|
resolution: {integrity: sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==}
|
||||||
engines: {node: '>= 0.4'}
|
engines: {node: '>= 0.4'}
|
||||||
@@ -7517,10 +7578,6 @@ packages:
|
|||||||
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
resolution: {integrity: sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
|
|
||||||
mime-db@1.53.0:
|
|
||||||
resolution: {integrity: sha512-oHlN/w+3MQ3rba9rqFr6V/ypF10LSkdwUysQL7GkXoTgIWeV+tcXGA852TBxH+gsh8UWoyhR1hKcoMJTuWflpg==}
|
|
||||||
engines: {node: '>= 0.6'}
|
|
||||||
|
|
||||||
mime-db@1.54.0:
|
mime-db@1.54.0:
|
||||||
resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
|
resolution: {integrity: sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
@@ -7714,6 +7771,9 @@ packages:
|
|||||||
resolution: {integrity: sha512-fiVbT7BqxiQqjlR9U3FDGOSERFCKoXVCdxV2FwZuNN7/cmJ42iQx35nUFOAFDcyvemu9Adp+IlsCGlKQYLmBKw==}
|
resolution: {integrity: sha512-fiVbT7BqxiQqjlR9U3FDGOSERFCKoXVCdxV2FwZuNN7/cmJ42iQx35nUFOAFDcyvemu9Adp+IlsCGlKQYLmBKw==}
|
||||||
deprecated: Package no longer supported. Contact support@npmjs.com for more info.
|
deprecated: Package no longer supported. Contact support@npmjs.com for more info.
|
||||||
|
|
||||||
|
non-layered-tidy-tree-layout@2.0.2:
|
||||||
|
resolution: {integrity: sha512-gkXMxRzUH+PB0ax9dUN0yYF0S25BqeAYqhgMaLUFmpXLEk7Fcu8f4emJuOAY0V8kjDICxROIKsTAKsV/v355xw==}
|
||||||
|
|
||||||
normalize-path@3.0.0:
|
normalize-path@3.0.0:
|
||||||
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
resolution: {integrity: sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==}
|
||||||
engines: {node: '>=0.10.0'}
|
engines: {node: '>=0.10.0'}
|
||||||
@@ -9594,6 +9654,18 @@ packages:
|
|||||||
peerDependencies:
|
peerDependencies:
|
||||||
vite: '>=4 <=6'
|
vite: '>=4 <=6'
|
||||||
|
|
||||||
|
vite-plugin-pwa@0.21.2:
|
||||||
|
resolution: {integrity: sha512-vFhH6Waw8itNu37hWUJxL50q+CBbNcMVzsKaYHQVrfxTt3ihk3PeLO22SbiP1UNWzcEPaTQv+YVxe4G0KOjAkg==}
|
||||||
|
engines: {node: '>=16.0.0'}
|
||||||
|
peerDependencies:
|
||||||
|
'@vite-pwa/assets-generator': ^0.2.6
|
||||||
|
vite: ^3.1.0 || ^4.0.0 || ^5.0.0 || ^6.0.0
|
||||||
|
workbox-build: ^7.3.0
|
||||||
|
workbox-window: ^7.3.0
|
||||||
|
peerDependenciesMeta:
|
||||||
|
'@vite-pwa/assets-generator':
|
||||||
|
optional: true
|
||||||
|
|
||||||
vite-plugin-pwa@1.0.0:
|
vite-plugin-pwa@1.0.0:
|
||||||
resolution: {integrity: sha512-X77jo0AOd5OcxmWj3WnVti8n7Kw2tBgV1c8MCXFclrSlDV23ePzv2eTDIALXI2Qo6nJ5pZJeZAuX0AawvRfoeA==}
|
resolution: {integrity: sha512-X77jo0AOd5OcxmWj3WnVti8n7Kw2tBgV1c8MCXFclrSlDV23ePzv2eTDIALXI2Qo6nJ5pZJeZAuX0AawvRfoeA==}
|
||||||
engines: {node: '>=16.0.0'}
|
engines: {node: '>=16.0.0'}
|
||||||
@@ -10648,7 +10720,7 @@ snapshots:
|
|||||||
|
|
||||||
'@babel/code-frame@7.26.2':
|
'@babel/code-frame@7.26.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/helper-validator-identifier': 7.25.9
|
'@babel/helper-validator-identifier': 7.27.1
|
||||||
js-tokens: 4.0.0
|
js-tokens: 4.0.0
|
||||||
picocolors: 1.1.1
|
picocolors: 1.1.1
|
||||||
|
|
||||||
@@ -10670,10 +10742,10 @@ snapshots:
|
|||||||
'@babel/helper-compilation-targets': 7.26.5
|
'@babel/helper-compilation-targets': 7.26.5
|
||||||
'@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9)
|
'@babel/helper-module-transforms': 7.26.0(@babel/core@7.26.9)
|
||||||
'@babel/helpers': 7.26.9
|
'@babel/helpers': 7.26.9
|
||||||
'@babel/parser': 7.26.9
|
'@babel/parser': 7.27.2
|
||||||
'@babel/template': 7.26.9
|
'@babel/template': 7.26.9
|
||||||
'@babel/traverse': 7.26.9
|
'@babel/traverse': 7.26.9
|
||||||
'@babel/types': 7.26.9
|
'@babel/types': 7.27.1
|
||||||
convert-source-map: 2.0.0
|
convert-source-map: 2.0.0
|
||||||
debug: 4.4.0(supports-color@8.1.1)
|
debug: 4.4.0(supports-color@8.1.1)
|
||||||
gensync: 1.0.0-beta.2
|
gensync: 1.0.0-beta.2
|
||||||
@@ -10704,8 +10776,8 @@ snapshots:
|
|||||||
|
|
||||||
'@babel/generator@7.26.9':
|
'@babel/generator@7.26.9':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/parser': 7.26.9
|
'@babel/parser': 7.27.2
|
||||||
'@babel/types': 7.26.9
|
'@babel/types': 7.27.1
|
||||||
'@jridgewell/gen-mapping': 0.3.8
|
'@jridgewell/gen-mapping': 0.3.8
|
||||||
'@jridgewell/trace-mapping': 0.3.25
|
'@jridgewell/trace-mapping': 0.3.25
|
||||||
jsesc: 3.1.0
|
jsesc: 3.1.0
|
||||||
@@ -10810,7 +10882,7 @@ snapshots:
|
|||||||
'@babel/helper-module-imports@7.25.9':
|
'@babel/helper-module-imports@7.25.9':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/traverse': 7.26.9
|
'@babel/traverse': 7.26.9
|
||||||
'@babel/types': 7.26.9
|
'@babel/types': 7.27.1
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
@@ -10825,7 +10897,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.26.9
|
'@babel/core': 7.26.9
|
||||||
'@babel/helper-module-imports': 7.25.9
|
'@babel/helper-module-imports': 7.25.9
|
||||||
'@babel/helper-validator-identifier': 7.25.9
|
'@babel/helper-validator-identifier': 7.27.1
|
||||||
'@babel/traverse': 7.26.9
|
'@babel/traverse': 7.26.9
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -10901,8 +10973,6 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
'@babel/helper-string-parser@7.25.9': {}
|
|
||||||
|
|
||||||
'@babel/helper-string-parser@7.27.1': {}
|
'@babel/helper-string-parser@7.27.1': {}
|
||||||
|
|
||||||
'@babel/helper-validator-identifier@7.25.9': {}
|
'@babel/helper-validator-identifier@7.25.9': {}
|
||||||
@@ -10924,7 +10994,7 @@ snapshots:
|
|||||||
'@babel/helpers@7.26.9':
|
'@babel/helpers@7.26.9':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/template': 7.26.9
|
'@babel/template': 7.26.9
|
||||||
'@babel/types': 7.26.9
|
'@babel/types': 7.27.1
|
||||||
|
|
||||||
'@babel/helpers@7.27.1':
|
'@babel/helpers@7.27.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -10933,7 +11003,7 @@ snapshots:
|
|||||||
|
|
||||||
'@babel/parser@7.26.9':
|
'@babel/parser@7.26.9':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.26.9
|
'@babel/types': 7.27.1
|
||||||
|
|
||||||
'@babel/parser@7.27.2':
|
'@babel/parser@7.27.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -11945,8 +12015,8 @@ snapshots:
|
|||||||
'@babel/template@7.26.9':
|
'@babel/template@7.26.9':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/code-frame': 7.26.2
|
'@babel/code-frame': 7.26.2
|
||||||
'@babel/parser': 7.26.9
|
'@babel/parser': 7.27.2
|
||||||
'@babel/types': 7.26.9
|
'@babel/types': 7.27.1
|
||||||
|
|
||||||
'@babel/template@7.27.2':
|
'@babel/template@7.27.2':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -11958,9 +12028,9 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@babel/code-frame': 7.26.2
|
'@babel/code-frame': 7.26.2
|
||||||
'@babel/generator': 7.26.9
|
'@babel/generator': 7.26.9
|
||||||
'@babel/parser': 7.26.9
|
'@babel/parser': 7.27.2
|
||||||
'@babel/template': 7.26.9
|
'@babel/template': 7.26.9
|
||||||
'@babel/types': 7.26.9
|
'@babel/types': 7.27.1
|
||||||
debug: 4.4.0(supports-color@8.1.1)
|
debug: 4.4.0(supports-color@8.1.1)
|
||||||
globals: 11.12.0
|
globals: 11.12.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -11980,8 +12050,8 @@ snapshots:
|
|||||||
|
|
||||||
'@babel/types@7.26.9':
|
'@babel/types@7.26.9':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/helper-string-parser': 7.25.9
|
'@babel/helper-string-parser': 7.27.1
|
||||||
'@babel/helper-validator-identifier': 7.25.9
|
'@babel/helper-validator-identifier': 7.27.1
|
||||||
|
|
||||||
'@babel/types@7.27.1':
|
'@babel/types@7.27.1':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -13634,24 +13704,24 @@ snapshots:
|
|||||||
|
|
||||||
'@types/babel__core@7.20.5':
|
'@types/babel__core@7.20.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/parser': 7.26.9
|
'@babel/parser': 7.27.2
|
||||||
'@babel/types': 7.26.9
|
'@babel/types': 7.27.1
|
||||||
'@types/babel__generator': 7.6.8
|
'@types/babel__generator': 7.6.8
|
||||||
'@types/babel__template': 7.4.4
|
'@types/babel__template': 7.4.4
|
||||||
'@types/babel__traverse': 7.20.6
|
'@types/babel__traverse': 7.20.6
|
||||||
|
|
||||||
'@types/babel__generator@7.6.8':
|
'@types/babel__generator@7.6.8':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.26.9
|
'@babel/types': 7.27.1
|
||||||
|
|
||||||
'@types/babel__template@7.4.4':
|
'@types/babel__template@7.4.4':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/parser': 7.26.9
|
'@babel/parser': 7.27.2
|
||||||
'@babel/types': 7.26.9
|
'@babel/types': 7.27.1
|
||||||
|
|
||||||
'@types/babel__traverse@7.20.6':
|
'@types/babel__traverse@7.20.6':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/types': 7.26.9
|
'@babel/types': 7.27.1
|
||||||
|
|
||||||
'@types/body-parser@1.19.5':
|
'@types/body-parser@1.19.5':
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -14191,6 +14261,16 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- vue
|
- vue
|
||||||
|
|
||||||
|
'@unocss/astro@66.0.0(vite@6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(vue@3.5.13(typescript@5.7.3))':
|
||||||
|
dependencies:
|
||||||
|
'@unocss/core': 66.0.0
|
||||||
|
'@unocss/reset': 66.0.0
|
||||||
|
'@unocss/vite': 66.0.0(vite@6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(vue@3.5.13(typescript@5.7.3))
|
||||||
|
optionalDependencies:
|
||||||
|
vite: 6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- vue
|
||||||
|
|
||||||
'@unocss/cli@66.0.0':
|
'@unocss/cli@66.0.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@ampproject/remapping': 2.3.0
|
'@ampproject/remapping': 2.3.0
|
||||||
@@ -14326,6 +14406,24 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- vue
|
- vue
|
||||||
|
|
||||||
|
'@unocss/vite@66.0.0(vite@6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(vue@3.5.13(typescript@5.7.3))':
|
||||||
|
dependencies:
|
||||||
|
'@ampproject/remapping': 2.3.0
|
||||||
|
'@unocss/config': 66.0.0
|
||||||
|
'@unocss/core': 66.0.0
|
||||||
|
'@unocss/inspector': 66.0.0(vue@3.5.13(typescript@5.7.3))
|
||||||
|
chokidar: 3.6.0
|
||||||
|
magic-string: 0.30.17
|
||||||
|
tinyglobby: 0.2.12
|
||||||
|
unplugin-utils: 0.2.4
|
||||||
|
vite: 6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- vue
|
||||||
|
|
||||||
|
'@vite-pwa/vitepress@0.5.4(vite-plugin-pwa@0.21.2(vite@6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0))':
|
||||||
|
dependencies:
|
||||||
|
vite-plugin-pwa: 0.21.2(vite@6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0)
|
||||||
|
|
||||||
'@vite-pwa/vitepress@1.0.0(vite-plugin-pwa@1.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0))':
|
'@vite-pwa/vitepress@1.0.0(vite-plugin-pwa@1.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0))':
|
||||||
dependencies:
|
dependencies:
|
||||||
vite-plugin-pwa: 1.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0)
|
vite-plugin-pwa: 1.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0)
|
||||||
@@ -14340,6 +14438,11 @@ snapshots:
|
|||||||
vite: 6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
|
vite: 6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
|
||||||
vue: 3.5.13(typescript@5.7.3)
|
vue: 3.5.13(typescript@5.7.3)
|
||||||
|
|
||||||
|
'@vitejs/plugin-vue@5.2.1(vite@6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(vue@3.5.13(typescript@5.7.3))':
|
||||||
|
dependencies:
|
||||||
|
vite: 6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
|
||||||
|
vue: 3.5.13(typescript@5.7.3)
|
||||||
|
|
||||||
'@vitest/coverage-v8@3.0.6(vitest@3.0.6)':
|
'@vitest/coverage-v8@3.0.6(vitest@3.0.6)':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@ampproject/remapping': 2.3.0
|
'@ampproject/remapping': 2.3.0
|
||||||
@@ -14418,7 +14521,7 @@ snapshots:
|
|||||||
|
|
||||||
'@vue/compiler-core@3.5.13':
|
'@vue/compiler-core@3.5.13':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/parser': 7.26.9
|
'@babel/parser': 7.27.2
|
||||||
'@vue/shared': 3.5.13
|
'@vue/shared': 3.5.13
|
||||||
entities: 4.5.0
|
entities: 4.5.0
|
||||||
estree-walker: 2.0.2
|
estree-walker: 2.0.2
|
||||||
@@ -14431,7 +14534,7 @@ snapshots:
|
|||||||
|
|
||||||
'@vue/compiler-sfc@3.5.13':
|
'@vue/compiler-sfc@3.5.13':
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/parser': 7.26.9
|
'@babel/parser': 7.27.2
|
||||||
'@vue/compiler-core': 3.5.13
|
'@vue/compiler-core': 3.5.13
|
||||||
'@vue/compiler-dom': 3.5.13
|
'@vue/compiler-dom': 3.5.13
|
||||||
'@vue/compiler-ssr': 3.5.13
|
'@vue/compiler-ssr': 3.5.13
|
||||||
@@ -14884,7 +14987,7 @@ snapshots:
|
|||||||
|
|
||||||
array-buffer-byte-length@1.0.2:
|
array-buffer-byte-length@1.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.3
|
call-bound: 1.0.4
|
||||||
is-array-buffer: 3.0.5
|
is-array-buffer: 3.0.5
|
||||||
|
|
||||||
array-flatten@1.1.1: {}
|
array-flatten@1.1.1: {}
|
||||||
@@ -14989,7 +15092,7 @@ snapshots:
|
|||||||
babel-plugin-jest-hoist@29.6.3:
|
babel-plugin-jest-hoist@29.6.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/template': 7.26.9
|
'@babel/template': 7.26.9
|
||||||
'@babel/types': 7.26.9
|
'@babel/types': 7.27.1
|
||||||
'@types/babel__core': 7.20.5
|
'@types/babel__core': 7.20.5
|
||||||
'@types/babel__traverse': 7.20.6
|
'@types/babel__traverse': 7.20.6
|
||||||
|
|
||||||
@@ -15233,14 +15336,9 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
call-bind-apply-helpers: 1.0.2
|
call-bind-apply-helpers: 1.0.2
|
||||||
es-define-property: 1.0.1
|
es-define-property: 1.0.1
|
||||||
get-intrinsic: 1.2.7
|
get-intrinsic: 1.3.0
|
||||||
set-function-length: 1.2.2
|
set-function-length: 1.2.2
|
||||||
|
|
||||||
call-bound@1.0.3:
|
|
||||||
dependencies:
|
|
||||||
call-bind-apply-helpers: 1.0.2
|
|
||||||
get-intrinsic: 1.2.7
|
|
||||||
|
|
||||||
call-bound@1.0.4:
|
call-bound@1.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind-apply-helpers: 1.0.2
|
call-bind-apply-helpers: 1.0.2
|
||||||
@@ -15508,7 +15606,7 @@ snapshots:
|
|||||||
|
|
||||||
compressible@2.0.18:
|
compressible@2.0.18:
|
||||||
dependencies:
|
dependencies:
|
||||||
mime-db: 1.53.0
|
mime-db: 1.54.0
|
||||||
|
|
||||||
compression@1.7.4:
|
compression@1.7.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -16175,7 +16273,7 @@ snapshots:
|
|||||||
array-buffer-byte-length: 1.0.2
|
array-buffer-byte-length: 1.0.2
|
||||||
call-bind: 1.0.8
|
call-bind: 1.0.8
|
||||||
es-get-iterator: 1.1.3
|
es-get-iterator: 1.1.3
|
||||||
get-intrinsic: 1.2.7
|
get-intrinsic: 1.3.0
|
||||||
is-arguments: 1.1.1
|
is-arguments: 1.1.1
|
||||||
is-array-buffer: 3.0.5
|
is-array-buffer: 3.0.5
|
||||||
is-date-object: 1.1.0
|
is-date-object: 1.1.0
|
||||||
@@ -16498,7 +16596,7 @@ snapshots:
|
|||||||
es-get-iterator@1.1.3:
|
es-get-iterator@1.1.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind: 1.0.8
|
call-bind: 1.0.8
|
||||||
get-intrinsic: 1.2.7
|
get-intrinsic: 1.3.0
|
||||||
has-symbols: 1.1.0
|
has-symbols: 1.1.0
|
||||||
is-arguments: 1.1.1
|
is-arguments: 1.1.1
|
||||||
is-map: 2.0.3
|
is-map: 2.0.3
|
||||||
@@ -16518,7 +16616,7 @@ snapshots:
|
|||||||
es-set-tostringtag@2.1.0:
|
es-set-tostringtag@2.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
get-intrinsic: 1.2.7
|
get-intrinsic: 1.3.0
|
||||||
has-tostringtag: 1.0.2
|
has-tostringtag: 1.0.2
|
||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
|
|
||||||
@@ -17214,7 +17312,7 @@ snapshots:
|
|||||||
|
|
||||||
find-test-names@1.29.5(@babel/core@7.26.9):
|
find-test-names@1.29.5(@babel/core@7.26.9):
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/parser': 7.26.9
|
'@babel/parser': 7.27.2
|
||||||
'@babel/plugin-syntax-jsx': 7.25.7(@babel/core@7.26.9)
|
'@babel/plugin-syntax-jsx': 7.25.7(@babel/core@7.26.9)
|
||||||
acorn-walk: 8.3.4
|
acorn-walk: 8.3.4
|
||||||
debug: 4.4.0(supports-color@8.1.1)
|
debug: 4.4.0(supports-color@8.1.1)
|
||||||
@@ -17376,19 +17474,6 @@ snapshots:
|
|||||||
|
|
||||||
get-east-asian-width@1.3.0: {}
|
get-east-asian-width@1.3.0: {}
|
||||||
|
|
||||||
get-intrinsic@1.2.7:
|
|
||||||
dependencies:
|
|
||||||
call-bind-apply-helpers: 1.0.2
|
|
||||||
es-define-property: 1.0.1
|
|
||||||
es-errors: 1.3.0
|
|
||||||
es-object-atoms: 1.1.1
|
|
||||||
function-bind: 1.1.2
|
|
||||||
get-proto: 1.0.1
|
|
||||||
gopd: 1.2.0
|
|
||||||
has-symbols: 1.1.0
|
|
||||||
hasown: 2.0.2
|
|
||||||
math-intrinsics: 1.1.0
|
|
||||||
|
|
||||||
get-intrinsic@1.3.0:
|
get-intrinsic@1.3.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind-apply-helpers: 1.0.2
|
call-bind-apply-helpers: 1.0.2
|
||||||
@@ -17842,8 +17927,8 @@ snapshots:
|
|||||||
is-array-buffer@3.0.5:
|
is-array-buffer@3.0.5:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind: 1.0.8
|
call-bind: 1.0.8
|
||||||
call-bound: 1.0.3
|
call-bound: 1.0.4
|
||||||
get-intrinsic: 1.2.7
|
get-intrinsic: 1.3.0
|
||||||
|
|
||||||
is-arrayish@0.2.1: {}
|
is-arrayish@0.2.1: {}
|
||||||
|
|
||||||
@@ -17867,7 +17952,7 @@ snapshots:
|
|||||||
|
|
||||||
is-boolean-object@1.2.2:
|
is-boolean-object@1.2.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.3
|
call-bound: 1.0.4
|
||||||
has-tostringtag: 1.0.2
|
has-tostringtag: 1.0.2
|
||||||
|
|
||||||
is-builtin-module@5.0.0:
|
is-builtin-module@5.0.0:
|
||||||
@@ -17888,7 +17973,7 @@ snapshots:
|
|||||||
|
|
||||||
is-date-object@1.1.0:
|
is-date-object@1.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.3
|
call-bound: 1.0.4
|
||||||
has-tostringtag: 1.0.2
|
has-tostringtag: 1.0.2
|
||||||
|
|
||||||
is-decimal@1.0.4: {}
|
is-decimal@1.0.4: {}
|
||||||
@@ -17937,7 +18022,7 @@ snapshots:
|
|||||||
|
|
||||||
is-number-object@1.1.1:
|
is-number-object@1.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.3
|
call-bound: 1.0.4
|
||||||
has-tostringtag: 1.0.2
|
has-tostringtag: 1.0.2
|
||||||
|
|
||||||
is-number@7.0.0: {}
|
is-number@7.0.0: {}
|
||||||
@@ -17960,7 +18045,7 @@ snapshots:
|
|||||||
|
|
||||||
is-regex@1.2.1:
|
is-regex@1.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.3
|
call-bound: 1.0.4
|
||||||
gopd: 1.2.0
|
gopd: 1.2.0
|
||||||
has-tostringtag: 1.0.2
|
has-tostringtag: 1.0.2
|
||||||
hasown: 2.0.2
|
hasown: 2.0.2
|
||||||
@@ -17971,7 +18056,7 @@ snapshots:
|
|||||||
|
|
||||||
is-shared-array-buffer@1.0.4:
|
is-shared-array-buffer@1.0.4:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.3
|
call-bound: 1.0.4
|
||||||
|
|
||||||
is-stream@1.1.0: {}
|
is-stream@1.1.0: {}
|
||||||
|
|
||||||
@@ -17981,7 +18066,7 @@ snapshots:
|
|||||||
|
|
||||||
is-string@1.1.1:
|
is-string@1.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.3
|
call-bound: 1.0.4
|
||||||
has-tostringtag: 1.0.2
|
has-tostringtag: 1.0.2
|
||||||
|
|
||||||
is-subdir@1.2.0:
|
is-subdir@1.2.0:
|
||||||
@@ -17990,7 +18075,7 @@ snapshots:
|
|||||||
|
|
||||||
is-symbol@1.1.1:
|
is-symbol@1.1.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.3
|
call-bound: 1.0.4
|
||||||
has-symbols: 1.1.0
|
has-symbols: 1.1.0
|
||||||
safe-regex-test: 1.1.0
|
safe-regex-test: 1.1.0
|
||||||
|
|
||||||
@@ -18015,7 +18100,7 @@ snapshots:
|
|||||||
is-weakset@2.0.3:
|
is-weakset@2.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind: 1.0.8
|
call-bind: 1.0.8
|
||||||
get-intrinsic: 1.2.7
|
get-intrinsic: 1.3.0
|
||||||
|
|
||||||
is-what@4.1.16: {}
|
is-what@4.1.16: {}
|
||||||
|
|
||||||
@@ -18053,7 +18138,7 @@ snapshots:
|
|||||||
istanbul-lib-instrument@5.2.1:
|
istanbul-lib-instrument@5.2.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.26.9
|
'@babel/core': 7.26.9
|
||||||
'@babel/parser': 7.26.9
|
'@babel/parser': 7.27.2
|
||||||
'@istanbuljs/schema': 0.1.3
|
'@istanbuljs/schema': 0.1.3
|
||||||
istanbul-lib-coverage: 3.2.2
|
istanbul-lib-coverage: 3.2.2
|
||||||
semver: 6.3.1
|
semver: 6.3.1
|
||||||
@@ -18063,7 +18148,7 @@ snapshots:
|
|||||||
istanbul-lib-instrument@6.0.3:
|
istanbul-lib-instrument@6.0.3:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/core': 7.26.9
|
'@babel/core': 7.26.9
|
||||||
'@babel/parser': 7.26.9
|
'@babel/parser': 7.27.2
|
||||||
'@istanbuljs/schema': 0.1.3
|
'@istanbuljs/schema': 0.1.3
|
||||||
istanbul-lib-coverage: 3.2.2
|
istanbul-lib-coverage: 3.2.2
|
||||||
semver: 7.7.1
|
semver: 7.7.1
|
||||||
@@ -18382,7 +18467,7 @@ snapshots:
|
|||||||
'@babel/generator': 7.26.9
|
'@babel/generator': 7.26.9
|
||||||
'@babel/plugin-syntax-jsx': 7.25.7(@babel/core@7.26.9)
|
'@babel/plugin-syntax-jsx': 7.25.7(@babel/core@7.26.9)
|
||||||
'@babel/plugin-syntax-typescript': 7.25.7(@babel/core@7.26.9)
|
'@babel/plugin-syntax-typescript': 7.25.7(@babel/core@7.26.9)
|
||||||
'@babel/types': 7.26.9
|
'@babel/types': 7.27.1
|
||||||
'@jest/expect-utils': 29.7.0
|
'@jest/expect-utils': 29.7.0
|
||||||
'@jest/transform': 29.7.0
|
'@jest/transform': 29.7.0
|
||||||
'@jest/types': 29.6.3
|
'@jest/types': 29.6.3
|
||||||
@@ -19246,8 +19331,6 @@ snapshots:
|
|||||||
|
|
||||||
mime-db@1.52.0: {}
|
mime-db@1.52.0: {}
|
||||||
|
|
||||||
mime-db@1.53.0: {}
|
|
||||||
|
|
||||||
mime-db@1.54.0: {}
|
mime-db@1.54.0: {}
|
||||||
|
|
||||||
mime-types@2.1.35:
|
mime-types@2.1.35:
|
||||||
@@ -19392,13 +19475,15 @@ snapshots:
|
|||||||
|
|
||||||
node-source-walk@7.0.0:
|
node-source-walk@7.0.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@babel/parser': 7.26.9
|
'@babel/parser': 7.27.2
|
||||||
|
|
||||||
nomnom@1.5.2:
|
nomnom@1.5.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
colors: 0.5.1
|
colors: 0.5.1
|
||||||
underscore: 1.1.7
|
underscore: 1.1.7
|
||||||
|
|
||||||
|
non-layered-tidy-tree-layout@2.0.2: {}
|
||||||
|
|
||||||
normalize-path@3.0.0: {}
|
normalize-path@3.0.0: {}
|
||||||
|
|
||||||
normalize-url@6.1.0: {}
|
normalize-url@6.1.0: {}
|
||||||
@@ -19497,7 +19582,7 @@ snapshots:
|
|||||||
object.assign@4.1.7:
|
object.assign@4.1.7:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bind: 1.0.8
|
call-bind: 1.0.8
|
||||||
call-bound: 1.0.3
|
call-bound: 1.0.4
|
||||||
define-properties: 1.2.1
|
define-properties: 1.2.1
|
||||||
es-object-atoms: 1.1.1
|
es-object-atoms: 1.1.1
|
||||||
has-symbols: 1.1.0
|
has-symbols: 1.1.0
|
||||||
@@ -20388,7 +20473,7 @@ snapshots:
|
|||||||
|
|
||||||
safe-regex-test@1.1.0:
|
safe-regex-test@1.1.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.3
|
call-bound: 1.0.4
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
is-regex: 1.2.1
|
is-regex: 1.2.1
|
||||||
|
|
||||||
@@ -20524,7 +20609,7 @@ snapshots:
|
|||||||
define-data-property: 1.1.4
|
define-data-property: 1.1.4
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
function-bind: 1.1.2
|
function-bind: 1.1.2
|
||||||
get-intrinsic: 1.2.7
|
get-intrinsic: 1.3.0
|
||||||
gopd: 1.2.0
|
gopd: 1.2.0
|
||||||
has-property-descriptors: 1.0.2
|
has-property-descriptors: 1.0.2
|
||||||
|
|
||||||
@@ -20613,16 +20698,16 @@ snapshots:
|
|||||||
|
|
||||||
side-channel-map@1.0.1:
|
side-channel-map@1.0.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.3
|
call-bound: 1.0.4
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
get-intrinsic: 1.2.7
|
get-intrinsic: 1.3.0
|
||||||
object-inspect: 1.13.4
|
object-inspect: 1.13.4
|
||||||
|
|
||||||
side-channel-weakmap@1.0.2:
|
side-channel-weakmap@1.0.2:
|
||||||
dependencies:
|
dependencies:
|
||||||
call-bound: 1.0.3
|
call-bound: 1.0.4
|
||||||
es-errors: 1.3.0
|
es-errors: 1.3.0
|
||||||
get-intrinsic: 1.2.7
|
get-intrinsic: 1.3.0
|
||||||
object-inspect: 1.13.4
|
object-inspect: 1.13.4
|
||||||
side-channel-map: 1.0.1
|
side-channel-map: 1.0.1
|
||||||
|
|
||||||
@@ -21085,7 +21170,7 @@ snapshots:
|
|||||||
terser@5.34.1:
|
terser@5.34.1:
|
||||||
dependencies:
|
dependencies:
|
||||||
'@jridgewell/source-map': 0.3.6
|
'@jridgewell/source-map': 0.3.6
|
||||||
acorn: 8.14.0
|
acorn: 8.14.1
|
||||||
commander: 2.20.3
|
commander: 2.20.3
|
||||||
source-map-support: 0.5.21
|
source-map-support: 0.5.21
|
||||||
|
|
||||||
@@ -21455,6 +21540,33 @@ snapshots:
|
|||||||
- supports-color
|
- supports-color
|
||||||
- vue
|
- vue
|
||||||
|
|
||||||
|
unocss@66.0.0(postcss@8.5.3)(vite@6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(vue@3.5.13(typescript@5.7.3)):
|
||||||
|
dependencies:
|
||||||
|
'@unocss/astro': 66.0.0(vite@6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(vue@3.5.13(typescript@5.7.3))
|
||||||
|
'@unocss/cli': 66.0.0
|
||||||
|
'@unocss/core': 66.0.0
|
||||||
|
'@unocss/postcss': 66.0.0(postcss@8.5.3)
|
||||||
|
'@unocss/preset-attributify': 66.0.0
|
||||||
|
'@unocss/preset-icons': 66.0.0
|
||||||
|
'@unocss/preset-mini': 66.0.0
|
||||||
|
'@unocss/preset-tagify': 66.0.0
|
||||||
|
'@unocss/preset-typography': 66.0.0
|
||||||
|
'@unocss/preset-uno': 66.0.0
|
||||||
|
'@unocss/preset-web-fonts': 66.0.0
|
||||||
|
'@unocss/preset-wind': 66.0.0
|
||||||
|
'@unocss/preset-wind3': 66.0.0
|
||||||
|
'@unocss/transformer-attributify-jsx': 66.0.0
|
||||||
|
'@unocss/transformer-compile-class': 66.0.0
|
||||||
|
'@unocss/transformer-directives': 66.0.0
|
||||||
|
'@unocss/transformer-variant-group': 66.0.0
|
||||||
|
'@unocss/vite': 66.0.0(vite@6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(vue@3.5.13(typescript@5.7.3))
|
||||||
|
optionalDependencies:
|
||||||
|
vite: 6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- postcss
|
||||||
|
- supports-color
|
||||||
|
- vue
|
||||||
|
|
||||||
unpipe@1.0.0: {}
|
unpipe@1.0.0: {}
|
||||||
|
|
||||||
unplugin-utils@0.2.4:
|
unplugin-utils@0.2.4:
|
||||||
@@ -21480,7 +21592,7 @@ snapshots:
|
|||||||
|
|
||||||
unplugin@2.2.0:
|
unplugin@2.2.0:
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.14.0
|
acorn: 8.14.1
|
||||||
webpack-virtual-modules: 0.6.2
|
webpack-virtual-modules: 0.6.2
|
||||||
|
|
||||||
untildify@4.0.0: {}
|
untildify@4.0.0: {}
|
||||||
@@ -21570,6 +21682,17 @@ snapshots:
|
|||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
|
|
||||||
|
vite-plugin-pwa@0.21.2(vite@6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0):
|
||||||
|
dependencies:
|
||||||
|
debug: 4.4.0(supports-color@8.1.1)
|
||||||
|
pretty-bytes: 6.1.1
|
||||||
|
tinyglobby: 0.2.12
|
||||||
|
vite: 6.1.6(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1)
|
||||||
|
workbox-build: 7.1.1(@types/babel__core@7.20.5)
|
||||||
|
workbox-window: 7.3.0
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
|
||||||
vite-plugin-pwa@1.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0):
|
vite-plugin-pwa@1.0.0(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.1))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0):
|
||||||
dependencies:
|
dependencies:
|
||||||
debug: 4.4.0(supports-color@8.1.1)
|
debug: 4.4.0(supports-color@8.1.1)
|
||||||
@@ -22035,7 +22158,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
available-typed-arrays: 1.0.7
|
available-typed-arrays: 1.0.7
|
||||||
call-bind: 1.0.8
|
call-bind: 1.0.8
|
||||||
call-bound: 1.0.3
|
call-bound: 1.0.4
|
||||||
for-each: 0.3.5
|
for-each: 0.3.5
|
||||||
gopd: 1.2.0
|
gopd: 1.2.0
|
||||||
has-tostringtag: 1.0.2
|
has-tostringtag: 1.0.2
|
||||||
|
Reference in New Issue
Block a user