Compare commits

..

8 Commits

Author SHA1 Message Date
darshanr0107
f7d7fe42aa fix: prevent edge direction tokens L,R,T,B from breaking ID parsing
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-27 13:33:48 +05:30
Knut Sveidqvist
fed8a523a4 Merge pull request #7076 from mermaid-js/6919-fix-incorrect-viewBox-casing
6919: correct viewBox casing in Radar & Packet
2025-10-21 12:20:04 +00:00
Knut Sveidqvist
33b4946e21 Merge branch 'develop' into 6919-fix-incorrect-viewBox-casing 2025-10-21 10:33:21 +02:00
Justin Greywolf
3d768f3adf Merge pull request #6975 from ilovelinux/fix/6974-ilovelinux-fix-classdiagram-example
Fix classDiagram example
2025-10-17 02:56:34 +00:00
darshanr0107
76e17ffd20 fix: add validation to ensure correct casing of 'viewBox' in all rendering tests
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-15 18:56:49 +05:30
darshanr0107
60f633101c chore: added changeset
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-13 19:14:22 +05:30
darshanr0107
7def6eecbf fix: correct viewBox casing in radar and packet diagram
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-10-13 18:15:38 +05:30
Antonio Spadaro
ac411a7d7e Fix class diagram example 2025-10-11 22:56:37 +02:00
24 changed files with 117 additions and 141 deletions

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Correct viewBox casing and make SVGs responsive

View File

@@ -1,5 +0,0 @@
---
'mermaid': patch
---
fix: Proper separation between strings and markdown strings

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Allow IDs starting with L, R, T, or B in parser

View File

@@ -99,6 +99,7 @@ export const openURLAndVerifyRendering = (
cy.visit(url); cy.visit(url);
cy.window().should('have.property', 'rendered', true); cy.window().should('have.property', 'rendered', true);
cy.get('svg').should('be.visible'); cy.get('svg').should('be.visible');
cy.get('svg').should('not.have.attr', 'viewbox');
if (validation) { if (validation) {
cy.get('svg').should(validation); cy.get('svg').should(validation);

View File

@@ -1174,8 +1174,8 @@ end
end end
githost["Github, Gitlab, BitBucket, etc."] githost["Github, Gitlab, BitBucket, etc."]
githost2["\`Github, Gitlab, BitBucket, etc.\`"] githost2["\`Github, Gitlab, BitBucket, etc.\`"]
a["\`1.\`"] a["1."]
b["\`- x\`"] b["- x"]
`; `;
it('should render raw strings', () => { it('should render raw strings', () => {

View File

@@ -1003,49 +1003,4 @@ graph TD
} }
); );
}); });
it('#5824: should be able to render string and markdown labels', () => {
imgSnapshotTest(
`
flowchart TB
mermaid{"What is\nyourmermaid version?"} --> v10["<11"] --"\`<**1**1\`"--> fine["No bug"]
mermaid --> v11[">= v11"] -- ">= v11" --> broken["Affected by https://github.com/mermaid-js/mermaid/issues/5824"]
subgraph subgraph1["\`How to fix **fix**\`"]
broken --> B["B"]
end
githost["Github, Gitlab, BitBucket, etc."]
githost2["\`Github, Gitlab, BitBucket, etc.\`"]
a["1."]
b["- x"]
`,
{
flowchart: { htmlLabels: true },
securityLevel: 'loose',
}
);
});
it('69: should render subgraphs with adhoc list headings', () => {
imgSnapshotTest(
`
graph TB
subgraph "1. first"
a1-->a2
end
subgraph 2. second
b1-->b2
end
`,
{ fontFamily: 'courier' }
);
});
it('70: should render subgraphs with markdown headings', () => {
imgSnapshotTest(
`
graph TB
subgraph "\`**strong**\`"
a1-->a2
end
`,
{ fontFamily: 'courier' }
);
});
}); });

View File

@@ -10,7 +10,7 @@
# Interface: ParseOptions # Interface: ParseOptions
Defined in: [packages/mermaid/src/types.ts:89](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L89) Defined in: [packages/mermaid/src/types.ts:88](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L88)
## Properties ## Properties
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:89](https://github.com/mermaid-js/mer
> `optional` **suppressErrors**: `boolean` > `optional` **suppressErrors**: `boolean`
Defined in: [packages/mermaid/src/types.ts:94](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L94) Defined in: [packages/mermaid/src/types.ts:93](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L93)
If `true`, parse will return `false` instead of throwing error when the diagram is invalid. If `true`, parse will return `false` instead of throwing error when the diagram is invalid.
The `parseError` function will not be called. The `parseError` function will not be called.

View File

@@ -10,7 +10,7 @@
# Interface: ParseResult # Interface: ParseResult
Defined in: [packages/mermaid/src/types.ts:97](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L97) Defined in: [packages/mermaid/src/types.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L96)
## Properties ## Properties
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:97](https://github.com/mermaid-js/mer
> **config**: [`MermaidConfig`](MermaidConfig.md) > **config**: [`MermaidConfig`](MermaidConfig.md)
Defined in: [packages/mermaid/src/types.ts:105](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L105) Defined in: [packages/mermaid/src/types.ts:104](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L104)
The config passed as YAML frontmatter or directives The config passed as YAML frontmatter or directives
@@ -28,6 +28,6 @@ The config passed as YAML frontmatter or directives
> **diagramType**: `string` > **diagramType**: `string`
Defined in: [packages/mermaid/src/types.ts:101](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L101) Defined in: [packages/mermaid/src/types.ts:100](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L100)
The diagram type, e.g. 'flowchart', 'sequence', etc. The diagram type, e.g. 'flowchart', 'sequence', etc.

View File

@@ -10,7 +10,7 @@
# Interface: RenderResult # Interface: RenderResult
Defined in: [packages/mermaid/src/types.ts:115](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L115) Defined in: [packages/mermaid/src/types.ts:114](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L114)
## Properties ## Properties
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/types.ts:115](https://github.com/mermaid-js/me
> `optional` **bindFunctions**: (`element`) => `void` > `optional` **bindFunctions**: (`element`) => `void`
Defined in: [packages/mermaid/src/types.ts:133](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L133) Defined in: [packages/mermaid/src/types.ts:132](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L132)
Bind function to be called after the svg has been inserted into the DOM. Bind function to be called after the svg has been inserted into the DOM.
This is necessary for adding event listeners to the elements in the svg. This is necessary for adding event listeners to the elements in the svg.
@@ -45,7 +45,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
> **diagramType**: `string` > **diagramType**: `string`
Defined in: [packages/mermaid/src/types.ts:123](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L123) Defined in: [packages/mermaid/src/types.ts:122](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L122)
The diagram type, e.g. 'flowchart', 'sequence', etc. The diagram type, e.g. 'flowchart', 'sequence', etc.
@@ -55,6 +55,6 @@ The diagram type, e.g. 'flowchart', 'sequence', etc.
> **svg**: `string` > **svg**: `string`
Defined in: [packages/mermaid/src/types.ts:119](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L119) Defined in: [packages/mermaid/src/types.ts:118](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L118)
The svg code for the rendered graph. The svg code for the rendered graph.

View File

@@ -21,7 +21,7 @@ title: Animal example
classDiagram classDiagram
note "From Duck till Zebra" note "From Duck till Zebra"
Animal <|-- Duck Animal <|-- Duck
note for Duck "can fly\ncan swim\ncan dive\ncan help in debugging" note for Duck "can fly<br>can swim<br>can dive<br>can help in debugging"
Animal <|-- Fish Animal <|-- Fish
Animal <|-- Zebra Animal <|-- Zebra
Animal : +int age Animal : +int age
@@ -50,7 +50,7 @@ title: Animal example
classDiagram classDiagram
note "From Duck till Zebra" note "From Duck till Zebra"
Animal <|-- Duck Animal <|-- Duck
note for Duck "can fly\ncan swim\ncan dive\ncan help in debugging" note for Duck "can fly<br>can swim<br>can dive<br>can help in debugging"
Animal <|-- Fish Animal <|-- Fish
Animal <|-- Zebra Animal <|-- Zebra
Animal : +int age Animal : +int age

View File

@@ -85,17 +85,6 @@ export class FlowDB implements DiagramDB {
return common.sanitizeText(txt, this.config); return common.sanitizeText(txt, this.config);
} }
private sanitizeNodeLabelType(labelType?: string) {
switch (labelType) {
case 'markdown':
case 'string':
case 'text':
return labelType;
default:
return 'markdown';
}
}
/** /**
* Function to lookup domId from id in the graph definition. * Function to lookup domId from id in the graph definition.
* *
@@ -219,7 +208,6 @@ export class FlowDB implements DiagramDB {
if (doc?.label) { if (doc?.label) {
vertex.text = doc?.label; vertex.text = doc?.label;
vertex.labelType = this.sanitizeNodeLabelType(doc?.labelType);
} }
if (doc?.icon) { if (doc?.icon) {
vertex.icon = doc?.icon; vertex.icon = doc?.icon;
@@ -279,7 +267,7 @@ export class FlowDB implements DiagramDB {
if (edge.text.startsWith('"') && edge.text.endsWith('"')) { if (edge.text.startsWith('"') && edge.text.endsWith('"')) {
edge.text = edge.text.substring(1, edge.text.length - 1); edge.text = edge.text.substring(1, edge.text.length - 1);
} }
edge.labelType = this.sanitizeNodeLabelType(linkTextObj.type); edge.labelType = linkTextObj.type;
} }
if (type !== undefined) { if (type !== undefined) {
@@ -714,7 +702,7 @@ You have to call mermaid.initialize.`
title: title.trim(), title: title.trim(),
classes: [], classes: [],
dir, dir,
labelType: this.sanitizeNodeLabelType(_title?.type), labelType: _title.type,
}; };
log.info('Adding', subGraph.id, subGraph.nodes, subGraph.dir); log.info('Adding', subGraph.id, subGraph.nodes, subGraph.dir);
@@ -1024,7 +1012,6 @@ You have to call mermaid.initialize.`
const baseNode = { const baseNode = {
id: vertex.id, id: vertex.id,
label: vertex.text, label: vertex.text,
labelType: vertex.labelType,
labelStyle: '', labelStyle: '',
parentId, parentId,
padding: config.flowchart?.padding || 8, padding: config.flowchart?.padding || 8,
@@ -1101,7 +1088,6 @@ You have to call mermaid.initialize.`
id: subGraph.id, id: subGraph.id,
label: subGraph.title, label: subGraph.title,
labelStyle: '', labelStyle: '',
labelType: subGraph.labelType,
parentId: parentDB.get(subGraph.id), parentId: parentDB.get(subGraph.id),
padding: 8, padding: 8,
cssCompiledStyles: this.getCompiledStyles(subGraph.classes), cssCompiledStyles: this.getCompiledStyles(subGraph.classes),
@@ -1133,7 +1119,6 @@ You have to call mermaid.initialize.`
end: rawEdge.end, end: rawEdge.end,
type: rawEdge.type ?? 'normal', type: rawEdge.type ?? 'normal',
label: rawEdge.text, label: rawEdge.text,
labelType: rawEdge.labelType,
labelpos: 'c', labelpos: 'c',
thickness: rawEdge.stroke, thickness: rawEdge.stroke,
minlen: rawEdge.length, minlen: rawEdge.length,

View File

@@ -29,7 +29,7 @@ export interface FlowVertex {
domId: string; domId: string;
haveCallback?: boolean; haveCallback?: boolean;
id: string; id: string;
labelType: 'markdown' | 'string' | 'text'; labelType: 'text';
link?: string; link?: string;
linkTarget?: string; linkTarget?: string;
props?: any; props?: any;
@@ -62,7 +62,7 @@ export interface FlowEdge {
style?: string[]; style?: string[];
length?: number; length?: number;
text: string; text: string;
labelType: 'markdown' | 'string' | 'text'; labelType: 'text';
classes: string[]; classes: string[];
id?: string; id?: string;
animation?: 'fast' | 'slow'; animation?: 'fast' | 'slow';

View File

@@ -62,7 +62,6 @@ const getData = function () {
const node = { const node = {
id: section.id, id: section.id,
label: sanitizeText(section.label ?? '', conf), label: sanitizeText(section.label ?? '', conf),
labelType: 'markdown',
isGroup: true, isGroup: true,
ticket: section.ticket, ticket: section.ticket,
shape: 'kanbanSection', shape: 'kanbanSection',
@@ -77,7 +76,6 @@ const getData = function () {
id: item.id, id: item.id,
parentId: section.id, parentId: section.id,
label: sanitizeText(item.label ?? '', conf), label: sanitizeText(item.label ?? '', conf),
labelType: 'markdown',
isGroup: false, isGroup: false,
ticket: item?.ticket, ticket: item?.ticket,
priority: item?.priority, priority: item?.priority,

View File

@@ -260,7 +260,6 @@ export class MindmapDB {
id: node.id.toString(), id: node.id.toString(),
domId: 'node_' + node.id.toString(), domId: 'node_' + node.id.toString(),
label: node.descr, label: node.descr,
labelType: 'markdown',
isGroup: false, isGroup: false,
shape: getShapeFromType(node.type), shape: getShapeFromType(node.type),
width: node.width, width: node.width,

View File

@@ -16,7 +16,6 @@ export interface MindmapNode {
x?: number; x?: number;
y?: number; y?: number;
isRoot?: boolean; isRoot?: boolean;
labelType?: string;
} }
export type FilledMindMapNode = RequiredDeep<MindmapNode>; export type FilledMindMapNode = RequiredDeep<MindmapNode>;

View File

@@ -16,7 +16,7 @@ const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
const svgWidth = bitWidth * bitsPerRow + 2; const svgWidth = bitWidth * bitsPerRow + 2;
const svg: SVG = selectSvgElement(id); const svg: SVG = selectSvgElement(id);
svg.attr('viewbox', `0 0 ${svgWidth} ${svgHeight}`); svg.attr('viewBox', `0 0 ${svgWidth} ${svgHeight}`);
configureSvgSize(svg, svgHeight, svgWidth, config.useMaxWidth); configureSvgSize(svg, svgHeight, svgWidth, config.useMaxWidth);
for (const [word, packet] of words.entries()) { for (const [word, packet] of words.entries()) {

View File

@@ -2,6 +2,7 @@ import type { Diagram } from '../../Diagram.js';
import type { RadarDiagramConfig } from '../../config.type.js'; import type { RadarDiagramConfig } from '../../config.type.js';
import type { DiagramRenderer, DrawDefinition, SVG, SVGGroup } from '../../diagram-api/types.js'; import type { DiagramRenderer, DrawDefinition, SVG, SVGGroup } from '../../diagram-api/types.js';
import { selectSvgElement } from '../../rendering-util/selectSvgElement.js'; import { selectSvgElement } from '../../rendering-util/selectSvgElement.js';
import { configureSvgSize } from '../../setupGraphViewbox.js';
import type { RadarDB, RadarAxis, RadarCurve } from './types.js'; import type { RadarDB, RadarAxis, RadarCurve } from './types.js';
const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => { const draw: DrawDefinition = (_text, id, _version, diagram: Diagram) => {
@@ -53,11 +54,9 @@ const drawFrame = (svg: SVG, config: Required<RadarDiagramConfig>): SVGGroup =>
x: config.marginLeft + config.width / 2, x: config.marginLeft + config.width / 2,
y: config.marginTop + config.height / 2, y: config.marginTop + config.height / 2,
}; };
// Initialize the SVG configureSvgSize(svg, totalHeight, totalWidth, config.useMaxWidth ?? true);
svg
.attr('viewbox', `0 0 ${totalWidth} ${totalHeight}`) svg.attr('viewBox', `0 0 ${totalWidth} ${totalHeight}`);
.attr('width', totalWidth)
.attr('height', totalHeight);
// g element to center the radar chart // g element to center the radar chart
return svg.append('g').attr('transform', `translate(${center.x}, ${center.y})`); return svg.append('g').attr('transform', `translate(${center.x}, ${center.y})`);
}; };

View File

@@ -15,7 +15,7 @@ title: Animal example
classDiagram classDiagram
note "From Duck till Zebra" note "From Duck till Zebra"
Animal <|-- Duck Animal <|-- Duck
note for Duck "can fly\ncan swim\ncan dive\ncan help in debugging" note for Duck "can fly<br>can swim<br>can dive<br>can help in debugging"
Animal <|-- Fish Animal <|-- Fish
Animal <|-- Zebra Animal <|-- Zebra
Animal : +int age Animal : +int age

View File

@@ -30,17 +30,11 @@ const rect = async (parent, node) => {
// Create the label and insert it after the rect // Create the label and insert it after the rect
const labelEl = shapeSvg.insert('g').attr('class', 'cluster-label '); const labelEl = shapeSvg.insert('g').attr('class', 'cluster-label ');
let text; const text = await createText(labelEl, node.label, {
if (node.labelType === 'markdown') { style: node.labelStyle,
text = await createText(labelEl, node.label, { useHtmlLabels,
style: node.labelStyle, isNode: true,
useHtmlLabels, });
isNode: true,
});
} else {
const labelElement = await createLabel(node.label, node.labelStyle, false, true);
text = labelEl.node()?.appendChild(labelElement);
}
// Get the size of the label // Get the size of the label
let bbox = text.getBBox(); let bbox = text.getBBox();

View File

@@ -29,7 +29,7 @@ import {
import rough from 'roughjs'; import rough from 'roughjs';
import createLabel from './createLabel.js'; import createLabel from './createLabel.js';
import { addEdgeMarkers } from './edgeMarker.ts'; import { addEdgeMarkers } from './edgeMarker.ts';
import { isLabelStyle } from './shapes/handDrawnShapeStyles.js'; import { isLabelStyle, styles2String } from './shapes/handDrawnShapeStyles.js';
export const edgeLabels = new Map(); export const edgeLabels = new Map();
export const terminalLabels = new Map(); export const terminalLabels = new Map();
@@ -47,16 +47,14 @@ export const getLabelStyles = (styleArray) => {
export const insertEdgeLabel = async (elem, edge) => { export const insertEdgeLabel = async (elem, edge) => {
let useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels); let useHtmlLabels = evaluate(getConfig().flowchart.htmlLabels);
const labelElement = const { labelStyles } = styles2String(edge);
edge.labelType === 'markdown' edge.labelStyle = labelStyles;
? await createText(elem, edge.label, { const labelElement = await createText(elem, edge.label, {
style: getLabelStyles(edge.labelStyle), style: edge.labelStyle,
useHtmlLabels, useHtmlLabels,
addSvgBackground: true, addSvgBackground: true,
isNode: false, isNode: false,
}) });
: await createLabel(edge.label, getLabelStyles(edge.labelStyle), undefined, false);
log.info('abc82', edge, edge.labelType); log.info('abc82', edge, edge.labelType);
// Create outer g, edgeLabel, this will be positioned after graph layout // Create outer g, edgeLabel, this will be positioned after graph layout

View File

@@ -1,4 +1,3 @@
import createLabel from '../createLabel.js';
import { createText } from '../../createText.js'; import { createText } from '../../createText.js';
import type { Node } from '../../types.js'; import type { Node } from '../../types.js';
import { getConfig } from '../../../diagram-api/diagramAPI.js'; import { getConfig } from '../../../diagram-api/diagramAPI.js';
@@ -14,7 +13,7 @@ export const labelHelper = async <T extends SVGGraphicsElement>(
_classes?: string _classes?: string
) => { ) => {
let cssClasses; let cssClasses;
const useHtmlLabels = node.useHtmlLabels || evaluate(getConfig()?.flowchart?.htmlLabels); const useHtmlLabels = node.useHtmlLabels || evaluate(getConfig()?.htmlLabels);
if (!_classes) { if (!_classes) {
cssClasses = 'node default'; cssClasses = 'node default';
} else { } else {
@@ -41,26 +40,14 @@ export const labelHelper = async <T extends SVGGraphicsElement>(
label = typeof node.label === 'string' ? node.label : node.label[0]; label = typeof node.label === 'string' ? node.label : node.label[0];
} }
let text; const text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), {
if (node.labelType === 'markdown') { useHtmlLabels,
text = await createText(labelEl, sanitizeText(decodeEntities(label), getConfig()), { width: node.width || getConfig().flowchart?.wrappingWidth,
useHtmlLabels, // @ts-expect-error -- This is currently not used. Should this be `classes` instead?
width: node.width || getConfig().flowchart?.wrappingWidth, cssClasses: 'markdown-node-label',
// @ts-expect-error -- This is currently not used. Should this be `classes` instead? style: node.labelStyle,
cssClasses: 'markdown-node-label', addSvgBackground: !!node.icon || !!node.img,
style: node.labelStyle, });
addSvgBackground: !!node.icon || !!node.img,
});
} else {
const labelElement = await createLabel(
sanitizeText(decodeEntities(label), getConfig()),
node.labelStyle,
false,
true
);
text = labelEl.node()?.appendChild(labelElement);
}
// Get the size of the label // Get the size of the label
let bbox = text.getBBox(); let bbox = text.getBBox();
const halfPadding = (node?.padding ?? 0) / 2; const halfPadding = (node?.padding ?? 0) / 2;

View File

@@ -1,7 +1,6 @@
export interface NodeMetaData { export interface NodeMetaData {
shape?: string; shape?: string;
label?: string; label?: string;
labelType?: string;
icon?: string; icon?: string;
form?: string; form?: string;
pos?: 't' | 'b'; pos?: 't' | 'b';

View File

@@ -20,11 +20,11 @@ fragment Statement:
; ;
fragment LeftPort: fragment LeftPort:
':'lhsDir=ARROW_DIRECTION ':' lhsDir=ID
; ;
fragment RightPort: fragment RightPort:
rhsDir=ARROW_DIRECTION':' rhsDir=ID ':'
; ;
fragment Arrow: fragment Arrow:
@@ -47,6 +47,5 @@ Edge:
lhsId=ID lhsGroup?=ARROW_GROUP? Arrow rhsId=ID rhsGroup?=ARROW_GROUP? EOL lhsId=ID lhsGroup?=ARROW_GROUP? Arrow rhsId=ID rhsGroup?=ARROW_GROUP? EOL
; ;
terminal ARROW_DIRECTION: 'L' | 'R' | 'T' | 'B';
terminal ARROW_GROUP: /\{group\}/; terminal ARROW_GROUP: /\{group\}/;
terminal ARROW_INTO: /<|>/; terminal ARROW_INTO: /<|>/;

View File

@@ -19,6 +19,64 @@ describe('architecture', () => {
}); });
}); });
describe('should handle services', () => {
it('should handle service with icon', () => {
const context = `architecture-beta
service TH(disk)
`;
const result = parse(context);
expectNoErrorsOrAlternatives(result);
expect(result.value.$type).toBe(Architecture);
expect(result.value.services).toHaveLength(1);
expect(result.value.services?.[0].id).toBe('TH');
expect(result.value.services?.[0].icon).toBe('disk');
});
it('should handle service with icon starting with arrow direction letters', () => {
const context = `architecture-beta
service T(disk)
service TH(database)
service L(server)
service R(cloud)
service B(internet)
service TOP(disk)
service LEFT(disk)
service RIGHT(disk)
service BOTTOM(disk)
`;
const result = parse(context);
expectNoErrorsOrAlternatives(result);
expect(result.value.$type).toBe(Architecture);
expect(result.value.services).toHaveLength(9);
});
it('should handle service with icon and title', () => {
const context = `architecture-beta
service db(database)[Database]
`;
const result = parse(context);
expectNoErrorsOrAlternatives(result);
expect(result.value.$type).toBe(Architecture);
expect(result.value.services).toHaveLength(1);
expect(result.value.services?.[0].id).toBe('db');
expect(result.value.services?.[0].icon).toBe('database');
expect(result.value.services?.[0].title).toBe('Database');
});
it('should handle service in a group', () => {
const context = `architecture-beta
group api(cloud)[API]
service db(database)[Database] in api
`;
const result = parse(context);
expectNoErrorsOrAlternatives(result);
expect(result.value.$type).toBe(Architecture);
expect(result.value.services).toHaveLength(1);
expect(result.value.services?.[0].id).toBe('db');
expect(result.value.services?.[0].in).toBe('api');
});
});
describe('should handle TitleAndAccessibilities', () => { describe('should handle TitleAndAccessibilities', () => {
it.each([ it.each([
`architecture-beta title sample title`, `architecture-beta title sample title`,