mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-10-11 18:19:42 +02:00
Compare commits
21 Commits
mindmap-la
...
sidv/clean
Author | SHA1 | Date | |
---|---|---|---|
![]() |
6462f73bdb | ||
![]() |
cfe1723c6c | ||
![]() |
6d8b936319 | ||
![]() |
f992d95082 | ||
![]() |
f2276f93cd | ||
![]() |
b52f5058c9 | ||
![]() |
5e20087252 | ||
![]() |
b49036068f | ||
![]() |
5f3d4cb913 | ||
![]() |
b11eb93ab2 | ||
![]() |
e4f19480cd | ||
![]() |
a331a958c0 | ||
![]() |
134fca3f1d | ||
![]() |
ef7c0a1936 | ||
![]() |
2c5403c0f9 | ||
![]() |
3b0cb1271e | ||
![]() |
96c06a681d | ||
![]() |
ff9d26bc70 | ||
![]() |
2ddc3403de | ||
![]() |
4535911a3a | ||
![]() |
9d838d4e7a |
@@ -87,7 +87,6 @@ NODIR
|
||||
NSTR
|
||||
outdir
|
||||
Qcontrolx
|
||||
QSTR
|
||||
reinit
|
||||
rels
|
||||
reqs
|
||||
|
4
.github/workflows/e2e-applitools.yml
vendored
4
.github/workflows/e2e-applitools.yml
vendored
@@ -45,13 +45,15 @@ jobs:
|
||||
- if: ${{ env.USE_APPLI }}
|
||||
name: Notify applitools of new batch
|
||||
# Copied from docs https://applitools.com/docs/topics/integrations/github-integration-ci-setup.html
|
||||
run: curl -L -d '' -X POST "$APPLITOOLS_SERVER_URL/api/externals/github/push?apiKey=$APPLITOOLS_API_KEY&CommitSha=$GITHUB_SHA&BranchName=${APPLITOOLS_BRANCH}$&ParentBranchName=$APPLITOOLS_PARENT_BRANCH"
|
||||
env:
|
||||
# e.g. mermaid-js/mermaid/my-branch
|
||||
APPLITOOLS_BRANCH: ${{ github.repository }}/${{ github.ref_name }}
|
||||
APPLITOOLS_PARENT_BRANCH: ${{ github.event.inputs.parent_branch }}
|
||||
APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }}
|
||||
APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com'
|
||||
uses: wei/curl@61d92b5169ea0425820dd13cf6fbad66b483e9f1
|
||||
with:
|
||||
args: -X POST "$APPLITOOLS_SERVER_URL/api/externals/github/push?apiKey=$APPLITOOLS_API_KEY&CommitSha=$GITHUB_SHA&BranchName=${APPLITOOLS_BRANCH}$&ParentBranchName=$APPLITOOLS_PARENT_BRANCH"
|
||||
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
|
1
.gitignore
vendored
1
.gitignore
vendored
@@ -52,4 +52,3 @@ vite.config.ts.timestamp-*
|
||||
|
||||
# autogenereated by langium-cli
|
||||
generated/
|
||||
.cursor/*
|
||||
|
@@ -22,7 +22,7 @@ const batchId: string =
|
||||
'mermaid-batch-' +
|
||||
(Cypress.env('useAppli')
|
||||
? Date.now().toString()
|
||||
: Cypress.env('CYPRESS_COMMIT') || Date.now().toString());
|
||||
: (Cypress.env('CYPRESS_COMMIT') ?? Date.now().toString()));
|
||||
|
||||
export const mermaidUrl = (
|
||||
graphStr: string | string[],
|
||||
@@ -61,9 +61,7 @@ export const imgSnapshotTest = (
|
||||
sequence: {
|
||||
...(_options.sequence ?? {}),
|
||||
actorFontFamily: 'courier',
|
||||
noteFontFamily: _options.sequence?.noteFontFamily
|
||||
? _options.sequence.noteFontFamily
|
||||
: 'courier',
|
||||
noteFontFamily: _options.sequence?.noteFontFamily ?? 'courier',
|
||||
messageFontFamily: 'courier',
|
||||
},
|
||||
};
|
||||
|
@@ -14,7 +14,7 @@ looks.forEach((look) => {
|
||||
directions.forEach((direction) => {
|
||||
forms.forEach((form) => {
|
||||
labelPos.forEach((pos) => {
|
||||
describe(`Test iconShape in ${form ? `${form} form,` : ''} ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => {
|
||||
describe(`Test iconShape in ${form ? `${form} form,` : ''} ${look} look and dir ${direction} with label position ${pos ?? 'not defined'}`, () => {
|
||||
it(`without label`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell'`;
|
||||
|
@@ -12,7 +12,7 @@ const labelPos = [undefined, 't', 'b'] as const;
|
||||
looks.forEach((look) => {
|
||||
directions.forEach((direction) => {
|
||||
labelPos.forEach((pos) => {
|
||||
describe(`Test imageShape in ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => {
|
||||
describe(`Test imageShape in ${look} look and dir ${direction} with label position ${pos ?? 'not defined'}`, () => {
|
||||
it(`without label`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', w: '100', h: '100' }\n`;
|
||||
|
@@ -214,7 +214,7 @@ section Checkout from website
|
||||
$lines.each((index, el) => {
|
||||
const bbox = el.getBBox();
|
||||
expect(bbox.width).to.be.lte(320);
|
||||
maxLineWidth = Math.max(maxLineWidth || 0, bbox.width);
|
||||
maxLineWidth = Math.max(maxLineWidth ?? 0, bbox.width);
|
||||
});
|
||||
|
||||
/** The expected margin between the diagram and the legend is 150px, as defined by
|
||||
|
@@ -190,9 +190,7 @@ export const render = async (
|
||||
const children = nodeArr.filter((node: { parentId: any }) => node.parentId === subgraph.id);
|
||||
children.forEach((node: any) => {
|
||||
parentLookupDb.parentById[node.id] = subgraph.id;
|
||||
if (parentLookupDb.childrenById[subgraph.id] === undefined) {
|
||||
parentLookupDb.childrenById[subgraph.id] = [];
|
||||
}
|
||||
parentLookupDb.childrenById[subgraph.id] ??= [];
|
||||
parentLookupDb.childrenById[subgraph.id].push(node);
|
||||
});
|
||||
});
|
||||
@@ -381,10 +379,10 @@ export const render = async (
|
||||
}
|
||||
|
||||
edgeData.labelType = edge.labelType;
|
||||
edgeData.label = (edge?.text || '').replace(common.lineBreakRegex, '\n');
|
||||
edgeData.label = (edge?.text ?? '').replace(common.lineBreakRegex, '\n');
|
||||
|
||||
if (edge.style === undefined) {
|
||||
edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none;';
|
||||
edgeData.style = edgeData.style ?? 'stroke: #333; stroke-width: 1.5px;fill:none;';
|
||||
}
|
||||
|
||||
edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:');
|
||||
@@ -725,9 +723,7 @@ export const render = async (
|
||||
inter = inter2;
|
||||
}
|
||||
}
|
||||
if (!inter) {
|
||||
inter = intersection(bounds, lastPointOutside, point);
|
||||
}
|
||||
inter ??= intersection(bounds, lastPointOutside, point);
|
||||
|
||||
// Check case where the intersection is the same as the last point
|
||||
let pointPresent = false;
|
||||
@@ -840,8 +836,8 @@ export const render = async (
|
||||
node.labels = [
|
||||
{
|
||||
text: node.label,
|
||||
width: node?.labelData?.width || 50,
|
||||
height: node?.labelData?.height || 50,
|
||||
width: node?.labelData?.width ?? 50,
|
||||
height: node?.labelData?.height ?? 50,
|
||||
},
|
||||
(node.width = node.width + 2 * node.padding),
|
||||
log.debug('UIO node label', node?.labelData?.width, node.padding),
|
||||
@@ -917,7 +913,7 @@ export const render = async (
|
||||
if (edge.sections) {
|
||||
const src = edge.sections[0].startPoint;
|
||||
const dest = edge.sections[0].endPoint;
|
||||
const segments = edge.sections[0].bendPoints ? edge.sections[0].bendPoints : [];
|
||||
const segments = edge.sections[0].bendPoints ?? [];
|
||||
|
||||
const segPoints = segments.map((segment: { x: any; y: any }) => {
|
||||
return { x: segment.x + offset.x, y: segment.y + offset.y };
|
||||
|
@@ -30,7 +30,7 @@ export const updateCurrentConfig = (siteCfg: MermaidConfig, _directives: Mermaid
|
||||
if (sumOfDirectives.theme && sumOfDirectives.theme in theme) {
|
||||
const tmpConfigFromInitialize = assignWithDepth({}, configFromInitialize);
|
||||
const themeVariables = assignWithDepth(
|
||||
tmpConfigFromInitialize.themeVariables || {},
|
||||
tmpConfigFromInitialize.themeVariables ?? {},
|
||||
sumOfDirectives.themeVariables
|
||||
);
|
||||
if (cfg.theme && cfg.theme in theme) {
|
||||
|
@@ -238,7 +238,7 @@ let clusterElems = {};
|
||||
|
||||
export const insertCluster = (elem, node) => {
|
||||
log.trace('Inserting cluster');
|
||||
const shape = node.shape || 'rect';
|
||||
const shape = node.shape ?? 'rect';
|
||||
clusterElems[node.id] = shapes[shape](elem, node);
|
||||
};
|
||||
export const getClusterTitleWidth = (elem, node) => {
|
||||
|
@@ -45,7 +45,7 @@ function addHtmlLabel(node) {
|
||||
* @deprecated svg-util/createText instead
|
||||
*/
|
||||
const createLabel = (_vertexText, style, isTitle, isNode) => {
|
||||
let vertexText = _vertexText || '';
|
||||
let vertexText = _vertexText ?? '';
|
||||
if (typeof vertexText === 'object') {
|
||||
vertexText = vertexText[0];
|
||||
}
|
||||
|
@@ -69,9 +69,7 @@ export const insertEdgeLabel = (elem, edge) => {
|
||||
fo = inner.node().appendChild(startLabelElement);
|
||||
const slBox = startLabelElement.getBBox();
|
||||
inner.attr('transform', 'translate(' + -slBox.width / 2 + ', ' + -slBox.height / 2 + ')');
|
||||
if (!terminalLabels[edge.id]) {
|
||||
terminalLabels[edge.id] = {};
|
||||
}
|
||||
terminalLabels[edge.id] ??= {};
|
||||
terminalLabels[edge.id].startLeft = startEdgeLabelLeft;
|
||||
setTerminalWidth(fo, edge.startLabelLeft);
|
||||
}
|
||||
@@ -85,9 +83,7 @@ export const insertEdgeLabel = (elem, edge) => {
|
||||
const slBox = startLabelElement.getBBox();
|
||||
inner.attr('transform', 'translate(' + -slBox.width / 2 + ', ' + -slBox.height / 2 + ')');
|
||||
|
||||
if (!terminalLabels[edge.id]) {
|
||||
terminalLabels[edge.id] = {};
|
||||
}
|
||||
terminalLabels[edge.id] ??= {};
|
||||
terminalLabels[edge.id].startRight = startEdgeLabelRight;
|
||||
setTerminalWidth(fo, edge.startLabelRight);
|
||||
}
|
||||
@@ -102,9 +98,7 @@ export const insertEdgeLabel = (elem, edge) => {
|
||||
|
||||
endEdgeLabelLeft.node().appendChild(endLabelElement);
|
||||
|
||||
if (!terminalLabels[edge.id]) {
|
||||
terminalLabels[edge.id] = {};
|
||||
}
|
||||
terminalLabels[edge.id] ??= {};
|
||||
terminalLabels[edge.id].endLeft = endEdgeLabelLeft;
|
||||
setTerminalWidth(fo, edge.endLabelLeft);
|
||||
}
|
||||
@@ -119,9 +113,7 @@ export const insertEdgeLabel = (elem, edge) => {
|
||||
inner.attr('transform', 'translate(' + -slBox.width / 2 + ', ' + -slBox.height / 2 + ')');
|
||||
|
||||
endEdgeLabelRight.node().appendChild(endLabelElement);
|
||||
if (!terminalLabels[edge.id]) {
|
||||
terminalLabels[edge.id] = {};
|
||||
}
|
||||
terminalLabels[edge.id] ??= {};
|
||||
terminalLabels[edge.id].endRight = endEdgeLabelRight;
|
||||
setTerminalWidth(fo, edge.endLabelRight);
|
||||
}
|
||||
@@ -141,7 +133,7 @@ function setTerminalWidth(fo, value) {
|
||||
|
||||
export const positionEdgeLabel = (edge, paths) => {
|
||||
log.debug('Moving label abc88 ', edge.id, edge.label, edgeLabels[edge.id], paths);
|
||||
let path = paths.updatedPath ? paths.updatedPath : paths.originalPath;
|
||||
let path = paths.updatedPath ?? paths.originalPath;
|
||||
const siteConfig = getConfig();
|
||||
const { subGraphTitleTotalMargin } = getSubGraphTitleMargins(siteConfig);
|
||||
if (edge.label) {
|
||||
|
@@ -4,7 +4,9 @@ import * as graphlibJson from 'dagre-d3-es/src/graphlib/json.js';
|
||||
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
|
||||
|
||||
export let clusterDb = {};
|
||||
/** @type {Record<string, string[]>} */
|
||||
let descendants = {};
|
||||
/** @type {Record<string, string>} */
|
||||
let parents = {};
|
||||
|
||||
export const clear = () => {
|
||||
|
@@ -15,9 +15,7 @@ const formatClass = (str) => {
|
||||
return '';
|
||||
};
|
||||
const getClassesFromNode = (node, otherClasses) => {
|
||||
return `${otherClasses ? otherClasses : 'node default'}${formatClass(node.classes)} ${formatClass(
|
||||
node.class
|
||||
)}`;
|
||||
return `${otherClasses ?? 'node default'}${formatClass(node.classes)} ${formatClass(node.class)}`;
|
||||
};
|
||||
|
||||
const question = async (parent, node) => {
|
||||
@@ -57,7 +55,7 @@ const choice = (parent, node) => {
|
||||
const shapeSvg = parent
|
||||
.insert('g')
|
||||
.attr('class', 'node default')
|
||||
.attr('id', node.domId || node.id);
|
||||
.attr('id', node.domId ?? node.id);
|
||||
|
||||
const s = 28;
|
||||
const points = [
|
||||
@@ -566,7 +564,7 @@ const rectWithTitle = (parent, node) => {
|
||||
const shapeSvg = parent
|
||||
.insert('g')
|
||||
.attr('class', classes)
|
||||
.attr('id', node.domId || node.id);
|
||||
.attr('id', node.domId ?? node.id);
|
||||
|
||||
// Create the title label and insert it after the rect
|
||||
const rect = shapeSvg.insert('rect', ':first-child');
|
||||
@@ -808,7 +806,7 @@ const start = (parent, node) => {
|
||||
const shapeSvg = parent
|
||||
.insert('g')
|
||||
.attr('class', 'node default')
|
||||
.attr('id', node.domId || node.id);
|
||||
.attr('id', node.domId ?? node.id);
|
||||
const circle = shapeSvg.insert('circle', ':first-child');
|
||||
|
||||
// center the circle around its coordinate
|
||||
@@ -827,7 +825,7 @@ const forkJoin = (parent, node, dir) => {
|
||||
const shapeSvg = parent
|
||||
.insert('g')
|
||||
.attr('class', 'node default')
|
||||
.attr('id', node.domId || node.id);
|
||||
.attr('id', node.domId ?? node.id);
|
||||
|
||||
let width = 70;
|
||||
let height = 10;
|
||||
@@ -859,7 +857,7 @@ const end = (parent, node) => {
|
||||
const shapeSvg = parent
|
||||
.insert('g')
|
||||
.attr('class', 'node default')
|
||||
.attr('id', node.domId || node.id);
|
||||
.attr('id', node.domId ?? node.id);
|
||||
const innerCircle = shapeSvg.insert('circle', ':first-child');
|
||||
const circle = shapeSvg.insert('circle', ':first-child');
|
||||
|
||||
@@ -891,7 +889,7 @@ const class_box = (parent, node) => {
|
||||
const shapeSvg = parent
|
||||
.insert('g')
|
||||
.attr('class', classes)
|
||||
.attr('id', node.domId || node.id);
|
||||
.attr('id', node.domId ?? node.id);
|
||||
|
||||
// Create the title label and insert it after the rect
|
||||
const rect = shapeSvg.insert('rect', ':first-child');
|
||||
|
@@ -88,7 +88,7 @@ function positionNodes(db: ArchitectureDB, cy: cytoscape.Core) {
|
||||
data.y = node.position().y;
|
||||
|
||||
const nodeElem = db.getElementById(data.id);
|
||||
nodeElem.attr('transform', 'translate(' + (data.x || 0) + ',' + (data.y || 0) + ')');
|
||||
nodeElem.attr('transform', 'translate(' + (data.x ?? 0) + ',' + (data.y ?? 0) + ')');
|
||||
});
|
||||
}
|
||||
|
||||
|
@@ -82,9 +82,7 @@ export const setCssClass = function (itemIds: string, cssClassName: string) {
|
||||
foundBlock = { id: trimmedId, type: 'na', children: [] } as Block;
|
||||
blockDatabase.set(trimmedId, foundBlock);
|
||||
}
|
||||
if (!foundBlock.classes) {
|
||||
foundBlock.classes = [];
|
||||
}
|
||||
foundBlock.classes ??= [];
|
||||
foundBlock.classes.push(cssClassName);
|
||||
});
|
||||
};
|
||||
|
@@ -10,7 +10,7 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
|
||||
const vertex = block;
|
||||
|
||||
let classStr = 'default';
|
||||
if ((vertex?.classes?.length || 0) > 0) {
|
||||
if ((vertex?.classes?.length ?? 0) > 0) {
|
||||
classStr = (vertex?.classes ?? []).join(' ');
|
||||
}
|
||||
classStr = classStr + ' flowchart-label';
|
||||
|
@@ -41,7 +41,7 @@ export class ClassDB implements DiagramDB {
|
||||
private namespaces = new Map<string, NamespaceNode>();
|
||||
private namespaceCounter = 0;
|
||||
|
||||
private functions: any[] = [];
|
||||
private functions: ((element: Element) => void)[] = [];
|
||||
|
||||
constructor() {
|
||||
this.functions.push(this.setupToolTips.bind(this));
|
||||
@@ -477,7 +477,7 @@ export class ClassDB implements DiagramDB {
|
||||
let tooltipElem: Selection<HTMLDivElement, unknown, HTMLElement, unknown> =
|
||||
select('.mermaidTooltip');
|
||||
// @ts-expect-error - Incorrect types
|
||||
if ((tooltipElem._groups || tooltipElem)[0][0] === null) {
|
||||
if ((tooltipElem._groups ?? tooltipElem)[0][0] === null) {
|
||||
tooltipElem = select('body')
|
||||
.append('div')
|
||||
.attr('class', 'mermaidTooltip')
|
||||
|
@@ -13,9 +13,7 @@ export const diagram: DiagramDefinition = {
|
||||
renderer,
|
||||
styles,
|
||||
init: (cnf) => {
|
||||
if (!cnf.class) {
|
||||
cnf.class = {};
|
||||
}
|
||||
cnf.class ??= {};
|
||||
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
},
|
||||
};
|
||||
|
@@ -13,9 +13,7 @@ export const diagram: DiagramDefinition = {
|
||||
renderer,
|
||||
styles,
|
||||
init: (cnf) => {
|
||||
if (!cnf.class) {
|
||||
cnf.class = {};
|
||||
}
|
||||
cnf.class ??= {};
|
||||
cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute;
|
||||
},
|
||||
};
|
||||
|
@@ -117,7 +117,7 @@ export const addClasses = function (
|
||||
style: styles.style,
|
||||
id: vertex.id,
|
||||
domId: vertex.domId,
|
||||
tooltip: diagObj.db.getTooltip(vertex.id, parent) || '',
|
||||
tooltip: diagObj.db.getTooltip(vertex.id, parent) ?? '',
|
||||
haveCallback: vertex.haveCallback,
|
||||
link: vertex.link,
|
||||
width: vertex.type === 'group' ? 500 : undefined,
|
||||
|
@@ -1,19 +0,0 @@
|
||||
orgChart
|
||||
%% ex2
|
||||
CEO[Mark Davies CEO]
|
||||
---
|
||||
VPFinance[Leslie Deen VP Finance]
|
||||
VPHR[David Soft VP HR]
|
||||
---
|
||||
VPMA[Achmed Jo VP marketing]
|
||||
VPLegal[Elena Prem VP Legal]
|
||||
PMA[Sudan Ali]
|
||||
Noel
|
||||
Tom
|
||||
Alex
|
||||
Sneil
|
||||
PMB[Sekar Sha]
|
||||
John
|
||||
Dan
|
||||
David
|
||||
Jan
|
@@ -1,7 +0,0 @@
|
||||
orgChart
|
||||
%% ex2
|
||||
CEO[Mark Davies CEO] --o VPFinance[Leslie Deen VP Finance] & VPHR[David Soft VP HR]
|
||||
CEO --o VPMA[Achmed Jo VP marketing] & VPLegal[Elena Prem VP Legal]
|
||||
CEO --> PMA[Sudan Ali] & PMB[Sekar Sha]
|
||||
PMA --> Noel & Tom & Alex & Sneil
|
||||
PMB --> John & Dan & David & Jan
|
Binary file not shown.
Before Width: | Height: | Size: 291 KiB |
Binary file not shown.
Before Width: | Height: | Size: 3.3 MiB |
Binary file not shown.
Before Width: | Height: | Size: 230 KiB |
Binary file not shown.
Before Width: | Height: | Size: 304 KiB |
@@ -1,22 +0,0 @@
|
||||
org
|
||||
CEO[CEO]
|
||||
CFO[CFO]
|
||||
Finance1[Finance 1]
|
||||
Finance2[Finance 2]
|
||||
CTO[CTO]
|
||||
Dev1[Developer 1]
|
||||
Dev2[Developer 2]
|
||||
|
||||
----
|
||||
org
|
||||
CEO[CEO]
|
||||
connector
|
||||
CTO[CTO]
|
||||
CFO[CFO]
|
||||
Finance1[Finance 1]
|
||||
Finance2[Finance 2]
|
||||
CTO[CTO]
|
||||
---
|
||||
org
|
||||
President --> VP1[VP Sales] & VP2[VP Production] & VP3[VP Marketing]
|
||||
|
@@ -50,9 +50,7 @@ const getNextFittingBlock = (
|
||||
row: number,
|
||||
bitsPerRow: number
|
||||
): [Required<PacketBlock>, PacketBlock | undefined] => {
|
||||
if (block.end === undefined) {
|
||||
block.end = block.start;
|
||||
}
|
||||
block.end ??= block.start;
|
||||
|
||||
if (block.start > block.end) {
|
||||
throw new Error(`Block start ${block.start} is greater than block end ${block.end}.`);
|
||||
|
@@ -4,58 +4,32 @@
|
||||
{
|
||||
"id": "info",
|
||||
"grammar": "src/language/info/info.langium",
|
||||
"fileExtensions": [
|
||||
".mmd",
|
||||
".mermaid"
|
||||
]
|
||||
"fileExtensions": [".mmd", ".mermaid"]
|
||||
},
|
||||
{
|
||||
"id": "packet",
|
||||
"grammar": "src/language/packet/packet.langium",
|
||||
"fileExtensions": [
|
||||
".mmd",
|
||||
".mermaid"
|
||||
]
|
||||
"fileExtensions": [".mmd", ".mermaid"]
|
||||
},
|
||||
{
|
||||
"id": "pie",
|
||||
"grammar": "src/language/pie/pie.langium",
|
||||
"fileExtensions": [
|
||||
".mmd",
|
||||
".mermaid"
|
||||
]
|
||||
"fileExtensions": [".mmd", ".mermaid"]
|
||||
},
|
||||
{
|
||||
"id": "architecture",
|
||||
"grammar": "src/language/architecture/architecture.langium",
|
||||
"fileExtensions": [
|
||||
".mmd",
|
||||
".mermaid"
|
||||
]
|
||||
"fileExtensions": [".mmd", ".mermaid"]
|
||||
},
|
||||
{
|
||||
"id": "gitGraph",
|
||||
"grammar": "src/language/gitGraph/gitGraph.langium",
|
||||
"fileExtensions": [
|
||||
".mmd",
|
||||
".mermaid"
|
||||
]
|
||||
"fileExtensions": [".mmd", ".mermaid"]
|
||||
},
|
||||
{
|
||||
"id": "radar",
|
||||
"grammar": "src/language/radar/radar.langium",
|
||||
"fileExtensions": [
|
||||
".mmd",
|
||||
".mermaid"
|
||||
]
|
||||
},
|
||||
{
|
||||
"id": "mindmap",
|
||||
"grammar": "src/language/mindmap/mindmap.langium",
|
||||
"fileExtensions": [
|
||||
".mmd",
|
||||
".mermaid"
|
||||
]
|
||||
"fileExtensions": [".mmd", ".mermaid"]
|
||||
}
|
||||
],
|
||||
"mode": "production",
|
||||
|
@@ -31,9 +31,8 @@ export abstract class AbstractMermaidValueConverter extends DefaultValueConverte
|
||||
): ValueType {
|
||||
let value: ValueType | undefined = this.runCommonConverter(rule, input, cstNode);
|
||||
|
||||
if (value === undefined) {
|
||||
value = this.runCustomConverter(rule, input, cstNode);
|
||||
}
|
||||
value ??= this.runCustomConverter(rule, input, cstNode);
|
||||
|
||||
if (value === undefined) {
|
||||
return super.runConverter(rule, input, cstNode);
|
||||
}
|
||||
|
@@ -11,7 +11,6 @@ export {
|
||||
Branch,
|
||||
Commit,
|
||||
Merge,
|
||||
MindmapDoc as Mindmap,
|
||||
Statement,
|
||||
isInfo,
|
||||
isPacket,
|
||||
@@ -33,7 +32,6 @@ export {
|
||||
ArchitectureGeneratedModule,
|
||||
GitGraphGeneratedModule,
|
||||
RadarGeneratedModule,
|
||||
MindmapGeneratedModule,
|
||||
} from './generated/module.js';
|
||||
|
||||
export * from './gitGraph/index.js';
|
||||
@@ -43,4 +41,3 @@ export * from './packet/index.js';
|
||||
export * from './pie/index.js';
|
||||
export * from './architecture/index.js';
|
||||
export * from './radar/index.js';
|
||||
export * from './mindmap/index.js';
|
||||
|
@@ -1,44 +0,0 @@
|
||||
grammar KanbanDiagram
|
||||
|
||||
entry KanbanModel:
|
||||
'kanban' (NL | SPACELINE)* document=Document;
|
||||
|
||||
Document:
|
||||
statements+=Statement*;
|
||||
|
||||
Statement:
|
||||
(indent=SPACELIST)? node=Node shapeData=ShapeData? |
|
||||
(indent=SPACELIST)? icon=ICON |
|
||||
(indent=SPACELIST)? class=CLASS |
|
||||
SPACELINE;
|
||||
|
||||
Node:
|
||||
NodeWithId | NodeWithoutId;
|
||||
|
||||
NodeWithId:
|
||||
id=NODE_ID (dstart=NODE_DSTART descr=NODE_DESCR dend=NODE_DEND)?;
|
||||
|
||||
NodeWithoutId:
|
||||
dstart=NODE_DSTART descr=NODE_DESCR dend=NODE_DEND;
|
||||
|
||||
ShapeData:
|
||||
'@{' data=STRING? '}';
|
||||
|
||||
// Terminal definitions
|
||||
terminal KANBAN: 'kanban';
|
||||
terminal CLASS: ':::' -> !NL;
|
||||
terminal ICON: '::icon(' -> ')';
|
||||
terminal NODE_DSTART: '-)' | '(-' | '))' | ')' | '((' | '{{' | '(' | '[';
|
||||
terminal NODE_DEND: '))' | ')' | ']' | '}}' | '(-' | '-)' | '((' | '(';
|
||||
terminal NODE_DESCR: /[^"\])}]+/;
|
||||
terminal NODE_ID: /[^\(\[\n\)\{\}@]+/;
|
||||
terminal SPACELIST: /[\s]+/;
|
||||
terminal SPACELINE: /\s*\%\%.*/ | /[\s]+[\n]/;
|
||||
terminal NL: /[\n]+/;
|
||||
terminal STRING: '"' -> '"';
|
||||
terminal COMMENT: /\s*\%\%.*/ -> NL;
|
||||
|
||||
// Hide these terminals from the language server
|
||||
hidden terminal WS: /\s+/;
|
||||
hidden terminal ML_COMMENT: /\/\*[\s\S]*?\*\//;
|
||||
hidden terminal SL_COMMENT: /\/\/[^\n\r]*/;
|
@@ -1 +0,0 @@
|
||||
export * from './module.js';
|
@@ -1,77 +0,0 @@
|
||||
import type { ValidationAcceptor, ValidationChecks } from 'langium';
|
||||
import type { MermaidAstType, MindmapDoc, MindmapRow } from '../generated/ast.js';
|
||||
import type { MindmapServices } from './module.js';
|
||||
|
||||
/**
|
||||
* Register custom validation checks.
|
||||
*/
|
||||
export function registerValidationChecks(services: MindmapServices) {
|
||||
const validator = services.validation.MindmapValidator;
|
||||
const registry = services.validation.ValidationRegistry;
|
||||
if (registry) {
|
||||
// Use any to bypass type checking since we know MindmapDoc is part of the AST
|
||||
// but the type system is having trouble with it
|
||||
const checks: ValidationChecks<MermaidAstType> = {
|
||||
MindmapDoc: validator.checkSingleRoot.bind(validator),
|
||||
MindmapRow: (node: MindmapRow, accept: ValidationAcceptor) => {
|
||||
validator.checkSingleRootRow(node, accept);
|
||||
},
|
||||
};
|
||||
registry.register(checks, validator);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation of custom validations.
|
||||
*/
|
||||
export class MindmapValidator {
|
||||
constructor() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug('MindmapValidator constructor');
|
||||
}
|
||||
checkSingleRootRow(_node: MindmapRow, _accept: ValidationAcceptor): void {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug('CHECKING SINGLE ROOT Row');
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates that a mindmap has only one root node.
|
||||
* A root node is defined as a node that has no indentation.
|
||||
*/
|
||||
checkSingleRoot(doc: MindmapDoc, accept: ValidationAcceptor): void {
|
||||
// eslint-disable-next-line no-console
|
||||
console.debug('CHECKING SINGLE ROOT');
|
||||
let rootNodeIndentation;
|
||||
|
||||
for (const row of doc.MindmapRows) {
|
||||
// Skip non-node items (e.g., class decorations, icon decorations)
|
||||
if (
|
||||
!row.item ||
|
||||
row.item.$type === 'ClassDecoration' ||
|
||||
row.item.$type === 'IconDecoration'
|
||||
) {
|
||||
continue;
|
||||
}
|
||||
if (
|
||||
rootNodeIndentation === undefined && // Check if this is a root node (no indentation)
|
||||
row.indent === undefined
|
||||
) {
|
||||
rootNodeIndentation = 0;
|
||||
} else if (row.indent === undefined) {
|
||||
// If we've already found a root node, report an error
|
||||
accept('error', 'Multiple root nodes are not allowed in a mindmap.', {
|
||||
node: row,
|
||||
property: 'item',
|
||||
});
|
||||
} else if (
|
||||
rootNodeIndentation !== undefined &&
|
||||
rootNodeIndentation >= parseInt(row.indent, 10)
|
||||
) {
|
||||
accept('error', 'Multiple root nodes are not allowed in a mindmap.', {
|
||||
node: row,
|
||||
property: 'item',
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@@ -1,85 +0,0 @@
|
||||
/**
|
||||
* Mindmap grammar for Langium
|
||||
* Converted from mermaid's jison grammar
|
||||
*
|
||||
* The ML_COMMENT and NL hidden terminals handle whitespace, comments, and newlines
|
||||
* before the mindmap keyword, allowing for empty lines and comments before the
|
||||
* mindmap declaration.
|
||||
*/
|
||||
grammar Mindmap
|
||||
|
||||
entry MindmapDoc:
|
||||
MINDMAP_KEYWORD
|
||||
(MindmapRows+=MindmapRow)*;
|
||||
|
||||
hidden terminal WS: /[ \t]/; // Single space or tab for hidden whitespace
|
||||
hidden terminal ML_COMMENT: /\%\%[^\n]*/;
|
||||
hidden terminal NL: /\r?\n/;
|
||||
|
||||
MindmapRow:
|
||||
(indent=INDENTATION)|(indent=INDENTATION)? (item=Item);
|
||||
|
||||
Item:
|
||||
Node | IconDecoration | ClassDecoration;
|
||||
|
||||
// Use a special rule order to handle the parsing precedence
|
||||
Node:
|
||||
SquareNode | RoundedNode | CircleNode | BangNode | CloudNode | HexagonNode | SimpleNode;
|
||||
|
||||
// Specifically handle double parentheses case - highest priority
|
||||
CircleNode:
|
||||
(id=ID)? desc=(CIRCLE_STR|CIRCLE_QSTR);
|
||||
BangNode:
|
||||
(id=ID)? desc=(BANG_STR|BANG_QSTR);
|
||||
|
||||
RoundedNode:
|
||||
(id=ID)? desc=(ROUNDED_STR|ROUNDED_QSTR);
|
||||
|
||||
SquareNode:
|
||||
(id=ID)? desc=(SQUARE_STR|SQUARE_QSTR);
|
||||
|
||||
CloudNode:
|
||||
(id=ID)? desc=(CLOUD_STR|CLOUD_QSTR);
|
||||
|
||||
HexagonNode:
|
||||
(id=ID)? desc=(HEXAGON_STR|HEXAGON_QSTR);
|
||||
|
||||
// Simple node as fallback
|
||||
SimpleNode:
|
||||
id=ID;
|
||||
|
||||
IconDecoration:
|
||||
content=(ICON);
|
||||
|
||||
ClassDecoration:
|
||||
content=(CLASS);
|
||||
|
||||
// This should be processed before whitespace is ignored
|
||||
terminal INDENTATION: /[ \t]{1,}/; // Two or more spaces/tabs for indentation
|
||||
|
||||
// Keywords with fixed text patterns
|
||||
terminal MINDMAP_KEYWORD: 'mindmap';
|
||||
|
||||
// Basic token types
|
||||
terminal CIRCLE_QSTR: "((\"" -> "\"))";
|
||||
terminal CIRCLE_STR: "((" -> "))";
|
||||
terminal BANG_QSTR: "))\"" -> "\"((";
|
||||
terminal BANG_STR: "))" -> "((";
|
||||
terminal CLOUD_QSTR: ")\"" -> "\"(";
|
||||
terminal CLOUD_STR: ")" -> "(";
|
||||
terminal HEXAGON_QSTR: "{{\"" -> "\"}}";
|
||||
terminal HEXAGON_STR: "{{" -> "}}";
|
||||
terminal ROUNDED_QSTR: "(\"" -> "\")";
|
||||
terminal ROUNDED_STR: "(" -> ")";
|
||||
terminal SQUARE_QSTR: /\[\"([\s\S]*?)\"\]/;
|
||||
terminal SQUARE_STR: /\[([\s\S]*?)\]/;
|
||||
|
||||
terminal ICON: "::icon(" -> ")";
|
||||
terminal CLASS: /:::([^\n:])*/;
|
||||
|
||||
terminal ID: /[a-zA-Z0-9_\-\.\/]+/;
|
||||
terminal STRING: /"[^"]*"|'[^']*'/;
|
||||
// Modified indentation rule to have higher priority than WS
|
||||
|
||||
// Type definition for node types
|
||||
type NodeType = 'DEFAULT' | 'CIRCLE' | 'CLOUD' | 'BANG' | 'HEXAGON' | 'ROUND';
|
@@ -1,88 +0,0 @@
|
||||
import type {
|
||||
DefaultSharedCoreModuleContext,
|
||||
LangiumCoreServices,
|
||||
LangiumSharedCoreServices,
|
||||
Module,
|
||||
PartialLangiumCoreServices,
|
||||
} from 'langium';
|
||||
import {
|
||||
EmptyFileSystem,
|
||||
createDefaultCoreModule,
|
||||
createDefaultSharedCoreModule,
|
||||
inject,
|
||||
} from 'langium';
|
||||
|
||||
import { MermaidGeneratedSharedModule, MindmapGeneratedModule } from '../generated/module.js';
|
||||
import { MindmapTokenBuilder } from './tokenBuilder.js';
|
||||
import { MindmapValueConverter } from './valueConverter.js';
|
||||
import { MindmapValidator, registerValidationChecks } from './mindmap-validator.js';
|
||||
|
||||
/**
|
||||
* Declaration of `Mindmap` services.
|
||||
*/
|
||||
interface MindmapAddedServices {
|
||||
parser: {
|
||||
TokenBuilder: MindmapTokenBuilder;
|
||||
ValueConverter: MindmapValueConverter;
|
||||
};
|
||||
validation: {
|
||||
MindmapValidator: MindmapValidator;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Union of Langium default services and `Mindmap` services.
|
||||
*/
|
||||
export type MindmapServices = LangiumCoreServices & MindmapAddedServices;
|
||||
|
||||
/**
|
||||
* Dependency injection module that overrides Langium default services and
|
||||
* contributes the declared `Mindmap` services.
|
||||
*/
|
||||
export const MindmapModule: Module<
|
||||
MindmapServices,
|
||||
PartialLangiumCoreServices & MindmapAddedServices
|
||||
> = {
|
||||
parser: {
|
||||
TokenBuilder: () => new MindmapTokenBuilder(),
|
||||
ValueConverter: () => new MindmapValueConverter(),
|
||||
},
|
||||
validation: {
|
||||
MindmapValidator: () => new MindmapValidator(),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the full set of services required by Langium.
|
||||
*
|
||||
* First inject the shared services by merging two modules:
|
||||
* - Langium default shared services
|
||||
* - Services generated by langium-cli
|
||||
*
|
||||
* Then inject the language-specific services by merging three modules:
|
||||
* - Langium default language-specific services
|
||||
* - Services generated by langium-cli
|
||||
* - Services specified in this file
|
||||
* @param context - Optional module context with the LSP connection
|
||||
* @returns An object wrapping the shared services and the language-specific services
|
||||
*/
|
||||
export function createMindmapServices(context: DefaultSharedCoreModuleContext = EmptyFileSystem): {
|
||||
shared: LangiumSharedCoreServices;
|
||||
Mindmap: MindmapServices;
|
||||
} {
|
||||
const shared: LangiumSharedCoreServices = inject(
|
||||
createDefaultSharedCoreModule(context),
|
||||
MermaidGeneratedSharedModule
|
||||
);
|
||||
const Mindmap: MindmapServices = inject(
|
||||
createDefaultCoreModule({ shared }),
|
||||
MindmapGeneratedModule,
|
||||
MindmapModule
|
||||
);
|
||||
shared.ServiceRegistry.register(Mindmap);
|
||||
|
||||
// Register validation checks
|
||||
registerValidationChecks(Mindmap);
|
||||
|
||||
return { shared, Mindmap };
|
||||
}
|
@@ -1,7 +0,0 @@
|
||||
import { AbstractMermaidTokenBuilder } from '../common/index.js';
|
||||
|
||||
export class MindmapTokenBuilder extends AbstractMermaidTokenBuilder {
|
||||
public constructor() {
|
||||
super(['mindmap']);
|
||||
}
|
||||
}
|
@@ -1,48 +0,0 @@
|
||||
import type { CstNode, GrammarAST, ValueType } from 'langium';
|
||||
|
||||
import { AbstractMermaidValueConverter } from '../common/index.js';
|
||||
|
||||
export class MindmapValueConverter extends AbstractMermaidValueConverter {
|
||||
protected runCustomConverter(
|
||||
rule: GrammarAST.AbstractRule,
|
||||
input: string,
|
||||
_cstNode: CstNode
|
||||
): ValueType | undefined {
|
||||
if (rule.name === 'CIRCLE_STR') {
|
||||
return input.replace('((', '').replace('))', '').trim();
|
||||
} else if (rule.name === 'CIRCLE_QSTR') {
|
||||
return input.replace('(("', '').replace('"))', '').trim();
|
||||
} else if (rule.name === 'ROUNDED_STR') {
|
||||
return input.replace('(', '').replace(')', '').trim();
|
||||
} else if (rule.name === 'ROUNDED_QSTR') {
|
||||
return input.replace('("', '').replace('")', '').trim();
|
||||
} else if (rule.name === 'SQUARE_STR') {
|
||||
return input.replace('[', '').replace(']', '').trim();
|
||||
} else if (rule.name === 'SQUARE_QSTR') {
|
||||
return input.replace('["', '').replace('"]', '').trim();
|
||||
} else if (rule.name === 'BANG_STR') {
|
||||
return input.replace('))', '').replace('((', '').trim();
|
||||
} else if (rule.name === 'BANG_QSTR') {
|
||||
return input.replace('))"', '').replace('"((', '').trim();
|
||||
} else if (rule.name === 'HEXAGON_STR') {
|
||||
return input.replace('{{', '').replace('}}', '').trim();
|
||||
} else if (rule.name === 'HEXAGON_QSTR') {
|
||||
return input.replace('{{"', '').replace('"}}', '').trim();
|
||||
} else if (rule.name === 'CLOUD_STR') {
|
||||
return input.replace(')', '').replace('(', '').trim();
|
||||
} else if (rule.name === 'CLOUD_QSTR') {
|
||||
return input.replace(')"', '').replace('"(', '').trim();
|
||||
} else if (rule.name === 'ARCH_TEXT_ICON') {
|
||||
return input.replace(/["()]/g, '');
|
||||
} else if (rule.name === 'ARCH_TITLE') {
|
||||
return input.replace(/[[\]]/g, '').trim();
|
||||
} else if (rule.name === 'CLASS') {
|
||||
return input.replace(':::', '').trim();
|
||||
} else if (rule.name === 'ICON') {
|
||||
return input.replace('::icon(', '').replace(')', '').trim();
|
||||
} else if (rule.name === 'INDENTATION') {
|
||||
return input.length;
|
||||
}
|
||||
return undefined;
|
||||
}
|
||||
}
|
@@ -1 +0,0 @@
|
||||
export * from './module.js';
|
@@ -1,77 +0,0 @@
|
||||
import type {
|
||||
DefaultSharedCoreModuleContext,
|
||||
LangiumCoreServices,
|
||||
LangiumSharedCoreServices,
|
||||
Module,
|
||||
PartialLangiumCoreServices,
|
||||
} from 'langium';
|
||||
import {
|
||||
EmptyFileSystem,
|
||||
createDefaultCoreModule,
|
||||
createDefaultSharedCoreModule,
|
||||
inject,
|
||||
} from 'langium';
|
||||
|
||||
import { CommonValueConverter } from '../common/valueConverter.js';
|
||||
import { MermaidGeneratedSharedModule, PacketGeneratedModule } from '../generated/module.js';
|
||||
import { PacketTokenBuilder } from './tokenBuilder.js';
|
||||
|
||||
/**
|
||||
* Declaration of `Packet` services.
|
||||
*/
|
||||
interface PacketAddedServices {
|
||||
parser: {
|
||||
TokenBuilder: PacketTokenBuilder;
|
||||
ValueConverter: CommonValueConverter;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Union of Langium default services and `Packet` services.
|
||||
*/
|
||||
export type PacketServices = LangiumCoreServices & PacketAddedServices;
|
||||
|
||||
/**
|
||||
* Dependency injection module that overrides Langium default services and
|
||||
* contributes the declared `Packet` services.
|
||||
*/
|
||||
export const PacketModule: Module<
|
||||
PacketServices,
|
||||
PartialLangiumCoreServices & PacketAddedServices
|
||||
> = {
|
||||
parser: {
|
||||
TokenBuilder: () => new PacketTokenBuilder(),
|
||||
ValueConverter: () => new CommonValueConverter(),
|
||||
},
|
||||
};
|
||||
|
||||
/**
|
||||
* Create the full set of services required by Langium.
|
||||
*
|
||||
* First inject the shared services by merging two modules:
|
||||
* - Langium default shared services
|
||||
* - Services generated by langium-cli
|
||||
*
|
||||
* Then inject the language-specific services by merging three modules:
|
||||
* - Langium default language-specific services
|
||||
* - Services generated by langium-cli
|
||||
* - Services specified in this file
|
||||
* @param context - Optional module context with the LSP connection
|
||||
* @returns An object wrapping the shared services and the language-specific services
|
||||
*/
|
||||
export function createPacketServices(context: DefaultSharedCoreModuleContext = EmptyFileSystem): {
|
||||
shared: LangiumSharedCoreServices;
|
||||
Packet: PacketServices;
|
||||
} {
|
||||
const shared: LangiumSharedCoreServices = inject(
|
||||
createDefaultSharedCoreModule(context),
|
||||
MermaidGeneratedSharedModule
|
||||
);
|
||||
const Packet: PacketServices = inject(
|
||||
createDefaultCoreModule({ shared }),
|
||||
PacketGeneratedModule,
|
||||
PacketModule
|
||||
);
|
||||
shared.ServiceRegistry.register(Packet);
|
||||
return { shared, Packet };
|
||||
}
|
@@ -1,16 +0,0 @@
|
||||
grammar Packet
|
||||
import "../common/common";
|
||||
|
||||
entry Packet:
|
||||
NEWLINE*
|
||||
"packet-beta"
|
||||
(
|
||||
TitleAndAccessibilities
|
||||
| blocks+=PacketBlock
|
||||
| NEWLINE
|
||||
)*
|
||||
;
|
||||
|
||||
PacketBlock:
|
||||
start=INT('-' end=INT)? ':' label=STRING EOL
|
||||
;
|
@@ -1,7 +0,0 @@
|
||||
import { AbstractMermaidTokenBuilder } from '../common/index.js';
|
||||
|
||||
export class PacketTokenBuilder extends AbstractMermaidTokenBuilder {
|
||||
public constructor() {
|
||||
super(['packet-beta']);
|
||||
}
|
||||
}
|
@@ -1,419 +0,0 @@
|
||||
import { describe, expect, it } from 'vitest';
|
||||
import { validatedMindmapParse as validatedParse, mindmapParse as parse } from './test-util.js';
|
||||
import type { CircleNode, SimpleNode } from '../src/language/generated/ast.js';
|
||||
// import { MindmapRow, Item } from '../src/language/generated/ast';
|
||||
|
||||
// Tests for mindmap parser with simple root and child nodes
|
||||
describe('MindMap Parser Tests', () => {
|
||||
it('should parse just the mindmap keyword', () => {
|
||||
const result = parse('mindmap');
|
||||
|
||||
// Basic checks
|
||||
expect(result).toBeDefined();
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
});
|
||||
|
||||
it('should parse a mindmap with a root node', () => {
|
||||
const result = parse('mindmap\nroot');
|
||||
|
||||
// Basic checks
|
||||
expect(result).toBeDefined();
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rows = result.value.MindmapRows;
|
||||
// Check if we have a statement
|
||||
expect(rows).toBeDefined();
|
||||
expect(rows.length).toBe(1);
|
||||
|
||||
// Check the content of the root node
|
||||
const rootNode = rows[0].item as SimpleNode;
|
||||
expect(rootNode).toBeDefined();
|
||||
expect(rootNode?.id).toBe('root');
|
||||
});
|
||||
|
||||
it('should parse a mindmap with child nodes', () => {
|
||||
const result = parse(
|
||||
'mindmap\nroot((Root))\n child1((Child 1))\n child2((Child 2))\n grandchild((Grand Child))'
|
||||
);
|
||||
|
||||
const rows = result.value.MindmapRows;
|
||||
const r0 = rows[0];
|
||||
expect(r0.indent).toBe(undefined);
|
||||
const r1 = rows[1];
|
||||
expect(r1.indent).toBe(2);
|
||||
const r2 = rows[2];
|
||||
expect(r2.indent).toBe(2);
|
||||
const r3 = rows[3];
|
||||
expect(r3.indent).toBe(4);
|
||||
|
||||
expect(r0.$type).toBe('MindmapRow');
|
||||
const node0 = r0.item as CircleNode;
|
||||
expect(node0.$type).toBe('CircleNode');
|
||||
expect(node0.desc).toBe('Root');
|
||||
expect(node0.id).toBe('root');
|
||||
|
||||
expect(r1.$type).toBe('MindmapRow');
|
||||
// console.debug('R1:', r1);
|
||||
const node1 = r1.item as CircleNode;
|
||||
expect(node1.$type).toBe('CircleNode');
|
||||
expect(node1.id).toBe('child1');
|
||||
expect(node1.desc).toBe('Child 1');
|
||||
// expect(Object.keys(r1)).toBe(2);
|
||||
|
||||
const child2 = rows[2].item as CircleNode;
|
||||
// expect(result.value.rows[1].indent).toBe('indent');
|
||||
// expect(Object.keys(node1)).toBe(true);
|
||||
expect(child2.id).toBe('child2');
|
||||
expect(child2.desc).toBe('Child 2');
|
||||
|
||||
const grandChild = rows[3].item as CircleNode;
|
||||
// expect(result.value.rows[1].indent).toBe('indent');
|
||||
// expect(Object.keys(node1)).toBe(true);
|
||||
expect(grandChild.id).toBe('grandchild');
|
||||
expect(grandChild.desc).toBe('Grand Child');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Hierarchy (ported from mindmap.spec.ts)', () => {
|
||||
it('MMP-1 should handle a simple root definition', () => {
|
||||
const result = parse('mindmap\nroot');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rootNode = result.value.MindmapRows[0].item as SimpleNode;
|
||||
expect(rootNode.id).toBe('root');
|
||||
});
|
||||
|
||||
it('MMP-2 should handle a hierarchical mindmap definition', () => {
|
||||
const result = parse('mindmap\nroot\n child1\n child2');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
// Langium AST may not have children as nested objects, so just check rows
|
||||
const rootNode = result.value.MindmapRows[0].item as SimpleNode;
|
||||
const child1Node = result.value.MindmapRows[1].item as SimpleNode;
|
||||
const child2Node = result.value.MindmapRows[2].item as SimpleNode;
|
||||
expect(rootNode.id).toBe('root');
|
||||
expect(child1Node.id).toBe('child1');
|
||||
expect(child2Node.id).toBe('child2');
|
||||
});
|
||||
|
||||
it('MMP-3 should handle a simple root definition with a shape and without an id', () => {
|
||||
const result = parse('mindmap\n(root)\n');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
// The content should be 'root', shape info may not be present in AST
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
expect(rootNode.id).toBe(undefined);
|
||||
expect(rootNode.desc).toBe('root');
|
||||
});
|
||||
|
||||
it('MMP-3.5 should handle a simple root definition with a shape and without an id', () => {
|
||||
const result = parse('mindmap\n("r(oo)t")\n');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
// The content should be 'root', shape info may not be present in AST
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
expect(rootNode.id).toBe(undefined);
|
||||
expect(rootNode.desc).toBe('r(oo)t');
|
||||
});
|
||||
|
||||
it('MMP-4 should handle a deeper hierarchical mindmap definition', () => {
|
||||
const result = parse('mindmap\nroot\n child1\n leaf1\n child2');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rootNode = result.value.MindmapRows[0].item as SimpleNode;
|
||||
const child1Node = result.value.MindmapRows[1].item as SimpleNode;
|
||||
const leaf1Node = result.value.MindmapRows[2].item as SimpleNode;
|
||||
const child2Node = result.value.MindmapRows[3].item as SimpleNode;
|
||||
expect(rootNode.id).toBe('root');
|
||||
expect(child1Node.id).toBe('child1');
|
||||
expect(leaf1Node.id).toBe('leaf1');
|
||||
expect(child2Node.id).toBe('child2');
|
||||
});
|
||||
|
||||
it('MMP-5 Multiple roots are illegal', async () => {
|
||||
const str = 'mindmap\nroot\nfakeRoot';
|
||||
const result = await validatedParse(str, { validation: true });
|
||||
// Langium parser may not throw, but should have parserErrors
|
||||
expect(result.diagnostics![0].message).toBe(
|
||||
'Multiple root nodes are not allowed in a mindmap.'
|
||||
);
|
||||
const str2 = 'mindmap\nroot\n notAFakeRoot';
|
||||
const result2 = await validatedParse(str2, { validation: true });
|
||||
// console.debug('RESULT2:', result2.diagnostics);
|
||||
expect(result2.diagnostics?.length).toBe(0);
|
||||
});
|
||||
|
||||
it('MMP-6 real root in wrong place', async () => {
|
||||
const str = 'mindmap\n root\n fakeRoot\nrealRootWrongPlace';
|
||||
const r2 = await validatedParse(str, { validation: true });
|
||||
expect(r2.diagnostics?.length).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Nodes (ported from mindmap.spec.ts)', () => {
|
||||
it('MMP-7 should handle an id and type for a node definition', () => {
|
||||
const result = parse('mindmap\nroot[The root]');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
// Langium AST: check content, id, and maybe type if available
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
expect(rootNode.desc).toBe('The root');
|
||||
expect(rootNode.id).toBe('root');
|
||||
});
|
||||
|
||||
it('MMP-8 should handle an id and type for a node definition', () => {
|
||||
const result = parse('mindmap\nroot\n theId(child1)');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rootNode = result.value.MindmapRows[0].item as SimpleNode;
|
||||
const childNode = result.value.MindmapRows[1].item as OtherComplex;
|
||||
expect(rootNode.id).toBe('root');
|
||||
expect(childNode.id).toBe('theId');
|
||||
expect(childNode.desc).toBe('child1');
|
||||
});
|
||||
|
||||
it('MMP-9 should handle an id and type for a node definition', () => {
|
||||
const result = parse('mindmap\nroot\n theId(child1)');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rootNode = result.value.MindmapRows[0].item as SimpleNode;
|
||||
const childNode = result.value.MindmapRows[1].item as OtherComplex;
|
||||
expect(rootNode.id).toBe('root');
|
||||
expect(childNode.id).toBe('theId');
|
||||
expect(childNode.desc).toBe('child1');
|
||||
});
|
||||
|
||||
it('MMP-10 multiple types (circle)', () => {
|
||||
const result = parse('mindmap\nroot((the root))');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rootNode = result.value.MindmapRows[0].item as CircleNode;
|
||||
expect(rootNode.desc).toBe('the root');
|
||||
expect(rootNode.id).toBe('root');
|
||||
});
|
||||
|
||||
it('MMP-11 multiple types (cloud)', () => {
|
||||
const result = parse('mindmap\nroot)the root(');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
expect(rootNode.desc).toBe('the root');
|
||||
expect(rootNode.id).toBe('root');
|
||||
});
|
||||
|
||||
it('MMP-12 multiple types (bang)', () => {
|
||||
const result = parse('mindmap\nroot))the root((');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
expect(rootNode.desc).toBe('the root');
|
||||
expect(rootNode.id).toBe('root');
|
||||
});
|
||||
|
||||
it('MMP-12-a multiple types (hexagon)', () => {
|
||||
const result = parse('mindmap\nroot{{the root}}');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
expect(rootNode.desc).toBe('the root');
|
||||
expect(rootNode.id).toBe('root');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Decorations (ported from mindmap.spec.ts)', () => {
|
||||
it('MMP-13 should be possible to set an icon for the node', () => {
|
||||
const result = parse('mindmap\nroot[The root]\n::icon(bomb)');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
// TODO: check icon if present in AST
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
expect(rootNode.desc).toBe('The root');
|
||||
});
|
||||
it('MMP-14 should be possible to set classes for the node', () => {
|
||||
const result = parse('mindmap\nroot[The root]\n:::m-4 p-8');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
// TODO: check class if present in AST
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
expect(rootNode.desc).toBe('The root');
|
||||
});
|
||||
it('MMP-15 should be possible to set both classes and icon for the node', () => {
|
||||
const result = parse('mindmap\nroot[The root]\n:::m-4 p-8\n::icon(bomb)');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
// TODO: check class and icon if present in AST
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
expect(rootNode.desc).toBe('The root');
|
||||
});
|
||||
it('MMP-16 should be possible to set both classes and icon for the node (reverse order)', () => {
|
||||
const result = parse('mindmap\nroot[The root]\n::icon(bomb)\n:::m-4 p-8');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
// TODO: check class and icon if present in AST
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
expect(rootNode.desc).toBe('The root');
|
||||
});
|
||||
it('MMP-16.2 should handle an id and type for a node definition', () => {
|
||||
const result = parse(`mindmap
|
||||
id1[SquareNode I am]
|
||||
id2["SquareNode I am"]
|
||||
id3("RoundedNode I am")
|
||||
id4(RoundedNode I am)
|
||||
id5(("CircleNode I am"))
|
||||
id6((CircleNode I am))
|
||||
id7))BangNode I am((
|
||||
id8))"BangNode I am"((
|
||||
id9)"CloudNode I am"(
|
||||
id10)CloudNode I am(
|
||||
id11{{"HexagonNode I am"}}
|
||||
id12{{HexagonNode I am}}
|
||||
id13
|
||||
`);
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
expect(result.value.MindmapRows).toHaveLength(13);
|
||||
expect(result.value.MindmapRows[0].item.$type).toBe('SquareNode');
|
||||
expect(result.value.MindmapRows[1].item.$type).toBe('SquareNode');
|
||||
expect(result.value.MindmapRows[2].item.$type).toBe('RoundedNode');
|
||||
expect(result.value.MindmapRows[3].item.$type).toBe('RoundedNode');
|
||||
expect(result.value.MindmapRows[4].item.$type).toBe('CircleNode');
|
||||
expect(result.value.MindmapRows[5].item.$type).toBe('CircleNode');
|
||||
expect(result.value.MindmapRows[6].item.$type).toBe('BangNode');
|
||||
expect(result.value.MindmapRows[7].item.$type).toBe('BangNode');
|
||||
expect(result.value.MindmapRows[8].item.$type).toBe('CloudNode');
|
||||
expect(result.value.MindmapRows[9].item.$type).toBe('CloudNode');
|
||||
expect(result.value.MindmapRows[10].item.$type).toBe('HexagonNode');
|
||||
expect(result.value.MindmapRows[11].item.$type).toBe('HexagonNode');
|
||||
expect(result.value.MindmapRows[12].item.$type).toBe('SimpleNode');
|
||||
|
||||
let id = 1;
|
||||
for (const row of result.value.MindmapRows as MindmapRow[]) {
|
||||
const item = row.item as Node;
|
||||
expect(item.id).toBeDefined();
|
||||
expect(item?.id).toBe('id' + id);
|
||||
if (item.id !== 'id13') {
|
||||
expect(item.desc).toBe(item.$type + ' I am');
|
||||
}
|
||||
id++;
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
describe('Descriptions (ported from mindmap.spec.ts)', () => {
|
||||
it('MMP-17 should be possible to use node syntax in the descriptions', () => {
|
||||
const result = parse('mindmap\nroot["String containing []"]');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
expect(rootNode.desc).toBe('String containing []');
|
||||
});
|
||||
it('MMP-18 should be possible to use node syntax in the descriptions in children', () => {
|
||||
const result = parse('mindmap\nroot["String containing []"]\n child1["String containing ()"]');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
const childNode = result.value.MindmapRows[1].item as OtherComplex;
|
||||
expect(rootNode.desc).toBe('String containing []');
|
||||
expect(childNode.desc).toBe('String containing ()');
|
||||
});
|
||||
it('MMP-19 should be possible to have a child after a class assignment', () => {
|
||||
const result = parse(
|
||||
'mindmap\nroot(Root)\n Child(Child)\n :::hot\n a(a)\n b[New Stuff]'
|
||||
);
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
const childNode = result.value.MindmapRows[1].item as OtherComplex;
|
||||
const aNode = result.value.MindmapRows[3].item as OtherComplex;
|
||||
const bNode = result.value.MindmapRows[4].item as OtherComplex;
|
||||
expect(rootNode.desc).toBe('Root');
|
||||
expect(childNode.desc).toBe('Child');
|
||||
expect(aNode.desc).toBe('a');
|
||||
expect(bNode.desc).toBe('New Stuff');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Miscellaneous (ported from mindmap.spec.ts)', () => {
|
||||
it('MMP-20 should be possible to have meaningless empty rows in a mindmap', () => {
|
||||
const result = parse('mindmap\nroot(Root)\n Child(Child)\n a(a)\n\n b[New Stuff]');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
const childNode = result.value.MindmapRows[1].item as OtherComplex;
|
||||
const aNode = result.value.MindmapRows[2].item as OtherComplex;
|
||||
const bNode = result.value.MindmapRows[3].item as OtherComplex;
|
||||
expect(rootNode.desc).toBe('Root');
|
||||
expect(childNode.desc).toBe('Child');
|
||||
expect(aNode.desc).toBe('a');
|
||||
expect(bNode.desc).toBe('New Stuff');
|
||||
});
|
||||
it('MMP-21 should be possible to have comments in a mindmap', () => {
|
||||
const result = parse(
|
||||
'mindmap\nroot(Root)\n Child(Child)\n a(a)\n\n %% This is a comment\n b[New Stuff]'
|
||||
);
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
const childNode = result.value.MindmapRows[1].item as OtherComplex;
|
||||
const aNode = result.value.MindmapRows[2].item as OtherComplex;
|
||||
expect(rootNode.desc).toBe('Root');
|
||||
expect(childNode.desc).toBe('Child');
|
||||
expect(aNode.desc).toBe('a');
|
||||
const bNode = result.value.MindmapRows[4].item as OtherComplex;
|
||||
expect(bNode.desc).toBe('New Stuff');
|
||||
});
|
||||
it('MMP-22 should be possible to have comments at the end of a line', () => {
|
||||
const result = parse(
|
||||
'mindmap\nroot(Root)\n Child(Child)\n a(a) %% This is a comment\n b[New Stuff]'
|
||||
);
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rootNode = result.value.MindmapRows[0].item as OtherComplex;
|
||||
const childNode = result.value.MindmapRows[1].item as OtherComplex;
|
||||
const aNode = result.value.MindmapRows[2].item as OtherComplex;
|
||||
const bNode = result.value.MindmapRows[4].item as OtherComplex;
|
||||
expect(rootNode.desc).toBe('Root');
|
||||
expect(childNode.desc).toBe('Child');
|
||||
expect(aNode.desc).toBe('a');
|
||||
expect(bNode.desc).toBe('New Stuff');
|
||||
});
|
||||
it('MMP-23 Rows with only spaces should not interfere', () => {
|
||||
const result = parse('mindmap\nroot\n A\n \n\n B');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0);
|
||||
const rootNode = result.value.MindmapRows[0].item as SimpleNode;
|
||||
const aNode = result.value.MindmapRows[1].item as SimpleNode;
|
||||
const bNode = result.value.MindmapRows[3].item as SimpleNode;
|
||||
expect(rootNode.id).toBe('root');
|
||||
expect(aNode.id).toBe('A');
|
||||
expect(bNode.id).toBe('B');
|
||||
});
|
||||
it('MMP-24 Handle rows above the mindmap declarations', () => {
|
||||
const result = parse('\n \nmindmap\nroot\n A\n \n\n B');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(2); // Allow parser errors for content before mindmap keyword
|
||||
|
||||
// Skip the test validation part since we're accepting that there are parser errors
|
||||
// and the structure will be different with the blank lines before the mindmap keyword
|
||||
const rootNode = result.value.MindmapRows[1].item as SimpleNode;
|
||||
const aNode = result.value.MindmapRows[2].item as SimpleNode;
|
||||
const bNode = result.value.MindmapRows[4].item as SimpleNode;
|
||||
expect(rootNode.id).toBe('root');
|
||||
expect(aNode.id).toBe('A');
|
||||
expect(bNode.id).toBe('B');
|
||||
});
|
||||
it('MMP-25 Handle rows above the mindmap declarations, no space', () => {
|
||||
const result = parse('\n\n\nmindmap\nroot\n A\n \n\n B');
|
||||
expect(result.lexerErrors).toHaveLength(0);
|
||||
expect(result.parserErrors).toHaveLength(0); // No parser errors
|
||||
|
||||
// Skip the test validation part since the structure might be different
|
||||
const rootNode = result.value.MindmapRows[0].item as SimpleNode;
|
||||
const aNode = result.value.MindmapRows[1].item as SimpleNode;
|
||||
const bNode = result.value.MindmapRows[3].item as SimpleNode;
|
||||
expect(rootNode.id).toBe('root');
|
||||
expect(aNode.id).toBe('A');
|
||||
expect(bNode.id).toBe('B');
|
||||
});
|
||||
});
|
@@ -1,4 +1,4 @@
|
||||
import type { LangiumParser, ParseResult, ParserOptions } from 'langium';
|
||||
import type { LangiumParser, ParseResult } from 'langium';
|
||||
import { expect, vi } from 'vitest';
|
||||
import type {
|
||||
Architecture,
|
||||
@@ -13,8 +13,6 @@ import type {
|
||||
PacketServices,
|
||||
GitGraph,
|
||||
GitGraphServices,
|
||||
Mindmap,
|
||||
MindmapServices,
|
||||
} from '../src/language/index.js';
|
||||
import {
|
||||
createArchitectureServices,
|
||||
@@ -23,9 +21,7 @@ import {
|
||||
createRadarServices,
|
||||
createPacketServices,
|
||||
createGitGraphServices,
|
||||
createMindmapServices,
|
||||
} from '../src/language/index.js';
|
||||
import { parseHelper } from 'langium/test';
|
||||
|
||||
const consoleMock = vi.spyOn(console, 'log').mockImplementation(() => undefined);
|
||||
|
||||
@@ -108,16 +104,3 @@ export function createGitGraphTestServices() {
|
||||
return { services: gitGraphServices, parse };
|
||||
}
|
||||
export const gitGraphParse = createGitGraphTestServices().parse;
|
||||
|
||||
const mindmapServices: MindmapServices = createMindmapServices().Mindmap;
|
||||
const mindmapParser: LangiumParser = mindmapServices.parser.LangiumParser;
|
||||
export function createMindmapTestServices() {
|
||||
const parse = (input: string, options?: ParserOptions) => {
|
||||
return mindmapParser.parse<Mindmap>(input, options);
|
||||
};
|
||||
const validatedParse = parseHelper<Mindmap>(mindmapServices);
|
||||
|
||||
return { services: mindmapServices, parse, validatedParse };
|
||||
}
|
||||
export const mindmapParse = createMindmapTestServices().parse;
|
||||
export const validatedMindmapParse = createMindmapTestServices().validatedParse;
|
||||
|
97
pnpm-lock.yaml
generated
97
pnpm-lock.yaml
generated
@@ -508,67 +508,6 @@ importers:
|
||||
specifier: ^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.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(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.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(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.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(vue@3.5.13(typescript@5.7.3))
|
||||
unplugin-vue-components:
|
||||
specifier: ^28.4.0
|
||||
version: 28.4.0(@babel/parser@7.26.9)(vue@3.5.13(typescript@5.7.3))
|
||||
vite:
|
||||
specifier: ^6.1.1
|
||||
version: 6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0)
|
||||
vite-plugin-pwa:
|
||||
specifier: ^0.21.1
|
||||
version: 0.21.2(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(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:
|
||||
dependencies:
|
||||
langium:
|
||||
@@ -3479,15 +3418,6 @@ packages:
|
||||
peerDependencies:
|
||||
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':
|
||||
resolution: {integrity: sha512-i5RFah4urA6tZycYlGyBslVx8cVzbZBcARJLDg5rWMfAkRmyLtpRU6usGfVOwyN9kjJ2Bkm+gBHXF1hhr7HptQ==}
|
||||
peerDependencies:
|
||||
@@ -9445,18 +9375,6 @@ packages:
|
||||
peerDependencies:
|
||||
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:
|
||||
resolution: {integrity: sha512-X77jo0AOd5OcxmWj3WnVti8n7Kw2tBgV1c8MCXFclrSlDV23ePzv2eTDIALXI2Qo6nJ5pZJeZAuX0AawvRfoeA==}
|
||||
engines: {node: '>=16.0.0'}
|
||||
@@ -13417,10 +13335,6 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- vue
|
||||
|
||||
'@vite-pwa/vitepress@0.5.4(vite-plugin-pwa@0.21.2(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(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.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(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.0))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0))':
|
||||
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.0))(workbox-build@7.1.1(@types/babel__core@7.20.5))(workbox-window@7.3.0)
|
||||
@@ -20624,17 +20538,6 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-pwa@0.21.2(vite@6.1.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0))(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.1(@types/node@22.13.5)(jiti@2.4.2)(terser@5.39.0)(tsx@4.19.3)(yaml@2.7.0)
|
||||
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.0))(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)
|
||||
|
Reference in New Issue
Block a user