Merge branch 'develop' of github.com-mermaid:mermaid-js/mermaid into saurabh/refactor-fontawesome-icon-usage

This commit is contained in:
saurabhg772244
2025-02-21 23:00:33 +05:30
37 changed files with 3210 additions and 2315 deletions

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
`mermaidAPI.getDiagramFromText()` now returns a new db instance on each call for state diagrams

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
Added versioning to StateDB and updated tests and diagrams to use it.

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: `mermaidAPI.getDiagramFromText()` now returns a new different db for each sequence diagram. Added unique IDs for messages.

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: `getDirection` and `setDirection` in `stateDb` refactored to return and set actual direction

5
.github/lychee.toml vendored
View File

@@ -47,7 +47,10 @@ exclude = [
"https://(www.)?drupal.org",
# Swimm returns 404, eventhough the link is valid
"https://docs.swimm.io"
"https://docs.swimm.io",
# Timeout
"https://huehive.co"
]
# Exclude all private IPs from checking.

View File

@@ -36,7 +36,7 @@ jobs:
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/init@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
with:
config-file: ./.github/codeql/codeql-config.yml
languages: ${{ matrix.language }}
@@ -48,7 +48,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/autobuild@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -62,4 +62,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/analyze@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13

View File

@@ -17,4 +17,4 @@ jobs:
- name: 'Checkout Repository'
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: 'Dependency Review'
uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4
uses: actions/dependency-review-action@a6993e2c61fd5dc440b409aa1d6904921c5e1894 # v4.3.5

View File

@@ -26,11 +26,11 @@ jobs:
with:
node-version-file: '.node-version'
- name: Install dependencies
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b # v6.7.8
with:
runTests: false
- name: Cypress run
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b # v6.7.8
id: cypress
with:
install: false

View File

@@ -7,9 +7,6 @@ on:
- master
- release/**
pull_request:
issue_comment:
types:
- created
merge_group:
concurrency: ${{ github.workflow }}-${{ github.ref }}
@@ -31,12 +28,10 @@ env:
) ||
github.event.before
}}
# Check if this is a new comment with '/visual-test'
RUN_VISUAL_TEST: >-
${{ github.event_name == 'issue_comment' && github.event.action == 'created' && contains(github.event.comment.body, '/visual-test') && github.event.issue.pull_request != null }}
${{ github.repository == 'mermaid-js/mermaid' && (github.event_name != 'pull_request' || !startsWith(github.head_ref, 'renovate/')) }}
jobs:
cache:
if: ${{ github.event_name != 'issue_comment' || contains(github.event.comment.body, '/visual-test') }}
runs-on: ubuntu-latest
container:
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1
@@ -50,9 +45,8 @@ jobs:
node-version-file: '.node-version'
- name: Cache snapshots
id: cache-snapshot
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
with:
save-always: true
path: ./cypress/snapshots
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
@@ -65,7 +59,7 @@ jobs:
- name: Install dependencies
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b # v6.7.8
with:
# just perform install
runTests: false
@@ -101,13 +95,13 @@ jobs:
# These cached snapshots are downloaded, providing the reference snapshots.
- name: Cache snapshots
id: cache-snapshot
uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache/restore@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
with:
path: ./cypress/snapshots
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
- name: Install dependencies
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b # v6.7.8
with:
runTests: false
@@ -123,7 +117,7 @@ jobs:
# Install NPM dependencies, cache them correctly
# and run all Cypress tests
- name: Cypress run
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
uses: cypress-io/github-action@57b70560982e6a11d23d4b8bec7f8a487cdbb71b # v6.7.8
id: cypress
with:
install: false
@@ -134,8 +128,6 @@ jobs:
# e.g. if this action was run from a fork
record: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.CYPRESS_RECORD_KEY != '' }}
env:
# Only set Argos environment variables if the visual test comment trigger is present
ARGOS_TOKEN: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.ARGOS_TOKEN || '' }}
ARGOS_PARALLEL: ${{ env.RUN_VISUAL_TEST == 'true' }}
ARGOS_PARALLEL_TOTAL: ${{ env.RUN_VISUAL_TEST == 'true' && strategy.job-total || 1 }}
ARGOS_PARALLEL_INDEX: ${{ env.RUN_VISUAL_TEST == 'true' && matrix.containers || 1 }}

View File

@@ -32,7 +32,7 @@ jobs:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- name: Restore lychee cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
with:
path: .lycheecache
key: cache-lychee-${{ github.sha }}

View File

@@ -36,7 +36,7 @@ jobs:
- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@3de3850952bec538fde60aac71731376e57b9b57 # v1.4.8
uses: changesets/action@c8bada60c408975afd1a20b3db81d6eee6789308 # v1.4.9
with:
version: pnpm changeset:version
publish: pnpm changeset:publish

View File

@@ -32,6 +32,6 @@ jobs:
path: results.sarif
retention-days: 5
- name: Upload to code-scanning
uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/upload-sarif@f779452ac5af1c261dce0346a8f964149f49322b # v3.26.13
with:
sarif_file: results.sarif

View File

@@ -23,12 +23,10 @@ export default eyesPlugin(
});
// copy any needed variables from process.env to config.env
config.env.useAppli = process.env.USE_APPLI ? true : false;
config.env.useArgos = !!process.env.CI && !!process.env.ARGOS_TOKEN;
config.env.useArgos = process.env.RUN_VISUAL_TEST === 'true';
if (config.env.useArgos) {
registerArgosTask(on, config, {
token: 'fc3a35cf5200db928d65b2047861582d9444032b',
});
registerArgosTask(on, config);
} else {
addMatchImageSnapshotPlugin(on, config);
}

View File

@@ -11,7 +11,7 @@
rel="stylesheet"
/>
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/all.min.css"
rel="stylesheet"
/>
<link

View File

@@ -137,7 +137,6 @@ export default tseslint.config(
'unicorn/no-instanceof-array': 'error',
'unicorn/no-typeof-undefined': 'error',
'unicorn/no-unnecessary-await': 'error',
'unicorn/no-unsafe-regex': 'warn',
'unicorn/no-useless-promise-resolve-reject': 'error',
'unicorn/prefer-array-find': 'error',
'unicorn/prefer-array-flat-map': 'error',

View File

@@ -92,10 +92,10 @@
"cypress": "^13.14.1",
"cypress-image-snapshot": "^4.0.1",
"cypress-split": "^1.24.0",
"esbuild": "^0.21.5",
"esbuild": "^0.25.0",
"eslint": "^9.4.0",
"eslint-config-prettier": "^9.1.0",
"eslint-plugin-cypress": "^3.3.0",
"eslint-config-prettier": "^10.0.0",
"eslint-plugin-cypress": "^4.0.0",
"eslint-plugin-html": "^8.1.1",
"eslint-plugin-jest": "^28.6.0",
"eslint-plugin-jsdoc": "^50.0.0",
@@ -103,8 +103,8 @@
"eslint-plugin-lodash": "^8.0.0",
"eslint-plugin-markdown": "^5.0.0",
"eslint-plugin-no-only-tests": "^3.1.0",
"eslint-plugin-tsdoc": "^0.3.0",
"eslint-plugin-unicorn": "^56.0.0",
"eslint-plugin-tsdoc": "^0.4.0",
"eslint-plugin-unicorn": "^57.0.0",
"express": "^4.19.1",
"globals": "^15.4.0",
"globby": "^14.0.1",
@@ -123,6 +123,7 @@
"rimraf": "^5.0.5",
"rollup-plugin-visualizer": "^5.12.0",
"start-server-and-test": "^2.0.3",
"tslib": "^2.8.1",
"tsx": "^4.7.1",
"typescript": "~5.4.5",
"typescript-eslint": "^8.0.0-alpha.34",

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.

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

@@ -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);
});
});

2433
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff