Merge branch 'develop' of github.com:yari-dewalt/mermaid into fix/could_not_find_a_suitable_point_for_the_given_distance

This commit is contained in:
yari-dewalt
2025-02-25 10:12:43 -08:00
177 changed files with 8421 additions and 8675 deletions

View File

@@ -37,14 +37,14 @@
]
},
"dependencies": {
"@braintree/sanitize-url": "^7.0.0",
"@braintree/sanitize-url": "^7.0.4",
"d3": "^7.9.0",
"khroma": "^2.1.0"
},
"devDependencies": {
"concurrently": "^8.2.2",
"concurrently": "^9.1.2",
"mermaid": "workspace:*",
"rimraf": "^5.0.5"
"rimraf": "^6.0.1"
},
"files": [
"dist"

View File

@@ -37,7 +37,7 @@
"mermaid": "workspace:^"
},
"peerDependencies": {
"mermaid": "^11.0.0"
"mermaid": "^11.0.2"
},
"files": [
"dist"

View File

@@ -33,7 +33,7 @@
],
"license": "MIT",
"dependencies": {
"@zenuml/core": "^3.23.27"
"@zenuml/core": "^3.23.28"
},
"devDependencies": {
"mermaid": "workspace:^"

View File

@@ -67,68 +67,67 @@
]
},
"dependencies": {
"@braintree/sanitize-url": "^7.0.1",
"@iconify/utils": "^2.1.32",
"@braintree/sanitize-url": "^7.0.4",
"@iconify/utils": "^2.1.33",
"@mermaid-js/parser": "workspace:^",
"@types/d3": "^7.4.3",
"cytoscape": "^3.29.2",
"cytoscape": "^3.29.3",
"cytoscape-cose-bilkent": "^4.1.0",
"cytoscape-fcose": "^2.2.0",
"d3": "^7.9.0",
"d3-sankey": "^0.12.3",
"dagre-d3-es": "7.0.11",
"dayjs": "^1.11.10",
"dayjs": "^1.11.13",
"dompurify": "^3.2.1",
"katex": "^0.16.9",
"khroma": "^2.1.0",
"lodash-es": "^4.17.21",
"marked": "^13.0.2",
"marked": "^15.0.7",
"roughjs": "^4.6.6",
"stylis": "^4.3.1",
"stylis": "^4.3.6",
"ts-dedent": "^2.2.0",
"uuid": "^9.0.1"
"uuid": "^11.1.0"
},
"devDependencies": {
"@adobe/jsonschema2md": "^8.0.0",
"@adobe/jsonschema2md": "^8.0.2",
"@iconify/types": "^2.0.0",
"@types/cytoscape": "^3.21.4",
"@types/cytoscape": "^3.21.9",
"@types/cytoscape-fcose": "^2.2.4",
"@types/d3-sankey": "^0.12.4",
"@types/d3-scale": "^4.0.8",
"@types/d3-scale-chromatic": "^3.0.3",
"@types/d3-selection": "^3.0.10",
"@types/d3-shape": "^3.1.6",
"@types/jsdom": "^21.1.6",
"@types/d3-scale": "^4.0.9",
"@types/d3-scale-chromatic": "^3.1.0",
"@types/d3-selection": "^3.0.11",
"@types/d3-shape": "^3.1.7",
"@types/jsdom": "^21.1.7",
"@types/katex": "^0.16.7",
"@types/lodash-es": "^4.17.12",
"@types/micromatch": "^4.0.6",
"@types/prettier": "^3.0.0",
"@types/stylis": "^4.2.5",
"@types/uuid": "^9.0.8",
"ajv": "^8.12.0",
"chokidar": "^3.6.0",
"concurrently": "^8.2.2",
"csstree-validator": "^3.0.0",
"globby": "^14.0.1",
"@types/micromatch": "^4.0.9",
"@types/stylis": "^4.2.7",
"@types/uuid": "^10.0.0",
"ajv": "^8.17.1",
"chokidar": "^4.0.3",
"concurrently": "^9.1.2",
"csstree-validator": "^4.0.1",
"globby": "^14.0.2",
"jison": "^0.4.18",
"js-base64": "^3.7.7",
"jsdom": "^24.0.0",
"json-schema-to-typescript": "^13.1.2",
"micromatch": "^4.0.5",
"jsdom": "^26.0.0",
"json-schema-to-typescript": "^15.0.4",
"micromatch": "^4.0.8",
"path-browserify": "^1.0.1",
"prettier": "^3.2.5",
"prettier": "^3.5.2",
"remark": "^15.0.1",
"remark-frontmatter": "^5.0.0",
"remark-gfm": "^4.0.0",
"rimraf": "^5.0.5",
"start-server-and-test": "^2.0.3",
"type-fest": "^4.13.1",
"typedoc": "^0.25.12",
"typedoc-plugin-markdown": "^3.17.1",
"typescript": "~5.4.3",
"remark-gfm": "^4.0.1",
"rimraf": "^6.0.1",
"start-server-and-test": "^2.0.10",
"type-fest": "^4.35.0",
"typedoc": "^0.27.8",
"typedoc-plugin-markdown": "^4.4.2",
"typescript": "~5.7.3",
"unist-util-flatmap": "^1.0.0",
"unist-util-visit": "^5.0.0",
"vitepress": "^1.0.1",
"vitepress": "^1.0.2",
"vitepress-plugin-search": "1.0.4-alpha.22"
},
"files": [

View File

@@ -230,7 +230,7 @@ const ConfigWarning = {
} as const;
type ConfigWarningStrings = keyof typeof ConfigWarning;
const issuedWarnings: { [key in ConfigWarningStrings]?: boolean } = {};
const issuedWarnings: Partial<Record<ConfigWarningStrings, boolean>> = {};
const issueWarning = (warning: ConfigWarningStrings) => {
if (issuedWarnings[warning]) {
return;

View File

@@ -106,9 +106,7 @@ export const isValidArchitectureDirectionPair = function (
return x !== 'LL' && x !== 'RR' && x !== 'TT' && x !== 'BB';
};
export type ArchitectureDirectionPairMap = {
[key in ArchitectureDirectionPair]?: string;
};
export type ArchitectureDirectionPairMap = Partial<Record<ArchitectureDirectionPair, string>>;
/**
* Creates a pair of the directions of each side of an edge. This function should be used instead of manually creating it to ensure that the source is always the first character.

View File

@@ -84,7 +84,7 @@ describe('when parsing a gitGraph', function () {
const commits = db.getCommits();
expect(commits.size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('a commit');
expect(db.getCurrentBranch()).toBe('main');
});
@@ -246,7 +246,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('');
expect(commits.get(key)?.id).not.toBeNull();
expect(commits.get(key)?.tags).toStrictEqual([]);
@@ -263,7 +263,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('');
expect(commits.get(key)?.id).toBe('1111');
expect(commits.get(key)?.tags).toStrictEqual([]);
@@ -281,7 +281,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('');
expect(commits.get(key)?.id).not.toBeNull();
expect(commits.get(key)?.tags).toStrictEqual(['test']);
@@ -299,7 +299,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('');
expect(commits.get(key)?.id).not.toBeNull();
expect(commits.get(key)?.tags).toStrictEqual([]);
@@ -317,7 +317,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('');
expect(commits.get(key)?.id).not.toBeNull();
expect(commits.get(key)?.tags).toStrictEqual([]);
@@ -335,7 +335,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('');
expect(commits.get(key)?.id).not.toBeNull();
expect(commits.get(key)?.tags).toStrictEqual([]);
@@ -353,7 +353,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('test commit');
expect(commits.get(key)?.id).not.toBeNull();
expect(commits.get(key)?.tags).toStrictEqual([]);
@@ -371,7 +371,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('test commit');
expect(commits.get(key)?.id).not.toBeNull();
expect(commits.get(key)?.tags).toStrictEqual([]);
@@ -389,7 +389,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('');
expect(commits.get(key)?.id).toBe('1111');
expect(commits.get(key)?.tags).toStrictEqual(['test tag']);
@@ -407,7 +407,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('');
expect(commits.get(key)?.id).not.toBeNull();
expect(commits.get(key)?.tags).toStrictEqual(['test tag']);
@@ -425,7 +425,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('');
expect(commits.get(key)?.id).not.toBeNull();
expect(commits.get(key)?.tags).toStrictEqual(['test tag']);
@@ -443,7 +443,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('');
expect(commits.get(key)?.id).toBe('1111');
expect(commits.get(key)?.tags).toStrictEqual(['test tag']);
@@ -461,7 +461,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('test msg');
expect(commits.get(key)?.id).toBe('1111');
expect(commits.get(key)?.tags).toStrictEqual(['test tag']);
@@ -480,7 +480,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('test msg');
expect(commits.get(key)?.id).toBe('1111');
expect(commits.get(key)?.tags).toStrictEqual(['test tag']);
@@ -498,7 +498,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('test msg');
expect(commits.get(key)?.id).toBe('1111');
expect(commits.get(key)?.tags).toStrictEqual(['test tag']);
@@ -516,7 +516,7 @@ describe('when parsing a gitGraph', function () {
expect(db.getCurrentBranch()).toBe('main');
expect(db.getDirection()).toBe('LR');
expect(db.getBranches().size).toBe(1);
const key = commits.keys().next().value;
const key = commits.keys().next().value!;
expect(commits.get(key)?.message).toBe('test msg');
expect(commits.get(key)?.id).toBe('1111');
expect(commits.get(key)?.tags).toStrictEqual(['test tag']);

View File

@@ -1,7 +1,7 @@
import type { InfoFields, InfoDB } from './infoTypes.js';
import { version } from '../../../package.json';
import packageJson from '../../../package.json' assert { type: 'json' };
export const DEFAULT_INFO_DB: InfoFields = { version } as const;
export const DEFAULT_INFO_DB: InfoFields = { version: packageJson.version } as const;
export const getVersion = (): string => DEFAULT_INFO_DB.version;

View File

@@ -9,7 +9,7 @@ const parserFnConstructor = (str: string) => {
};
};
const mockDB: Record<string, Mock<any, any>> = {
const mockDB: Record<string, Mock<any>> = {
setQuadrant1Text: vi.fn(),
setQuadrant2Text: vi.fn(),
setQuadrant3Text: vi.fn(),

File diff suppressed because it is too large Load Diff

View File

@@ -1,16 +1,26 @@
import type { DiagramDefinition } from '../../diagram-api/types.js';
// @ts-ignore: JISON doesn't support types
import parser from './parser/sequenceDiagram.jison';
import db from './sequenceDb.js';
import { SequenceDB } from './sequenceDb.js';
import styles from './styles.js';
import { setConfig } from '../../diagram-api/diagramAPI.js';
import renderer from './sequenceRenderer.js';
import type { MermaidConfig } from '../../config.type.js';
export const diagram: DiagramDefinition = {
parser,
db,
get db() {
return new SequenceDB();
},
renderer,
styles,
init: ({ wrap }) => {
db.setWrap(wrap);
init: (cnf: MermaidConfig) => {
if (!cnf.sequence) {
cnf.sequence = {};
}
if (cnf.wrap) {
cnf.sequence.wrap = cnf.wrap;
setConfig({ sequence: { wrap: cnf.wrap } });
}
},
};

View File

@@ -1538,7 +1538,6 @@ const calculateLoopBounds = async function (messages, actors, _maxWidthPerActor,
let current, noteModel, msgModel;
for (const msg of messages) {
msg.id = utils.random({ length: 10 });
switch (msg.type) {
case diagObj.db.LINETYPE.LOOP_START:
case diagObj.db.LINETYPE.ALT_START:

View File

@@ -20,6 +20,7 @@ export interface Actor {
}
export interface Message {
id: string;
from?: string;
to?: string;
message:

View File

@@ -1,4 +1,4 @@
import stateDb from '../stateDb.js';
import { StateDB } from '../stateDb.js';
import stateDiagram from './stateDiagram.jison';
import { setConfig } from '../../../config.js';
@@ -7,7 +7,9 @@ setConfig({
});
describe('state parser can parse...', () => {
let stateDb;
beforeEach(function () {
stateDb = new StateDB(2);
stateDiagram.parser.yy = stateDb;
stateDiagram.parser.yy.clear();
});
@@ -18,7 +20,6 @@ describe('state parser can parse...', () => {
const diagramText = `stateDiagram-v2
state "Small State 1" as namedState1`;
stateDiagram.parser.parse(diagramText);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const states = stateDiagram.parser.yy.getStates();
expect(states.get('namedState1')).not.toBeUndefined();
@@ -31,7 +32,6 @@ describe('state parser can parse...', () => {
const diagramText = `stateDiagram-v2
namedState1 : Small State 1`;
stateDiagram.parser.parse(diagramText);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const states = stateDiagram.parser.yy.getStates();
expect(states.get('namedState1')).not.toBeUndefined();
@@ -42,7 +42,6 @@ describe('state parser can parse...', () => {
const diagramText = `stateDiagram-v2
namedState1:Small State 1`;
stateDiagram.parser.parse(diagramText);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const states = stateDiagram.parser.yy.getStates();
expect(states.get('namedState1')).not.toBeUndefined();
@@ -60,7 +59,6 @@ describe('state parser can parse...', () => {
state assemblies
`;
stateDiagram.parser.parse(diagramText);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const states = stateDiagram.parser.yy.getStates();
expect(states.get('assemble')).not.toBeUndefined();
expect(states.get('assemblies')).not.toBeUndefined();
@@ -71,7 +69,6 @@ describe('state parser can parse...', () => {
state "as" as as
`;
stateDiagram.parser.parse(diagramText);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const states = stateDiagram.parser.yy.getStates();
expect(states.get('as')).not.toBeUndefined();
expect(states.get('as').descriptions.join(' ')).toEqual('as');
@@ -96,7 +93,6 @@ describe('state parser can parse...', () => {
namedState2 --> bigState2: should point to \\nbigState2 container`;
stateDiagram.parser.parse(diagramText);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const states = stateDiagram.parser.yy.getStates();
expect(states.get('namedState1')).not.toBeUndefined();
@@ -120,7 +116,6 @@ describe('state parser can parse...', () => {
inner1 --> inner2
}`;
stateDiagram.parser.parse(diagramText);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const states = stateDiagram.parser.yy.getStates();
expect(states.get('bigState1')).not.toBeUndefined();
@@ -137,7 +132,6 @@ describe('state parser can parse...', () => {
stateDiagram-v2
[*] --> ${prop}
${prop} --> [*]`);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const states = stateDiagram.parser.yy.getStates();
expect(states.get(prop)).not.toBeUndefined();
});

View File

@@ -1,13 +1,15 @@
import stateDb from '../stateDb.js';
import stateDiagram from './stateDiagram.jison';
import { setConfig } from '../../../config.js';
import { StateDB } from '../stateDb.js';
import stateDiagram from './stateDiagram.jison';
setConfig({
securityLevel: 'strict',
});
describe('ClassDefs and classes when parsing a State diagram', () => {
let stateDb;
beforeEach(function () {
stateDb = new StateDB(2);
stateDiagram.parser.yy = stateDb;
stateDiagram.parser.yy.clear();
});
@@ -16,7 +18,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
describe('defining (classDef)', () => {
it('has "classDef" as a keyword, an id, and can set a css style attribute', function () {
stateDiagram.parser.parse('stateDiagram-v2\n classDef exampleClass background:#bbb;');
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const styleClasses = stateDb.getClasses();
expect(styleClasses.get('exampleClass').styles.length).toEqual(1);
@@ -27,7 +28,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
stateDiagram.parser.parse(
'stateDiagram-v2\n classDef exampleClass background:#bbb, font-weight:bold, font-style:italic;'
);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const styleClasses = stateDb.getClasses();
expect(styleClasses.get('exampleClass').styles.length).toEqual(3);
@@ -41,7 +41,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
stateDiagram.parser.parse(
'stateDiagram-v2\n classDef exampleStyleClass background:#bbb,border:1.5px solid red;'
);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const classes = stateDiagram.parser.yy.getClasses();
expect(classes.get('exampleStyleClass').styles.length).toBe(2);
@@ -53,7 +52,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
stateDiagram.parser.parse(
'stateDiagram-v2\n classDef exampleStyleClass background: #bbb,border:1.5px solid red;'
);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const classes = stateDiagram.parser.yy.getClasses();
expect(classes.get('exampleStyleClass').styles.length).toBe(2);
@@ -65,7 +63,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
stateDiagram.parser.parse(
'stateDiagram-v2\n classDef __proto__ background:#bbb,border:1.5px solid red;\n classDef constructor background:#bbb,border:1.5px solid red;'
);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const classes = stateDiagram.parser.yy.getClasses();
expect(classes.get('__proto__').styles.length).toBe(2);
expect(classes.get('constructor').styles.length).toBe(2);
@@ -81,7 +78,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
diagram += 'class a exampleStyleClass';
stateDiagram.parser.parse(diagram);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const classes = stateDb.getClasses();
expect(classes.get('exampleStyleClass').styles.length).toEqual(2);
@@ -102,7 +98,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
diagram += 'class a_a exampleStyleClass';
stateDiagram.parser.parse(diagram);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const classes = stateDiagram.parser.yy.getClasses();
expect(classes.get('exampleStyleClass').styles.length).toBe(2);
@@ -122,7 +117,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
diagram += 'a --> b:::exampleStyleClass' + '\n';
stateDiagram.parser.parse(diagram);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const states = stateDiagram.parser.yy.getStates();
const classes = stateDiagram.parser.yy.getClasses();
@@ -141,7 +135,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
diagram += '[*]:::exampleStyleClass --> b\n';
stateDiagram.parser.parse(diagram);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const states = stateDiagram.parser.yy.getStates();
const classes = stateDiagram.parser.yy.getClasses();
@@ -161,7 +154,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
diagram += 'class a,b exampleStyleClass';
stateDiagram.parser.parse(diagram);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
let classes = stateDiagram.parser.yy.getClasses();
let states = stateDiagram.parser.yy.getStates();
@@ -180,7 +172,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
diagram += 'class a,b,c, d, e exampleStyleClass';
stateDiagram.parser.parse(diagram);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const classes = stateDiagram.parser.yy.getClasses();
const states = stateDiagram.parser.yy.getStates();
@@ -208,7 +199,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
diagram += '}\n';
stateDiagram.parser.parse(diagram);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const states = stateDiagram.parser.yy.getStates();
@@ -224,7 +214,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
stateDiagram.parser.parse(`stateDiagram-v2
id1
style id1 background:#bbb`);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const data4Layout = stateDiagram.parser.yy.getData();
expect(data4Layout.nodes[0].cssStyles).toEqual(['background:#bbb']);
@@ -234,7 +223,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
id1
id2
style id1,id2 background:#bbb`);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const data4Layout = stateDiagram.parser.yy.getData();
expect(data4Layout.nodes[0].cssStyles).toEqual(['background:#bbb']);
@@ -247,7 +235,6 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
id2
style id1,id2 background:#bbb, font-weight:bold, font-style:italic;`);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const data4Layout = stateDiagram.parser.yy.getData();
expect(data4Layout.nodes[0].cssStyles).toEqual([

View File

@@ -1,6 +1,6 @@
import { line, curveBasis } from 'd3';
import idCache from './id-cache.js';
import stateDb from './stateDb.js';
import { StateDB } from './stateDb.js';
import utils from '../../utils.js';
import common from '../common/common.js';
import { getConfig } from '../../diagram-api/diagramAPI.js';
@@ -414,13 +414,13 @@ let edgeCount = 0;
export const drawEdge = function (elem, path, relation) {
const getRelationType = function (type) {
switch (type) {
case stateDb.relationType.AGGREGATION:
case StateDB.relationType.AGGREGATION:
return 'aggregation';
case stateDb.relationType.EXTENSION:
case StateDB.relationType.EXTENSION:
return 'extension';
case stateDb.relationType.COMPOSITION:
case StateDB.relationType.COMPOSITION:
return 'composition';
case stateDb.relationType.DEPENDENCY:
case StateDB.relationType.DEPENDENCY:
return 'dependency';
}
};
@@ -459,7 +459,7 @@ export const drawEdge = function (elem, path, relation) {
svgPath.attr(
'marker-end',
'url(' + url + '#' + getRelationType(stateDb.relationType.DEPENDENCY) + 'End' + ')'
'url(' + url + '#' + getRelationType(StateDB.relationType.DEPENDENCY) + 'End' + ')'
);
if (relation.title !== undefined) {

View File

@@ -3,11 +3,14 @@
*/
// default diagram direction
export const DEFAULT_DIAGRAM_DIRECTION = 'LR';
export const DEFAULT_DIAGRAM_DIRECTION = 'TB';
// default direction for any nested documents (composites)
export const DEFAULT_NESTED_DOC_DIR = 'TB';
// parsed statement type for a direction
export const STMT_DIRECTION = 'dir';
// parsed statement type for a state
export const STMT_STATE = 'state';
// parsed statement type for a relation

File diff suppressed because it is too large Load Diff

View File

@@ -1,8 +1,9 @@
import stateDb from './stateDb.js';
import { StateDB } from './stateDb.js';
describe('State Diagram stateDb', () => {
let stateDb;
beforeEach(() => {
stateDb.clear();
stateDb = new StateDB(1);
});
describe('addStyleClass', () => {
@@ -20,8 +21,9 @@ describe('State Diagram stateDb', () => {
});
describe('addDescription to a state', () => {
let stateDb;
beforeEach(() => {
stateDb.clear();
stateDb = new StateDB(1);
stateDb.addState('state1');
});
@@ -73,3 +75,25 @@ describe('State Diagram stateDb', () => {
});
});
});
describe('state db class', () => {
let stateDb;
beforeEach(() => {
stateDb = new StateDB(1);
});
// This is to ensure that functions used in state JISON are exposed as function from StateDb
it('should have functions used in flow JISON as own property', () => {
const functionsUsedInParser = [
'setRootDoc',
'trimColon',
'getDividerId',
'setAccTitle',
'setAccDescription',
'setDirection',
];
for (const fun of functionsUsedInParser) {
expect(Object.hasOwn(stateDb, fun)).toBe(true);
}
});
});

View File

@@ -1,11 +1,13 @@
import { parser } from './parser/stateDiagram.jison';
import stateDb from './stateDb.js';
import stateDiagram from './parser/stateDiagram.jison';
import stateDiagram, { parser } from './parser/stateDiagram.jison';
import { DEFAULT_DIAGRAM_DIRECTION } from './stateCommon.js';
import { StateDB } from './stateDb.js';
describe('state diagram V2, ', function () {
// TODO - these examples should be put into ./parser/stateDiagram.spec.js
describe('when parsing an info graph it', function () {
let stateDb;
beforeEach(function () {
stateDb = new StateDB(2);
parser.yy = stateDb;
stateDiagram.parser.yy = stateDb;
stateDiagram.parser.yy.clear();
@@ -127,7 +129,6 @@ describe('state diagram V2, ', function () {
`;
stateDiagram.parser.parse(diagram);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const rels = stateDb.getRelations();
const rel_1_2 = rels.find((rel) => rel.id1 === 'State1' && rel.id2 === 'State2');
@@ -402,7 +403,6 @@ describe('state diagram V2, ', function () {
`;
stateDiagram.parser.parse(diagram);
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
const states = stateDb.getStates();
expect(states.get('Active').doc[0].id).toEqual('Idle');
@@ -413,5 +413,34 @@ describe('state diagram V2, ', function () {
const rel_Active_Active = rels.find((rel) => rel.id1 === 'Active' && rel.id2 === 'Active');
expect(rel_Active_Active.relationTitle).toEqual('LOG');
});
it('should check default diagram direction', () => {
const diagram = `
stateDiagram
[*] --> Still
Still --> [*]
`;
parser.parse(diagram);
// checking default direction if no direction is specified
const defaultDir = stateDb.getDirection();
expect(defaultDir).toEqual(DEFAULT_DIAGRAM_DIRECTION);
});
it('retrieve the diagram direction correctly', () => {
const diagram = `
stateDiagram
direction LR
[*] --> Still
Still --> [*]
`;
parser.parse(diagram);
//retrieve the diagram direction
const currentDirection = stateDb.getDirection();
expect(currentDirection).toEqual('LR');
});
});
});

View File

@@ -1,13 +1,15 @@
import type { DiagramDefinition } from '../../diagram-api/types.js';
// @ts-ignore: JISON doesn't support types
import parser from './parser/stateDiagram.jison';
import db from './stateDb.js';
import { StateDB } from './stateDb.js';
import styles from './styles.js';
import renderer from './stateRenderer-v3-unified.js';
export const diagram: DiagramDefinition = {
parser,
db,
get db() {
return new StateDB(2);
},
renderer,
styles,
init: (cnf) => {

View File

@@ -1,9 +1,11 @@
import { parser } from './parser/stateDiagram.jison';
import stateDb from './stateDb.js';
import { StateDB } from './stateDb.js';
describe('state diagram, ', function () {
describe('when parsing an info graph it', function () {
let stateDb;
beforeEach(function () {
stateDb = new StateDB(1);
parser.yy = stateDb;
});

View File

@@ -1,13 +1,15 @@
import type { DiagramDefinition } from '../../diagram-api/types.js';
// @ts-ignore: JISON doesn't support types
import parser from './parser/stateDiagram.jison';
import db from './stateDb.js';
import { StateDB } from './stateDb.js';
import styles from './styles.js';
import renderer from './stateRenderer.js';
export const diagram: DiagramDefinition = {
parser,
db,
get db() {
return new StateDB(1);
},
renderer,
styles,
init: (cnf) => {

View File

@@ -36,7 +36,6 @@ export const getClasses = function (
text: string,
diagramObj: any
): Map<string, DiagramStyleClassDef> {
diagramObj.db.extract(diagramObj.db.getRootDocV2());
return diagramObj.db.getClasses();
};

View File

@@ -136,7 +136,6 @@ const renderDoc = (doc, diagram, parentId, altBkg, root, domDocument, diagObj) =
return {};
});
diagObj.db.extract(doc);
const states = diagObj.db.getStates();
const relations = diagObj.db.getRelations();

View File

@@ -9,7 +9,7 @@ const parserFnConstructor = (str: string) => {
};
};
const mockDB: Record<string, Mock<any, any>> = {
const mockDB: Record<string, Mock<any>> = {
setOrientation: vi.fn(),
setDiagramTitle: vi.fn(),
setXAxisTitle: vi.fn(),

View File

@@ -16,7 +16,7 @@ import { teamMembers } from '../contributors';
<p text-lg max-w-200 text-center leading-7>
<Contributors />
<br />
<a href="https://discord.gg/AgrbSrBer3" rel="noopener noreferrer">Join the community</a>
<a href="https://discord.gg/sKeNQX4Wtj" rel="noopener noreferrer">Join the community</a>
and get involved!
</p>
</div>

View File

@@ -1,40 +1,114 @@
<script setup lang="ts">
import { ref, onMounted } from 'vue';
import { ref, onMounted, computed } from 'vue';
interface Taglines {
label: string;
url: string;
}
const taglines: Taglines[] = [
{
label: 'Explore the Mermaid Whiteboard from the creators of Mermaid',
url: 'https://www.mermaidchart.com/whiteboard?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=whiteboard',
const allTaglines: { [key: string]: { design: number; taglines: Taglines[] } } = {
A: {
design: 1,
taglines: [
{
label: 'Replace ChatGPT Pro, Mermaid.live, and Lucid Chart with Mermaid Chart',
url: 'https://www.mermaidchart.com/play?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=AIbundle_A',
},
{
label: 'Diagram live with teammates in Mermaid Chart',
url: 'https://www.mermaidchart.com/play?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=teams_A',
},
{
label: 'Use the Visual Editor in Mermaid Chart to design and build diagrams',
url: 'https://www.mermaidchart.com/play?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=visual_editor_A',
},
{
label: 'Explore the Mermaid Whiteboard from the creators of Mermaid',
url: 'https://www.mermaidchart.com/whiteboard?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=whiteboard_A',
},
],
},
{
label: 'Use the Visual Editor in Mermaid Chart to design and build diagrams',
url: 'https://www.mermaidchart.com/play?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=visual_editor',
B: {
design: 2,
taglines: [
{
label: 'Replace ChatGPT Pro, Mermaid.live, and Lucid Chart with Mermaid Chart',
url: 'https://www.mermaidchart.com/play?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=AIbundle_B',
},
{
label: 'Diagram live with teammates in Mermaid Chart',
url: 'https://www.mermaidchart.com/play?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=teams_B',
},
{
label: 'Use the Visual Editor in Mermaid Chart to design and build diagrams',
url: 'https://www.mermaidchart.com/play?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=visual_editor_B',
},
{
label: 'Explore the Mermaid Whiteboard from the creators of Mermaid',
url: 'https://www.mermaidchart.com/whiteboard?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=whiteboard_B',
},
],
},
{
label: 'Diagram live with teammates in Mermaid Chart',
url: 'https://www.mermaidchart.com/play?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=teams',
C: {
design: 1,
taglines: [
{
label: 'Replace ChatGPT Pro, Mermaid.live, and Lucid Chart with Mermaid Pro',
url: 'https://www.mermaidchart.com/play?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=AIbundle_C',
},
{
label: 'Diagram live with teammates in Mermaid Pro',
url: 'https://www.mermaidchart.com/play?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=teams_C',
},
{
label: 'Use the Visual Editor in Mermaid Pro to design and build diagrams',
url: 'https://www.mermaidchart.com/play?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=visual_editor_C',
},
{
label: 'Explore the Mermaid Whiteboard from the creators of Mermaid',
url: 'https://www.mermaidchart.com/whiteboard?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=whiteboard_A',
},
],
},
{
label: 'Replace ChatGPT Pro, Mermaid.live, and LucidChart with Mermaid Pro',
url: 'https://www.mermaidchart.com/play?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=AIbundle',
D: {
design: 2,
taglines: [
{
label: 'Replace ChatGPT Pro, Mermaid.live, and Lucid Chart with Mermaid Pro',
url: 'https://www.mermaidchart.com/play?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=AIbundle_D',
},
{
label: 'Diagram live with teammates in Mermaid Pro',
url: 'https://www.mermaidchart.com/play?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=teams_D',
},
{
label: 'Use the Visual Editor in Mermaid Pro to design and build diagrams',
url: 'https://www.mermaidchart.com/play?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=visual_editor_D',
},
{
label: 'Explore the Mermaid Whiteboard from the creators of Mermaid',
url: 'https://www.mermaidchart.com/whiteboard?utm_source=mermaid_js&utm_medium=banner_ad&utm_campaign=whiteboard_B',
},
],
},
];
};
const { design, taglines } =
Object.values(allTaglines)[Math.floor(Math.random() * Object.values(allTaglines).length)];
let index = ref(Math.floor(Math.random() * taglines.length));
onMounted(() => {
setInterval(() => {
index.value = (index.value + 1) % taglines.length;
}, 40_000);
}, 5_000);
});
</script>
<template>
<div class="mb-4 w-full top-bar bg-gradient-to-r from-[#bd34fe] to-[#ff3670] flex p-1">
<div
:class="[design === 1 ? 'bg-gradient-to-r from-[#bd34fe] to-[#ff3670] ' : 'bg-[#E0095F]']"
class="mb-4 w-full top-bar flex p-2"
>
<p class="w-full tracking-wide fade-text">
<transition name="fade" mode="out-in">
<a
@@ -44,7 +118,7 @@ onMounted(() => {
class="unstyled flex justify-center items-center gap-4 text-white tracking-wide plausible-event-name=bannerClick"
>
<span class="font-semibold">{{ taglines[index].label }}</span>
<button class="rounded bg-[#111113] p-1 px-2 text-sm font-semibold tracking-wide">
<button class="bg-[#1E1A2E] rounded-lg p-1.5 px-4 font-semibold tracking-wide">
Try now
</button>
</a>

View File

@@ -1,6 +1,6 @@
import type { MarkdownOptions } from 'vitepress';
import { defineConfig } from 'vitepress';
import { version } from '../../../package.json';
import packageJson from '../../../package.json' assert { type: 'json' };
import MermaidExample from './mermaid-markdown-all.js';
const allMarkdownTransformers: MarkdownOptions = {
@@ -58,7 +58,7 @@ export default defineConfig({
{ icon: 'github', link: 'https://github.com/mermaid-js/mermaid' },
{
icon: 'discord',
link: 'https://discord.gg/AgrbSrBer3',
link: 'https://discord.gg/sKeNQX4Wtj',
},
{
icon: {
@@ -95,7 +95,7 @@ function nav() {
activeMatch: '/announcements',
},
{
text: version,
text: packageJson.version,
items: [
{
text: 'Changelog',

View File

@@ -39,7 +39,7 @@ Where to start:
- You could work on a new feature! [These](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Area%3A+Development%22+label%3A%22Type%3A+Enhancement%22+label%3A%22Status%3A+Approved%22+) are some ideas!
- You could confirm the bugs in [these issues](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue+is%3Aopen+label%3A%22Status%3A+Triage%22++label%3A%22Type%3A+Bug+%2F+Error%22).
[You can join our Discord server if you want closer contact!](https://discord.gg/AgrbSrBer3)
[You can join our Discord server if you want closer contact!](https://discord.gg/sKeNQX4Wtj)
## A Question Or a Suggestion?
@@ -53,6 +53,6 @@ If you have faced a vulnerability [report it to us](./security.md).
Don't get daunted if it is hard in the beginning. We have a great community with only encouraging words. So, if you get stuck, ask for help and hints in the Slack forum. If you want to show off something good, show it off there.
[You can join our Discord server if you want closer contact!](https://discord.gg/AgrbSrBer3)
[You can join our Discord server if you want closer contact!](https://discord.gg/sKeNQX4Wtj)
![Image of superhero wishing you good luck](https://media.giphy.com/media/l49JHz7kJvl6MCj3G/giphy.gif)

Binary file not shown.

After

Width:  |  Height:  |  Size: 256 KiB

View File

@@ -18,7 +18,7 @@ Currently pending [IANA](https://www.iana.org/) recognition.
### Mermaid Discord workspace
We would love to see what you create with Mermaid. Please share your creations with us in our [Discord](https://discord.gg/AgrbSrBer3) server [#showcase](https://discord.com/channels/1079455296289788015/1079502635054399649) channel.
We would love to see what you create with Mermaid. Please share your creations with us in our [Discord](https://discord.gg/sKeNQX4Wtj) server [#showcase](https://discord.com/channels/1079455296289788015/1079502635054399649) channel.
### Add to Mermaid Ecosystem

View File

@@ -42,7 +42,7 @@ Try the Ultimate AI, Mermaid, and Visual Diagramming Suite by creating an accoun
## Plans
- **Free** - A free plan that includes five diagrams.
- **Free** - A free plan that includes three diagrams.
- **Pro** - A paid plan that includes unlimited diagrams, access to the collaboration feature, and more.
@@ -50,7 +50,7 @@ Try the Ultimate AI, Mermaid, and Visual Diagramming Suite by creating an accoun
To learn more, visit our [Pricing](https://mermaidchart.com/pricing) page.
Mermaid Chart is currently offering a 14-day free trial on our Pro and Enterprise tiers. Sign up for a free account at [Mermaid Chart](https://www.mermaidchart.com/app/sign-up).
Mermaid Chart is currently offering a 7-day free trial on our Pro and Enterprise tiers. Sign up for a free account at [Mermaid Chart](https://www.mermaidchart.com/app/sign-up).
## Mermaid JS contributions

View File

@@ -46,28 +46,33 @@ https://codepen.io/Ryuno-Ki/pen/LNxwgR
[K8s.dev blog: Improve your documentation with Mermaid.js diagrams](https://www.kubernetes.dev/blog/2021/12/01/improve-your-documentation-with-mermaid.js-diagrams/)
## Jupyter Integration with mermaid-js
## Jupyter / Python Integration with mermaid-js
Here's an example of Python integration with mermaid-js which uses the mermaid.ink service, that displays the graph in a Jupyter notebook.
Here's an example of Python integration with mermaid-js which uses the mermaid.ink service, that displays the graph in a Jupyter notebook and save it as _.png_ image with the stated resolution (in this example, `dpi=1200`).
```python
import base64
import io, requests
from IPython.display import Image, display
from PIL import Image as im
import matplotlib.pyplot as plt
def mm(graph):
graphbytes = graph.encode("utf8")
base64_bytes = base64.urlsafe_b64encode(graphbytes)
base64_string = base64_bytes.decode("ascii")
display(Image(url="https://mermaid.ink/img/" + base64_string))
img = im.open(io.BytesIO(requests.get('https://mermaid.ink/img/' + base64_string).content))
plt.imshow(img)
plt.axis('off') # allow to hide axis
plt.savefig('image.png', dpi=1200)
mm("""
graph LR;
A--> B & C & D;
B--> A & E;
C--> A & E;
D--> A & E;
E--> B & C & D;
A--> B & C & D
B--> A & E
C--> A & E
D--> A & E
E--> B & C & D
""")
```
@@ -75,4 +80,4 @@ graph LR;
![Example graph of the Python integration](img/python-mermaid-integration.png)
<!--- cspell:ignore Elle Jaoude Neurodiverse graphbytes --->
<!--- cspell:ignore Elle Jaoude Neurodiverse graphbytes imshow savefig --->

View File

@@ -16,7 +16,7 @@ It is a JavaScript based diagramming and charting tool that renders Markdown-ins
[![Coverage Status](https://coveralls.io/repos/github/mermaid-js/mermaid/badge.svg?branch=master)](https://coveralls.io/github/mermaid-js/mermaid?branch=master)
[![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid)
[![NPM](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid)
[![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/AgrbSrBer3)
[![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/sKeNQX4Wtj)
[![Twitter Follow](https://img.shields.io/twitter/follow/mermaidjs_?style=social)](https://twitter.com/mermaidjs_)
</div>

View File

@@ -1,17 +1,35 @@
# Blog
## [GUI for editing Mermaid Class Diagrams](https://docs.mermaidchart.com/blog/posts/gui-for-editing-mermaid-class-diagrams)
1/17/2025 • 5 mins
Discover how the latest update to the Mermaid Visual Editor transforms class diagramming. With new intuitive tools for creating and editing diagrams, dynamic relationship management, and customizable layouts, this feature-packed enhancement streamlines your diagramming experience like never before.
## [7 ER Diagram Examples For Database Modeling from Mermaid AI](https://docs.mermaidchart.com/blog/posts/7-er-diagram-examples-for-database-modeling-from-mermaid-ai)
1/16/2025 • 6 mins
Entity relationship (ER) diagrams are a cornerstone of database design, providing a blueprint for modeling your database and enabling clear communication across functions in your organization. As data volumes continue to soar and as AI models demand clean, well-organized data, ER diagrams have become more vital than ever. You can now quickly build ER diagrams with Mermaid Chart, Mermaid AI to Kickstart and fine tune your diagrams . From e-commerce payment flows to social media interactions and healthcare systems, ER diagrams are powering modern, data-driven environments.
## [Mermaid Whiteboard: Visual Collaboration Made Universal](https://docs.mermaidchart.com/blog/posts/mermaid-whiteboard-visual-collaboration-made-universal)
12/6/2024 • 2 mins
The Mermaid Whiteboard combines Mermaid syntax with a drag-and-drop interface, making it easier for teams to create, edit, and refine diagrams together. Whether you prefer working with code, visuals, Mermaid AI or all three, this tool adapts to your needs while keeping everything tied to Mermaids syntax. Key Features 1. Dual-Mode Editing Switch seamlessly between […]
## [Mermaid 11.4 is out: New Features and Kanban Diagramming](https://www.mermaidchart.com/blog/posts/mermaid-11-4-is-out-new-features-and-kanban-diagramming)
Mermaid 11.4 brings enhanced functionality with the introduction of Kanban diagrams, allowing users to create visual workflows with status columns and task details.
October 31, 2024 · 2 mins
Mermaid 11.4 brings enhanced functionality with the introduction of Kanban diagrams, allowing users to create visual workflows with status columns and task details.
## [How To Build an ER Diagram with Mermaid Chart](https://www.mermaidchart.com/blog/posts/how-to-build-an-er-diagram-with-mermaid-chart)
An entity relationship (ER) diagram acts like a blueprint for your database. This makes ER diagrams effective tools for anyone dealing with complex databases, data modeling, and AI model training.
October 24, 2024 · 4 mins
An entity relationship (ER) diagram acts like a blueprint for your database. This makes ER diagrams effective tools for anyone dealing with complex databases, data modeling, and AI model training.
## [Expanding the Horizons of Mermaid Flowcharts: Introducing 30 New Shapes!](https://www.mermaidchart.com/blog/posts/new-mermaid-flowchart-shapes/)
24 September 2024 · 5 mins

View File

@@ -16,26 +16,26 @@
"fetch-contributors": "tsx .vitepress/scripts/fetch-contributors.ts"
},
"dependencies": {
"@mdi/font": "^7.0.0",
"@vueuse/core": "^10.9.0",
"@mdi/font": "^7.4.47",
"@vueuse/core": "^12.7.0",
"font-awesome": "^4.7.0",
"jiti": "^1.21.0",
"jiti": "^2.4.2",
"mermaid": "workspace:^",
"vue": "^3.4.21"
"vue": "^3.4.38"
},
"devDependencies": {
"@iconify-json/carbon": "^1.1.31",
"@unocss/reset": "^0.59.0",
"@vite-pwa/vitepress": "^0.4.0",
"@vitejs/plugin-vue": "^5.0.0",
"fast-glob": "^3.3.2",
"@iconify-json/carbon": "^1.1.37",
"@unocss/reset": "^66.0.0",
"@vite-pwa/vitepress": "^0.5.3",
"@vitejs/plugin-vue": "^5.0.5",
"fast-glob": "^3.3.3",
"https-localhost": "^4.7.1",
"pathe": "^1.1.2",
"unocss": "^0.59.0",
"unplugin-vue-components": "^0.26.0",
"vite": "^5.0.0",
"vite-plugin-pwa": "^0.19.7",
"vitepress": "1.1.4",
"workbox-window": "^7.0.0"
"pathe": "^2.0.3",
"unocss": "^66.0.0",
"unplugin-vue-components": "^28.4.0",
"vite": "^6.1.1",
"vite-plugin-pwa": "^0.21.1",
"vitepress": "1.6.3",
"workbox-window": "^7.3.0"
}
}

View File

@@ -67,10 +67,12 @@ vi.mock('stylis', () => {
import { compile, serialize } from 'stylis';
import { Diagram } from './Diagram.js';
import { decodeEntities, encodeEntities } from './utils.js';
import { toBase64 } from './utils/base64.js';
import { ClassDB } from './diagrams/class/classDb.js';
import { FlowDB } from './diagrams/flowchart/flowDb.js';
import { SequenceDB } from './diagrams/sequence/sequenceDb.js';
import { decodeEntities, encodeEntities } from './utils.js';
import { toBase64 } from './utils/base64.js';
import { StateDB } from './diagrams/state/stateDb.js';
/**
* @see https://vitest.dev/guide/mocking.html Mock part of a module
@@ -836,6 +838,31 @@ graph TD;A--x|text including URL space|B;`)
});
it('should not modify db when rendering different diagrams', async () => {
const stateDiagram1 = await mermaidAPI.getDiagramFromText(
`stateDiagram
direction LR
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]`
);
const stateDiagram2 = await mermaidAPI.getDiagramFromText(
`stateDiagram
direction TB
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*]`
);
expect(stateDiagram1.db).not.toBe(stateDiagram2.db);
assert(stateDiagram1.db instanceof StateDB);
assert(stateDiagram2.db instanceof StateDB);
expect(stateDiagram1.db.getDirection()).not.toEqual(stateDiagram2.db.getDirection());
const flowDiagram1 = await mermaidAPI.getDiagramFromText(
`flowchart LR
A -- text --> B -- text2 --> C`
@@ -899,28 +926,18 @@ graph TD;A--x|text including URL space|B;`)
);
const sequenceDiagram2 = await mermaidAPI.getDiagramFromText(
`sequenceDiagram
actor A1
Alice->>+John: Hello John, how are you?
Alice->>+John: John, can you hear me?
John-->>-Alice: Hi Alice, I can hear you!
John-->>-Alice: I feel great!`
);
// Since sequenceDiagram will return same Db object each time, we can compare the db to be same.
expect(sequenceDiagram1.db).toBe(sequenceDiagram2.db);
// Since sequenceDiagram will return new Db object each time, we can compare the db to be different.
expect(sequenceDiagram1.db).not.toBe(sequenceDiagram2.db);
assert(sequenceDiagram1.db instanceof SequenceDB);
assert(sequenceDiagram2.db instanceof SequenceDB);
expect(sequenceDiagram1.db.getActors()).not.toEqual(sequenceDiagram2.db.getActors());
});
});
// Sequence Diagram currently uses a singleton DB, so this test will fail
it.fails('should not modify db when rendering different sequence diagrams', async () => {
const sequenceDiagram1 = await mermaidAPI.getDiagramFromText(
`sequenceDiagram
Alice->>Bob: Hello Bob, how are you?
Bob-->>John: How about you John?`
);
const sequenceDiagram2 = await mermaidAPI.getDiagramFromText(
`sequenceDiagram
Alice->>Bob: Hello Bob, how are you?
Bob-->>John: How about you John?`
);
expect(sequenceDiagram1.db).not.toBe(sequenceDiagram2.db);
});
});

View File

@@ -8,7 +8,7 @@ import { compile, serialize, stringify } from 'stylis';
// @ts-ignore: TODO Fix ts errors
import DOMPurify from 'dompurify';
import isEmpty from 'lodash-es/isEmpty.js';
import { version } from '../package.json';
import packageJson from '../package.json' assert { type: 'json' };
import { addSVGa11yTitleDescription, setA11yDiagramInfo } from './accessibility.js';
import assignWithDepth from './assignWithDepth.js';
import * as configApi from './config.js';
@@ -422,12 +422,12 @@ const render = async function (
// -------------------------------------------------------------------------------
// Draw the diagram with the renderer
try {
await diag.renderer.draw(text, id, version, diag);
await diag.renderer.draw(text, id, packageJson.version, diag);
} catch (e) {
if (config.suppressErrorRendering) {
removeTempElements();
} else {
errorRenderer.draw(text, id, version);
errorRenderer.draw(text, id, packageJson.version);
}
throw e;
}

View File

@@ -1,4 +1,5 @@
{
"$schema": "https://typedoc.org/schema.json",
"plugin": ["typedoc-plugin-markdown"],
"readme": "none",
"githubPages": false,
@@ -6,6 +7,5 @@
"gitRevision": "master",
"out": "src/docs/config/setup",
"entryPointStrategy": "expand",
"hideBreadcrumbs": true,
"hideInPageTOC": true
"hideBreadcrumbs": true
}

View File

@@ -33,7 +33,7 @@
"ast"
],
"dependencies": {
"langium": "3.0.0"
"langium": "3.3.1"
},
"devDependencies": {
"chevrotain": "^11.0.3"