feat: Link docs for the diagram types added in mermaid 11.6–12

Adds docs paths for agentflow, cynefin, eventmodeling, ishikawa, radar,
the four railroad variants, swimlane, treeView, usecase, venn and
wardley, taken from packages/mermaid/src/docs/syntax in the mermaid repo
and checked against the published pages (config anchors included).

A new test parses every @mermaid-js/examples sample and fails when a
detected diagram type has no docs entry, so the next new type is caught
on the dependency bump instead of silently linking to the docs home.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Sidharth VinodandClaude Opus 5.5 committed 2026-09-30 10:29:49 +05:30
1 parent ff0c822bd0
commit 7cb51a1d4f
3 files changed
+77 -2

No files matched your search

+29 -2
View File
@@ -1,3 +1,5 @@
import { diagramData } from '@mermaid-js/examples';
import mermaid from 'mermaid';
import { describe, expect, it } from 'vitest';
import { describeDiagram } from './diagramTypes';
@@ -47,11 +49,36 @@ describe('describeDiagram', () => {
expect(describeDiagram('sequence')?.externalServices).toBe(true);
});
it.each([
['railroadEbnf', '/syntax/railroad.html#ebnf-railroad-ebnf-beta'],
['swimlane', '/syntax/swimlanes.html'],
['treeView', '/syntax/treeView.html']
])('links %s to its docs page', (detected, code) => {
expect(describeDiagram(detected)?.docs?.code).toBe(code);
});
it('describes unknown diagram types without docs', () => {
expect(describeDiagram('venn')).toEqual({
expect(describeDiagram('not-a-diagram')).toEqual({
externalServices: true,
id: 'venn',
id: 'not-a-diagram',
visualEdit: false
});
});
// Fails when mermaid ships a diagram type the catalog doesn't know yet:
// add its docs paths from packages/mermaid/src/docs/syntax in the mermaid repo.
it('has docs for every sample diagram', async () => {
const missing: string[] = [];
for (const { name, examples } of diagramData) {
const example = examples?.[0];
if (!example) {
continue;
}
const { diagramType } = await mermaid.parse(example.code);
if (!describeDiagram(diagramType)?.docs) {
missing.push(`${name} (${diagramType})`);
}
}
expect(missing).toEqual([]);
});
});
+42
View File
@@ -31,6 +31,9 @@ const aliases: Record<string, string> = {
};
const catalog: Record<string, DiagramTraits> = {
agentflow: {
docs: { code: '/syntax/agentflow.html', config: '/syntax/agentflow.html#configuration' }
},
architecture: {
docs: { code: '/syntax/architecture.html' }
},
@@ -44,6 +47,9 @@ const catalog: Record<string, DiagramTraits> = {
docs: { code: '/syntax/classDiagram.html', config: '/syntax/classDiagram.html#configuration' },
visualEdit: true
},
cynefin: {
docs: { code: '/syntax/cynefin.html', config: '/syntax/cynefin.html#configuration' }
},
er: {
docs: {
code: '/syntax/entityRelationshipDiagram.html',
@@ -51,6 +57,9 @@ const catalog: Record<string, DiagramTraits> = {
},
visualEdit: true
},
eventmodeling: {
docs: { code: '/syntax/eventmodeling.html' }
},
flowchart: {
docs: { code: '/syntax/flowchart.html', config: '/syntax/flowchart.html#configuration' },
visualEdit: true
@@ -64,6 +73,9 @@ const catalog: Record<string, DiagramTraits> = {
config: '/syntax/gitgraph.html#gitgraph-specific-configuration-options'
}
},
ishikawa: {
docs: { code: '/syntax/ishikawa.html' }
},
journey: {
docs: { code: '/syntax/userJourney.html' }
},
@@ -89,6 +101,21 @@ const catalog: Record<string, DiagramTraits> = {
config: '/syntax/quadrantChart.html#chart-configurations'
}
},
radar: {
docs: { code: '/syntax/radar.html', config: '/syntax/radar.html#configuration' }
},
railroad: {
docs: { code: '/syntax/railroad.html#ir-primitives-railroad-beta' }
},
railroadAbnf: {
docs: { code: '/syntax/railroad.html#abnf-railroad-abnf-beta' }
},
railroadEbnf: {
docs: { code: '/syntax/railroad.html#ebnf-railroad-ebnf-beta' }
},
railroadPeg: {
docs: { code: '/syntax/railroad.html#peg-railroad-peg-beta' }
},
requirement: {
docs: { code: '/syntax/requirementDiagram.html' },
visualEdit: true
@@ -107,12 +134,27 @@ const catalog: Record<string, DiagramTraits> = {
docs: { code: '/syntax/stateDiagram.html' },
visualEdit: true
},
swimlane: {
docs: { code: '/syntax/swimlanes.html' }
},
timeline: {
docs: { code: '/syntax/timeline.html', config: '/syntax/timeline.html#themes' }
},
treeView: {
docs: { code: '/syntax/treeView.html', config: '/syntax/treeView.html#config-variables' }
},
treemap: {
docs: { code: '/syntax/treemap.html', config: '/syntax/treemap.html#configuration-options' }
},
usecase: {
docs: { code: '/syntax/usecase.html', config: '/syntax/usecase.html#configuration' }
},
venn: {
docs: { code: '/syntax/venn.html' }
},
wardley: {
docs: { code: '/syntax/wardley.html', config: '/syntax/wardley.html#configuration' }
},
xychart: {
docs: { code: '/syntax/xyChart.html', config: '/syntax/xyChart.html#chart-configurations' }
},
+6
View File
@@ -31,6 +31,12 @@ test.describe('Editor docs tests', () => {
await editPage.setEditorMode('Config');
await editPage.checkDocURL(/syntax\/classDiagram\.html#configuration/);
await editPage.setEditorMode('Code');
await editPage.loadSampleDiagram('Radar');
await editPage.checkDocURL(/syntax\/radar\.html/);
await editPage.setEditorMode('Config');
await editPage.checkDocURL(/syntax\/radar\.html#configuration/);
await editPage.setEditorMode('Code');
});
test("Test to check URLs for a case where config URL doesn't exist", async ({ editPage }) => {