mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-09 15:24:13 +01:00
Merge branch 'develop' into timeline
* develop: (45 commits) Showcase section to the docs - keepings docs up to date (#4055) bugfix: add missing d3 curves to flowchart and docs fix(deps): update dependency dagre-d3-es to v7.0.8 build(pre-commit): cache eslint in pre-commit build(lint): cache eslint with strategy content Update cypress/integration/rendering/sequencediagram.spec.js feat(er): allow leading underscore for attributes name ci(lint): show nice error on lint failure chore: add moment to dependencies Update docs Update mindmap.md chore: remove moment-mini docs(readme-ch): fix twitter link build(lint): cache prettier on `pnpm run lint` fix: moment-mini default exporter docs(readme): update broken twitter badge test(er): improve tests on multiple key constraints Fixes Typo, remove console.log doc(er): add documentation on multiple key constraints feat(er): allow multiple constraints on attributes ...
This commit is contained in:
@@ -4,3 +4,4 @@ docs/Setup.md
|
|||||||
cypress.config.js
|
cypress.config.js
|
||||||
cypress/plugins/index.js
|
cypress/plugins/index.js
|
||||||
coverage
|
coverage
|
||||||
|
*.json
|
||||||
150
.eslintrc.cjs
Normal file
150
.eslintrc.cjs
Normal file
@@ -0,0 +1,150 @@
|
|||||||
|
module.exports = {
|
||||||
|
env: {
|
||||||
|
browser: true,
|
||||||
|
es6: true,
|
||||||
|
'jest/globals': true,
|
||||||
|
node: true,
|
||||||
|
},
|
||||||
|
root: true,
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
parserOptions: {
|
||||||
|
ecmaFeatures: {
|
||||||
|
experimentalObjectRestSpread: true,
|
||||||
|
jsx: true,
|
||||||
|
},
|
||||||
|
tsconfigRootDir: __dirname,
|
||||||
|
sourceType: 'module',
|
||||||
|
ecmaVersion: 2020,
|
||||||
|
allowAutomaticSingleRunInference: true,
|
||||||
|
project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'],
|
||||||
|
parser: '@typescript-eslint/parser',
|
||||||
|
},
|
||||||
|
extends: [
|
||||||
|
'eslint:recommended',
|
||||||
|
'plugin:@typescript-eslint/recommended',
|
||||||
|
'plugin:json/recommended',
|
||||||
|
'plugin:markdown/recommended',
|
||||||
|
'plugin:@cspell/recommended',
|
||||||
|
'prettier',
|
||||||
|
],
|
||||||
|
plugins: [
|
||||||
|
'@typescript-eslint',
|
||||||
|
'no-only-tests',
|
||||||
|
'html',
|
||||||
|
'jest',
|
||||||
|
'jsdoc',
|
||||||
|
'json',
|
||||||
|
'@cspell',
|
||||||
|
'lodash',
|
||||||
|
'unicorn',
|
||||||
|
],
|
||||||
|
rules: {
|
||||||
|
curly: 'error',
|
||||||
|
'no-console': 'error',
|
||||||
|
'no-prototype-builtins': 'off',
|
||||||
|
'no-unused-vars': 'off',
|
||||||
|
'cypress/no-async-tests': 'off',
|
||||||
|
'@typescript-eslint/no-floating-promises': 'error',
|
||||||
|
'@typescript-eslint/no-misused-promises': 'error',
|
||||||
|
'@typescript-eslint/ban-ts-comment': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
'ts-expect-error': 'allow-with-description',
|
||||||
|
'ts-ignore': 'allow-with-description',
|
||||||
|
'ts-nocheck': 'allow-with-description',
|
||||||
|
'ts-check': 'allow-with-description',
|
||||||
|
minimumDescriptionLength: 10,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'json/*': ['error', 'allowComments'],
|
||||||
|
'@cspell/spellchecker': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
checkIdentifiers: false,
|
||||||
|
checkStrings: false,
|
||||||
|
checkStringTemplates: false,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'no-empty': [
|
||||||
|
'error',
|
||||||
|
{
|
||||||
|
allowEmptyCatch: true,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
'no-only-tests/no-only-tests': 'error',
|
||||||
|
'lodash/import-scope': ['error', 'method'],
|
||||||
|
'unicorn/better-regex': 'error',
|
||||||
|
'unicorn/no-abusive-eslint-disable': 'error',
|
||||||
|
'unicorn/no-array-push-push': 'error',
|
||||||
|
'unicorn/no-for-loop': 'error',
|
||||||
|
'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',
|
||||||
|
'unicorn/prefer-array-index-of': 'error',
|
||||||
|
'unicorn/prefer-array-some': 'error',
|
||||||
|
'unicorn/prefer-default-parameters': 'error',
|
||||||
|
'unicorn/prefer-includes': 'error',
|
||||||
|
'unicorn/prefer-negative-index': 'error',
|
||||||
|
'unicorn/prefer-object-from-entries': 'error',
|
||||||
|
'unicorn/prefer-string-starts-ends-with': 'error',
|
||||||
|
'unicorn/prefer-string-trim-start-end': 'error',
|
||||||
|
'unicorn/string-content': 'error',
|
||||||
|
'unicorn/prefer-spread': 'error',
|
||||||
|
'unicorn/no-lonely-if': 'error',
|
||||||
|
},
|
||||||
|
overrides: [
|
||||||
|
{
|
||||||
|
files: ['cypress/**', 'demos/**'],
|
||||||
|
rules: {
|
||||||
|
'no-console': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['*.{js,jsx,mjs,cjs}'],
|
||||||
|
extends: ['plugin:jsdoc/recommended'],
|
||||||
|
rules: {
|
||||||
|
'jsdoc/check-indentation': 'off',
|
||||||
|
'jsdoc/check-alignment': 'off',
|
||||||
|
'jsdoc/check-line-alignment': 'off',
|
||||||
|
'jsdoc/multiline-blocks': 'off',
|
||||||
|
'jsdoc/newline-after-description': 'off',
|
||||||
|
'jsdoc/tag-lines': 'off',
|
||||||
|
'jsdoc/require-param-description': 'off',
|
||||||
|
'jsdoc/require-param-type': 'off',
|
||||||
|
'jsdoc/require-returns': 'off',
|
||||||
|
'jsdoc/require-returns-description': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['*.{ts,tsx}'],
|
||||||
|
plugins: ['tsdoc'],
|
||||||
|
rules: {
|
||||||
|
'tsdoc/syntax': 'error',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['*.spec.{ts,js}', 'cypress/**', 'demos/**', '**/docs/**'],
|
||||||
|
rules: {
|
||||||
|
'jsdoc/require-jsdoc': 'off',
|
||||||
|
'@typescript-eslint/no-unused-vars': 'off',
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
files: ['*.html', '*.md', '**/*.md/*'],
|
||||||
|
rules: {
|
||||||
|
'no-var': 'error',
|
||||||
|
'no-undef': 'off',
|
||||||
|
'@typescript-eslint/no-unused-vars': 'off',
|
||||||
|
'@typescript-eslint/no-floating-promises': 'off',
|
||||||
|
'@typescript-eslint/no-misused-promises': 'off',
|
||||||
|
},
|
||||||
|
parserOptions: {
|
||||||
|
project: null,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
],
|
||||||
|
};
|
||||||
137
.eslintrc.json
137
.eslintrc.json
@@ -1,137 +0,0 @@
|
|||||||
{
|
|
||||||
"env": {
|
|
||||||
"browser": true,
|
|
||||||
"es6": true,
|
|
||||||
"jest/globals": true,
|
|
||||||
"node": true
|
|
||||||
},
|
|
||||||
"parser": "@typescript-eslint/parser",
|
|
||||||
"parserOptions": {
|
|
||||||
"ecmaFeatures": {
|
|
||||||
"experimentalObjectRestSpread": true,
|
|
||||||
"jsx": true
|
|
||||||
},
|
|
||||||
"sourceType": "module"
|
|
||||||
},
|
|
||||||
"extends": [
|
|
||||||
"eslint:recommended",
|
|
||||||
"plugin:@typescript-eslint/recommended",
|
|
||||||
"plugin:json/recommended",
|
|
||||||
"plugin:markdown/recommended",
|
|
||||||
"plugin:@cspell/recommended",
|
|
||||||
"prettier"
|
|
||||||
],
|
|
||||||
"plugins": [
|
|
||||||
"@typescript-eslint",
|
|
||||||
"no-only-tests",
|
|
||||||
"html",
|
|
||||||
"jest",
|
|
||||||
"jsdoc",
|
|
||||||
"json",
|
|
||||||
"@cspell",
|
|
||||||
"lodash",
|
|
||||||
"unicorn"
|
|
||||||
],
|
|
||||||
"rules": {
|
|
||||||
"curly": "error",
|
|
||||||
"no-console": "error",
|
|
||||||
"no-prototype-builtins": "off",
|
|
||||||
"no-unused-vars": "off",
|
|
||||||
"cypress/no-async-tests": "off",
|
|
||||||
"@typescript-eslint/ban-ts-comment": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"ts-expect-error": "allow-with-description",
|
|
||||||
"ts-ignore": "allow-with-description",
|
|
||||||
"ts-nocheck": "allow-with-description",
|
|
||||||
"ts-check": "allow-with-description",
|
|
||||||
"minimumDescriptionLength": 10
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"json/*": ["error", "allowComments"],
|
|
||||||
"@cspell/spellchecker": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"checkIdentifiers": false,
|
|
||||||
"checkStrings": false,
|
|
||||||
"checkStringTemplates": false
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"no-empty": [
|
|
||||||
"error",
|
|
||||||
{
|
|
||||||
"allowEmptyCatch": true
|
|
||||||
}
|
|
||||||
],
|
|
||||||
"no-only-tests/no-only-tests": "error",
|
|
||||||
"lodash/import-scope": ["error", "method"],
|
|
||||||
"unicorn/better-regex": "error",
|
|
||||||
"unicorn/no-abusive-eslint-disable": "error",
|
|
||||||
"unicorn/no-array-push-push": "error",
|
|
||||||
"unicorn/no-for-loop": "error",
|
|
||||||
"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",
|
|
||||||
"unicorn/prefer-array-index-of": "error",
|
|
||||||
"unicorn/prefer-array-some": "error",
|
|
||||||
"unicorn/prefer-default-parameters": "error",
|
|
||||||
"unicorn/prefer-includes": "error",
|
|
||||||
"unicorn/prefer-negative-index": "error",
|
|
||||||
"unicorn/prefer-object-from-entries": "error",
|
|
||||||
"unicorn/prefer-string-starts-ends-with": "error",
|
|
||||||
"unicorn/prefer-string-trim-start-end": "error",
|
|
||||||
"unicorn/string-content": "error",
|
|
||||||
"unicorn/prefer-spread": "error",
|
|
||||||
"unicorn/no-lonely-if": "error"
|
|
||||||
},
|
|
||||||
"overrides": [
|
|
||||||
{
|
|
||||||
"files": ["cypress/**", "demos/**"],
|
|
||||||
"rules": {
|
|
||||||
"no-console": "off"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"files": ["*.{js,jsx,mjs,cjs}"],
|
|
||||||
"extends": ["plugin:jsdoc/recommended"],
|
|
||||||
"rules": {
|
|
||||||
"jsdoc/check-indentation": "off",
|
|
||||||
"jsdoc/check-alignment": "off",
|
|
||||||
"jsdoc/check-line-alignment": "off",
|
|
||||||
"jsdoc/multiline-blocks": "off",
|
|
||||||
"jsdoc/newline-after-description": "off",
|
|
||||||
"jsdoc/tag-lines": "off",
|
|
||||||
"jsdoc/require-param-description": "off",
|
|
||||||
"jsdoc/require-param-type": "off",
|
|
||||||
"jsdoc/require-returns": "off",
|
|
||||||
"jsdoc/require-returns-description": "off"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"files": ["*.{ts,tsx}"],
|
|
||||||
"plugins": ["tsdoc"],
|
|
||||||
"rules": {
|
|
||||||
"tsdoc/syntax": "error"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"files": ["*.spec.{ts,js}", "cypress/**", "demos/**", "**/docs/**"],
|
|
||||||
"rules": {
|
|
||||||
"jsdoc/require-jsdoc": "off",
|
|
||||||
"@typescript-eslint/no-unused-vars": "off"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
{
|
|
||||||
"files": ["*.html", "*.md", "**/*.md/*"],
|
|
||||||
"rules": {
|
|
||||||
"no-var": "error",
|
|
||||||
"no-undef": "off",
|
|
||||||
"@typescript-eslint/no-unused-vars": "off"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
]
|
|
||||||
}
|
|
||||||
15
.github/workflows/lint.yml
vendored
15
.github/workflows/lint.yml
vendored
@@ -37,7 +37,20 @@ jobs:
|
|||||||
CYPRESS_CACHE_FOLDER: .cache/Cypress
|
CYPRESS_CACHE_FOLDER: .cache/Cypress
|
||||||
|
|
||||||
- name: Run Linting
|
- name: Run Linting
|
||||||
run: pnpm run lint
|
shell: bash
|
||||||
|
run: |
|
||||||
|
if ! pnpm run lint; then
|
||||||
|
# print a nice error message on lint failure
|
||||||
|
ERROR_MESSAGE='Running `pnpm run lint` failed.'
|
||||||
|
ERROR_MESSAGE+=' Running `pnpm run lint:fix` may fix this issue. '
|
||||||
|
ERROR_MESSAGE+=" If this error doesn't occur on your local machine,"
|
||||||
|
ERROR_MESSAGE+=' make sure your packages are up-to-date by running `pnpm install`.'
|
||||||
|
ERROR_MESSAGE+=' You may also need to delete your prettier cache by running'
|
||||||
|
ERROR_MESSAGE+=' `rm ./node_modules/.cache/prettier/.prettier-cache`.'
|
||||||
|
echo "::error title=Lint failure::${ERROR_MESSAGE}"
|
||||||
|
# make sure to return an error exitcode so that GitHub actions shows a red-cross
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
|
||||||
- name: Verify Docs
|
- name: Verify Docs
|
||||||
id: verifyDocs
|
id: verifyDocs
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
export default {
|
export default {
|
||||||
'!(docs/**/*)*.{ts,js,json,html,md,mts}': ['eslint --fix', 'prettier --write'],
|
'!(docs/**/*)*.{ts,js,json,html,md,mts}': [
|
||||||
|
'eslint --cache --cache-strategy content --fix',
|
||||||
|
// don't cache prettier yet, since we use `prettier-plugin-jsdoc`,
|
||||||
|
// and prettier doesn't invalidate cache on plugin updates"
|
||||||
|
// https://prettier.io/docs/en/cli.html#--cache
|
||||||
|
'prettier --write',
|
||||||
|
],
|
||||||
'cSpell.json': ['ts-node-esm scripts/fixCSpell.ts'],
|
'cSpell.json': ['ts-node-esm scripts/fixCSpell.ts'],
|
||||||
'**/*.jison': ['pnpm -w run lint:jison'],
|
'**/*.jison': ['pnpm -w run lint:jison'],
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# mermaid
|
# mermaid
|
||||||
|
|
||||||
[](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml) [](https://www.npmjs.com/package/mermaid) [](https://bundlephobia.com/package/mermaid) [](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [](https://www.jsdelivr.com/package/npm/mermaid) [](https://www.npmjs.com/package/mermaid) [](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [](https://twitter.com/mermaidjs_)
|
[](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml) [](https://www.npmjs.com/package/mermaid) [](https://bundlephobia.com/package/mermaid) [](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [](https://www.jsdelivr.com/package/npm/mermaid) [](https://www.npmjs.com/package/mermaid) [](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [](https://twitter.com/mermaidjs_)
|
||||||
|
|
||||||
English | [简体中文](./README.zh-CN.md)
|
English | [简体中文](./README.zh-CN.md)
|
||||||
|
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# mermaid
|
# mermaid
|
||||||
|
|
||||||
[](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml) [](https://www.npmjs.com/package/mermaid) [](https://bundlephobia.com/package/mermaid) [](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [](https://www.jsdelivr.com/package/npm/mermaid) [](https://www.npmjs.com/package/mermaid) [](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [](https://twitter.com/mermaidjs_)
|
[](https://github.com/mermaid-js/mermaid/actions/workflows/build.yml) [](https://www.npmjs.com/package/mermaid) [](https://bundlephobia.com/package/mermaid) [](https://coveralls.io/github/mermaid-js/mermaid?branch=master) [](https://www.jsdelivr.com/package/npm/mermaid) [](https://www.npmjs.com/package/mermaid) [](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE) [](https://twitter.com/mermaidjs_)
|
||||||
|
|
||||||
[English](./README.md) | 简体中文
|
[English](./README.md) | 简体中文
|
||||||
|
|
||||||
|
|||||||
@@ -3,6 +3,42 @@
|
|||||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
|
import { imgSnapshotTest, renderGraph } from '../../helpers/util';
|
||||||
|
|
||||||
context('Sequence diagram', () => {
|
context('Sequence diagram', () => {
|
||||||
|
it('should render a sequence diagram with boxes', () => {
|
||||||
|
renderGraph(
|
||||||
|
`
|
||||||
|
sequenceDiagram
|
||||||
|
box LightGrey Alice and Bob
|
||||||
|
participant Alice
|
||||||
|
participant Bob
|
||||||
|
end
|
||||||
|
participant John as John<br/>Second Line
|
||||||
|
Alice ->> Bob: Hello Bob, how are you?
|
||||||
|
Bob-->>John: How about you John?
|
||||||
|
Bob--x Alice: I am good thanks!
|
||||||
|
Bob-x John: I am good thanks!
|
||||||
|
Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row.
|
||||||
|
Bob-->Alice: Checking with John...
|
||||||
|
alt either this
|
||||||
|
Alice->>John: Yes
|
||||||
|
else or this
|
||||||
|
Alice->>John: No
|
||||||
|
else or this will happen
|
||||||
|
Alice->John: Maybe
|
||||||
|
end
|
||||||
|
par this happens in parallel
|
||||||
|
Alice -->> Bob: Parallel message 1
|
||||||
|
and
|
||||||
|
Alice -->> John: Parallel message 2
|
||||||
|
end
|
||||||
|
`,
|
||||||
|
{ sequence: { useMaxWidth: false } }
|
||||||
|
);
|
||||||
|
cy.get('svg').should((svg) => {
|
||||||
|
const width = parseFloat(svg.attr('width'));
|
||||||
|
expect(width).to.be.within(830 * 0.95, 830 * 1.05);
|
||||||
|
expect(svg).to.not.have.attr('style');
|
||||||
|
});
|
||||||
|
});
|
||||||
it('should render a simple sequence diagram', () => {
|
it('should render a simple sequence diagram', () => {
|
||||||
imgSnapshotTest(
|
imgSnapshotTest(
|
||||||
`
|
`
|
||||||
|
|||||||
@@ -151,7 +151,7 @@ if (typeof document !== 'undefined') {
|
|||||||
contentLoadedApi();
|
contentLoadedApi();
|
||||||
} else {
|
} else {
|
||||||
this.console.log('Not using api');
|
this.console.log('Not using api');
|
||||||
contentLoaded();
|
void contentLoaded();
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
false
|
false
|
||||||
|
|||||||
@@ -71,6 +71,44 @@
|
|||||||
</pre>
|
</pre>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
<pre class="mermaid">
|
||||||
|
erDiagram
|
||||||
|
"HOSPITAL" {
|
||||||
|
int id PK
|
||||||
|
int doctor_id PK, FK
|
||||||
|
string address UK
|
||||||
|
string name
|
||||||
|
string phone_number
|
||||||
|
string fax_number
|
||||||
|
}
|
||||||
|
</pre
|
||||||
|
>
|
||||||
|
<hr />
|
||||||
|
|
||||||
|
<pre class="mermaid">
|
||||||
|
erDiagram
|
||||||
|
CAR ||--o{ NAMED-DRIVER : allows
|
||||||
|
CAR {
|
||||||
|
string registrationNumber PK
|
||||||
|
string make
|
||||||
|
string model
|
||||||
|
string[] parts
|
||||||
|
}
|
||||||
|
PERSON ||--o{ NAMED-DRIVER : is
|
||||||
|
PERSON {
|
||||||
|
string driversLicense PK "The license #"
|
||||||
|
string(99) firstName "Only 99 characters are allowed"
|
||||||
|
string lastName
|
||||||
|
string phone UK
|
||||||
|
int age
|
||||||
|
}
|
||||||
|
NAMED-DRIVER {
|
||||||
|
string carRegistrationNumber PK, FK
|
||||||
|
string driverLicence PK,FK
|
||||||
|
}
|
||||||
|
MANUFACTURER only one to zero or more CAR : makes
|
||||||
|
</pre>
|
||||||
|
|
||||||
<script src="./mermaid.js"></script>
|
<script src="./mermaid.js"></script>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
mermaid.initialize({
|
mermaid.initialize({
|
||||||
|
|||||||
@@ -128,6 +128,22 @@
|
|||||||
</pre>
|
</pre>
|
||||||
<hr />
|
<hr />
|
||||||
|
|
||||||
|
<pre class="mermaid">
|
||||||
|
sequenceDiagram
|
||||||
|
box lightgreen Alice & John
|
||||||
|
participant A
|
||||||
|
participant J
|
||||||
|
end
|
||||||
|
box Another Group very very long description not wrapped
|
||||||
|
participant B
|
||||||
|
end
|
||||||
|
A->>J: Hello John, how are you?
|
||||||
|
J->>A: Great!
|
||||||
|
A->>B: Hello Bob, how are you ?
|
||||||
|
</pre
|
||||||
|
>
|
||||||
|
<hr />
|
||||||
|
|
||||||
<script src="./mermaid.js"></script>
|
<script src="./mermaid.js"></script>
|
||||||
<script>
|
<script>
|
||||||
mermaid.initialize({
|
mermaid.initialize({
|
||||||
|
|||||||
@@ -161,12 +161,19 @@
|
|||||||
First --> Second
|
First --> Second
|
||||||
First --> Third
|
First --> Third
|
||||||
|
|
||||||
state First {
|
state "the first composite" as First {
|
||||||
[*] --> 1st
|
[*] --> 1st
|
||||||
1st --> [*]
|
state innerFirst {
|
||||||
|
state "1 in innerFirst" as 1st1st
|
||||||
|
1st2nd: 2 in innerFirst
|
||||||
|
[*] --> 1st1st
|
||||||
|
1st1st --> 1st2nd
|
||||||
|
%% 1st2nd --> 1st
|
||||||
|
}
|
||||||
|
1st --> innerFirst
|
||||||
|
innerFirst --> 2nd
|
||||||
}
|
}
|
||||||
state Second {
|
state Second {
|
||||||
[*] --> 2nd
|
|
||||||
2nd --> [*]
|
2nd --> [*]
|
||||||
}
|
}
|
||||||
state Third {
|
state Third {
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
>
|
>
|
||||||
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
|
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
|
||||||
>
|
>
|
||||||
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/misc/faq.md](../../packages/mermaid/src/docs/misc/faq.md).
|
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/faq.md](../../packages/mermaid/src/docs/config/faq.md).
|
||||||
|
|
||||||
# Frequently Asked Questions
|
# Frequently Asked Questions
|
||||||
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
>
|
>
|
||||||
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
|
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
|
||||||
>
|
>
|
||||||
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/misc/integrations.md](../../packages/mermaid/src/docs/misc/integrations.md).
|
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/ecosystem/integrations.md](../../packages/mermaid/src/docs/ecosystem/integrations.md).
|
||||||
|
|
||||||
# Integrations
|
# Integrations
|
||||||
|
|
||||||
@@ -95,9 +95,10 @@ They also serve as proof of concept, for the variety of things that can be built
|
|||||||
|
|
||||||
## Editor Plugins
|
## Editor Plugins
|
||||||
|
|
||||||
- [Vs Code](https://code.visualstudio.com/)
|
- [VS Code](https://code.visualstudio.com/)
|
||||||
- [Markdown Preview Mermaid Support](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid)
|
- [Markdown Preview Mermaid Support](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid)
|
||||||
- [Mermaid Preview](https://marketplace.visualstudio.com/items?itemName=vstirbu.vscode-mermaid-preview)
|
- [Mermaid Preview](https://marketplace.visualstudio.com/items?itemName=vstirbu.vscode-mermaid-preview)
|
||||||
|
- [Markdown Preview Enhanced](https://marketplace.visualstudio.com/items?itemName=shd101wyy.markdown-preview-enhanced)
|
||||||
- [Mermaid Markdown Syntax Highlighting](https://marketplace.visualstudio.com/items?itemName=bpruitt-goddard.mermaid-markdown-syntax-highlighting)
|
- [Mermaid Markdown Syntax Highlighting](https://marketplace.visualstudio.com/items?itemName=bpruitt-goddard.mermaid-markdown-syntax-highlighting)
|
||||||
- [Mermaid Editor](https://marketplace.visualstudio.com/items?itemName=tomoyukim.vscode-mermaid-editor)
|
- [Mermaid Editor](https://marketplace.visualstudio.com/items?itemName=tomoyukim.vscode-mermaid-editor)
|
||||||
- [Mermaid Export](https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.mermaid-export)
|
- [Mermaid Export](https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.mermaid-export)
|
||||||
9
docs/ecosystem/showcases.md
Normal file
9
docs/ecosystem/showcases.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
> **Warning**
|
||||||
|
>
|
||||||
|
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
|
||||||
|
>
|
||||||
|
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/ecosystem/showcases.md](../../packages/mermaid/src/docs/ecosystem/showcases.md).
|
||||||
|
|
||||||
|
# Showcases
|
||||||
|
|
||||||
|
- [Swimm - Up-to-date diagrams with Swimm, the knowledge management tool for code](https://docs.swimm.io/Features/diagrams-and-charts).
|
||||||
@@ -200,14 +200,13 @@ The `type` and `name` values must begin with an alphabetic character and may con
|
|||||||
|
|
||||||
#### Attribute Keys and Comments
|
#### Attribute Keys and Comments
|
||||||
|
|
||||||
Attributes may also have a `key` or comment defined. Keys can be "PK", "FK" or "UK", for Primary Key, Foreign Key or Unique Key. And a `comment` is defined by double quotes at the end of an attribute. Comments themselves cannot have double-quote characters in them.
|
Attributes may also have a `key` or comment defined. Keys can be `PK`, `FK` or `UK`, for Primary Key, Foreign Key or Unique Key. To specify multiple key constraints on a single attribute, separate them with a comma (e.g., `PK, FK`).. A `comment` is defined by double quotes at the end of an attribute. Comments themselves cannot have double-quote characters in them.
|
||||||
|
|
||||||
```mermaid-example
|
```mermaid-example
|
||||||
erDiagram
|
erDiagram
|
||||||
CAR ||--o{ NAMED-DRIVER : allows
|
CAR ||--o{ NAMED-DRIVER : allows
|
||||||
CAR {
|
CAR {
|
||||||
string allowedDriver FK "The license of the allowed driver"
|
string registrationNumber PK
|
||||||
string registrationNumber UK
|
|
||||||
string make
|
string make
|
||||||
string model
|
string model
|
||||||
string[] parts
|
string[] parts
|
||||||
@@ -217,17 +216,21 @@ erDiagram
|
|||||||
string driversLicense PK "The license #"
|
string driversLicense PK "The license #"
|
||||||
string(99) firstName "Only 99 characters are allowed"
|
string(99) firstName "Only 99 characters are allowed"
|
||||||
string lastName
|
string lastName
|
||||||
|
string phone UK
|
||||||
int age
|
int age
|
||||||
}
|
}
|
||||||
MANUFACTURER only one to zero or more CAR
|
NAMED-DRIVER {
|
||||||
|
string carRegistrationNumber PK, FK
|
||||||
|
string driverLicence PK, FK
|
||||||
|
}
|
||||||
|
MANUFACTURER only one to zero or more CAR : makes
|
||||||
```
|
```
|
||||||
|
|
||||||
```mermaid
|
```mermaid
|
||||||
erDiagram
|
erDiagram
|
||||||
CAR ||--o{ NAMED-DRIVER : allows
|
CAR ||--o{ NAMED-DRIVER : allows
|
||||||
CAR {
|
CAR {
|
||||||
string allowedDriver FK "The license of the allowed driver"
|
string registrationNumber PK
|
||||||
string registrationNumber UK
|
|
||||||
string make
|
string make
|
||||||
string model
|
string model
|
||||||
string[] parts
|
string[] parts
|
||||||
@@ -237,9 +240,14 @@ erDiagram
|
|||||||
string driversLicense PK "The license #"
|
string driversLicense PK "The license #"
|
||||||
string(99) firstName "Only 99 characters are allowed"
|
string(99) firstName "Only 99 characters are allowed"
|
||||||
string lastName
|
string lastName
|
||||||
|
string phone UK
|
||||||
int age
|
int age
|
||||||
}
|
}
|
||||||
MANUFACTURER only one to zero or more CAR
|
NAMED-DRIVER {
|
||||||
|
string carRegistrationNumber PK, FK
|
||||||
|
string driverLicence PK, FK
|
||||||
|
}
|
||||||
|
MANUFACTURER only one to zero or more CAR : makes
|
||||||
```
|
```
|
||||||
|
|
||||||
### Other Things
|
### Other Things
|
||||||
|
|||||||
@@ -842,8 +842,8 @@ In the example below the style defined in the linkStyle statement will belong to
|
|||||||
### Styling line curves
|
### Styling line curves
|
||||||
|
|
||||||
It is possible to style the type of curve used for lines between items, if the default method does not meet your needs.
|
It is possible to style the type of curve used for lines between items, if the default method does not meet your needs.
|
||||||
Available curve styles include `basis`, `bump`, `linear`, `monotoneX`, `monotoneY`, `natural`, `step`, `stepAfter`,
|
Available curve styles include `basis`, `bumpX`, `bumpY`, `cardinal`, `catmullRom`, `linear`, `monotoneX`, `monotoneY`,
|
||||||
and `stepBefore`.
|
`natural`, `step`, `stepAfter`, and `stepBefore`.
|
||||||
|
|
||||||
In this example, a left-to-right graph uses the `stepBefore` curve style:
|
In this example, a left-to-right graph uses the `stepBefore` curve style:
|
||||||
|
|
||||||
|
|||||||
@@ -88,7 +88,7 @@ In this way we can use a text outline to generate a hierarchical mindmap.
|
|||||||
|
|
||||||
## Different shapes
|
## Different shapes
|
||||||
|
|
||||||
Mermaids mindmaps can show node using different shapes. When specifying a shape for a node the syntax for the is similar to flowchart nodes, with an id followed by the shape definition and with the text within the shape delimiters. Where possible we try/will try to keep the same shapes as for flowcharts even though they are not all supported from the start.
|
Mermaid mindmaps can show nodes using different shapes. When specifying a shape for a node the syntax is similar to flowchart nodes, with an id followed by the shape definition and with the text within the shape delimiters. Where possible we try/will try to keep the same shapes as for flowcharts, even though they are not all supported from the start.
|
||||||
|
|
||||||
Mindmap can show the following shapes:
|
Mindmap can show the following shapes:
|
||||||
|
|
||||||
|
|||||||
@@ -94,6 +94,59 @@ sequenceDiagram
|
|||||||
J->>A: Great!
|
J->>A: Great!
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Grouping / Box
|
||||||
|
|
||||||
|
The actor(s) can be grouped in vertical boxes. You can define a color (if not, it will be transparent) and/or a descriptive label using the following notation:
|
||||||
|
|
||||||
|
box Aqua Group Description
|
||||||
|
... actors ...
|
||||||
|
end
|
||||||
|
box Group without description
|
||||||
|
... actors ...
|
||||||
|
end
|
||||||
|
box rgb(33,66,99)
|
||||||
|
... actors ...
|
||||||
|
end
|
||||||
|
|
||||||
|
> **Note**
|
||||||
|
> If your group name is a color you can force the color to be transparent:
|
||||||
|
|
||||||
|
box transparent Aqua
|
||||||
|
... actors ...
|
||||||
|
end
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
sequenceDiagram
|
||||||
|
box Purple Alice & John
|
||||||
|
participant A
|
||||||
|
participant J
|
||||||
|
end
|
||||||
|
box Another Group
|
||||||
|
participant B
|
||||||
|
participant C
|
||||||
|
end
|
||||||
|
A->>J: Hello John, how are you?
|
||||||
|
J->>A: Great!
|
||||||
|
A->>B: Hello Bob, how is Charly ?
|
||||||
|
B->>C: Hello Charly, how are you?
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid
|
||||||
|
sequenceDiagram
|
||||||
|
box Purple Alice & John
|
||||||
|
participant A
|
||||||
|
participant J
|
||||||
|
end
|
||||||
|
box Another Group
|
||||||
|
participant B
|
||||||
|
participant C
|
||||||
|
end
|
||||||
|
A->>J: Hello John, how are you?
|
||||||
|
J->>A: Great!
|
||||||
|
A->>B: Hello Bob, how is Charly ?
|
||||||
|
B->>C: Hello Charly, how are you?
|
||||||
|
```
|
||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
Messages can be of two displayed either solid or with a dotted line.
|
Messages can be of two displayed either solid or with a dotted line.
|
||||||
|
|||||||
12
package.json
12
package.json
@@ -4,7 +4,7 @@
|
|||||||
"version": "9.3.0-rc1",
|
"version": "9.3.0-rc1",
|
||||||
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"packageManager": "pnpm@7.25.0",
|
"packageManager": "pnpm@7.25.1",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"diagram",
|
"diagram",
|
||||||
"markdown",
|
"markdown",
|
||||||
@@ -23,7 +23,7 @@
|
|||||||
"build": "pnpm run -r clean && concurrently \"pnpm build:vite\" \"pnpm build:types\"",
|
"build": "pnpm run -r clean && concurrently \"pnpm build:vite\" \"pnpm build:types\"",
|
||||||
"dev": "concurrently \"pnpm build:vite --watch\" \"ts-node-esm .vite/server.ts\"",
|
"dev": "concurrently \"pnpm build:vite --watch\" \"ts-node-esm .vite/server.ts\"",
|
||||||
"release": "pnpm build",
|
"release": "pnpm build",
|
||||||
"lint": "eslint --cache --ignore-path .gitignore . && pnpm lint:jison && prettier --check .",
|
"lint": "eslint --cache --cache-strategy content --ignore-path .gitignore . && pnpm lint:jison && prettier --cache --check .",
|
||||||
"lint:fix": "eslint --fix --ignore-path .gitignore . && prettier --write . && ts-node-esm scripts/fixCSpell.ts",
|
"lint:fix": "eslint --fix --ignore-path .gitignore . && prettier --write . && ts-node-esm scripts/fixCSpell.ts",
|
||||||
"lint:jison": "ts-node-esm ./scripts/jison/lint.mts",
|
"lint:jison": "ts-node-esm ./scripts/jison/lint.mts",
|
||||||
"cypress": "cypress run",
|
"cypress": "cypress run",
|
||||||
@@ -67,8 +67,8 @@
|
|||||||
"@types/node": "^18.11.9",
|
"@types/node": "^18.11.9",
|
||||||
"@types/prettier": "^2.7.1",
|
"@types/prettier": "^2.7.1",
|
||||||
"@types/rollup-plugin-visualizer": "^4.2.1",
|
"@types/rollup-plugin-visualizer": "^4.2.1",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.42.1",
|
"@typescript-eslint/eslint-plugin": "^5.48.2",
|
||||||
"@typescript-eslint/parser": "^5.42.1",
|
"@typescript-eslint/parser": "^5.48.2",
|
||||||
"@vitest/coverage-c8": "^0.27.0",
|
"@vitest/coverage-c8": "^0.27.0",
|
||||||
"@vitest/ui": "^0.27.0",
|
"@vitest/ui": "^0.27.0",
|
||||||
"concurrently": "^7.5.0",
|
"concurrently": "^7.5.0",
|
||||||
@@ -76,8 +76,8 @@
|
|||||||
"cypress": "^10.11.0",
|
"cypress": "^10.11.0",
|
||||||
"cypress-image-snapshot": "^4.0.1",
|
"cypress-image-snapshot": "^4.0.1",
|
||||||
"esbuild": "^0.17.0",
|
"esbuild": "^0.17.0",
|
||||||
"eslint": "^8.27.0",
|
"eslint": "^8.32.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.6.0",
|
||||||
"eslint-plugin-cypress": "^2.12.1",
|
"eslint-plugin-cypress": "^2.12.1",
|
||||||
"eslint-plugin-html": "^7.1.0",
|
"eslint-plugin-html": "^7.1.0",
|
||||||
"eslint-plugin-jest": "^27.1.5",
|
"eslint-plugin-jest": "^27.1.5",
|
||||||
|
|||||||
@@ -47,6 +47,7 @@
|
|||||||
"non-layered-tidy-tree-layout": "^2.0.2"
|
"non-layered-tidy-tree-layout": "^2.0.2"
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
|
"@types/cytoscape": "^3.19.9",
|
||||||
"concurrently": "^7.5.0",
|
"concurrently": "^7.5.0",
|
||||||
"mermaid": "workspace:*",
|
"mermaid": "workspace:*",
|
||||||
"rimraf": "^3.0.2"
|
"rimraf": "^3.0.2"
|
||||||
|
|||||||
@@ -54,12 +54,12 @@
|
|||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@braintree/sanitize-url": "^6.0.0",
|
"@braintree/sanitize-url": "^6.0.0",
|
||||||
"d3": "^7.0.0",
|
"d3": "^7.0.0",
|
||||||
"dagre-d3-es": "7.0.6",
|
"dagre-d3-es": "7.0.8",
|
||||||
"dompurify": "2.4.3",
|
"dompurify": "2.4.3",
|
||||||
"elkjs": "^0.8.2",
|
"elkjs": "^0.8.2",
|
||||||
"khroma": "^2.0.0",
|
"khroma": "^2.0.0",
|
||||||
"lodash-es": "^4.17.21",
|
"lodash-es": "^4.17.21",
|
||||||
"moment-mini": "^2.24.0",
|
"moment": "^2.29.4",
|
||||||
"non-layered-tidy-tree-layout": "^2.0.2",
|
"non-layered-tidy-tree-layout": "^2.0.2",
|
||||||
"stylis": "^4.1.2",
|
"stylis": "^4.1.2",
|
||||||
"ts-dedent": "^2.2.0",
|
"ts-dedent": "^2.2.0",
|
||||||
@@ -86,10 +86,10 @@
|
|||||||
"js-base64": "^3.7.2",
|
"js-base64": "^3.7.2",
|
||||||
"jsdom": "^20.0.2",
|
"jsdom": "^20.0.2",
|
||||||
"micromatch": "^4.0.5",
|
"micromatch": "^4.0.5",
|
||||||
"moment": "^2.29.4",
|
|
||||||
"path-browserify": "^1.0.1",
|
"path-browserify": "^1.0.1",
|
||||||
"prettier": "^2.7.1",
|
"prettier": "^2.7.1",
|
||||||
"remark": "^14.0.2",
|
"remark": "^14.0.2",
|
||||||
|
"remark-frontmatter": "^4.0.1",
|
||||||
"remark-gfm": "^3.0.1",
|
"remark-gfm": "^3.0.1",
|
||||||
"rimraf": "^3.0.2",
|
"rimraf": "^3.0.2",
|
||||||
"start-server-and-test": "^1.14.0",
|
"start-server-and-test": "^1.14.0",
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ import { extractFrontMatter } from './diagram-api/frontmatter';
|
|||||||
import { isDetailedError } from './utils';
|
import { isDetailedError } from './utils';
|
||||||
import type { DetailedError } from './utils';
|
import type { DetailedError } from './utils';
|
||||||
|
|
||||||
export type ParseErrorFunction = (err: string | DetailedError, hash?: any) => void;
|
export type ParseErrorFunction = (err: string | DetailedError | unknown, hash?: any) => void;
|
||||||
|
|
||||||
export class Diagram {
|
export class Diagram {
|
||||||
type = 'graph';
|
type = 'graph';
|
||||||
|
|||||||
@@ -59,7 +59,7 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => {
|
|||||||
|
|
||||||
// Check to see if any of the attributes has a key or a comment
|
// Check to see if any of the attributes has a key or a comment
|
||||||
attributes.forEach((item) => {
|
attributes.forEach((item) => {
|
||||||
if (item.attributeKeyType !== undefined) {
|
if (item.attributeKeyTypeList !== undefined && item.attributeKeyTypeList.length > 0) {
|
||||||
hasKeyType = true;
|
hasKeyType = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -112,6 +112,9 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => {
|
|||||||
nodeHeight = Math.max(typeBBox.height, nameBBox.height);
|
nodeHeight = Math.max(typeBBox.height, nameBBox.height);
|
||||||
|
|
||||||
if (hasKeyType) {
|
if (hasKeyType) {
|
||||||
|
const keyTypeNodeText =
|
||||||
|
item.attributeKeyTypeList !== undefined ? item.attributeKeyTypeList.join(',') : '';
|
||||||
|
|
||||||
const keyTypeNode = groupNode
|
const keyTypeNode = groupNode
|
||||||
.append('text')
|
.append('text')
|
||||||
.classed('er entityLabel', true)
|
.classed('er entityLabel', true)
|
||||||
@@ -122,7 +125,7 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => {
|
|||||||
.style('text-anchor', 'left')
|
.style('text-anchor', 'left')
|
||||||
.style('font-family', getConfig().fontFamily)
|
.style('font-family', getConfig().fontFamily)
|
||||||
.style('font-size', attrFontSize + 'px')
|
.style('font-size', attrFontSize + 'px')
|
||||||
.text(item.attributeKeyType || '');
|
.text(keyTypeNodeText);
|
||||||
|
|
||||||
attributeNode.kn = keyTypeNode;
|
attributeNode.kn = keyTypeNode;
|
||||||
const keyTypeBBox = keyTypeNode.node().getBBox();
|
const keyTypeBBox = keyTypeNode.node().getBBox();
|
||||||
|
|||||||
@@ -28,10 +28,11 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
|||||||
\"[^"]*\" return 'WORD';
|
\"[^"]*\" return 'WORD';
|
||||||
"erDiagram" return 'ER_DIAGRAM';
|
"erDiagram" return 'ER_DIAGRAM';
|
||||||
"{" { this.begin("block"); return 'BLOCK_START'; }
|
"{" { this.begin("block"); return 'BLOCK_START'; }
|
||||||
|
<block>"," return 'COMMA';
|
||||||
<block>\s+ /* skip whitespace in block */
|
<block>\s+ /* skip whitespace in block */
|
||||||
<block>\b((?:PK)|(?:FK)|(?:UK))\b return 'ATTRIBUTE_KEY'
|
<block>\b((?:PK)|(?:FK)|(?:UK))\b return 'ATTRIBUTE_KEY'
|
||||||
<block>(.*?)[~](.*?)*[~] return 'ATTRIBUTE_WORD';
|
<block>(.*?)[~](.*?)*[~] return 'ATTRIBUTE_WORD';
|
||||||
<block>[A-Za-z][A-Za-z0-9\-_\[\]\(\)]* return 'ATTRIBUTE_WORD'
|
<block>[A-Za-z_][A-Za-z0-9\-_\[\]\(\)]* return 'ATTRIBUTE_WORD'
|
||||||
<block>\"[^"]*\" return 'COMMENT';
|
<block>\"[^"]*\" return 'COMMENT';
|
||||||
<block>[\n]+ /* nothing */
|
<block>[\n]+ /* nothing */
|
||||||
<block>"}" { this.popState(); return 'BLOCK_STOP'; }
|
<block>"}" { this.popState(); return 'BLOCK_STOP'; }
|
||||||
@@ -131,11 +132,12 @@ attributes
|
|||||||
|
|
||||||
attribute
|
attribute
|
||||||
: attributeType attributeName { $$ = { attributeType: $1, attributeName: $2 }; }
|
: attributeType attributeName { $$ = { attributeType: $1, attributeName: $2 }; }
|
||||||
| attributeType attributeName attributeKeyType { $$ = { attributeType: $1, attributeName: $2, attributeKeyType: $3 }; }
|
| attributeType attributeName attributeKeyTypeList { $$ = { attributeType: $1, attributeName: $2, attributeKeyTypeList: $3 }; }
|
||||||
| attributeType attributeName attributeComment { $$ = { attributeType: $1, attributeName: $2, attributeComment: $3 }; }
|
| attributeType attributeName attributeComment { $$ = { attributeType: $1, attributeName: $2, attributeComment: $3 }; }
|
||||||
| attributeType attributeName attributeKeyType attributeComment { $$ = { attributeType: $1, attributeName: $2, attributeKeyType: $3, attributeComment: $4 }; }
|
| attributeType attributeName attributeKeyTypeList attributeComment { $$ = { attributeType: $1, attributeName: $2, attributeKeyTypeList: $3, attributeComment: $4 }; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
|
||||||
attributeType
|
attributeType
|
||||||
: ATTRIBUTE_WORD { $$=$1; }
|
: ATTRIBUTE_WORD { $$=$1; }
|
||||||
;
|
;
|
||||||
@@ -144,6 +146,11 @@ attributeName
|
|||||||
: ATTRIBUTE_WORD { $$=$1; }
|
: ATTRIBUTE_WORD { $$=$1; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
attributeKeyTypeList
|
||||||
|
: attributeKeyType { $$ = [$1]; }
|
||||||
|
| attributeKeyTypeList COMMA attributeKeyType { $1.push($3); $$ = $1; }
|
||||||
|
;
|
||||||
|
|
||||||
attributeKeyType
|
attributeKeyType
|
||||||
: ATTRIBUTE_KEY { $$=$1; }
|
: ATTRIBUTE_KEY { $$=$1; }
|
||||||
;
|
;
|
||||||
|
|||||||
@@ -135,6 +135,37 @@ describe('when parsing ER diagram it...', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('attribute name', () => {
|
||||||
|
it('should allow alphanumeric characters, dashes, underscores and brackets (not leading chars)', function () {
|
||||||
|
const entity = 'BOOK';
|
||||||
|
const attribute1 = 'string myBookTitle';
|
||||||
|
const attribute2 = 'string MYBOOKSUBTITLE_1';
|
||||||
|
const attribute3 = 'string author-ref[name](1)';
|
||||||
|
|
||||||
|
erDiagram.parser.parse(
|
||||||
|
`erDiagram\n${entity} {\n${attribute1}\n${attribute2}\n${attribute3}\n}`
|
||||||
|
);
|
||||||
|
const entities = erDb.getEntities();
|
||||||
|
|
||||||
|
expect(Object.keys(entities).length).toBe(1);
|
||||||
|
expect(entities[entity].attributes.length).toBe(3);
|
||||||
|
expect(entities[entity].attributes[0].attributeName).toBe('myBookTitle');
|
||||||
|
expect(entities[entity].attributes[1].attributeName).toBe('MYBOOKSUBTITLE_1');
|
||||||
|
expect(entities[entity].attributes[2].attributeName).toBe('author-ref[name](1)');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should not allow leading numbers, dashes or brackets', function () {
|
||||||
|
const entity = 'BOOK';
|
||||||
|
const nonLeadingChars = '0-[]()';
|
||||||
|
[...nonLeadingChars].forEach((nonLeadingChar) => {
|
||||||
|
expect(() => {
|
||||||
|
const attribute = `string ${nonLeadingChar}author`;
|
||||||
|
erDiagram.parser.parse(`erDiagram\n${entity} {\n${attribute}\n}`);
|
||||||
|
}).toThrow();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
it('should allow an entity with a single attribute to be defined', function () {
|
it('should allow an entity with a single attribute to be defined', function () {
|
||||||
const entity = 'BOOK';
|
const entity = 'BOOK';
|
||||||
const attribute = 'string title';
|
const attribute = 'string title';
|
||||||
@@ -190,6 +221,28 @@ describe('when parsing ER diagram it...', function () {
|
|||||||
expect(entities[entity].attributes.length).toBe(4);
|
expect(entities[entity].attributes.length).toBe(4);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should allow an entity with attributes that have many constraints and comments', function () {
|
||||||
|
const entity = 'CUSTOMER';
|
||||||
|
const attribute1 = 'int customer_number PK, FK "comment1"';
|
||||||
|
const attribute2 = 'datetime customer_status_start_datetime PK,UK, FK';
|
||||||
|
const attribute3 = 'datetime customer_status_end_datetime PK , UK "comment3"';
|
||||||
|
const attribute4 = 'string customer_firstname';
|
||||||
|
const attribute5 = 'string customer_lastname "comment5"';
|
||||||
|
|
||||||
|
erDiagram.parser.parse(
|
||||||
|
`erDiagram\n${entity} {\n${attribute1}\n${attribute2}\n${attribute3}\n${attribute4}\n${attribute5}\n}`
|
||||||
|
);
|
||||||
|
const entities = erDb.getEntities();
|
||||||
|
expect(entities[entity].attributes[0].attributeKeyTypeList).toEqual(['PK', 'FK']);
|
||||||
|
expect(entities[entity].attributes[0].attributeComment).toBe('comment1');
|
||||||
|
expect(entities[entity].attributes[1].attributeKeyTypeList).toEqual(['PK', 'UK', 'FK']);
|
||||||
|
expect(entities[entity].attributes[2].attributeKeyTypeList).toEqual(['PK', 'UK']);
|
||||||
|
expect(entities[entity].attributes[2].attributeComment).toBe('comment3');
|
||||||
|
expect(entities[entity].attributes[3].attributeKeyTypeList).toBeUndefined();
|
||||||
|
expect(entities[entity].attributes[4].attributeKeyTypeList).toBeUndefined();
|
||||||
|
expect(entities[entity].attributes[4].attributeComment).toBe('comment5');
|
||||||
|
});
|
||||||
|
|
||||||
it('should allow an entity with attribute that has a generic type', function () {
|
it('should allow an entity with attribute that has a generic type', function () {
|
||||||
const entity = 'BOOK';
|
const entity = 'BOOK';
|
||||||
const attribute1 = 'type~T~ type';
|
const attribute1 = 'type~T~ type';
|
||||||
|
|||||||
@@ -609,7 +609,7 @@ const insertChildren = (nodeArray, parentLookupDb) => {
|
|||||||
* @param id
|
* @param id
|
||||||
*/
|
*/
|
||||||
|
|
||||||
export const draw = function (text, id, _version, diagObj) {
|
export const draw = async function (text, id, _version, diagObj) {
|
||||||
// Add temporary render element
|
// Add temporary render element
|
||||||
diagObj.db.clear();
|
diagObj.db.clear();
|
||||||
nodeDb = {};
|
nodeDb = {};
|
||||||
@@ -617,149 +617,128 @@ export const draw = function (text, id, _version, diagObj) {
|
|||||||
// Parse the graph definition
|
// Parse the graph definition
|
||||||
diagObj.parser.parse(text);
|
diagObj.parser.parse(text);
|
||||||
|
|
||||||
return new Promise(function (resolve, reject) {
|
const renderEl = select('body').append('div').attr('style', 'height:400px').attr('id', 'cy');
|
||||||
const renderEl = select('body').append('div').attr('style', 'height:400px').attr('id', 'cy');
|
let graph = {
|
||||||
// .attr('style', 'display:none')
|
id: 'root',
|
||||||
let graph = {
|
layoutOptions: {
|
||||||
id: 'root',
|
'elk.hierarchyHandling': 'INCLUDE_CHILDREN',
|
||||||
layoutOptions: {
|
'org.eclipse.elk.padding': '[top=100, left=100, bottom=110, right=110]',
|
||||||
'elk.hierarchyHandling': 'INCLUDE_CHILDREN',
|
'elk.layered.spacing.edgeNodeBetweenLayers': '30',
|
||||||
// 'elk.hierarchyHandling': 'SEPARATE_CHILDREN',
|
'elk.direction': 'DOWN',
|
||||||
'org.eclipse.elk.padding': '[top=100, left=100, bottom=110, right=110]',
|
},
|
||||||
// 'org.eclipse.elk.layered.spacing.nodeNodeBetweenLayers': 120,
|
children: [],
|
||||||
// 'elk.layered.spacing.nodeNodeBetweenLayers': '140',
|
edges: [],
|
||||||
'elk.layered.spacing.edgeNodeBetweenLayers': '30',
|
};
|
||||||
// 'elk.algorithm': 'layered',
|
log.info('Drawing flowchart using v3 renderer');
|
||||||
'elk.direction': 'DOWN',
|
|
||||||
// 'elk.port.side': 'SOUTH',
|
|
||||||
// 'nodePlacement.strategy': 'SIMPLE',
|
|
||||||
// 'org.eclipse.elk.spacing.labelLabel': 120,
|
|
||||||
// 'org.eclipse.elk.graphviz.concentrate': true,
|
|
||||||
// 'org.eclipse.elk.spacing.nodeNode': 120,
|
|
||||||
// 'org.eclipse.elk.spacing.edgeEdge': 120,
|
|
||||||
// 'org.eclipse.elk.spacing.edgeNode': 120,
|
|
||||||
// 'org.eclipse.elk.spacing.nodeEdge': 120,
|
|
||||||
// 'org.eclipse.elk.spacing.componentComponent': 120,
|
|
||||||
},
|
|
||||||
children: [],
|
|
||||||
edges: [],
|
|
||||||
};
|
|
||||||
log.info('Drawing flowchart using v3 renderer');
|
|
||||||
|
|
||||||
// Set the direction,
|
// Set the direction,
|
||||||
// Fetch the default direction, use TD if none was found
|
// Fetch the default direction, use TD if none was found
|
||||||
let dir = diagObj.db.getDirection();
|
let dir = diagObj.db.getDirection();
|
||||||
switch (dir) {
|
switch (dir) {
|
||||||
case 'BT':
|
case 'BT':
|
||||||
graph.layoutOptions['elk.direction'] = 'UP';
|
graph.layoutOptions['elk.direction'] = 'UP';
|
||||||
break;
|
break;
|
||||||
case 'TB':
|
case 'TB':
|
||||||
graph.layoutOptions['elk.direction'] = 'DOWN';
|
graph.layoutOptions['elk.direction'] = 'DOWN';
|
||||||
break;
|
break;
|
||||||
case 'LR':
|
case 'LR':
|
||||||
graph.layoutOptions['elk.direction'] = 'RIGHT';
|
graph.layoutOptions['elk.direction'] = 'RIGHT';
|
||||||
break;
|
break;
|
||||||
case 'RL':
|
case 'RL':
|
||||||
graph.layoutOptions['elk.direction'] = 'LEFT';
|
graph.layoutOptions['elk.direction'] = 'LEFT';
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
|
const { securityLevel, flowchart: conf } = getConfig();
|
||||||
|
|
||||||
|
// Find the root dom node to ne used in rendering
|
||||||
|
// Handle root and document for when rendering in sandbox mode
|
||||||
|
let sandboxElement;
|
||||||
|
if (securityLevel === 'sandbox') {
|
||||||
|
sandboxElement = select('#i' + id);
|
||||||
|
}
|
||||||
|
const root =
|
||||||
|
securityLevel === 'sandbox'
|
||||||
|
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||||
|
: select('body');
|
||||||
|
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||||
|
|
||||||
|
const svg = root.select(`[id="${id}"]`);
|
||||||
|
|
||||||
|
// Define the supported markers for the diagram
|
||||||
|
const markers = ['point', 'circle', 'cross'];
|
||||||
|
|
||||||
|
// Add the marker definitions to the svg as marker tags
|
||||||
|
insertMarkers(svg, markers, diagObj.type, diagObj.arrowMarkerAbsolute);
|
||||||
|
|
||||||
|
// Fetch the vertices/nodes and edges/links from the parsed graph definition
|
||||||
|
const vert = diagObj.db.getVertices();
|
||||||
|
|
||||||
|
// Setup nodes from the subgraphs with type group, these will be used
|
||||||
|
// as nodes with children in the subgraph
|
||||||
|
let subG;
|
||||||
|
const subGraphs = diagObj.db.getSubGraphs();
|
||||||
|
log.info('Subgraphs - ', subGraphs);
|
||||||
|
for (let i = subGraphs.length - 1; i >= 0; i--) {
|
||||||
|
subG = subGraphs[i];
|
||||||
|
diagObj.db.addVertex(subG.id, subG.title, 'group', undefined, subG.classes, subG.dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add an element in the svg to be used to hold the subgraphs container
|
||||||
|
// elements
|
||||||
|
const subGraphsEl = svg.insert('g').attr('class', 'subgraphs');
|
||||||
|
|
||||||
|
// Create the lookup db for the subgraphs and their children to used when creating
|
||||||
|
// the tree structured graph
|
||||||
|
const parentLookupDb = addSubGraphs(diagObj.db);
|
||||||
|
|
||||||
|
// Add the nodes to the graph, this will entail creating the actual nodes
|
||||||
|
// in order to get the size of the node. You can't get the size of a node
|
||||||
|
// that is not in the dom so we need to add it to the dom, get the size
|
||||||
|
// we will position the nodes when we get the layout from elkjs
|
||||||
|
graph = addVertices(vert, id, root, doc, diagObj, parentLookupDb, graph);
|
||||||
|
|
||||||
|
// Time for the edges, we start with adding an element in the node to hold the edges
|
||||||
|
const edgesEl = svg.insert('g').attr('class', 'edges edgePath');
|
||||||
|
// Fetch the edges form the parsed graph definition
|
||||||
|
const edges = diagObj.db.getEdges();
|
||||||
|
|
||||||
|
// Add the edges to the graph, this will entail creating the actual edges
|
||||||
|
graph = addEdges(edges, diagObj, graph, svg);
|
||||||
|
|
||||||
|
// Iterate through all nodes and add the top level nodes to the graph
|
||||||
|
const nodes = Object.keys(nodeDb);
|
||||||
|
nodes.forEach((nodeId) => {
|
||||||
|
const node = nodeDb[nodeId];
|
||||||
|
if (!node.parent) {
|
||||||
|
graph.children.push(node);
|
||||||
}
|
}
|
||||||
const { securityLevel, flowchart: conf } = getConfig();
|
// Subgraph
|
||||||
|
if (parentLookupDb.childrenById[nodeId] !== undefined) {
|
||||||
// Find the root dom node to ne used in rendering
|
node.labels = [
|
||||||
// Handle root and document for when rendering in sandbox mode
|
{
|
||||||
let sandboxElement;
|
text: node.labelText,
|
||||||
if (securityLevel === 'sandbox') {
|
layoutOptions: {
|
||||||
sandboxElement = select('#i' + id);
|
'nodeLabels.placement': '[H_CENTER, V_TOP, INSIDE]',
|
||||||
}
|
|
||||||
const root =
|
|
||||||
securityLevel === 'sandbox'
|
|
||||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
|
||||||
: select('body');
|
|
||||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
|
||||||
|
|
||||||
const svg = root.select(`[id="${id}"]`);
|
|
||||||
|
|
||||||
// Define the supported markers for the diagram
|
|
||||||
const markers = ['point', 'circle', 'cross'];
|
|
||||||
|
|
||||||
// Add the marker definitions to the svg as marker tags
|
|
||||||
insertMarkers(svg, markers, diagObj.type, diagObj.arrowMarkerAbsolute);
|
|
||||||
|
|
||||||
// Fetch the vertices/nodes and edges/links from the parsed graph definition
|
|
||||||
const vert = diagObj.db.getVertices();
|
|
||||||
|
|
||||||
// Setup nodes from the subgraphs with type group, these will be used
|
|
||||||
// as nodes with children in the subgraph
|
|
||||||
let subG;
|
|
||||||
const subGraphs = diagObj.db.getSubGraphs();
|
|
||||||
log.info('Subgraphs - ', subGraphs);
|
|
||||||
for (let i = subGraphs.length - 1; i >= 0; i--) {
|
|
||||||
subG = subGraphs[i];
|
|
||||||
diagObj.db.addVertex(subG.id, subG.title, 'group', undefined, subG.classes, subG.dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Add an element in the svg to be used to hold the subgraphs container
|
|
||||||
// elements
|
|
||||||
const subGraphsEl = svg.insert('g').attr('class', 'subgraphs');
|
|
||||||
|
|
||||||
// Create the lookup db for the subgraphs and their children to used when creating
|
|
||||||
// the tree structured graph
|
|
||||||
const parentLookupDb = addSubGraphs(diagObj.db);
|
|
||||||
|
|
||||||
// Add the nodes to the graph, this will entail creating the actual nodes
|
|
||||||
// in order to get the size of the node. You can't get the size of a node
|
|
||||||
// that is not in the dom so we need to add it to the dom, get the size
|
|
||||||
// we will position the nodes when we get the layout from elkjs
|
|
||||||
graph = addVertices(vert, id, root, doc, diagObj, parentLookupDb, graph);
|
|
||||||
|
|
||||||
// Time for the edges, we start with adding an element in the node to hold the edges
|
|
||||||
const edgesEl = svg.insert('g').attr('class', 'edges edgePath');
|
|
||||||
// Fetch the edges form the parsed graph definition
|
|
||||||
const edges = diagObj.db.getEdges();
|
|
||||||
|
|
||||||
// Add the edges to the graph, this will entail creating the actual edges
|
|
||||||
graph = addEdges(edges, diagObj, graph, svg);
|
|
||||||
|
|
||||||
// Iterate through all nodes and add the top level nodes to the graph
|
|
||||||
const nodes = Object.keys(nodeDb);
|
|
||||||
nodes.forEach((nodeId) => {
|
|
||||||
const node = nodeDb[nodeId];
|
|
||||||
if (!node.parent) {
|
|
||||||
graph.children.push(node);
|
|
||||||
}
|
|
||||||
// node.nodePadding = [120, 50, 50, 50];
|
|
||||||
// node['org.eclipse.elk.spacing.nodeNode'] = 120;
|
|
||||||
// Subgraph
|
|
||||||
if (parentLookupDb.childrenById[nodeId] !== undefined) {
|
|
||||||
node.labels = [
|
|
||||||
{
|
|
||||||
text: node.labelText,
|
|
||||||
layoutOptions: {
|
|
||||||
'nodeLabels.placement': '[H_CENTER, V_TOP, INSIDE]',
|
|
||||||
},
|
|
||||||
width: node.labelData.width,
|
|
||||||
height: node.labelData.height,
|
|
||||||
},
|
},
|
||||||
];
|
width: node.labelData.width,
|
||||||
delete node.x;
|
height: node.labelData.height,
|
||||||
delete node.y;
|
},
|
||||||
delete node.width;
|
];
|
||||||
delete node.height;
|
delete node.x;
|
||||||
}
|
delete node.y;
|
||||||
});
|
delete node.width;
|
||||||
insertChildren(graph.children, parentLookupDb);
|
delete node.height;
|
||||||
elk.layout(graph).then(function (g) {
|
}
|
||||||
drawNodes(0, 0, g.children, svg, subGraphsEl, diagObj, 0);
|
|
||||||
|
|
||||||
g.edges.map((edge, id) => {
|
|
||||||
insertEdge(edgesEl, edge, edge.edgeData, diagObj, parentLookupDb);
|
|
||||||
});
|
|
||||||
setupGraphViewbox({}, svg, conf.diagramPadding, conf.useMaxWidth);
|
|
||||||
resolve();
|
|
||||||
});
|
|
||||||
// Remove element after layout
|
|
||||||
renderEl.remove();
|
|
||||||
});
|
});
|
||||||
|
insertChildren(graph.children, parentLookupDb);
|
||||||
|
const g = await elk.layout(graph);
|
||||||
|
drawNodes(0, 0, g.children, svg, subGraphsEl, diagObj, 0);
|
||||||
|
g.edges?.map((edge) => {
|
||||||
|
insertEdge(edgesEl, edge, edge.edgeData, diagObj, parentLookupDb);
|
||||||
|
});
|
||||||
|
setupGraphViewbox({}, svg, conf.diagramPadding, conf.useMaxWidth);
|
||||||
|
// Remove element after layout
|
||||||
|
renderEl.remove();
|
||||||
};
|
};
|
||||||
|
|
||||||
const drawNodes = (relX, relY, nodeArray, svg, subgraphsEl, diagObj, depth) => {
|
const drawNodes = (relX, relY, nodeArray, svg, subgraphsEl, diagObj, depth) => {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import moment from 'moment-mini';
|
import moment from 'moment';
|
||||||
import { sanitizeUrl } from '@braintree/sanitize-url';
|
import { sanitizeUrl } from '@braintree/sanitize-url';
|
||||||
import { log } from '../../logger';
|
import { log } from '../../logger';
|
||||||
import * as configApi from '../../config';
|
import * as configApi from '../../config';
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
// @ts-nocheck TODO: Fix TS
|
// @ts-nocheck TODO: Fix TS
|
||||||
import moment from 'moment-mini';
|
import moment from 'moment';
|
||||||
import ganttDb from './ganttDb';
|
import ganttDb from './ganttDb';
|
||||||
import { convert } from '../../tests/util';
|
import { convert } from '../../tests/util';
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import moment from 'moment-mini';
|
import moment from 'moment';
|
||||||
import { log } from '../../logger';
|
import { log } from '../../logger';
|
||||||
import {
|
import {
|
||||||
select,
|
select,
|
||||||
|
|||||||
@@ -35,8 +35,9 @@
|
|||||||
\%%(?!\{)[^\n]* /* skip comments */
|
\%%(?!\{)[^\n]* /* skip comments */
|
||||||
[^\}]\%\%[^\n]* /* skip comments */
|
[^\}]\%\%[^\n]* /* skip comments */
|
||||||
[0-9]+(?=[ \n]+) return 'NUM';
|
[0-9]+(?=[ \n]+) return 'NUM';
|
||||||
|
"box" { this.begin('LINE'); return 'box'; }
|
||||||
"participant" { this.begin('ID'); return 'participant'; }
|
"participant" { this.begin('ID'); return 'participant'; }
|
||||||
"actor" { this.begin('ID'); return 'participant_actor'; }
|
"actor" { this.begin('ID'); return 'participant_actor'; }
|
||||||
<ID>[^\->:\n,;]+?([\-]*[^\->:\n,;]+?)*?(?=((?!\n)\s)+"as"(?!\n)\s|[#\n;]|$) { yytext = yytext.trim(); this.begin('ALIAS'); return 'ACTOR'; }
|
<ID>[^\->:\n,;]+?([\-]*[^\->:\n,;]+?)*?(?=((?!\n)\s)+"as"(?!\n)\s|[#\n;]|$) { yytext = yytext.trim(); this.begin('ALIAS'); return 'ACTOR'; }
|
||||||
<ALIAS>"as" { this.popState(); this.popState(); this.begin('LINE'); return 'AS'; }
|
<ALIAS>"as" { this.popState(); this.popState(); this.begin('LINE'); return 'AS'; }
|
||||||
<ALIAS>(?:) { this.popState(); this.popState(); return 'NEWLINE'; }
|
<ALIAS>(?:) { this.popState(); this.popState(); return 'NEWLINE'; }
|
||||||
@@ -117,16 +118,30 @@ line
|
|||||||
| NEWLINE { $$=[]; }
|
| NEWLINE { $$=[]; }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
box_section
|
||||||
|
: /* empty */ { $$ = [] }
|
||||||
|
| box_section box_line {$1.push($2);$$ = $1}
|
||||||
|
;
|
||||||
|
|
||||||
|
box_line
|
||||||
|
: SPACE participant_statement { $$ = $2 }
|
||||||
|
| participant_statement { $$ = $1 }
|
||||||
|
| NEWLINE { $$=[]; }
|
||||||
|
;
|
||||||
|
|
||||||
|
|
||||||
directive
|
directive
|
||||||
: openDirective typeDirective closeDirective 'NEWLINE'
|
: openDirective typeDirective closeDirective 'NEWLINE'
|
||||||
| openDirective typeDirective ':' argDirective closeDirective 'NEWLINE'
|
| openDirective typeDirective ':' argDirective closeDirective 'NEWLINE'
|
||||||
;
|
;
|
||||||
|
|
||||||
statement
|
statement
|
||||||
: 'participant' actor 'AS' restOfLine 'NEWLINE' {$2.type='addParticipant';$2.description=yy.parseMessage($4); $$=$2;}
|
: participant_statement
|
||||||
| 'participant' actor 'NEWLINE' {$2.type='addParticipant';$$=$2;}
|
| 'box' restOfLine box_section end
|
||||||
| 'participant_actor' actor 'AS' restOfLine 'NEWLINE' {$2.type='addActor';$2.description=yy.parseMessage($4); $$=$2;}
|
{
|
||||||
| 'participant_actor' actor 'NEWLINE' {$2.type='addActor'; $$=$2;}
|
$3.unshift({type: 'boxStart', boxData:yy.parseBoxData($2) });
|
||||||
|
$3.push({type: 'boxEnd', boxText:$2});
|
||||||
|
$$=$3;}
|
||||||
| signal 'NEWLINE'
|
| signal 'NEWLINE'
|
||||||
| autonumber NUM NUM 'NEWLINE' { $$= {type:'sequenceIndex',sequenceIndex: Number($2), sequenceIndexStep:Number($3), sequenceVisible:true, signalType:yy.LINETYPE.AUTONUMBER};}
|
| autonumber NUM NUM 'NEWLINE' { $$= {type:'sequenceIndex',sequenceIndex: Number($2), sequenceIndexStep:Number($3), sequenceVisible:true, signalType:yy.LINETYPE.AUTONUMBER};}
|
||||||
| autonumber NUM 'NEWLINE' { $$ = {type:'sequenceIndex',sequenceIndex: Number($2), sequenceIndexStep:1, sequenceVisible:true, signalType:yy.LINETYPE.AUTONUMBER};}
|
| autonumber NUM 'NEWLINE' { $$ = {type:'sequenceIndex',sequenceIndex: Number($2), sequenceIndexStep:1, sequenceVisible:true, signalType:yy.LINETYPE.AUTONUMBER};}
|
||||||
@@ -209,6 +224,13 @@ else_sections
|
|||||||
{ $$ = $1.concat([{type: 'else', altText:yy.parseMessage($3), signalType: yy.LINETYPE.ALT_ELSE}, $4]); }
|
{ $$ = $1.concat([{type: 'else', altText:yy.parseMessage($3), signalType: yy.LINETYPE.ALT_ELSE}, $4]); }
|
||||||
;
|
;
|
||||||
|
|
||||||
|
participant_statement
|
||||||
|
: 'participant' actor 'AS' restOfLine 'NEWLINE' {$2.type='addParticipant';$2.description=yy.parseMessage($4); $$=$2;}
|
||||||
|
| 'participant' actor 'NEWLINE' {$2.type='addParticipant';$$=$2;}
|
||||||
|
| 'participant_actor' actor 'AS' restOfLine 'NEWLINE' {$2.type='addActor';$2.description=yy.parseMessage($4); $$=$2;}
|
||||||
|
| 'participant_actor' actor 'NEWLINE' {$2.type='addActor'; $$=$2;}
|
||||||
|
;
|
||||||
|
|
||||||
note_statement
|
note_statement
|
||||||
: 'note' placement actor text2
|
: 'note' placement actor text2
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -14,20 +14,52 @@ import {
|
|||||||
|
|
||||||
let prevActor = undefined;
|
let prevActor = undefined;
|
||||||
let actors = {};
|
let actors = {};
|
||||||
|
let boxes = [];
|
||||||
let messages = [];
|
let messages = [];
|
||||||
const notes = [];
|
const notes = [];
|
||||||
let sequenceNumbersEnabled = false;
|
let sequenceNumbersEnabled = false;
|
||||||
let wrapEnabled;
|
let wrapEnabled;
|
||||||
|
let currentBox = undefined;
|
||||||
|
|
||||||
export const parseDirective = function (statement, context, type) {
|
export const parseDirective = function (statement, context, type) {
|
||||||
mermaidAPI.parseDirective(this, statement, context, type);
|
mermaidAPI.parseDirective(this, statement, context, type);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const addBox = function (data) {
|
||||||
|
boxes.push({
|
||||||
|
name: data.text,
|
||||||
|
wrap: (data.wrap === undefined && autoWrap()) || !!data.wrap,
|
||||||
|
fill: data.color,
|
||||||
|
actorKeys: [],
|
||||||
|
});
|
||||||
|
currentBox = boxes.slice(-1)[0];
|
||||||
|
};
|
||||||
|
|
||||||
export const addActor = function (id, name, description, type) {
|
export const addActor = function (id, name, description, type) {
|
||||||
// Don't allow description nulling
|
let assignedBox = currentBox;
|
||||||
const old = actors[id];
|
const old = actors[id];
|
||||||
if (old && name === old.name && description == null) {
|
if (old) {
|
||||||
return;
|
// If already set and trying to set to a new one throw error
|
||||||
|
if (currentBox && old.box && currentBox !== old.box) {
|
||||||
|
throw new Error(
|
||||||
|
'A same participant should only be defined in one Box: ' +
|
||||||
|
old.name +
|
||||||
|
" can't be in '" +
|
||||||
|
old.box.name +
|
||||||
|
"' and in '" +
|
||||||
|
currentBox.name +
|
||||||
|
"' at the same time."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Don't change the box if already
|
||||||
|
assignedBox = old.box ? old.box : currentBox;
|
||||||
|
old.box = assignedBox;
|
||||||
|
|
||||||
|
// Don't allow description nulling
|
||||||
|
if (old && name === old.name && description == null) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Don't allow null descriptions, either
|
// Don't allow null descriptions, either
|
||||||
@@ -39,6 +71,7 @@ export const addActor = function (id, name, description, type) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
actors[id] = {
|
actors[id] = {
|
||||||
|
box: assignedBox,
|
||||||
name: name,
|
name: name,
|
||||||
description: description.text,
|
description: description.text,
|
||||||
wrap: (description.wrap === undefined && autoWrap()) || !!description.wrap,
|
wrap: (description.wrap === undefined && autoWrap()) || !!description.wrap,
|
||||||
@@ -53,6 +86,9 @@ export const addActor = function (id, name, description, type) {
|
|||||||
actors[prevActor].nextActor = id;
|
actors[prevActor].nextActor = id;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (currentBox) {
|
||||||
|
currentBox.actorKeys.push(id);
|
||||||
|
}
|
||||||
prevActor = id;
|
prevActor = id;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -111,10 +147,21 @@ export const addSignal = function (
|
|||||||
return true;
|
return true;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const hasAtLeastOneBox = function () {
|
||||||
|
return boxes.length > 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
export const hasAtLeastOneBoxWithTitle = function () {
|
||||||
|
return boxes.some((b) => b.name);
|
||||||
|
};
|
||||||
|
|
||||||
export const getMessages = function () {
|
export const getMessages = function () {
|
||||||
return messages;
|
return messages;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const getBoxes = function () {
|
||||||
|
return boxes;
|
||||||
|
};
|
||||||
export const getActors = function () {
|
export const getActors = function () {
|
||||||
return actors;
|
return actors;
|
||||||
};
|
};
|
||||||
@@ -147,6 +194,7 @@ export const autoWrap = () => {
|
|||||||
|
|
||||||
export const clear = function () {
|
export const clear = function () {
|
||||||
actors = {};
|
actors = {};
|
||||||
|
boxes = [];
|
||||||
messages = [];
|
messages = [];
|
||||||
sequenceNumbersEnabled = false;
|
sequenceNumbersEnabled = false;
|
||||||
commonClear();
|
commonClear();
|
||||||
@@ -167,6 +215,47 @@ export const parseMessage = function (str) {
|
|||||||
return message;
|
return message;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// We expect the box statement to be color first then description
|
||||||
|
// The color can be rgb,rgba,hsl,hsla, or css code names #hex codes are not supported for now because of the way the char # is handled
|
||||||
|
// We extract first segment as color, the rest of the line is considered as text
|
||||||
|
export const parseBoxData = function (str) {
|
||||||
|
const match = str.match(/^((?:rgba?|hsla?)\s*\(.*\)|\w*)(.*)$/);
|
||||||
|
let color = match != null && match[1] ? match[1].trim() : 'transparent';
|
||||||
|
let title = match != null && match[2] ? match[2].trim() : undefined;
|
||||||
|
|
||||||
|
// check that the string is a color
|
||||||
|
if (window && window.CSS) {
|
||||||
|
if (!window.CSS.supports('color', color)) {
|
||||||
|
color = 'transparent';
|
||||||
|
title = str.trim();
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
const style = new Option().style;
|
||||||
|
style.color = color;
|
||||||
|
if (style.color !== color) {
|
||||||
|
color = 'transparent';
|
||||||
|
title = str.trim();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const boxData = {
|
||||||
|
color: color,
|
||||||
|
text:
|
||||||
|
title !== undefined
|
||||||
|
? sanitizeText(title.replace(/^:?(?:no)?wrap:/, ''), configApi.getConfig())
|
||||||
|
: undefined,
|
||||||
|
wrap:
|
||||||
|
title !== undefined
|
||||||
|
? title.match(/^:?wrap:/) !== null
|
||||||
|
? true
|
||||||
|
: title.match(/^:?nowrap:/) !== null
|
||||||
|
? false
|
||||||
|
: undefined
|
||||||
|
: undefined,
|
||||||
|
};
|
||||||
|
return boxData;
|
||||||
|
};
|
||||||
|
|
||||||
export const LINETYPE = {
|
export const LINETYPE = {
|
||||||
SOLID: 0,
|
SOLID: 0,
|
||||||
DOTTED: 1,
|
DOTTED: 1,
|
||||||
@@ -311,6 +400,13 @@ function insertProperties(actor, properties) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
function boxEnd() {
|
||||||
|
currentBox = undefined;
|
||||||
|
}
|
||||||
|
|
||||||
export const addDetails = function (actorId, text) {
|
export const addDetails = function (actorId, text) {
|
||||||
// find the actor
|
// find the actor
|
||||||
const actor = getActor(actorId);
|
const actor = getActor(actorId);
|
||||||
@@ -391,6 +487,12 @@ export const apply = function (param) {
|
|||||||
case 'addMessage':
|
case 'addMessage':
|
||||||
addSignal(param.from, param.to, param.msg, param.signalType);
|
addSignal(param.from, param.to, param.msg, param.signalType);
|
||||||
break;
|
break;
|
||||||
|
case 'boxStart':
|
||||||
|
addBox(param.boxData);
|
||||||
|
break;
|
||||||
|
case 'boxEnd':
|
||||||
|
boxEnd();
|
||||||
|
break;
|
||||||
case 'loopStart':
|
case 'loopStart':
|
||||||
addSignal(undefined, undefined, param.loopText, param.signalType);
|
addSignal(undefined, undefined, param.loopText, param.signalType);
|
||||||
break;
|
break;
|
||||||
@@ -467,12 +569,14 @@ export default {
|
|||||||
getActorKeys,
|
getActorKeys,
|
||||||
getActorProperty,
|
getActorProperty,
|
||||||
getAccTitle,
|
getAccTitle,
|
||||||
|
getBoxes,
|
||||||
getDiagramTitle,
|
getDiagramTitle,
|
||||||
setDiagramTitle,
|
setDiagramTitle,
|
||||||
parseDirective,
|
parseDirective,
|
||||||
getConfig: () => configApi.getConfig().sequence,
|
getConfig: () => configApi.getConfig().sequence,
|
||||||
clear,
|
clear,
|
||||||
parseMessage,
|
parseMessage,
|
||||||
|
parseBoxData,
|
||||||
LINETYPE,
|
LINETYPE,
|
||||||
ARROWTYPE,
|
ARROWTYPE,
|
||||||
PLACEMENT,
|
PLACEMENT,
|
||||||
@@ -481,4 +585,6 @@ export default {
|
|||||||
apply,
|
apply,
|
||||||
setAccDescription,
|
setAccDescription,
|
||||||
getAccDescription,
|
getAccDescription,
|
||||||
|
hasAtLeastOneBox,
|
||||||
|
hasAtLeastOneBoxWithTitle,
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -52,8 +52,16 @@ vi.mock('d3', () => {
|
|||||||
curveBasis: 'basis',
|
curveBasis: 'basis',
|
||||||
curveBasisClosed: 'basisClosed',
|
curveBasisClosed: 'basisClosed',
|
||||||
curveBasisOpen: 'basisOpen',
|
curveBasisOpen: 'basisOpen',
|
||||||
curveLinear: 'linear',
|
curveBumpX: 'bumpX',
|
||||||
|
curveBumpY: 'bumpY',
|
||||||
|
curveBundle: 'bundle',
|
||||||
|
curveCardinalClosed: 'cardinalClosed',
|
||||||
|
curveCardinalOpen: 'cardinalOpen',
|
||||||
curveCardinal: 'cardinal',
|
curveCardinal: 'cardinal',
|
||||||
|
curveCatmullRomClosed: 'catmullRomClosed',
|
||||||
|
curveCatmullRomOpen: 'catmullRomOpen',
|
||||||
|
curveCatmullRom: 'catmullRom',
|
||||||
|
curveLinear: 'linear',
|
||||||
curveLinearClosed: 'linearClosed',
|
curveLinearClosed: 'linearClosed',
|
||||||
curveMonotoneX: 'monotoneX',
|
curveMonotoneX: 'monotoneX',
|
||||||
curveMonotoneY: 'monotoneY',
|
curveMonotoneY: 'monotoneY',
|
||||||
@@ -1299,8 +1307,76 @@ properties b: {"class": "external-service-actor", "icon": "@computer"}
|
|||||||
expect(actors.b.properties['icon']).toBe('@computer');
|
expect(actors.b.properties['icon']).toBe('@computer');
|
||||||
expect(actors.c.properties['class']).toBe(undefined);
|
expect(actors.c.properties['class']).toBe(undefined);
|
||||||
});
|
});
|
||||||
});
|
|
||||||
|
|
||||||
|
it('should handle box', function () {
|
||||||
|
const str = `
|
||||||
|
sequenceDiagram
|
||||||
|
box green Group 1
|
||||||
|
participant a as Alice
|
||||||
|
participant b as Bob
|
||||||
|
end
|
||||||
|
participant c as Charlie
|
||||||
|
links a: { "Repo": "https://repo.contoso.com/", "Dashboard": "https://dashboard.contoso.com/" }
|
||||||
|
links b: { "Dashboard": "https://dashboard.contoso.com/" }
|
||||||
|
links a: { "On-Call": "https://oncall.contoso.com/?svc=alice" }
|
||||||
|
link a: Endpoint @ https://alice.contoso.com
|
||||||
|
link a: Swagger @ https://swagger.contoso.com
|
||||||
|
link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com
|
||||||
|
`;
|
||||||
|
|
||||||
|
mermaidAPI.parse(str);
|
||||||
|
const boxes = diagram.db.getBoxes();
|
||||||
|
expect(boxes[0].name).toEqual('Group 1');
|
||||||
|
expect(boxes[0].actorKeys).toEqual(['a', 'b']);
|
||||||
|
expect(boxes[0].fill).toEqual('green');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle box without color', function () {
|
||||||
|
const str = `
|
||||||
|
sequenceDiagram
|
||||||
|
box Group 1
|
||||||
|
participant a as Alice
|
||||||
|
participant b as Bob
|
||||||
|
end
|
||||||
|
participant c as Charlie
|
||||||
|
links a: { "Repo": "https://repo.contoso.com/", "Dashboard": "https://dashboard.contoso.com/" }
|
||||||
|
links b: { "Dashboard": "https://dashboard.contoso.com/" }
|
||||||
|
links a: { "On-Call": "https://oncall.contoso.com/?svc=alice" }
|
||||||
|
link a: Endpoint @ https://alice.contoso.com
|
||||||
|
link a: Swagger @ https://swagger.contoso.com
|
||||||
|
link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com
|
||||||
|
`;
|
||||||
|
|
||||||
|
mermaidAPI.parse(str);
|
||||||
|
const boxes = diagram.db.getBoxes();
|
||||||
|
expect(boxes[0].name).toEqual('Group 1');
|
||||||
|
expect(boxes[0].actorKeys).toEqual(['a', 'b']);
|
||||||
|
expect(boxes[0].fill).toEqual('transparent');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle box without description', function () {
|
||||||
|
const str = `
|
||||||
|
sequenceDiagram
|
||||||
|
box Aqua
|
||||||
|
participant a as Alice
|
||||||
|
participant b as Bob
|
||||||
|
end
|
||||||
|
participant c as Charlie
|
||||||
|
links a: { "Repo": "https://repo.contoso.com/", "Dashboard": "https://dashboard.contoso.com/" }
|
||||||
|
links b: { "Dashboard": "https://dashboard.contoso.com/" }
|
||||||
|
links a: { "On-Call": "https://oncall.contoso.com/?svc=alice" }
|
||||||
|
link a: Endpoint @ https://alice.contoso.com
|
||||||
|
link a: Swagger @ https://swagger.contoso.com
|
||||||
|
link a: Tests @ https://tests.contoso.com/?svc=alice@contoso.com
|
||||||
|
`;
|
||||||
|
|
||||||
|
mermaidAPI.parse(str);
|
||||||
|
const boxes = diagram.db.getBoxes();
|
||||||
|
expect(boxes[0].name).toBeFalsy();
|
||||||
|
expect(boxes[0].actorKeys).toEqual(['a', 'b']);
|
||||||
|
expect(boxes[0].fill).toEqual('Aqua');
|
||||||
|
});
|
||||||
|
});
|
||||||
describe('when checking the bounds in a sequenceDiagram', function () {
|
describe('when checking the bounds in a sequenceDiagram', function () {
|
||||||
beforeAll(() => {
|
beforeAll(() => {
|
||||||
let conf = {
|
let conf = {
|
||||||
@@ -1573,6 +1649,24 @@ Alice->Bob: Hello Bob, how are you?`;
|
|||||||
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin);
|
||||||
expect(bounds.stopy).toBe(models.lastMessage().stopy + 10);
|
expect(bounds.stopy).toBe(models.lastMessage().stopy + 10);
|
||||||
});
|
});
|
||||||
|
it('should handle two actors in a box', function () {
|
||||||
|
const str = `
|
||||||
|
sequenceDiagram
|
||||||
|
box rgb(34, 56, 0) Group1
|
||||||
|
participant Alice
|
||||||
|
participant Bob
|
||||||
|
end
|
||||||
|
Alice->Bob: Hello Bob, how are you?`;
|
||||||
|
|
||||||
|
mermaidAPI.parse(str);
|
||||||
|
diagram.renderer.draw(str, 'tst', '1.2.3', diagram);
|
||||||
|
|
||||||
|
const { bounds, models } = diagram.renderer.bounds.getBounds();
|
||||||
|
expect(bounds.startx).toBe(0);
|
||||||
|
expect(bounds.starty).toBe(0);
|
||||||
|
expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin + conf.boxTextMargin * 2);
|
||||||
|
expect(bounds.stopy).toBe(models.lastMessage().stopy + 20);
|
||||||
|
});
|
||||||
it('should handle two actors with init directive', function () {
|
it('should handle two actors with init directive', function () {
|
||||||
const str = `
|
const str = `
|
||||||
%%{init: {'logLevel': 0}}%%
|
%%{init: {'logLevel': 0}}%%
|
||||||
|
|||||||
@@ -10,6 +10,7 @@ import assignWithDepth from '../../assignWithDepth';
|
|||||||
import utils from '../../utils';
|
import utils from '../../utils';
|
||||||
import { configureSvgSize } from '../../setupGraphViewbox';
|
import { configureSvgSize } from '../../setupGraphViewbox';
|
||||||
import Diagram from '../../Diagram';
|
import Diagram from '../../Diagram';
|
||||||
|
import { convert } from '../../tests/util';
|
||||||
|
|
||||||
let conf = {};
|
let conf = {};
|
||||||
|
|
||||||
@@ -43,10 +44,14 @@ export const bounds = {
|
|||||||
},
|
},
|
||||||
clear: function () {
|
clear: function () {
|
||||||
this.actors = [];
|
this.actors = [];
|
||||||
|
this.boxes = [];
|
||||||
this.loops = [];
|
this.loops = [];
|
||||||
this.messages = [];
|
this.messages = [];
|
||||||
this.notes = [];
|
this.notes = [];
|
||||||
},
|
},
|
||||||
|
addBox: function (boxModel) {
|
||||||
|
this.boxes.push(boxModel);
|
||||||
|
},
|
||||||
addActor: function (actorModel) {
|
addActor: function (actorModel) {
|
||||||
this.actors.push(actorModel);
|
this.actors.push(actorModel);
|
||||||
},
|
},
|
||||||
@@ -72,6 +77,7 @@ export const bounds = {
|
|||||||
return this.notes[this.notes.length - 1];
|
return this.notes[this.notes.length - 1];
|
||||||
},
|
},
|
||||||
actors: [],
|
actors: [],
|
||||||
|
boxes: [],
|
||||||
loops: [],
|
loops: [],
|
||||||
messages: [],
|
messages: [],
|
||||||
notes: [],
|
notes: [],
|
||||||
@@ -465,7 +471,8 @@ export const drawActors = function (
|
|||||||
actorKeys,
|
actorKeys,
|
||||||
verticalPos,
|
verticalPos,
|
||||||
configuration,
|
configuration,
|
||||||
messages
|
messages,
|
||||||
|
isFooter
|
||||||
) {
|
) {
|
||||||
if (configuration.hideUnusedParticipants === true) {
|
if (configuration.hideUnusedParticipants === true) {
|
||||||
const newActors = new Set();
|
const newActors = new Set();
|
||||||
@@ -480,8 +487,28 @@ export const drawActors = function (
|
|||||||
let prevWidth = 0;
|
let prevWidth = 0;
|
||||||
let prevMargin = 0;
|
let prevMargin = 0;
|
||||||
let maxHeight = 0;
|
let maxHeight = 0;
|
||||||
|
let prevBox = undefined;
|
||||||
|
|
||||||
for (const actorKey of actorKeys) {
|
for (const actorKey of actorKeys) {
|
||||||
const actor = actors[actorKey];
|
const actor = actors[actorKey];
|
||||||
|
const box = actor.box;
|
||||||
|
|
||||||
|
// end of box
|
||||||
|
if (prevBox && prevBox != box) {
|
||||||
|
if (!isFooter) {
|
||||||
|
bounds.models.addBox(prevBox);
|
||||||
|
}
|
||||||
|
prevMargin += conf.boxMargin + prevBox.margin;
|
||||||
|
}
|
||||||
|
|
||||||
|
// new box
|
||||||
|
if (box && box != prevBox) {
|
||||||
|
if (!isFooter) {
|
||||||
|
box.x = prevWidth + prevMargin;
|
||||||
|
box.y = verticalPos;
|
||||||
|
}
|
||||||
|
prevMargin += box.margin;
|
||||||
|
}
|
||||||
|
|
||||||
// Add some rendering data to the object
|
// Add some rendering data to the object
|
||||||
actor.width = actor.width || conf.width;
|
actor.width = actor.width || conf.width;
|
||||||
@@ -489,18 +516,27 @@ export const drawActors = function (
|
|||||||
actor.margin = actor.margin || conf.actorMargin;
|
actor.margin = actor.margin || conf.actorMargin;
|
||||||
|
|
||||||
actor.x = prevWidth + prevMargin;
|
actor.x = prevWidth + prevMargin;
|
||||||
actor.y = verticalPos;
|
actor.y = bounds.getVerticalPos();
|
||||||
|
|
||||||
// Draw the box with the attached line
|
// Draw the box with the attached line
|
||||||
const height = svgDraw.drawActor(diagram, actor, conf);
|
const height = svgDraw.drawActor(diagram, actor, conf, isFooter);
|
||||||
maxHeight = Math.max(maxHeight, height);
|
maxHeight = Math.max(maxHeight, height);
|
||||||
bounds.insert(actor.x, verticalPos, actor.x + actor.width, actor.height);
|
bounds.insert(actor.x, verticalPos, actor.x + actor.width, actor.height);
|
||||||
|
|
||||||
prevWidth += actor.width;
|
prevWidth += actor.width + prevMargin;
|
||||||
prevMargin += actor.margin;
|
if (actor.box) {
|
||||||
|
actor.box.width = prevWidth + box.margin - actor.box.x;
|
||||||
|
}
|
||||||
|
prevMargin = actor.margin;
|
||||||
|
prevBox = actor.box;
|
||||||
bounds.models.addActor(actor);
|
bounds.models.addActor(actor);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// end of box
|
||||||
|
if (prevBox && !isFooter) {
|
||||||
|
bounds.models.addBox(prevBox);
|
||||||
|
}
|
||||||
|
|
||||||
// Add a margin between the actor boxes and the first arrow
|
// Add a margin between the actor boxes and the first arrow
|
||||||
bounds.bumpVerticalPos(maxHeight);
|
bounds.bumpVerticalPos(maxHeight);
|
||||||
};
|
};
|
||||||
@@ -614,18 +650,27 @@ export const draw = function (_text: string, id: string, _version: string, diagO
|
|||||||
|
|
||||||
// Fetch data from the parsing
|
// Fetch data from the parsing
|
||||||
const actors = diagObj.db.getActors();
|
const actors = diagObj.db.getActors();
|
||||||
|
const boxes = diagObj.db.getBoxes();
|
||||||
const actorKeys = diagObj.db.getActorKeys();
|
const actorKeys = diagObj.db.getActorKeys();
|
||||||
const messages = diagObj.db.getMessages();
|
const messages = diagObj.db.getMessages();
|
||||||
const title = diagObj.db.getDiagramTitle();
|
const title = diagObj.db.getDiagramTitle();
|
||||||
|
const hasBoxes = diagObj.db.hasAtLeastOneBox();
|
||||||
|
const hasBoxTitles = diagObj.db.hasAtLeastOneBoxWithTitle();
|
||||||
const maxMessageWidthPerActor = getMaxMessageWidthPerActor(actors, messages, diagObj);
|
const maxMessageWidthPerActor = getMaxMessageWidthPerActor(actors, messages, diagObj);
|
||||||
conf.height = calculateActorMargins(actors, maxMessageWidthPerActor);
|
conf.height = calculateActorMargins(actors, maxMessageWidthPerActor, boxes);
|
||||||
|
|
||||||
svgDraw.insertComputerIcon(diagram);
|
svgDraw.insertComputerIcon(diagram);
|
||||||
svgDraw.insertDatabaseIcon(diagram);
|
svgDraw.insertDatabaseIcon(diagram);
|
||||||
svgDraw.insertClockIcon(diagram);
|
svgDraw.insertClockIcon(diagram);
|
||||||
|
|
||||||
drawActors(diagram, actors, actorKeys, 0, conf, messages);
|
if (hasBoxes) {
|
||||||
|
bounds.bumpVerticalPos(conf.boxMargin);
|
||||||
|
if (hasBoxTitles) {
|
||||||
|
bounds.bumpVerticalPos(boxes[0].textMaxHeight);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drawActors(diagram, actors, actorKeys, 0, conf, messages, false);
|
||||||
const loopWidths = calculateLoopBounds(messages, actors, maxMessageWidthPerActor, diagObj);
|
const loopWidths = calculateLoopBounds(messages, actors, maxMessageWidthPerActor, diagObj);
|
||||||
|
|
||||||
// The arrow head definition is attached to the svg once
|
// The arrow head definition is attached to the svg once
|
||||||
@@ -847,11 +892,26 @@ export const draw = function (_text: string, id: string, _version: string, diagO
|
|||||||
if (conf.mirrorActors) {
|
if (conf.mirrorActors) {
|
||||||
// Draw actors below diagram
|
// Draw actors below diagram
|
||||||
bounds.bumpVerticalPos(conf.boxMargin * 2);
|
bounds.bumpVerticalPos(conf.boxMargin * 2);
|
||||||
drawActors(diagram, actors, actorKeys, bounds.getVerticalPos(), conf, messages);
|
drawActors(diagram, actors, actorKeys, bounds.getVerticalPos(), conf, messages, true);
|
||||||
bounds.bumpVerticalPos(conf.boxMargin);
|
bounds.bumpVerticalPos(conf.boxMargin);
|
||||||
fixLifeLineHeights(diagram, bounds.getVerticalPos());
|
fixLifeLineHeights(diagram, bounds.getVerticalPos());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bounds.models.boxes.forEach(function (box) {
|
||||||
|
box.height = bounds.getVerticalPos() - box.y;
|
||||||
|
bounds.insert(box.x, box.y, box.x + box.width, box.height);
|
||||||
|
box.startx = box.x;
|
||||||
|
box.starty = box.y;
|
||||||
|
box.stopx = box.startx + box.width;
|
||||||
|
box.stopy = box.starty + box.height;
|
||||||
|
box.stroke = 'rgb(0,0,0, 0.5)';
|
||||||
|
svgDraw.drawBox(diagram, box, conf);
|
||||||
|
});
|
||||||
|
|
||||||
|
if (hasBoxes) {
|
||||||
|
bounds.bumpVerticalPos(conf.boxMargin);
|
||||||
|
}
|
||||||
|
|
||||||
// only draw popups for the top row of actors.
|
// only draw popups for the top row of actors.
|
||||||
const requiredBoxSize = drawActorsPopup(diagram, actors, actorKeys, doc);
|
const requiredBoxSize = drawActorsPopup(diagram, actors, actorKeys, doc);
|
||||||
|
|
||||||
@@ -1039,10 +1099,12 @@ const getRequiredPopupWidth = function (actor) {
|
|||||||
*
|
*
|
||||||
* @param actors - The actors map to calculate margins for
|
* @param actors - The actors map to calculate margins for
|
||||||
* @param actorToMessageWidth - A map of actor key → max message width it holds
|
* @param actorToMessageWidth - A map of actor key → max message width it holds
|
||||||
|
* @param boxes - The boxes around the actors if any
|
||||||
*/
|
*/
|
||||||
function calculateActorMargins(
|
function calculateActorMargins(
|
||||||
actors: { [id: string]: any },
|
actors: { [id: string]: any },
|
||||||
actorToMessageWidth: ReturnType<typeof getMaxMessageWidthPerActor>
|
actorToMessageWidth: ReturnType<typeof getMaxMessageWidthPerActor>,
|
||||||
|
boxes
|
||||||
) {
|
) {
|
||||||
let maxHeight = 0;
|
let maxHeight = 0;
|
||||||
Object.keys(actors).forEach((prop) => {
|
Object.keys(actors).forEach((prop) => {
|
||||||
@@ -1074,6 +1136,9 @@ function calculateActorMargins(
|
|||||||
|
|
||||||
// No need to space out an actor that doesn't have a next link
|
// No need to space out an actor that doesn't have a next link
|
||||||
if (!nextActor) {
|
if (!nextActor) {
|
||||||
|
const messageWidth = actorToMessageWidth[actorKey];
|
||||||
|
const actorWidth = messageWidth + conf.actorMargin - actor.width / 2;
|
||||||
|
actor.margin = Math.max(actorWidth, conf.actorMargin);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1083,6 +1148,29 @@ function calculateActorMargins(
|
|||||||
actor.margin = Math.max(actorWidth, conf.actorMargin);
|
actor.margin = Math.max(actorWidth, conf.actorMargin);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let maxBoxHeight = 0;
|
||||||
|
boxes.forEach((box) => {
|
||||||
|
const textFont = messageFont(conf);
|
||||||
|
let totalWidth = box.actorKeys.reduce((total, aKey) => {
|
||||||
|
return (total += actors[aKey].width + (actors[aKey].margin || 0));
|
||||||
|
}, 0);
|
||||||
|
|
||||||
|
totalWidth -= 2 * conf.boxTextMargin;
|
||||||
|
if (box.wrap) {
|
||||||
|
box.name = utils.wrapLabel(box.name, totalWidth - 2 * conf.wrapPadding, textFont);
|
||||||
|
}
|
||||||
|
|
||||||
|
const boxMsgDimensions = utils.calculateTextDimensions(box.name, textFont);
|
||||||
|
maxBoxHeight = Math.max(boxMsgDimensions.height, maxBoxHeight);
|
||||||
|
const minWidth = Math.max(totalWidth, boxMsgDimensions.width + 2 * conf.wrapPadding);
|
||||||
|
box.margin = conf.boxTextMargin;
|
||||||
|
if (totalWidth < minWidth) {
|
||||||
|
const missing = (minWidth - totalWidth) / 2;
|
||||||
|
box.margin += missing;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
boxes.forEach((box) => (box.textMaxHeight = maxBoxHeight));
|
||||||
|
|
||||||
return Math.max(maxHeight, conf.height);
|
return Math.max(maxHeight, conf.height);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -341,19 +341,21 @@ export const fixLifeLineHeights = (diagram, bounds) => {
|
|||||||
* @param {any} elem - The diagram we'll draw to.
|
* @param {any} elem - The diagram we'll draw to.
|
||||||
* @param {any} actor - The actor to draw.
|
* @param {any} actor - The actor to draw.
|
||||||
* @param {any} conf - DrawText implementation discriminator object
|
* @param {any} conf - DrawText implementation discriminator object
|
||||||
|
* @param {boolean} isFooter - If the actor is the footer one
|
||||||
*/
|
*/
|
||||||
const drawActorTypeParticipant = function (elem, actor, conf) {
|
const drawActorTypeParticipant = function (elem, actor, conf, isFooter) {
|
||||||
const center = actor.x + actor.width / 2;
|
const center = actor.x + actor.width / 2;
|
||||||
|
const centerY = actor.y + 5;
|
||||||
|
|
||||||
const boxpluslineGroup = elem.append('g');
|
const boxpluslineGroup = elem.append('g');
|
||||||
var g = boxpluslineGroup;
|
var g = boxpluslineGroup;
|
||||||
|
|
||||||
if (actor.y === 0) {
|
if (!isFooter) {
|
||||||
actorCnt++;
|
actorCnt++;
|
||||||
g.append('line')
|
g.append('line')
|
||||||
.attr('id', 'actor' + actorCnt)
|
.attr('id', 'actor' + actorCnt)
|
||||||
.attr('x1', center)
|
.attr('x1', center)
|
||||||
.attr('y1', 5)
|
.attr('y1', centerY)
|
||||||
.attr('x2', center)
|
.attr('x2', center)
|
||||||
.attr('y2', 2000)
|
.attr('y2', 2000)
|
||||||
.attr('class', 'actor-line')
|
.attr('class', 'actor-line')
|
||||||
@@ -416,16 +418,17 @@ const drawActorTypeParticipant = function (elem, actor, conf) {
|
|||||||
return height;
|
return height;
|
||||||
};
|
};
|
||||||
|
|
||||||
const drawActorTypeActor = function (elem, actor, conf) {
|
const drawActorTypeActor = function (elem, actor, conf, isFooter) {
|
||||||
const center = actor.x + actor.width / 2;
|
const center = actor.x + actor.width / 2;
|
||||||
|
const centerY = actor.y + 80;
|
||||||
|
|
||||||
if (actor.y === 0) {
|
if (!isFooter) {
|
||||||
actorCnt++;
|
actorCnt++;
|
||||||
elem
|
elem
|
||||||
.append('line')
|
.append('line')
|
||||||
.attr('id', 'actor' + actorCnt)
|
.attr('id', 'actor' + actorCnt)
|
||||||
.attr('x1', center)
|
.attr('x1', center)
|
||||||
.attr('y1', 80)
|
.attr('y1', centerY)
|
||||||
.attr('x2', center)
|
.attr('x2', center)
|
||||||
.attr('y2', 2000)
|
.attr('y2', 2000)
|
||||||
.attr('class', 'actor-line')
|
.attr('class', 'actor-line')
|
||||||
@@ -498,15 +501,34 @@ const drawActorTypeActor = function (elem, actor, conf) {
|
|||||||
return actor.height;
|
return actor.height;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const drawActor = function (elem, actor, conf) {
|
export const drawActor = function (elem, actor, conf, isFooter) {
|
||||||
switch (actor.type) {
|
switch (actor.type) {
|
||||||
case 'actor':
|
case 'actor':
|
||||||
return drawActorTypeActor(elem, actor, conf);
|
return drawActorTypeActor(elem, actor, conf, isFooter);
|
||||||
case 'participant':
|
case 'participant':
|
||||||
return drawActorTypeParticipant(elem, actor, conf);
|
return drawActorTypeParticipant(elem, actor, conf, isFooter);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const drawBox = function (elem, box, conf) {
|
||||||
|
const boxplustextGroup = elem.append('g');
|
||||||
|
const g = boxplustextGroup;
|
||||||
|
drawBackgroundRect(g, box);
|
||||||
|
if (box.name) {
|
||||||
|
_drawTextCandidateFunc(conf)(
|
||||||
|
box.name,
|
||||||
|
g,
|
||||||
|
box.x,
|
||||||
|
box.y + (box.textMaxHeight || 0) / 2,
|
||||||
|
box.width,
|
||||||
|
0,
|
||||||
|
{ class: 'text' },
|
||||||
|
conf
|
||||||
|
);
|
||||||
|
}
|
||||||
|
g.lower();
|
||||||
|
};
|
||||||
|
|
||||||
export const anchorElement = function (elem) {
|
export const anchorElement = function (elem) {
|
||||||
return elem.append('g');
|
return elem.append('g');
|
||||||
};
|
};
|
||||||
@@ -645,6 +667,7 @@ export const drawBackgroundRect = function (elem, bounds) {
|
|||||||
width: bounds.stopx - bounds.startx,
|
width: bounds.stopx - bounds.startx,
|
||||||
height: bounds.stopy - bounds.starty,
|
height: bounds.stopy - bounds.starty,
|
||||||
fill: bounds.fill,
|
fill: bounds.fill,
|
||||||
|
stroke: bounds.stroke,
|
||||||
class: 'rect',
|
class: 'rect',
|
||||||
});
|
});
|
||||||
rectElem.lower();
|
rectElem.lower();
|
||||||
@@ -1037,6 +1060,7 @@ export default {
|
|||||||
drawText,
|
drawText,
|
||||||
drawLabel,
|
drawLabel,
|
||||||
drawActor,
|
drawActor,
|
||||||
|
drawBox,
|
||||||
drawPopup,
|
drawPopup,
|
||||||
drawImage,
|
drawImage,
|
||||||
drawEmbeddedImage,
|
drawEmbeddedImage,
|
||||||
|
|||||||
133
packages/mermaid/src/diagrams/state/parser/state-parser.spec.js
Normal file
133
packages/mermaid/src/diagrams/state/parser/state-parser.spec.js
Normal file
@@ -0,0 +1,133 @@
|
|||||||
|
import stateDb from '../stateDb';
|
||||||
|
import stateDiagram from './stateDiagram';
|
||||||
|
import { setConfig } from '../../../config';
|
||||||
|
|
||||||
|
setConfig({
|
||||||
|
securityLevel: 'strict',
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('state parser can parse...', () => {
|
||||||
|
beforeEach(function () {
|
||||||
|
stateDiagram.parser.yy = stateDb;
|
||||||
|
stateDiagram.parser.yy.clear();
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('states with id displayed as a (name)', () => {
|
||||||
|
describe('syntax 1: stateID as "name in quotes"', () => {
|
||||||
|
it('stateID as "some name"', () => {
|
||||||
|
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['namedState1']).not.toBeUndefined();
|
||||||
|
expect(states['namedState1'].descriptions.join(' ')).toEqual('Small State 1');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('syntax 2: stateID: "name in quotes" [colon after the id]', () => {
|
||||||
|
it('space before and after the colon', () => {
|
||||||
|
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['namedState1']).not.toBeUndefined();
|
||||||
|
expect(states['namedState1'].descriptions.join(' ')).toEqual('Small State 1');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('no spaces before and after the colon', () => {
|
||||||
|
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['namedState1']).not.toBeUndefined();
|
||||||
|
expect(states['namedState1'].descriptions.join(' ')).toEqual('Small State 1');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('can handle "as" in a state name', () => {
|
||||||
|
it('assemble, assemblies, state assemble, state assemblies', function () {
|
||||||
|
const diagramText = `stateDiagram-v2
|
||||||
|
assemble
|
||||||
|
assemblies
|
||||||
|
state assemble
|
||||||
|
state assemblies
|
||||||
|
`;
|
||||||
|
stateDiagram.parser.parse(diagramText);
|
||||||
|
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||||
|
const states = stateDiagram.parser.yy.getStates();
|
||||||
|
expect(states['assemble']).not.toBeUndefined();
|
||||||
|
expect(states['assemblies']).not.toBeUndefined();
|
||||||
|
});
|
||||||
|
|
||||||
|
it('state "as" as as', function () {
|
||||||
|
const diagramText = `stateDiagram-v2
|
||||||
|
state "as" as as
|
||||||
|
`;
|
||||||
|
stateDiagram.parser.parse(diagramText);
|
||||||
|
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||||
|
const states = stateDiagram.parser.yy.getStates();
|
||||||
|
expect(states['as']).not.toBeUndefined();
|
||||||
|
expect(states['as'].descriptions.join(' ')).toEqual('as');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('groups (clusters/containers)', () => {
|
||||||
|
it('state "Group Name" as stateIdentifier', () => {
|
||||||
|
const diagramText = `stateDiagram-v2
|
||||||
|
state "Small State 1" as namedState1
|
||||||
|
%% Notice that this is named "Big State 1" with an "as"
|
||||||
|
state "Big State 1" as bigState1 {
|
||||||
|
bigState1InternalState
|
||||||
|
}
|
||||||
|
namedState1 --> bigState1: should point to \\nBig State 1 container
|
||||||
|
|
||||||
|
state "Small State 2" as namedState2
|
||||||
|
%% Notice that bigState2 does not have a name; no "as"
|
||||||
|
state bigState2 {
|
||||||
|
bigState2InternalState
|
||||||
|
}
|
||||||
|
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['namedState1']).not.toBeUndefined();
|
||||||
|
expect(states['bigState1']).not.toBeUndefined();
|
||||||
|
expect(states['bigState1'].doc[0].id).toEqual('bigState1InternalState');
|
||||||
|
expect(states['namedState2']).not.toBeUndefined();
|
||||||
|
expect(states['bigState2']).not.toBeUndefined();
|
||||||
|
expect(states['bigState2'].doc[0].id).toEqual('bigState2InternalState');
|
||||||
|
const relationships = stateDiagram.parser.yy.getRelations();
|
||||||
|
expect(relationships[0].id1).toEqual('namedState1');
|
||||||
|
expect(relationships[0].id2).toEqual('bigState1');
|
||||||
|
expect(relationships[1].id1).toEqual('namedState2');
|
||||||
|
expect(relationships[1].id2).toEqual('bigState2');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('group has a state with stateID AS "state name" and state2ID: "another state name"', () => {
|
||||||
|
const diagramText = `stateDiagram-v2
|
||||||
|
state "Big State 1" as bigState1 {
|
||||||
|
state "inner state 1" as inner1
|
||||||
|
inner2: inner state 2
|
||||||
|
inner1 --> inner2
|
||||||
|
}`;
|
||||||
|
stateDiagram.parser.parse(diagramText);
|
||||||
|
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||||
|
|
||||||
|
const states = stateDiagram.parser.yy.getStates();
|
||||||
|
expect(states['bigState1']).not.toBeUndefined();
|
||||||
|
expect(states['bigState1'].doc[0].id).toEqual('inner1');
|
||||||
|
expect(states['bigState1'].doc[0].description).toEqual('inner state 1');
|
||||||
|
expect(states['bigState1'].doc[1].id).toEqual('inner2');
|
||||||
|
expect(states['bigState1'].doc[1].description).toEqual('inner state 2');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -65,14 +65,14 @@
|
|||||||
\%%[^\n]* /* skip comments */
|
\%%[^\n]* /* skip comments */
|
||||||
"scale"\s+ { this.pushState('SCALE'); /* console.log('Got scale', yytext);*/ return 'scale'; }
|
"scale"\s+ { this.pushState('SCALE'); /* console.log('Got scale', yytext);*/ return 'scale'; }
|
||||||
<SCALE>\d+ return 'WIDTH';
|
<SCALE>\d+ return 'WIDTH';
|
||||||
<SCALE>\s+"width" {this.popState();}
|
<SCALE>\s+"width" { this.popState(); }
|
||||||
|
|
||||||
accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; }
|
accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; }
|
||||||
<acc_title>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; }
|
<acc_title>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; }
|
||||||
accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; }
|
accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; }
|
||||||
<acc_descr>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; }
|
<acc_descr>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; }
|
||||||
accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
|
accDescr\s*"{"\s* { this.begin("acc_descr_multiline"); }
|
||||||
<acc_descr_multiline>[\}] { this.popState(); }
|
<acc_descr_multiline>[\}] { this.popState(); }
|
||||||
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
|
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
|
||||||
|
|
||||||
<INITIAL,struct>"classDef"\s+ { this.pushState('CLASSDEF'); return 'classDef'; }
|
<INITIAL,struct>"classDef"\s+ { this.pushState('CLASSDEF'); return 'classDef'; }
|
||||||
@@ -81,57 +81,60 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
|
|||||||
<CLASSDEFID>[^\n]* { this.popState(); return 'CLASSDEF_STYLEOPTS' }
|
<CLASSDEFID>[^\n]* { this.popState(); return 'CLASSDEF_STYLEOPTS' }
|
||||||
|
|
||||||
<INITIAL,struct>"class"\s+ { this.pushState('CLASS'); return 'class'; }
|
<INITIAL,struct>"class"\s+ { this.pushState('CLASS'); return 'class'; }
|
||||||
<CLASS>(\w+)+((","\s*\w+)*) { this.popState(); this.pushState('CLASS_STYLE'); return 'CLASSENTITY_IDS' }
|
<CLASS>(\w+)+((","\s*\w+)*) { this.popState(); this.pushState('CLASS_STYLE'); return 'CLASSENTITY_IDS' }
|
||||||
<CLASS_STYLE>[^\n]* { this.popState(); return 'STYLECLASS' }
|
<CLASS_STYLE>[^\n]* { this.popState(); return 'STYLECLASS' }
|
||||||
|
|
||||||
"scale"\s+ { this.pushState('SCALE'); /* console.log('Got scale', yytext);*/ return 'scale'; }
|
"scale"\s+ { this.pushState('SCALE'); /* console.log('Got scale', yytext);*/ return 'scale'; }
|
||||||
<SCALE>\d+ return 'WIDTH';
|
<SCALE>\d+ return 'WIDTH';
|
||||||
<SCALE>\s+"width" {this.popState();}
|
<SCALE>\s+"width" {this.popState();}
|
||||||
|
|
||||||
|
<INITIAL,struct>"state"\s+ { /* console.log('Starting STATE '); */ this.pushState('STATE'); }
|
||||||
|
|
||||||
<INITIAL,struct>"state"\s+ { /*console.log('Starting STATE zxzx'+yy.getDirection());*/this.pushState('STATE'); }
|
|
||||||
<STATE>.*"<<fork>>" {this.popState();yytext=yytext.slice(0,-8).trim(); /*console.warn('Fork Fork: ',yytext);*/return 'FORK';}
|
<STATE>.*"<<fork>>" {this.popState();yytext=yytext.slice(0,-8).trim(); /*console.warn('Fork Fork: ',yytext);*/return 'FORK';}
|
||||||
<STATE>.*"<<join>>" {this.popState();yytext=yytext.slice(0,-8).trim();/*console.warn('Fork Join: ',yytext);*/return 'JOIN';}
|
<STATE>.*"<<join>>" {this.popState();yytext=yytext.slice(0,-8).trim();/*console.warn('Fork Join: ',yytext);*/return 'JOIN';}
|
||||||
<STATE>.*"<<choice>>" {this.popState();yytext=yytext.slice(0,-10).trim();/*console.warn('Fork Join: ',yytext);*/return 'CHOICE';}
|
<STATE>.*"<<choice>>" {this.popState();yytext=yytext.slice(0,-10).trim();/*console.warn('Fork Join: ',yytext);*/return 'CHOICE';}
|
||||||
<STATE>.*"[[fork]]" {this.popState();yytext=yytext.slice(0,-8).trim();/*console.warn('Fork Fork: ',yytext);*/return 'FORK';}
|
<STATE>.*"[[fork]]" {this.popState();yytext=yytext.slice(0,-8).trim();/*console.warn('Fork Fork: ',yytext);*/return 'FORK';}
|
||||||
<STATE>.*"[[join]]" {this.popState();yytext=yytext.slice(0,-8).trim();/*console.warn('Fork Join: ',yytext);*/return 'JOIN';}
|
<STATE>.*"[[join]]" {this.popState();yytext=yytext.slice(0,-8).trim();/*console.warn('Fork Join: ',yytext);*/return 'JOIN';}
|
||||||
<STATE>.*"[[choice]]" {this.popState();yytext=yytext.slice(0,-10).trim();/*console.warn('Fork Join: ',yytext);*/return 'CHOICE';}
|
<STATE>.*"[[choice]]" {this.popState();yytext=yytext.slice(0,-10).trim();/*console.warn('Fork Join: ',yytext);*/return 'CHOICE';}
|
||||||
|
|
||||||
<struct>.*direction\s+TB[^\n]* { return 'direction_tb';}
|
<struct>.*direction\s+TB[^\n]* { return 'direction_tb';}
|
||||||
<struct>.*direction\s+BT[^\n]* { return 'direction_bt';}
|
<struct>.*direction\s+BT[^\n]* { return 'direction_bt';}
|
||||||
<struct>.*direction\s+RL[^\n]* { return 'direction_rl';}
|
<struct>.*direction\s+RL[^\n]* { return 'direction_rl';}
|
||||||
<struct>.*direction\s+LR[^\n]* { return 'direction_lr';}
|
<struct>.*direction\s+LR[^\n]* { return 'direction_lr';}
|
||||||
|
|
||||||
<STATE>["] { /*console.log('Starting STATE_STRING zxzx');*/this.begin("STATE_STRING");}
|
<STATE>["] { /* console.log('Starting STATE_STRING'); */ this.pushState("STATE_STRING"); }
|
||||||
<STATE>\s*"as"\s+ {this.popState();this.pushState('STATE_ID');return "AS";}
|
<STATE>\s*"as"\s+ { this.pushState('STATE_ID'); /* console.log('pushState(STATE_ID)'); */ return "AS"; }
|
||||||
<STATE_ID>[^\n\{]* {this.popState();/* console.log('STATE_ID', yytext);*/return "ID";}
|
<STATE_ID>[^\n\{]* { this.popState(); /* console.log('STATE_ID', yytext); */ return "ID"; }
|
||||||
<STATE_STRING>["] this.popState();
|
<STATE_STRING>["] { this.popState(); }
|
||||||
<STATE_STRING>[^"]* { /*console.log('Long description:', yytext);*/return "STATE_DESCR";}
|
<STATE_STRING>[^"]* { /* console.log('Long description:', yytext); */ return "STATE_DESCR"; }
|
||||||
<STATE>[^\n\s\{]+ {/*console.log('COMPOSIT_STATE', yytext);*/return 'COMPOSIT_STATE';}
|
<STATE>[^\n\s\{]+ { /* console.log('COMPOSIT_STATE', yytext); */ return 'COMPOSIT_STATE'; }
|
||||||
<STATE>\n {this.popState();}
|
<STATE>\n { this.popState(); }
|
||||||
<INITIAL,STATE>\{ {this.popState();this.pushState('struct'); /*console.log('begin struct', yytext);*/return 'STRUCT_START';}
|
<INITIAL,STATE>\{ { this.popState(); this.pushState('struct'); /* console.log('begin struct', yytext); */ return 'STRUCT_START'; }
|
||||||
<struct>\%\%(?!\{)[^\n]* /* skip comments inside state*/
|
<struct>\%\%(?!\{)[^\n]* /* skip comments inside state*/
|
||||||
<struct>\} { /*console.log('Ending struct');*/ this.popState(); return 'STRUCT_STOP';}}
|
<struct>\} { /*console.log('Ending struct');*/ this.popState(); return 'STRUCT_STOP';} }
|
||||||
<struct>[\n] /* nothing */
|
<struct>[\n] /* nothing */
|
||||||
|
|
||||||
<INITIAL,struct>"note"\s+ { this.begin('NOTE'); return 'note'; }
|
<INITIAL,struct>"note"\s+ { this.begin('NOTE'); return 'note'; }
|
||||||
<NOTE>"left of" { this.popState();this.pushState('NOTE_ID');return 'left_of';}
|
<NOTE>"left of" { this.popState(); this.pushState('NOTE_ID'); return 'left_of'; }
|
||||||
<NOTE>"right of" { this.popState();this.pushState('NOTE_ID');return 'right_of';}
|
<NOTE>"right of" { this.popState(); this.pushState('NOTE_ID'); return 'right_of'; }
|
||||||
<NOTE>\" { this.popState();this.pushState('FLOATING_NOTE');}
|
<NOTE>\" { this.popState(); this.pushState('FLOATING_NOTE'); }
|
||||||
<FLOATING_NOTE>\s*"as"\s* {this.popState();this.pushState('FLOATING_NOTE_ID');return "AS";}
|
<FLOATING_NOTE>\s*"as"\s* { this.popState(); this.pushState('FLOATING_NOTE_ID'); return "AS"; }
|
||||||
<FLOATING_NOTE>["] /**/
|
<FLOATING_NOTE>["] /**/
|
||||||
<FLOATING_NOTE>[^"]* { /*console.log('Floating note text: ', yytext);*/return "NOTE_TEXT";}
|
<FLOATING_NOTE>[^"]* { /* console.log('Floating note text: ', yytext); */ return "NOTE_TEXT"; }
|
||||||
<FLOATING_NOTE_ID>[^\n]* {this.popState();/*console.log('Floating note ID', yytext);*/return "ID";}
|
<FLOATING_NOTE_ID>[^\n]* { this.popState(); /* console.log('Floating note ID', yytext);*/ return "ID"; }
|
||||||
<NOTE_ID>\s*[^:\n\s\-]+ { this.popState();this.pushState('NOTE_TEXT');/*console.log('Got ID for note', yytext);*/return 'ID';}
|
<NOTE_ID>\s*[^:\n\s\-]+ { this.popState(); this.pushState('NOTE_TEXT'); /*console.log('Got ID for note', yytext);*/ return 'ID'; }
|
||||||
<NOTE_TEXT>\s*":"[^:\n;]+ { this.popState();/*console.log('Got NOTE_TEXT for note',yytext);*/yytext = yytext.substr(2).trim();return 'NOTE_TEXT';}
|
<NOTE_TEXT>\s*":"[^:\n;]+ { this.popState(); /* console.log('Got NOTE_TEXT for note',yytext);*/yytext = yytext.substr(2).trim(); return 'NOTE_TEXT'; }
|
||||||
<NOTE_TEXT>[\s\S]*?"end note" { this.popState();/*console.log('Got NOTE_TEXT for note',yytext);*/yytext = yytext.slice(0,-8).trim();return 'NOTE_TEXT';}
|
<NOTE_TEXT>[\s\S]*?"end note" { this.popState(); /* console.log('Got NOTE_TEXT for note',yytext);*/yytext = yytext.slice(0,-8).trim(); return 'NOTE_TEXT'; }
|
||||||
|
|
||||||
"stateDiagram"\s+ { /*console.log('Got state diagram', yytext,'#');*/return 'SD'; }
|
"stateDiagram"\s+ { /* console.log('Got state diagram', yytext,'#'); */ return 'SD'; }
|
||||||
"stateDiagram-v2"\s+ { /*console.log('Got state diagram', yytext,'#');*/return 'SD'; }
|
"stateDiagram-v2"\s+ { /* console.log('Got state diagram', yytext,'#'); */ return 'SD'; }
|
||||||
"hide empty description" { /*console.log('HIDE_EMPTY', yytext,'#');*/return 'HIDE_EMPTY'; }
|
|
||||||
<INITIAL,struct>"[*]" { /*console.log('EDGE_STATE=',yytext);*/ return 'EDGE_STATE';}
|
"hide empty description" { /* console.log('HIDE_EMPTY', yytext,'#'); */ return 'HIDE_EMPTY'; }
|
||||||
<INITIAL,struct>[^:\n\s\-\{]+ { /*console.log('=>ID=',yytext);*/ return 'ID';}
|
|
||||||
// <INITIAL,struct>\s*":"[^\+\->:\n;]+ { yytext = yytext.trim(); /*console.log('Descr = ', yytext);*/ return 'DESCR'; }
|
<INITIAL,struct>"[*]" { /* console.log('EDGE_STATE=',yytext); */ return 'EDGE_STATE'; }
|
||||||
<INITIAL,struct>\s*":"[^:\n;]+ { yytext = yytext.trim(); /*console.log('Descr = ', yytext);*/ return 'DESCR'; }
|
<INITIAL,struct>[^:\n\s\-\{]+ { /* console.log('=>ID=',yytext); */ return 'ID'; }
|
||||||
|
// <INITIAL,struct>\s*":"[^\+\->:\n;]+ { yytext = yytext.trim(); /* console.log('Descr = ', yytext); */ return 'DESCR'; }
|
||||||
|
<INITIAL,struct>\s*":"[^:\n;]+ { yytext = yytext.trim(); /* console.log('Descr = ', yytext); */ return 'DESCR'; }
|
||||||
|
|
||||||
<INITIAL,struct>"-->" return '-->';
|
<INITIAL,struct>"-->" return '-->';
|
||||||
<struct>"--" return 'CONCURRENT';
|
<struct>"--" return 'CONCURRENT';
|
||||||
@@ -201,7 +204,7 @@ statement
|
|||||||
| COMPOSIT_STATE
|
| COMPOSIT_STATE
|
||||||
| COMPOSIT_STATE STRUCT_START document STRUCT_STOP
|
| COMPOSIT_STATE STRUCT_START document STRUCT_STOP
|
||||||
{
|
{
|
||||||
/* console.log('Adding document for state without id ', $1); */
|
// console.log('Adding document for state without id ', $1);
|
||||||
$$={ stmt: 'state', id: $1, type: 'default', description: '', doc: $3 }
|
$$={ stmt: 'state', id: $1, type: 'default', description: '', doc: $3 }
|
||||||
}
|
}
|
||||||
| STATE_DESCR AS ID {
|
| STATE_DESCR AS ID {
|
||||||
@@ -217,7 +220,7 @@ statement
|
|||||||
}
|
}
|
||||||
| STATE_DESCR AS ID STRUCT_START document STRUCT_STOP
|
| STATE_DESCR AS ID STRUCT_START document STRUCT_STOP
|
||||||
{
|
{
|
||||||
/* console.log('Adding document for state with id zxzx', $3, $4, yy.getDirection()); yy.addDocument($3);*/
|
// console.log('state with id ', $3,' document = ', $5, );
|
||||||
$$={ stmt: 'state', id: $3, type: 'default', description: $1, doc: $5 }
|
$$={ stmt: 'state', id: $3, type: 'default', description: $1, doc: $5 }
|
||||||
}
|
}
|
||||||
| FORK {
|
| FORK {
|
||||||
|
|||||||
@@ -94,9 +94,14 @@ const docTranslator = (parent, node, first) => {
|
|||||||
docTranslator(parent, node.state1, true);
|
docTranslator(parent, node.state1, true);
|
||||||
docTranslator(parent, node.state2, false);
|
docTranslator(parent, node.state2, false);
|
||||||
} else {
|
} else {
|
||||||
if (node.stmt === STMT_STATE && node.id === '[*]') {
|
if (node.stmt === STMT_STATE) {
|
||||||
node.id = first ? parent.id + '_start' : parent.id + '_end';
|
if (node.id === '[*]') {
|
||||||
node.start = first;
|
node.id = first ? parent.id + '_start' : parent.id + '_end';
|
||||||
|
node.start = first;
|
||||||
|
} else {
|
||||||
|
// This is just a plain state, not a start or end
|
||||||
|
node.id = node.id.trim();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.doc) {
|
if (node.doc) {
|
||||||
@@ -170,7 +175,7 @@ const extract = (_doc) => {
|
|||||||
switch (item.stmt) {
|
switch (item.stmt) {
|
||||||
case STMT_STATE:
|
case STMT_STATE:
|
||||||
addState(
|
addState(
|
||||||
item.id,
|
item.id.trim(),
|
||||||
item.type,
|
item.type,
|
||||||
item.doc,
|
item.doc,
|
||||||
item.description,
|
item.description,
|
||||||
@@ -184,10 +189,10 @@ const extract = (_doc) => {
|
|||||||
addRelation(item.state1, item.state2, item.description);
|
addRelation(item.state1, item.state2, item.description);
|
||||||
break;
|
break;
|
||||||
case STMT_CLASSDEF:
|
case STMT_CLASSDEF:
|
||||||
addStyleClass(item.id, item.classes);
|
addStyleClass(item.id.trim(), item.classes);
|
||||||
break;
|
break;
|
||||||
case STMT_APPLYCLASS:
|
case STMT_APPLYCLASS:
|
||||||
setCssClass(item.id, item.styleClass);
|
setCssClass(item.id.trim(), item.styleClass);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -215,11 +220,12 @@ export const addState = function (
|
|||||||
styles = null,
|
styles = null,
|
||||||
textStyles = null
|
textStyles = null
|
||||||
) {
|
) {
|
||||||
|
const trimmedId = id?.trim();
|
||||||
// add the state if needed
|
// add the state if needed
|
||||||
if (currentDocument.states[id] === undefined) {
|
if (currentDocument.states[trimmedId] === undefined) {
|
||||||
log.info('Adding state ', id, descr);
|
log.info('Adding state ', trimmedId, descr);
|
||||||
currentDocument.states[id] = {
|
currentDocument.states[trimmedId] = {
|
||||||
id: id,
|
id: trimmedId,
|
||||||
descriptions: [],
|
descriptions: [],
|
||||||
type,
|
type,
|
||||||
doc,
|
doc,
|
||||||
@@ -229,49 +235,49 @@ export const addState = function (
|
|||||||
textStyles: [],
|
textStyles: [],
|
||||||
};
|
};
|
||||||
} else {
|
} else {
|
||||||
if (!currentDocument.states[id].doc) {
|
if (!currentDocument.states[trimmedId].doc) {
|
||||||
currentDocument.states[id].doc = doc;
|
currentDocument.states[trimmedId].doc = doc;
|
||||||
}
|
}
|
||||||
if (!currentDocument.states[id].type) {
|
if (!currentDocument.states[trimmedId].type) {
|
||||||
currentDocument.states[id].type = type;
|
currentDocument.states[trimmedId].type = type;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (descr) {
|
if (descr) {
|
||||||
log.info('Setting state description', id, descr);
|
log.info('Setting state description', trimmedId, descr);
|
||||||
if (typeof descr === 'string') {
|
if (typeof descr === 'string') {
|
||||||
addDescription(id, descr.trim());
|
addDescription(trimmedId, descr.trim());
|
||||||
}
|
}
|
||||||
|
|
||||||
if (typeof descr === 'object') {
|
if (typeof descr === 'object') {
|
||||||
descr.forEach((des) => addDescription(id, des.trim()));
|
descr.forEach((des) => addDescription(trimmedId, des.trim()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (note) {
|
if (note) {
|
||||||
currentDocument.states[id].note = note;
|
currentDocument.states[trimmedId].note = note;
|
||||||
currentDocument.states[id].note.text = common.sanitizeText(
|
currentDocument.states[trimmedId].note.text = common.sanitizeText(
|
||||||
currentDocument.states[id].note.text,
|
currentDocument.states[trimmedId].note.text,
|
||||||
configApi.getConfig()
|
configApi.getConfig()
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (classes) {
|
if (classes) {
|
||||||
log.info('Setting state classes', id, classes);
|
log.info('Setting state classes', trimmedId, classes);
|
||||||
const classesList = typeof classes === 'string' ? [classes] : classes;
|
const classesList = typeof classes === 'string' ? [classes] : classes;
|
||||||
classesList.forEach((klass) => setCssClass(id, klass.trim()));
|
classesList.forEach((klass) => setCssClass(trimmedId, klass.trim()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (styles) {
|
if (styles) {
|
||||||
log.info('Setting state styles', id, styles);
|
log.info('Setting state styles', trimmedId, styles);
|
||||||
const stylesList = typeof styles === 'string' ? [styles] : styles;
|
const stylesList = typeof styles === 'string' ? [styles] : styles;
|
||||||
stylesList.forEach((style) => setStyle(id, style.trim()));
|
stylesList.forEach((style) => setStyle(trimmedId, style.trim()));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (textStyles) {
|
if (textStyles) {
|
||||||
log.info('Setting state styles', id, styles);
|
log.info('Setting state styles', trimmedId, styles);
|
||||||
const textStylesList = typeof textStyles === 'string' ? [textStyles] : textStyles;
|
const textStylesList = typeof textStyles === 'string' ? [textStyles] : textStyles;
|
||||||
textStylesList.forEach((textStyle) => setTextStyle(id, textStyle.trim()));
|
textStylesList.forEach((textStyle) => setTextStyle(trimmedId, textStyle.trim()));
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -368,10 +374,10 @@ function endTypeIfNeeded(id = '', type = DEFAULT_STATE_TYPE) {
|
|||||||
* @param relationTitle
|
* @param relationTitle
|
||||||
*/
|
*/
|
||||||
export function addRelationObjs(item1, item2, relationTitle) {
|
export function addRelationObjs(item1, item2, relationTitle) {
|
||||||
let id1 = startIdIfNeeded(item1.id);
|
let id1 = startIdIfNeeded(item1.id.trim());
|
||||||
let type1 = startTypeIfNeeded(item1.id, item1.type);
|
let type1 = startTypeIfNeeded(item1.id.trim(), item1.type);
|
||||||
let id2 = startIdIfNeeded(item2.id);
|
let id2 = startIdIfNeeded(item2.id.trim());
|
||||||
let type2 = startTypeIfNeeded(item2.id, item2.type);
|
let type2 = startTypeIfNeeded(item2.id.trim(), item2.type);
|
||||||
|
|
||||||
addState(
|
addState(
|
||||||
id1,
|
id1,
|
||||||
@@ -412,9 +418,9 @@ export const addRelation = function (item1, item2, title) {
|
|||||||
if (typeof item1 === 'object') {
|
if (typeof item1 === 'object') {
|
||||||
addRelationObjs(item1, item2, title);
|
addRelationObjs(item1, item2, title);
|
||||||
} else {
|
} else {
|
||||||
const id1 = startIdIfNeeded(item1);
|
const id1 = startIdIfNeeded(item1.trim());
|
||||||
const type1 = startTypeIfNeeded(item1);
|
const type1 = startTypeIfNeeded(item1);
|
||||||
const id2 = endIdIfNeeded(item2);
|
const id2 = endIdIfNeeded(item2.trim());
|
||||||
const type2 = endTypeIfNeeded(item2);
|
const type2 = endTypeIfNeeded(item2);
|
||||||
|
|
||||||
addState(id1, type1);
|
addState(id1, type1);
|
||||||
|
|||||||
@@ -307,8 +307,8 @@ const setupNode = (g, parent, parsedItem, diagramStates, diagramDb, altFlag) =>
|
|||||||
*
|
*
|
||||||
* @param g
|
* @param g
|
||||||
* @param parentParsedItem - parsed Item that is the parent of this document (doc)
|
* @param parentParsedItem - parsed Item that is the parent of this document (doc)
|
||||||
* @param doc - the document to set up
|
* @param doc - the document to set up; it is a list of parsed statements
|
||||||
* @param {object} diagramStates - the list of all known states for the diagram
|
* @param {object[]} diagramStates - the list of all known states for the diagram
|
||||||
* @param diagramDb
|
* @param diagramDb
|
||||||
* @param {boolean} altFlag
|
* @param {boolean} altFlag
|
||||||
* @todo This duplicates some of what is done in stateDb.js extract method
|
* @todo This duplicates some of what is done in stateDb.js extract method
|
||||||
|
|||||||
@@ -37,16 +37,14 @@ import { JSDOM } from 'jsdom';
|
|||||||
import type { Code, Root } from 'mdast';
|
import type { Code, Root } from 'mdast';
|
||||||
import { posix, dirname, relative, join } from 'path';
|
import { posix, dirname, relative, join } from 'path';
|
||||||
import prettier from 'prettier';
|
import prettier from 'prettier';
|
||||||
import { remark as remarkBuilder } from 'remark';
|
import { remark } from 'remark';
|
||||||
|
import remarkFrontmatter from 'remark-frontmatter';
|
||||||
import remarkGfm from 'remark-gfm';
|
import remarkGfm from 'remark-gfm';
|
||||||
import chokidar from 'chokidar';
|
import chokidar from 'chokidar';
|
||||||
import mm from 'micromatch';
|
import mm from 'micromatch';
|
||||||
// @ts-ignore No typescript declaration file
|
// @ts-ignore No typescript declaration file
|
||||||
import flatmap from 'unist-util-flatmap';
|
import flatmap from 'unist-util-flatmap';
|
||||||
|
|
||||||
// support tables and other GitHub Flavored Markdown syntax in markdown
|
|
||||||
const remark = remarkBuilder().use(remarkGfm);
|
|
||||||
|
|
||||||
const MERMAID_MAJOR_VERSION = (
|
const MERMAID_MAJOR_VERSION = (
|
||||||
JSON.parse(readFileSync('../mermaid/package.json', 'utf8')).version as string
|
JSON.parse(readFileSync('../mermaid/package.json', 'utf8')).version as string
|
||||||
).split('.')[0];
|
).split('.')[0];
|
||||||
@@ -90,7 +88,7 @@ const filesTransformed: Set<string> = new Set();
|
|||||||
|
|
||||||
const generateHeader = (file: string): string => {
|
const generateHeader = (file: string): string => {
|
||||||
// path from file in docs/* to repo root, e.g ../ or ../../ */
|
// path from file in docs/* to repo root, e.g ../ or ../../ */
|
||||||
const relativePath = relative(file, SOURCE_DOCS_DIR);
|
const relativePath = relative(file, SOURCE_DOCS_DIR).replaceAll('\\', '/');
|
||||||
const filePathFromRoot = posix.join('/packages/mermaid', file);
|
const filePathFromRoot = posix.join('/packages/mermaid', file);
|
||||||
const sourcePathRelativeToGenerated = posix.join(relativePath, filePathFromRoot);
|
const sourcePathRelativeToGenerated = posix.join(relativePath, filePathFromRoot);
|
||||||
return `
|
return `
|
||||||
@@ -191,7 +189,7 @@ const transformIncludeStatements = (file: string, text: string): string => {
|
|||||||
// resolve includes - src https://github.com/vuejs/vitepress/blob/428eec3750d6b5648a77ac52d88128df0554d4d1/src/node/markdownToVue.ts#L65-L76
|
// resolve includes - src https://github.com/vuejs/vitepress/blob/428eec3750d6b5648a77ac52d88128df0554d4d1/src/node/markdownToVue.ts#L65-L76
|
||||||
return text.replace(includesRE, (m, m1) => {
|
return text.replace(includesRE, (m, m1) => {
|
||||||
try {
|
try {
|
||||||
const includePath = join(dirname(file), m1);
|
const includePath = join(dirname(file), m1).replaceAll('\\', '/');
|
||||||
const content = readSyncedUTF8file(includePath);
|
const content = readSyncedUTF8file(includePath);
|
||||||
includedFiles.add(changeToFinalDocDir(includePath));
|
includedFiles.add(changeToFinalDocDir(includePath));
|
||||||
return content;
|
return content;
|
||||||
@@ -201,48 +199,86 @@ const transformIncludeStatements = (file: string, text: string): string => {
|
|||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/** Options for {@link transformMarkdownAst} */
|
||||||
|
interface TransformMarkdownAstOptions {
|
||||||
|
/**
|
||||||
|
* Used to indicate the original/source file.
|
||||||
|
*/
|
||||||
|
originalFilename: string;
|
||||||
|
/** If `true`, add a warning that the file is autogenerated */
|
||||||
|
addAutogeneratedWarning?: boolean;
|
||||||
|
/**
|
||||||
|
* If `true`, remove the YAML metadata from the Markdown input.
|
||||||
|
* Generally, YAML metadata is only used for Vitepress.
|
||||||
|
*/
|
||||||
|
removeYAML?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform code blocks in a Markdown file.
|
* Remark plugin that transforms mermaid repo markdown to Vitepress/GFM markdown.
|
||||||
* Use remark.parse() to turn the given content (a String) into an AST.
|
*
|
||||||
* For any AST node that is a code block: transform it as needed:
|
* For any AST node that is a code block: transform it as needed:
|
||||||
* - blocks marked as MERMAID_DIAGRAM_ONLY will be set to a 'mermaid' code block so it will be rendered as (only) a diagram
|
* - blocks marked as MERMAID_DIAGRAM_ONLY will be set to a 'mermaid' code block so it will be rendered as (only) a diagram
|
||||||
* - blocks marked as MERMAID_EXAMPLE_KEYWORDS will be copied and the original node will be a code only block and the copy with be rendered as the diagram
|
* - blocks marked as MERMAID_EXAMPLE_KEYWORDS will be copied and the original node will be a code only block and the copy with be rendered as the diagram
|
||||||
* - blocks marked as BLOCK_QUOTE_KEYWORDS will be transformed into block quotes
|
* - blocks marked as BLOCK_QUOTE_KEYWORDS will be transformed into block quotes
|
||||||
*
|
*
|
||||||
* Convert the AST back to a string and return it.
|
* If `addAutogeneratedWarning` is `true`, generates a header stating that this file is autogenerated.
|
||||||
*
|
*
|
||||||
* @param content - the contents of a Markdown file
|
* @returns plugin function for Remark
|
||||||
* @returns the contents with transformed code blocks
|
|
||||||
*/
|
*/
|
||||||
export const transformBlocks = (content: string): string => {
|
export function transformMarkdownAst({
|
||||||
const ast: Root = remark.parse(content);
|
originalFilename,
|
||||||
const astWithTransformedBlocks = flatmap(ast, (node: Code) => {
|
addAutogeneratedWarning,
|
||||||
if (node.type !== 'code' || !node.lang) {
|
removeYAML,
|
||||||
return [node]; // no transformation if this is not a code block
|
}: TransformMarkdownAstOptions) {
|
||||||
|
return (tree: Root, _file?: any): Root => {
|
||||||
|
const astWithTransformedBlocks = flatmap(tree, (node: Code) => {
|
||||||
|
if (node.type !== 'code' || !node.lang) {
|
||||||
|
return [node]; // no transformation if this is not a code block
|
||||||
|
}
|
||||||
|
|
||||||
|
if (node.lang === MERMAID_DIAGRAM_ONLY) {
|
||||||
|
// Set the lang to 'mermaid' so it will be rendered as a diagram.
|
||||||
|
node.lang = MERMAID_KEYWORD;
|
||||||
|
return [node];
|
||||||
|
} else if (MERMAID_EXAMPLE_KEYWORDS.includes(node.lang)) {
|
||||||
|
// Return 2 nodes:
|
||||||
|
// 1. the original node with the language now set to 'mermaid-example' (will be rendered as code), and
|
||||||
|
// 2. a copy of the original node with the language set to 'mermaid' (will be rendered as a diagram)
|
||||||
|
node.lang = MERMAID_CODE_ONLY_KEYWORD;
|
||||||
|
return [node, Object.assign({}, node, { lang: MERMAID_KEYWORD })];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Transform these blocks into block quotes.
|
||||||
|
if (BLOCK_QUOTE_KEYWORDS.includes(node.lang)) {
|
||||||
|
return [remark.parse(transformToBlockQuote(node.value, node.lang, node.meta))];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [node]; // default is to do nothing to the node
|
||||||
|
}) as Root;
|
||||||
|
|
||||||
|
if (addAutogeneratedWarning) {
|
||||||
|
// Add the header to the start of the file
|
||||||
|
const headerNode = remark.parse(generateHeader(originalFilename)).children[0];
|
||||||
|
if (astWithTransformedBlocks.children[0].type === 'yaml') {
|
||||||
|
// insert header after the YAML frontmatter if it exists
|
||||||
|
astWithTransformedBlocks.children.splice(1, 0, headerNode);
|
||||||
|
} else {
|
||||||
|
astWithTransformedBlocks.children.unshift(headerNode);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (node.lang === MERMAID_DIAGRAM_ONLY) {
|
if (removeYAML) {
|
||||||
// Set the lang to 'mermaid' so it will be rendered as a diagram.
|
const firstNode = astWithTransformedBlocks.children[0];
|
||||||
node.lang = MERMAID_KEYWORD;
|
if (firstNode.type == 'yaml') {
|
||||||
return [node];
|
// YAML is currently only used for Vitepress metadata, so we should remove it for GFM output
|
||||||
} else if (MERMAID_EXAMPLE_KEYWORDS.includes(node.lang)) {
|
astWithTransformedBlocks.children.shift();
|
||||||
// Return 2 nodes:
|
}
|
||||||
// 1. the original node with the language now set to 'mermaid-example' (will be rendered as code), and
|
|
||||||
// 2. a copy of the original node with the language set to 'mermaid' (will be rendered as a diagram)
|
|
||||||
node.lang = MERMAID_CODE_ONLY_KEYWORD;
|
|
||||||
return [node, Object.assign({}, node, { lang: MERMAID_KEYWORD })];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Transform these blocks into block quotes.
|
return astWithTransformedBlocks;
|
||||||
if (BLOCK_QUOTE_KEYWORDS.includes(node.lang)) {
|
};
|
||||||
return [remark.parse(transformToBlockQuote(node.value, node.lang, node.meta))];
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return [node]; // default is to do nothing to the node
|
|
||||||
});
|
|
||||||
|
|
||||||
return remark.stringify(astWithTransformedBlocks);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transform a markdown file and write the transformed file to the directory for published
|
* Transform a markdown file and write the transformed file to the directory for published
|
||||||
@@ -260,11 +296,18 @@ export const transformBlocks = (content: string): string => {
|
|||||||
*/
|
*/
|
||||||
const transformMarkdown = (file: string) => {
|
const transformMarkdown = (file: string) => {
|
||||||
const doc = injectPlaceholders(transformIncludeStatements(file, readSyncedUTF8file(file)));
|
const doc = injectPlaceholders(transformIncludeStatements(file, readSyncedUTF8file(file)));
|
||||||
let transformed = transformBlocks(doc);
|
|
||||||
if (!noHeader) {
|
let transformed = remark()
|
||||||
// Add the header to the start of the file
|
.use(remarkGfm)
|
||||||
transformed = `${generateHeader(file)}\n${transformed}`;
|
.use(remarkFrontmatter, ['yaml']) // support YAML front-matter in Markdown
|
||||||
}
|
.use(transformMarkdownAst, {
|
||||||
|
// mermaid project specific plugin
|
||||||
|
originalFilename: file,
|
||||||
|
addAutogeneratedWarning: !noHeader,
|
||||||
|
removeYAML: !noHeader,
|
||||||
|
})
|
||||||
|
.processSync(doc)
|
||||||
|
.toString();
|
||||||
|
|
||||||
if (vitepress && file === 'src/docs/index.md') {
|
if (vitepress && file === 'src/docs/index.md') {
|
||||||
// Skip transforming index if vitepress is enabled
|
// Skip transforming index if vitepress is enabled
|
||||||
@@ -331,7 +374,7 @@ const getFilesFromGlobs = async (globs: string[]): Promise<string[]> => {
|
|||||||
};
|
};
|
||||||
|
|
||||||
/** Main method (entry point) */
|
/** Main method (entry point) */
|
||||||
(async () => {
|
const main = async () => {
|
||||||
if (verifyOnly) {
|
if (verifyOnly) {
|
||||||
console.log('Verifying that all files are in sync with the source files');
|
console.log('Verifying that all files are in sync with the source files');
|
||||||
}
|
}
|
||||||
@@ -400,4 +443,6 @@ const getFilesFromGlobs = async (globs: string[]): Promise<string[]> => {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
})();
|
};
|
||||||
|
|
||||||
|
void main();
|
||||||
|
|||||||
@@ -1,40 +1,24 @@
|
|||||||
import { transformBlocks, transformToBlockQuote } from './docs.mjs';
|
import { transformMarkdownAst, transformToBlockQuote } from './docs.mjs';
|
||||||
import { remark as remarkBuilder } from 'remark'; // import it this way so we can mock it
|
|
||||||
|
import { remark } from 'remark'; // import it this way so we can mock it
|
||||||
|
import remarkFrontmatter from 'remark-frontmatter';
|
||||||
import { vi, afterEach, describe, it, expect } from 'vitest';
|
import { vi, afterEach, describe, it, expect } from 'vitest';
|
||||||
|
|
||||||
const remark = remarkBuilder();
|
|
||||||
|
|
||||||
vi.mock('remark', async (importOriginal) => {
|
|
||||||
const { remark: originalRemarkBuilder } = (await importOriginal()) as {
|
|
||||||
remark: typeof remarkBuilder;
|
|
||||||
};
|
|
||||||
|
|
||||||
// make sure that both `docs.mts` and this test file are using the same remark
|
|
||||||
// object so that we can mock it
|
|
||||||
const sharedRemark = originalRemarkBuilder();
|
|
||||||
return {
|
|
||||||
remark: () => sharedRemark,
|
|
||||||
};
|
|
||||||
});
|
|
||||||
|
|
||||||
afterEach(() => {
|
afterEach(() => {
|
||||||
vi.restoreAllMocks();
|
vi.restoreAllMocks();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
const originalFilename = 'example-input-filename.md';
|
||||||
|
const remarkBuilder = remark().use(remarkFrontmatter, ['yaml']); // support YAML front-matter in Markdown
|
||||||
|
|
||||||
describe('docs.mts', () => {
|
describe('docs.mts', () => {
|
||||||
describe('transformBlocks', () => {
|
describe('transformMarkdownAst', () => {
|
||||||
it('uses remark.parse to create the AST for the file ', () => {
|
|
||||||
const remarkParseSpy = vi
|
|
||||||
.spyOn(remark, 'parse')
|
|
||||||
.mockReturnValue({ type: 'root', children: [] });
|
|
||||||
const contents = 'Markdown file contents';
|
|
||||||
transformBlocks(contents);
|
|
||||||
expect(remarkParseSpy).toHaveBeenCalledWith(contents);
|
|
||||||
});
|
|
||||||
describe('checks each AST node', () => {
|
describe('checks each AST node', () => {
|
||||||
it('does no transformation if there are no code blocks', async () => {
|
it('does no transformation if there are no code blocks', async () => {
|
||||||
const contents = 'Markdown file contents\n';
|
const contents = 'Markdown file contents\n';
|
||||||
const result = transformBlocks(contents);
|
const result = (
|
||||||
|
await remarkBuilder().use(transformMarkdownAst, { originalFilename }).process(contents)
|
||||||
|
).toString();
|
||||||
expect(result).toEqual(contents);
|
expect(result).toEqual(contents);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -46,8 +30,12 @@ describe('docs.mts', () => {
|
|||||||
const lang_keyword = 'mermaid-nocode';
|
const lang_keyword = 'mermaid-nocode';
|
||||||
const contents = beforeCodeLine + '```' + lang_keyword + '\n' + diagram_text + '\n```\n';
|
const contents = beforeCodeLine + '```' + lang_keyword + '\n' + diagram_text + '\n```\n';
|
||||||
|
|
||||||
it('changes the language to "mermaid"', () => {
|
it('changes the language to "mermaid"', async () => {
|
||||||
const result = transformBlocks(contents);
|
const result = (
|
||||||
|
await remarkBuilder()
|
||||||
|
.use(transformMarkdownAst, { originalFilename })
|
||||||
|
.process(contents)
|
||||||
|
).toString();
|
||||||
expect(result).toEqual(
|
expect(result).toEqual(
|
||||||
beforeCodeLine + '\n' + '```' + 'mermaid' + '\n' + diagram_text + '\n```\n'
|
beforeCodeLine + '\n' + '```' + 'mermaid' + '\n' + diagram_text + '\n```\n'
|
||||||
);
|
);
|
||||||
@@ -61,8 +49,12 @@ describe('docs.mts', () => {
|
|||||||
const contents =
|
const contents =
|
||||||
beforeCodeLine + '```' + lang_keyword + '\n' + diagram_text + '\n```\n';
|
beforeCodeLine + '```' + lang_keyword + '\n' + diagram_text + '\n```\n';
|
||||||
|
|
||||||
it('changes the language to "mermaid-example" and adds a copy of the code block with language = "mermaid"', () => {
|
it('changes the language to "mermaid-example" and adds a copy of the code block with language = "mermaid"', async () => {
|
||||||
const result = transformBlocks(contents);
|
const result = (
|
||||||
|
await remarkBuilder()
|
||||||
|
.use(transformMarkdownAst, { originalFilename })
|
||||||
|
.process(contents)
|
||||||
|
).toString();
|
||||||
expect(result).toEqual(
|
expect(result).toEqual(
|
||||||
beforeCodeLine +
|
beforeCodeLine +
|
||||||
'\n' +
|
'\n' +
|
||||||
@@ -77,16 +69,40 @@ describe('docs.mts', () => {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('calls transformToBlockQuote with the node information', () => {
|
it('calls transformToBlockQuote with the node information', async () => {
|
||||||
const lang_keyword = 'note';
|
const lang_keyword = 'note';
|
||||||
const contents =
|
const contents =
|
||||||
beforeCodeLine + '```' + lang_keyword + '\n' + 'This is the text\n' + '```\n';
|
beforeCodeLine + '```' + lang_keyword + '\n' + 'This is the text\n' + '```\n';
|
||||||
|
|
||||||
const result = transformBlocks(contents);
|
const result = (
|
||||||
|
await remarkBuilder().use(transformMarkdownAst, { originalFilename }).process(contents)
|
||||||
|
).toString();
|
||||||
expect(result).toEqual(beforeCodeLine + '\n> **Note**\n' + '> This is the text\n');
|
expect(result).toEqual(beforeCodeLine + '\n> **Note**\n' + '> This is the text\n');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should remove YAML if `removeYAML` is true', async () => {
|
||||||
|
const contents = `---
|
||||||
|
title: Flowcharts Syntax
|
||||||
|
---
|
||||||
|
|
||||||
|
This Markdown should be kept.
|
||||||
|
`;
|
||||||
|
const withYaml = (
|
||||||
|
await remarkBuilder().use(transformMarkdownAst, { originalFilename }).process(contents)
|
||||||
|
).toString();
|
||||||
|
// no change
|
||||||
|
expect(withYaml).toEqual(contents);
|
||||||
|
|
||||||
|
const withoutYaml = (
|
||||||
|
await remarkBuilder()
|
||||||
|
.use(transformMarkdownAst, { originalFilename, removeYAML: true })
|
||||||
|
.process(contents)
|
||||||
|
).toString();
|
||||||
|
// no change
|
||||||
|
expect(withoutYaml).toEqual('This Markdown should be kept.\n');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('transformToBlockQuote', () => {
|
describe('transformToBlockQuote', () => {
|
||||||
|
|||||||
@@ -77,8 +77,8 @@ function sidebarAll() {
|
|||||||
],
|
],
|
||||||
},
|
},
|
||||||
...sidebarSyntax(),
|
...sidebarSyntax(),
|
||||||
|
...sidebarEcosystem(),
|
||||||
...sidebarConfig(),
|
...sidebarConfig(),
|
||||||
...sidebarMisc(),
|
|
||||||
...sidebarCommunity(),
|
...sidebarCommunity(),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
@@ -126,19 +126,20 @@ function sidebarConfig() {
|
|||||||
{ text: 'Accessibility', link: '/config/accessibility' },
|
{ text: 'Accessibility', link: '/config/accessibility' },
|
||||||
{ text: 'Mermaid CLI', link: '/config/mermaidCLI' },
|
{ text: 'Mermaid CLI', link: '/config/mermaidCLI' },
|
||||||
{ text: 'Advanced usage', link: '/config/n00b-advanced' },
|
{ text: 'Advanced usage', link: '/config/n00b-advanced' },
|
||||||
|
{ text: 'FAQ', link: '/config/faq' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
function sidebarMisc() {
|
function sidebarEcosystem() {
|
||||||
return [
|
return [
|
||||||
{
|
{
|
||||||
text: '📚 Misc',
|
text: '📚 Ecosystem',
|
||||||
collapsible: true,
|
collapsible: true,
|
||||||
items: [
|
items: [
|
||||||
{ text: 'Use-Cases and Integrations', link: '/misc/integrations' },
|
{ text: 'Showcases', link: '/ecosystem/showcases' },
|
||||||
{ text: 'FAQ', link: '/misc/faq' },
|
{ text: 'Use-Cases and Integrations', link: '/ecosystem/integrations' },
|
||||||
],
|
],
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|||||||
@@ -10,9 +10,6 @@ export default {
|
|||||||
// register global components
|
// register global components
|
||||||
app.component('Mermaid', Mermaid);
|
app.component('Mermaid', Mermaid);
|
||||||
router.onBeforeRouteChange = (to) => {
|
router.onBeforeRouteChange = (to) => {
|
||||||
if (router.route.path !== '/') {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
try {
|
try {
|
||||||
const newPath = getRedirect(to);
|
const newPath = getRedirect(to);
|
||||||
if (newPath) {
|
if (newPath) {
|
||||||
|
|||||||
@@ -5,31 +5,34 @@ import { expect, test } from 'vitest';
|
|||||||
import { getRedirect } from './redirect';
|
import { getRedirect } from './redirect';
|
||||||
|
|
||||||
test.each([
|
test.each([
|
||||||
|
// Old docs, localhost
|
||||||
['http://localhost:1234/mermaid/#/flowchart.md', 'syntax/flowchart.html'],
|
['http://localhost:1234/mermaid/#/flowchart.md', 'syntax/flowchart.html'],
|
||||||
['http://localhost/mermaid/#/flowchart.md', 'syntax/flowchart.html'],
|
['http://localhost/mermaid/#/flowchart.md', 'syntax/flowchart.html'],
|
||||||
['https://mermaid-js.github.io/mermaid/#/flowchart.md', 'syntax/flowchart.html'],
|
// Old docs, github pages
|
||||||
['https://mermaid.js.org/#/flowchart.md', 'syntax/flowchart.html'],
|
['https://mermaid-js.github.io/mermaid/#/flowchart.md', 'syntax/flowchart.html'], // without dot
|
||||||
['https://mermaid-js.github.io/mermaid/#/./flowchart', 'syntax/flowchart.html'],
|
['https://mermaid-js.github.io/mermaid/#/./flowchart', 'syntax/flowchart.html'], // with dot
|
||||||
['https://mermaid-js.github.io/mermaid/#/flowchart', 'syntax/flowchart.html'],
|
['https://mermaid-js.github.io/mermaid/#flowchart', 'syntax/flowchart.html'], // without slash
|
||||||
['https://mermaid-js.github.io/mermaid/#flowchart', 'syntax/flowchart.html'],
|
['https://mermaid-js.github.io/mermaid/#/flowchart', 'syntax/flowchart.html'], // with slash
|
||||||
['https://mermaid-js.github.io/mermaid/#/flowchart', 'syntax/flowchart.html'],
|
['https://mermaid-js.github.io/mermaid/#/flowchart.md?id=my-id', 'syntax/flowchart.html#my-id'], // with id
|
||||||
['https://mermaid-js.github.io/mermaid/#/flowchart.md?id=my-id', 'syntax/flowchart.html#my-id'],
|
['https://mermaid-js.github.io/mermaid/#/./flowchart.md?id=my-id', 'syntax/flowchart.html#my-id'], // with id and dot
|
||||||
['https://mermaid-js.github.io/mermaid/#/./flowchart.md?id=my-id', 'syntax/flowchart.html#my-id'],
|
|
||||||
[
|
[
|
||||||
'https://mermaid-js.github.io/mermaid/#/flowchart?another=test&id=my-id&one=more',
|
'https://mermaid-js.github.io/mermaid/#/flowchart?another=test&id=my-id&one=more', // with multiple params
|
||||||
'syntax/flowchart.html#my-id',
|
'syntax/flowchart.html#my-id',
|
||||||
],
|
],
|
||||||
['https://mermaid-js.github.io/mermaid/#/n00b-advanced', 'config/n00b-advanced.html'],
|
['https://mermaid-js.github.io/mermaid/#/n00b-advanced', 'config/n00b-advanced.html'], // without .md
|
||||||
['https://mermaid-js.github.io/mermaid/#/n00b-advanced.md', 'config/n00b-advanced.html'],
|
['https://mermaid-js.github.io/mermaid/#/n00b-advanced.md', 'config/n00b-advanced.html'], // with .md
|
||||||
[
|
[
|
||||||
'https://mermaid-js.github.io/mermaid/#/flowchart?id=a-node-in-the-form-of-a-circle',
|
'https://mermaid-js.github.io/mermaid/#/flowchart?id=a-node-in-the-form-of-a-circle', // with id, without .md
|
||||||
'syntax/flowchart.html#a-node-in-the-form-of-a-circle',
|
'syntax/flowchart.html#a-node-in-the-form-of-a-circle',
|
||||||
],
|
],
|
||||||
|
// Old docs, without base path, new domain
|
||||||
|
['https://mermaid.js.org/#/flowchart.md', 'syntax/flowchart.html'],
|
||||||
|
// New docs, without base path, new domain
|
||||||
|
['https://mermaid.js.org/misc/faq.html', 'configure/faq.html'],
|
||||||
|
[
|
||||||
|
'https://mermaid.js.org/misc/faq.html#frequently-asked-questions',
|
||||||
|
'configure/faq.html#frequently-asked-questions',
|
||||||
|
], // with hash
|
||||||
])('should process url %s to %s', (link: string, path: string) => {
|
])('should process url %s to %s', (link: string, path: string) => {
|
||||||
expect(getRedirect(link)).toBe(path);
|
expect(getRedirect(link)).toBe(path);
|
||||||
});
|
});
|
||||||
|
|
||||||
test('should throw for invalid URL', () => {
|
|
||||||
// Not mermaid domain
|
|
||||||
expect(() => getRedirect('https://www.google.com')).toThrowError();
|
|
||||||
});
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
export interface Redirect {
|
interface Redirect {
|
||||||
path: string;
|
path: string;
|
||||||
id?: string;
|
id?: string;
|
||||||
}
|
}
|
||||||
@@ -7,15 +7,7 @@ export interface Redirect {
|
|||||||
* Extracts the base slug from the old URL.
|
* Extracts the base slug from the old URL.
|
||||||
* @param link - The old URL.
|
* @param link - The old URL.
|
||||||
*/
|
*/
|
||||||
const getBaseFile = (link: string): Redirect => {
|
const getBaseFile = (url: URL): Redirect => {
|
||||||
const url = new URL(link);
|
|
||||||
if (
|
|
||||||
url.hostname !== 'mermaid-js.github.io' &&
|
|
||||||
url.hostname !== 'mermaid.js.org' &&
|
|
||||||
url.hostname !== 'localhost'
|
|
||||||
) {
|
|
||||||
throw new Error('Not mermaidjs url');
|
|
||||||
}
|
|
||||||
const [path, params, ...rest] = url.hash
|
const [path, params, ...rest] = url.hash
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.replace('.md', '')
|
.replace('.md', '')
|
||||||
@@ -32,7 +24,7 @@ const getBaseFile = (link: string): Redirect => {
|
|||||||
return { path, id };
|
return { path, id };
|
||||||
};
|
};
|
||||||
|
|
||||||
const redirectMap: Record<string, string> = {
|
const idRedirectMap: Record<string, string> = {
|
||||||
'8.6.0_docs': '',
|
'8.6.0_docs': '',
|
||||||
accessibility: 'config/theming',
|
accessibility: 'config/theming',
|
||||||
breakingchanges: '',
|
breakingchanges: '',
|
||||||
@@ -76,15 +68,25 @@ const redirectMap: Record<string, string> = {
|
|||||||
'user-journey': 'syntax/userJourney',
|
'user-journey': 'syntax/userJourney',
|
||||||
};
|
};
|
||||||
|
|
||||||
|
const urlRedirectMap: Record<string, string> = {
|
||||||
|
'/misc/faq.html': 'configure/faq.html',
|
||||||
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @param link - The old documentation URL.
|
* @param link - The old documentation URL.
|
||||||
* @returns The new documentation path.
|
* @returns The new documentation path.
|
||||||
*/
|
*/
|
||||||
export const getRedirect = (link: string): string | undefined => {
|
export const getRedirect = (link: string): string | undefined => {
|
||||||
const { path, id } = getBaseFile(link);
|
const url = new URL(link);
|
||||||
if (!(path in redirectMap)) {
|
// Redirects for deprecated vitepress URLs
|
||||||
return;
|
if (url.pathname in urlRedirectMap) {
|
||||||
|
return `${urlRedirectMap[url.pathname]}${url.hash}`;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Redirects for old docs URLs
|
||||||
|
const { path, id } = getBaseFile(url);
|
||||||
|
if (path in idRedirectMap) {
|
||||||
|
return `${idRedirectMap[path]}.html${id ? `#${id}` : ''}`;
|
||||||
}
|
}
|
||||||
return `${redirectMap[path]}.html${id ? `#${id}` : ''}`;
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -89,9 +89,10 @@ They also serve as proof of concept, for the variety of things that can be built
|
|||||||
|
|
||||||
## Editor Plugins
|
## Editor Plugins
|
||||||
|
|
||||||
- [Vs Code](https://code.visualstudio.com/)
|
- [VS Code](https://code.visualstudio.com/)
|
||||||
- [Markdown Preview Mermaid Support](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid)
|
- [Markdown Preview Mermaid Support](https://marketplace.visualstudio.com/items?itemName=bierner.markdown-mermaid)
|
||||||
- [Mermaid Preview](https://marketplace.visualstudio.com/items?itemName=vstirbu.vscode-mermaid-preview)
|
- [Mermaid Preview](https://marketplace.visualstudio.com/items?itemName=vstirbu.vscode-mermaid-preview)
|
||||||
|
- [Markdown Preview Enhanced](https://marketplace.visualstudio.com/items?itemName=shd101wyy.markdown-preview-enhanced)
|
||||||
- [Mermaid Markdown Syntax Highlighting](https://marketplace.visualstudio.com/items?itemName=bpruitt-goddard.mermaid-markdown-syntax-highlighting)
|
- [Mermaid Markdown Syntax Highlighting](https://marketplace.visualstudio.com/items?itemName=bpruitt-goddard.mermaid-markdown-syntax-highlighting)
|
||||||
- [Mermaid Editor](https://marketplace.visualstudio.com/items?itemName=tomoyukim.vscode-mermaid-editor)
|
- [Mermaid Editor](https://marketplace.visualstudio.com/items?itemName=tomoyukim.vscode-mermaid-editor)
|
||||||
- [Mermaid Export](https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.mermaid-export)
|
- [Mermaid Export](https://marketplace.visualstudio.com/items?itemName=Gruntfuggly.mermaid-export)
|
||||||
3
packages/mermaid/src/docs/ecosystem/showcases.md
Normal file
3
packages/mermaid/src/docs/ecosystem/showcases.md
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
# Showcases
|
||||||
|
|
||||||
|
- [Swimm - Up-to-date diagrams with Swimm, the knowledge management tool for code](https://docs.swimm.io/Features/diagrams-and-charts).
|
||||||
@@ -146,14 +146,13 @@ The `type` and `name` values must begin with an alphabetic character and may con
|
|||||||
|
|
||||||
#### Attribute Keys and Comments
|
#### Attribute Keys and Comments
|
||||||
|
|
||||||
Attributes may also have a `key` or comment defined. Keys can be "PK", "FK" or "UK", for Primary Key, Foreign Key or Unique Key. And a `comment` is defined by double quotes at the end of an attribute. Comments themselves cannot have double-quote characters in them.
|
Attributes may also have a `key` or comment defined. Keys can be `PK`, `FK` or `UK`, for Primary Key, Foreign Key or Unique Key. To specify multiple key constraints on a single attribute, separate them with a comma (e.g., `PK, FK`).. A `comment` is defined by double quotes at the end of an attribute. Comments themselves cannot have double-quote characters in them.
|
||||||
|
|
||||||
```mermaid-example
|
```mermaid-example
|
||||||
erDiagram
|
erDiagram
|
||||||
CAR ||--o{ NAMED-DRIVER : allows
|
CAR ||--o{ NAMED-DRIVER : allows
|
||||||
CAR {
|
CAR {
|
||||||
string allowedDriver FK "The license of the allowed driver"
|
string registrationNumber PK
|
||||||
string registrationNumber UK
|
|
||||||
string make
|
string make
|
||||||
string model
|
string model
|
||||||
string[] parts
|
string[] parts
|
||||||
@@ -163,9 +162,14 @@ erDiagram
|
|||||||
string driversLicense PK "The license #"
|
string driversLicense PK "The license #"
|
||||||
string(99) firstName "Only 99 characters are allowed"
|
string(99) firstName "Only 99 characters are allowed"
|
||||||
string lastName
|
string lastName
|
||||||
|
string phone UK
|
||||||
int age
|
int age
|
||||||
}
|
}
|
||||||
MANUFACTURER only one to zero or more CAR
|
NAMED-DRIVER {
|
||||||
|
string carRegistrationNumber PK, FK
|
||||||
|
string driverLicence PK, FK
|
||||||
|
}
|
||||||
|
MANUFACTURER only one to zero or more CAR : makes
|
||||||
```
|
```
|
||||||
|
|
||||||
### Other Things
|
### Other Things
|
||||||
|
|||||||
@@ -1,3 +1,8 @@
|
|||||||
|
---
|
||||||
|
title: Flowcharts Syntax
|
||||||
|
outline: 'deep' # shows all h3 headings in outline in Vitepress
|
||||||
|
---
|
||||||
|
|
||||||
# Flowcharts - Basic Syntax
|
# Flowcharts - Basic Syntax
|
||||||
|
|
||||||
All Flowcharts are composed of **nodes**, the geometric shapes and **edges**, the arrows or lines. The mermaid code defines the way that these **nodes** and **edges** are made and interact.
|
All Flowcharts are composed of **nodes**, the geometric shapes and **edges**, the arrows or lines. The mermaid code defines the way that these **nodes** and **edges** are made and interact.
|
||||||
@@ -547,8 +552,8 @@ linkStyle 3 stroke:#ff3,stroke-width:4px,color:red;
|
|||||||
### Styling line curves
|
### Styling line curves
|
||||||
|
|
||||||
It is possible to style the type of curve used for lines between items, if the default method does not meet your needs.
|
It is possible to style the type of curve used for lines between items, if the default method does not meet your needs.
|
||||||
Available curve styles include `basis`, `bump`, `linear`, `monotoneX`, `monotoneY`, `natural`, `step`, `stepAfter`,
|
Available curve styles include `basis`, `bumpX`, `bumpY`, `cardinal`, `catmullRom`, `linear`, `monotoneX`, `monotoneY`,
|
||||||
and `stepBefore`.
|
`natural`, `step`, `stepAfter`, and `stepBefore`.
|
||||||
|
|
||||||
In this example, a left-to-right graph uses the `stepBefore` curve style:
|
In this example, a left-to-right graph uses the `stepBefore` curve style:
|
||||||
|
|
||||||
|
|||||||
@@ -55,7 +55,7 @@ In this way we can use a text outline to generate a hierarchical mindmap.
|
|||||||
|
|
||||||
## Different shapes
|
## Different shapes
|
||||||
|
|
||||||
Mermaids mindmaps can show node using different shapes. When specifying a shape for a node the syntax for the is similar to flowchart nodes, with an id followed by the shape definition and with the text within the shape delimiters. Where possible we try/will try to keep the same shapes as for flowcharts even though they are not all supported from the start.
|
Mermaid mindmaps can show nodes using different shapes. When specifying a shape for a node the syntax is similar to flowchart nodes, with an id followed by the shape definition and with the text within the shape delimiters. Where possible we try/will try to keep the same shapes as for flowcharts, even though they are not all supported from the start.
|
||||||
|
|
||||||
Mindmap can show the following shapes:
|
Mindmap can show the following shapes:
|
||||||
|
|
||||||
|
|||||||
@@ -58,6 +58,48 @@ sequenceDiagram
|
|||||||
J->>A: Great!
|
J->>A: Great!
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Grouping / Box
|
||||||
|
|
||||||
|
The actor(s) can be grouped in vertical boxes. You can define a color (if not, it will be transparent) and/or a descriptive label using the following notation:
|
||||||
|
|
||||||
|
```
|
||||||
|
box Aqua Group Description
|
||||||
|
... actors ...
|
||||||
|
end
|
||||||
|
box Group without description
|
||||||
|
... actors ...
|
||||||
|
end
|
||||||
|
box rgb(33,66,99)
|
||||||
|
... actors ...
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
```note
|
||||||
|
If your group name is a color you can force the color to be transparent:
|
||||||
|
```
|
||||||
|
|
||||||
|
```
|
||||||
|
box transparent Aqua
|
||||||
|
... actors ...
|
||||||
|
end
|
||||||
|
```
|
||||||
|
|
||||||
|
```mermaid-example
|
||||||
|
sequenceDiagram
|
||||||
|
box Purple Alice & John
|
||||||
|
participant A
|
||||||
|
participant J
|
||||||
|
end
|
||||||
|
box Another Group
|
||||||
|
participant B
|
||||||
|
participant C
|
||||||
|
end
|
||||||
|
A->>J: Hello John, how are you?
|
||||||
|
J->>A: Great!
|
||||||
|
A->>B: Hello Bob, how is Charly ?
|
||||||
|
B->>C: Hello Charly, how are you?
|
||||||
|
```
|
||||||
|
|
||||||
## Messages
|
## Messages
|
||||||
|
|
||||||
Messages can be of two displayed either solid or with a dotted line.
|
Messages can be of two displayed either solid or with a dotted line.
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
/* eslint-disable @typescript-eslint/no-unused-vars */
|
/* eslint-disable @typescript-eslint/no-unused-vars */
|
||||||
/* eslint-disable @typescript-eslint/no-empty-function */
|
/* eslint-disable @typescript-eslint/no-empty-function */
|
||||||
/* eslint-disable no-console */
|
/* eslint-disable no-console */
|
||||||
import moment from 'moment-mini';
|
import moment from 'moment';
|
||||||
|
|
||||||
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
export type LogLevel = 'trace' | 'debug' | 'info' | 'warn' | 'error' | 'fatal';
|
||||||
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import { ExternalDiagramDefinition } from './diagram-api/types';
|
|||||||
|
|
||||||
export type { MermaidConfig, DetailedError, ExternalDiagramDefinition, ParseErrorFunction };
|
export type { MermaidConfig, DetailedError, ExternalDiagramDefinition, ParseErrorFunction };
|
||||||
|
|
||||||
let externalDiagramsRegistered = false;
|
|
||||||
/**
|
/**
|
||||||
* ## init
|
* ## init
|
||||||
*
|
*
|
||||||
@@ -51,12 +50,7 @@ const init = async function (
|
|||||||
callback?: Function
|
callback?: Function
|
||||||
) {
|
) {
|
||||||
try {
|
try {
|
||||||
// Not really sure if we need to check this, or simply call initThrowsErrorsAsync directly.
|
await initThrowsErrorsAsync(config, nodes, callback);
|
||||||
if (externalDiagramsRegistered) {
|
|
||||||
await initThrowsErrorsAsync(config, nodes, callback);
|
|
||||||
} else {
|
|
||||||
initThrowsErrors(config, nodes, callback);
|
|
||||||
}
|
|
||||||
} catch (e) {
|
} catch (e) {
|
||||||
log.warn('Syntax Error rendering');
|
log.warn('Syntax Error rendering');
|
||||||
if (isDetailedError(e)) {
|
if (isDetailedError(e)) {
|
||||||
@@ -68,8 +62,7 @@ const init = async function (
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
const handleError = (error: unknown, errors: DetailedError[], parseError?: ParseErrorFunction) => {
|
||||||
const handleError = (error: unknown, errors: DetailedError[], parseError?: Function) => {
|
|
||||||
log.warn(error);
|
log.warn(error);
|
||||||
if (isDetailedError(error)) {
|
if (isDetailedError(error)) {
|
||||||
// handle case where error string and hash were
|
// handle case where error string and hash were
|
||||||
@@ -225,7 +218,6 @@ const loadExternalDiagrams = async (...diagrams: ExternalDiagramDefinition[]) =>
|
|||||||
*/
|
*/
|
||||||
const initThrowsErrorsAsync = async function (
|
const initThrowsErrorsAsync = async function (
|
||||||
config?: MermaidConfig,
|
config?: MermaidConfig,
|
||||||
// eslint-disable-next-line no-undef
|
|
||||||
nodes?: string | HTMLElement | NodeListOf<HTMLElement>,
|
nodes?: string | HTMLElement | NodeListOf<HTMLElement>,
|
||||||
// eslint-disable-next-line @typescript-eslint/ban-types
|
// eslint-disable-next-line @typescript-eslint/ban-types
|
||||||
callback?: Function
|
callback?: Function
|
||||||
@@ -348,7 +340,7 @@ const contentLoaded = function () {
|
|||||||
if (mermaid.startOnLoad) {
|
if (mermaid.startOnLoad) {
|
||||||
const { startOnLoad } = mermaidAPI.getConfig();
|
const { startOnLoad } = mermaidAPI.getConfig();
|
||||||
if (startOnLoad) {
|
if (startOnLoad) {
|
||||||
mermaid.init();
|
mermaid.init().catch((err) => log.error('Mermaid failed to initialize', err));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
@@ -427,7 +419,7 @@ const parseAsync = (txt: string): Promise<boolean> => {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
executionQueue.push(performCall);
|
executionQueue.push(performCall);
|
||||||
executeQueue();
|
executeQueue().catch(reject);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -460,7 +452,7 @@ const renderAsync = (
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
executionQueue.push(performCall);
|
executionQueue.push(performCall);
|
||||||
executeQueue();
|
executeQueue().catch(reject);
|
||||||
});
|
});
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -4,6 +4,15 @@ import {
|
|||||||
curveBasis,
|
curveBasis,
|
||||||
curveBasisClosed,
|
curveBasisClosed,
|
||||||
curveBasisOpen,
|
curveBasisOpen,
|
||||||
|
curveBumpX,
|
||||||
|
curveBumpY,
|
||||||
|
curveBundle,
|
||||||
|
curveCardinalClosed,
|
||||||
|
curveCardinalOpen,
|
||||||
|
curveCardinal,
|
||||||
|
curveCatmullRomClosed,
|
||||||
|
curveCatmullRomOpen,
|
||||||
|
curveCatmullRom,
|
||||||
CurveFactory,
|
CurveFactory,
|
||||||
curveLinear,
|
curveLinear,
|
||||||
curveLinearClosed,
|
curveLinearClosed,
|
||||||
@@ -28,6 +37,15 @@ const d3CurveTypes = {
|
|||||||
curveBasis: curveBasis,
|
curveBasis: curveBasis,
|
||||||
curveBasisClosed: curveBasisClosed,
|
curveBasisClosed: curveBasisClosed,
|
||||||
curveBasisOpen: curveBasisOpen,
|
curveBasisOpen: curveBasisOpen,
|
||||||
|
curveBumpX: curveBumpX,
|
||||||
|
curveBumpY: curveBumpY,
|
||||||
|
curveBundle: curveBundle,
|
||||||
|
curveCardinalClosed: curveCardinalClosed,
|
||||||
|
curveCardinalOpen: curveCardinalOpen,
|
||||||
|
curveCardinal: curveCardinal,
|
||||||
|
curveCatmullRomClosed: curveCatmullRomClosed,
|
||||||
|
curveCatmullRomOpen: curveCatmullRomOpen,
|
||||||
|
curveCatmullRom: curveCatmullRom,
|
||||||
curveLinear: curveLinear,
|
curveLinear: curveLinear,
|
||||||
curveLinearClosed: curveLinearClosed,
|
curveLinearClosed: curveLinearClosed,
|
||||||
curveMonotoneX: curveMonotoneX,
|
curveMonotoneX: curveMonotoneX,
|
||||||
|
|||||||
342
pnpm-lock.yaml
generated
342
pnpm-lock.yaml
generated
@@ -44,11 +44,11 @@ importers:
|
|||||||
specifier: ^4.2.1
|
specifier: ^4.2.1
|
||||||
version: 4.2.1
|
version: 4.2.1
|
||||||
'@typescript-eslint/eslint-plugin':
|
'@typescript-eslint/eslint-plugin':
|
||||||
specifier: ^5.42.1
|
specifier: ^5.48.2
|
||||||
version: 5.42.1_2udltptbznfmezdozpdoa2aemq
|
version: 5.48.2_iljmjqxcygjq3saipl7gerxpvi
|
||||||
'@typescript-eslint/parser':
|
'@typescript-eslint/parser':
|
||||||
specifier: ^5.42.1
|
specifier: ^5.48.2
|
||||||
version: 5.42.1_rmayb2veg2btbq6mbmnyivgasy
|
version: 5.48.2_yygwinqv3a2io74xmwofqb7uka
|
||||||
'@vitest/coverage-c8':
|
'@vitest/coverage-c8':
|
||||||
specifier: ^0.27.0
|
specifier: ^0.27.0
|
||||||
version: 0.27.1_6vhkb7zox2ro6wmx3rlvm5i5ce
|
version: 0.27.1_6vhkb7zox2ro6wmx3rlvm5i5ce
|
||||||
@@ -71,32 +71,32 @@ importers:
|
|||||||
specifier: ^0.17.0
|
specifier: ^0.17.0
|
||||||
version: 0.17.0
|
version: 0.17.0
|
||||||
eslint:
|
eslint:
|
||||||
specifier: ^8.27.0
|
specifier: ^8.32.0
|
||||||
version: 8.27.0
|
version: 8.32.0
|
||||||
eslint-config-prettier:
|
eslint-config-prettier:
|
||||||
specifier: ^8.5.0
|
specifier: ^8.6.0
|
||||||
version: 8.5.0_eslint@8.27.0
|
version: 8.6.0_eslint@8.32.0
|
||||||
eslint-plugin-cypress:
|
eslint-plugin-cypress:
|
||||||
specifier: ^2.12.1
|
specifier: ^2.12.1
|
||||||
version: 2.12.1_eslint@8.27.0
|
version: 2.12.1_eslint@8.32.0
|
||||||
eslint-plugin-html:
|
eslint-plugin-html:
|
||||||
specifier: ^7.1.0
|
specifier: ^7.1.0
|
||||||
version: 7.1.0
|
version: 7.1.0
|
||||||
eslint-plugin-jest:
|
eslint-plugin-jest:
|
||||||
specifier: ^27.1.5
|
specifier: ^27.1.5
|
||||||
version: 27.1.5_kdswgjmqcx7mthqz7ow2zlfevy
|
version: 27.1.5_5rcd23qw3h5vuffwo2owxb3hw4
|
||||||
eslint-plugin-jsdoc:
|
eslint-plugin-jsdoc:
|
||||||
specifier: ^39.6.2
|
specifier: ^39.6.2
|
||||||
version: 39.6.2_eslint@8.27.0
|
version: 39.6.2_eslint@8.32.0
|
||||||
eslint-plugin-json:
|
eslint-plugin-json:
|
||||||
specifier: ^3.1.0
|
specifier: ^3.1.0
|
||||||
version: 3.1.0
|
version: 3.1.0
|
||||||
eslint-plugin-lodash:
|
eslint-plugin-lodash:
|
||||||
specifier: ^7.4.0
|
specifier: ^7.4.0
|
||||||
version: 7.4.0_eslint@8.27.0
|
version: 7.4.0_eslint@8.32.0
|
||||||
eslint-plugin-markdown:
|
eslint-plugin-markdown:
|
||||||
specifier: ^3.0.0
|
specifier: ^3.0.0
|
||||||
version: 3.0.0_eslint@8.27.0
|
version: 3.0.0_eslint@8.32.0
|
||||||
eslint-plugin-no-only-tests:
|
eslint-plugin-no-only-tests:
|
||||||
specifier: ^3.1.0
|
specifier: ^3.1.0
|
||||||
version: 3.1.0
|
version: 3.1.0
|
||||||
@@ -105,7 +105,7 @@ importers:
|
|||||||
version: 0.2.17
|
version: 0.2.17
|
||||||
eslint-plugin-unicorn:
|
eslint-plugin-unicorn:
|
||||||
specifier: ^45.0.0
|
specifier: ^45.0.0
|
||||||
version: 45.0.0_eslint@8.27.0
|
version: 45.0.0_eslint@8.32.0
|
||||||
express:
|
express:
|
||||||
specifier: ^4.18.2
|
specifier: ^4.18.2
|
||||||
version: 4.18.2
|
version: 4.18.2
|
||||||
@@ -173,8 +173,8 @@ importers:
|
|||||||
specifier: ^7.0.0
|
specifier: ^7.0.0
|
||||||
version: 7.6.1
|
version: 7.6.1
|
||||||
dagre-d3-es:
|
dagre-d3-es:
|
||||||
specifier: 7.0.6
|
specifier: 7.0.8
|
||||||
version: 7.0.6
|
version: 7.0.8
|
||||||
dompurify:
|
dompurify:
|
||||||
specifier: 2.4.3
|
specifier: 2.4.3
|
||||||
version: 2.4.3
|
version: 2.4.3
|
||||||
@@ -187,8 +187,8 @@ importers:
|
|||||||
lodash-es:
|
lodash-es:
|
||||||
specifier: ^4.17.21
|
specifier: ^4.17.21
|
||||||
version: 4.17.21
|
version: 4.17.21
|
||||||
moment-mini:
|
moment:
|
||||||
specifier: ^2.24.0
|
specifier: ^2.29.4
|
||||||
version: 2.29.4
|
version: 2.29.4
|
||||||
non-layered-tidy-tree-layout:
|
non-layered-tidy-tree-layout:
|
||||||
specifier: ^2.0.2
|
specifier: ^2.0.2
|
||||||
@@ -229,10 +229,10 @@ importers:
|
|||||||
version: 8.3.4
|
version: 8.3.4
|
||||||
'@typescript-eslint/eslint-plugin':
|
'@typescript-eslint/eslint-plugin':
|
||||||
specifier: ^5.42.1
|
specifier: ^5.42.1
|
||||||
version: 5.42.1_2udltptbznfmezdozpdoa2aemq
|
version: 5.42.1_qxgr6oy2qtsmmpo3f6iejuryuq
|
||||||
'@typescript-eslint/parser':
|
'@typescript-eslint/parser':
|
||||||
specifier: ^5.42.1
|
specifier: ^5.42.1
|
||||||
version: 5.42.1_rmayb2veg2btbq6mbmnyivgasy
|
version: 5.42.1_yygwinqv3a2io74xmwofqb7uka
|
||||||
chokidar:
|
chokidar:
|
||||||
specifier: ^3.5.3
|
specifier: ^3.5.3
|
||||||
version: 3.5.3
|
version: 3.5.3
|
||||||
@@ -263,9 +263,6 @@ importers:
|
|||||||
micromatch:
|
micromatch:
|
||||||
specifier: ^4.0.5
|
specifier: ^4.0.5
|
||||||
version: 4.0.5
|
version: 4.0.5
|
||||||
moment:
|
|
||||||
specifier: ^2.29.4
|
|
||||||
version: 2.29.4
|
|
||||||
path-browserify:
|
path-browserify:
|
||||||
specifier: ^1.0.1
|
specifier: ^1.0.1
|
||||||
version: 1.0.1
|
version: 1.0.1
|
||||||
@@ -275,6 +272,9 @@ importers:
|
|||||||
remark:
|
remark:
|
||||||
specifier: ^14.0.2
|
specifier: ^14.0.2
|
||||||
version: 14.0.2
|
version: 14.0.2
|
||||||
|
remark-frontmatter:
|
||||||
|
specifier: ^4.0.1
|
||||||
|
version: 4.0.1
|
||||||
remark-gfm:
|
remark-gfm:
|
||||||
specifier: ^3.0.1
|
specifier: ^3.0.1
|
||||||
version: 3.0.1
|
version: 3.0.1
|
||||||
@@ -336,6 +336,9 @@ importers:
|
|||||||
specifier: ^2.0.2
|
specifier: ^2.0.2
|
||||||
version: 2.0.2
|
version: 2.0.2
|
||||||
devDependencies:
|
devDependencies:
|
||||||
|
'@types/cytoscape':
|
||||||
|
specifier: ^3.19.9
|
||||||
|
version: 3.19.9
|
||||||
concurrently:
|
concurrently:
|
||||||
specifier: ^7.5.0
|
specifier: ^7.5.0
|
||||||
version: 7.5.0
|
version: 7.5.0
|
||||||
@@ -2160,14 +2163,14 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@eslint/eslintrc/1.3.3:
|
/@eslint/eslintrc/1.4.1:
|
||||||
resolution: {integrity: sha512-uj3pT6Mg+3t39fvLrj8iuCIJ38zKO9FpGtJ4BBJebJhEwjoT+KLVNCcHT5QC9NGRIEi7fZ0ZR8YRb884auB4Lg==}
|
resolution: {integrity: sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
dependencies:
|
dependencies:
|
||||||
ajv: 6.12.6
|
ajv: 6.12.6
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
espree: 9.4.0
|
espree: 9.4.0
|
||||||
globals: 13.17.0
|
globals: 13.19.0
|
||||||
ignore: 5.2.0
|
ignore: 5.2.0
|
||||||
import-fresh: 3.3.0
|
import-fresh: 3.3.0
|
||||||
js-yaml: 4.1.0
|
js-yaml: 4.1.0
|
||||||
@@ -2187,8 +2190,8 @@ packages:
|
|||||||
'@hapi/hoek': 9.3.0
|
'@hapi/hoek': 9.3.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@humanwhocodes/config-array/0.11.7:
|
/@humanwhocodes/config-array/0.11.8:
|
||||||
resolution: {integrity: sha512-kBbPWzN8oVMLb0hOUYXhmxggL/1cJE6ydvjDIGi9EnAGUyA7cLVKQg+d/Dsm+KZwx2czGHrCmMVLiyg8s5JPKw==}
|
resolution: {integrity: sha512-UybHIJzJnR5Qc/MsD9Kr+RpO2h+/P1GhOwdiLPXK5TWk5sgTdu88bTD9UP+CKbPPh5Rni1u0GjAdYQLemG8g+g==}
|
||||||
engines: {node: '>=10.10.0'}
|
engines: {node: '>=10.10.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
'@humanwhocodes/object-schema': 1.2.1
|
'@humanwhocodes/object-schema': 1.2.1
|
||||||
@@ -2672,6 +2675,10 @@ packages:
|
|||||||
'@types/node': 18.11.9
|
'@types/node': 18.11.9
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@types/cytoscape/3.19.9:
|
||||||
|
resolution: {integrity: sha512-oqCx0ZGiBO0UESbjgq052vjDAy2X53lZpMrWqiweMpvVwKw/2IiYDdzPFK6+f4tMfdv9YKEM9raO5bAZc3UYBg==}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@types/d3-array/3.0.3:
|
/@types/d3-array/3.0.3:
|
||||||
resolution: {integrity: sha512-Reoy+pKnvsksN0lQUlcH6dOGjRZ/3WRwXR//m+/8lt1BXeI4xyaUZoqULNjyXXRuh0Mj4LNpkCvhUpQlY3X5xQ==}
|
resolution: {integrity: sha512-Reoy+pKnvsksN0lQUlcH6dOGjRZ/3WRwXR//m+/8lt1BXeI4xyaUZoqULNjyXXRuh0Mj4LNpkCvhUpQlY3X5xQ==}
|
||||||
dev: true
|
dev: true
|
||||||
@@ -3152,7 +3159,7 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
optional: true
|
optional: true
|
||||||
|
|
||||||
/@typescript-eslint/eslint-plugin/5.42.1_2udltptbznfmezdozpdoa2aemq:
|
/@typescript-eslint/eslint-plugin/5.42.1_qxgr6oy2qtsmmpo3f6iejuryuq:
|
||||||
resolution: {integrity: sha512-LyR6x784JCiJ1j6sH5Y0K6cdExqCCm8DJUTcwG5ThNXJj/G8o5E56u5EdG4SLy+bZAwZBswC+GYn3eGdttBVCg==}
|
resolution: {integrity: sha512-LyR6x784JCiJ1j6sH5Y0K6cdExqCCm8DJUTcwG5ThNXJj/G8o5E56u5EdG4SLy+bZAwZBswC+GYn3eGdttBVCg==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3163,12 +3170,12 @@ packages:
|
|||||||
typescript:
|
typescript:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/parser': 5.42.1_rmayb2veg2btbq6mbmnyivgasy
|
'@typescript-eslint/parser': 5.42.1_yygwinqv3a2io74xmwofqb7uka
|
||||||
'@typescript-eslint/scope-manager': 5.42.1
|
'@typescript-eslint/scope-manager': 5.42.1
|
||||||
'@typescript-eslint/type-utils': 5.42.1_rmayb2veg2btbq6mbmnyivgasy
|
'@typescript-eslint/type-utils': 5.42.1_yygwinqv3a2io74xmwofqb7uka
|
||||||
'@typescript-eslint/utils': 5.42.1_rmayb2veg2btbq6mbmnyivgasy
|
'@typescript-eslint/utils': 5.42.1_yygwinqv3a2io74xmwofqb7uka
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.27.0
|
eslint: 8.32.0
|
||||||
ignore: 5.2.0
|
ignore: 5.2.0
|
||||||
natural-compare-lite: 1.4.0
|
natural-compare-lite: 1.4.0
|
||||||
regexpp: 3.2.0
|
regexpp: 3.2.0
|
||||||
@@ -3179,7 +3186,34 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@typescript-eslint/parser/5.42.1_rmayb2veg2btbq6mbmnyivgasy:
|
/@typescript-eslint/eslint-plugin/5.48.2_iljmjqxcygjq3saipl7gerxpvi:
|
||||||
|
resolution: {integrity: sha512-sR0Gja9Ky1teIq4qJOl0nC+Tk64/uYdX+mi+5iB//MH8gwyx8e3SOyhEzeLZEFEEfCaLf8KJq+Bd/6je1t+CAg==}
|
||||||
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
'@typescript-eslint/parser': ^5.0.0
|
||||||
|
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||||
|
typescript: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@typescript-eslint/parser': 5.48.2_yygwinqv3a2io74xmwofqb7uka
|
||||||
|
'@typescript-eslint/scope-manager': 5.48.2
|
||||||
|
'@typescript-eslint/type-utils': 5.48.2_yygwinqv3a2io74xmwofqb7uka
|
||||||
|
'@typescript-eslint/utils': 5.48.2_yygwinqv3a2io74xmwofqb7uka
|
||||||
|
debug: 4.3.4
|
||||||
|
eslint: 8.32.0
|
||||||
|
ignore: 5.2.0
|
||||||
|
natural-compare-lite: 1.4.0
|
||||||
|
regexpp: 3.2.0
|
||||||
|
semver: 7.3.8
|
||||||
|
tsutils: 3.21.0_typescript@4.8.4
|
||||||
|
typescript: 4.8.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/parser/5.42.1_yygwinqv3a2io74xmwofqb7uka:
|
||||||
resolution: {integrity: sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==}
|
resolution: {integrity: sha512-kAV+NiNBWVQDY9gDJDToTE/NO8BHi4f6b7zTsVAJoTkmB/zlfOpiEVBzHOKtlgTndCKe8vj9F/PuolemZSh50Q==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3193,7 +3227,27 @@ packages:
|
|||||||
'@typescript-eslint/types': 5.42.1
|
'@typescript-eslint/types': 5.42.1
|
||||||
'@typescript-eslint/typescript-estree': 5.42.1_typescript@4.8.4
|
'@typescript-eslint/typescript-estree': 5.42.1_typescript@4.8.4
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.27.0
|
eslint: 8.32.0
|
||||||
|
typescript: 4.8.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/parser/5.48.2_yygwinqv3a2io74xmwofqb7uka:
|
||||||
|
resolution: {integrity: sha512-38zMsKsG2sIuM5Oi/olurGwYJXzmtdsHhn5mI/pQogP+BjYVkK5iRazCQ8RGS0V+YLk282uWElN70zAAUmaYHw==}
|
||||||
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||||
|
typescript: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@typescript-eslint/scope-manager': 5.48.2
|
||||||
|
'@typescript-eslint/types': 5.48.2
|
||||||
|
'@typescript-eslint/typescript-estree': 5.48.2_typescript@4.8.4
|
||||||
|
debug: 4.3.4
|
||||||
|
eslint: 8.32.0
|
||||||
typescript: 4.8.4
|
typescript: 4.8.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -3207,7 +3261,15 @@ packages:
|
|||||||
'@typescript-eslint/visitor-keys': 5.42.1
|
'@typescript-eslint/visitor-keys': 5.42.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@typescript-eslint/type-utils/5.42.1_rmayb2veg2btbq6mbmnyivgasy:
|
/@typescript-eslint/scope-manager/5.48.2:
|
||||||
|
resolution: {integrity: sha512-zEUFfonQid5KRDKoI3O+uP1GnrFd4tIHlvs+sTJXiWuypUWMuDaottkJuR612wQfOkjYbsaskSIURV9xo4f+Fw==}
|
||||||
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
dependencies:
|
||||||
|
'@typescript-eslint/types': 5.48.2
|
||||||
|
'@typescript-eslint/visitor-keys': 5.48.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/type-utils/5.42.1_yygwinqv3a2io74xmwofqb7uka:
|
||||||
resolution: {integrity: sha512-WWiMChneex5w4xPIX56SSnQQo0tEOy5ZV2dqmj8Z371LJ0E+aymWD25JQ/l4FOuuX+Q49A7pzh/CGIQflxMVXg==}
|
resolution: {integrity: sha512-WWiMChneex5w4xPIX56SSnQQo0tEOy5ZV2dqmj8Z371LJ0E+aymWD25JQ/l4FOuuX+Q49A7pzh/CGIQflxMVXg==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3218,9 +3280,29 @@ packages:
|
|||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/typescript-estree': 5.42.1_typescript@4.8.4
|
'@typescript-eslint/typescript-estree': 5.42.1_typescript@4.8.4
|
||||||
'@typescript-eslint/utils': 5.42.1_rmayb2veg2btbq6mbmnyivgasy
|
'@typescript-eslint/utils': 5.42.1_yygwinqv3a2io74xmwofqb7uka
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
eslint: 8.27.0
|
eslint: 8.32.0
|
||||||
|
tsutils: 3.21.0_typescript@4.8.4
|
||||||
|
typescript: 4.8.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/type-utils/5.48.2_yygwinqv3a2io74xmwofqb7uka:
|
||||||
|
resolution: {integrity: sha512-QVWx7J5sPMRiOMJp5dYshPxABRoZV1xbRirqSk8yuIIsu0nvMTZesKErEA3Oix1k+uvsk8Cs8TGJ6kQ0ndAcew==}
|
||||||
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
eslint: '*'
|
||||||
|
typescript: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@typescript-eslint/typescript-estree': 5.48.2_typescript@4.8.4
|
||||||
|
'@typescript-eslint/utils': 5.48.2_yygwinqv3a2io74xmwofqb7uka
|
||||||
|
debug: 4.3.4
|
||||||
|
eslint: 8.32.0
|
||||||
tsutils: 3.21.0_typescript@4.8.4
|
tsutils: 3.21.0_typescript@4.8.4
|
||||||
typescript: 4.8.4
|
typescript: 4.8.4
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
@@ -3232,6 +3314,11 @@ packages:
|
|||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/types/5.48.2:
|
||||||
|
resolution: {integrity: sha512-hE7dA77xxu7ByBc6KCzikgfRyBCTst6dZQpwaTy25iMYOnbNljDT4hjhrGEJJ0QoMjrfqrx+j1l1B9/LtKeuqA==}
|
||||||
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@typescript-eslint/typescript-estree/5.42.1_typescript@4.8.4:
|
/@typescript-eslint/typescript-estree/5.42.1_typescript@4.8.4:
|
||||||
resolution: {integrity: sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==}
|
resolution: {integrity: sha512-qElc0bDOuO0B8wDhhW4mYVgi/LZL+igPwXtV87n69/kYC/7NG3MES0jHxJNCr4EP7kY1XVsRy8C/u3DYeTKQmw==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
@@ -3253,7 +3340,28 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/@typescript-eslint/utils/5.42.1_rmayb2veg2btbq6mbmnyivgasy:
|
/@typescript-eslint/typescript-estree/5.48.2_typescript@4.8.4:
|
||||||
|
resolution: {integrity: sha512-bibvD3z6ilnoVxUBFEgkO0k0aFvUc4Cttt0dAreEr+nrAHhWzkO83PEVVuieK3DqcgL6VAK5dkzK8XUVja5Zcg==}
|
||||||
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
typescript: '*'
|
||||||
|
peerDependenciesMeta:
|
||||||
|
typescript:
|
||||||
|
optional: true
|
||||||
|
dependencies:
|
||||||
|
'@typescript-eslint/types': 5.48.2
|
||||||
|
'@typescript-eslint/visitor-keys': 5.48.2
|
||||||
|
debug: 4.3.4
|
||||||
|
globby: 11.1.0
|
||||||
|
is-glob: 4.0.3
|
||||||
|
semver: 7.3.8
|
||||||
|
tsutils: 3.21.0_typescript@4.8.4
|
||||||
|
typescript: 4.8.4
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/utils/5.42.1_yygwinqv3a2io74xmwofqb7uka:
|
||||||
resolution: {integrity: sha512-Gxvf12xSp3iYZd/fLqiQRD4uKZjDNR01bQ+j8zvhPjpsZ4HmvEFL/tC4amGNyxN9Rq+iqvpHLhlqx6KTxz9ZyQ==}
|
resolution: {integrity: sha512-Gxvf12xSp3iYZd/fLqiQRD4uKZjDNR01bQ+j8zvhPjpsZ4HmvEFL/tC4amGNyxN9Rq+iqvpHLhlqx6KTxz9ZyQ==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -3264,9 +3372,29 @@ packages:
|
|||||||
'@typescript-eslint/scope-manager': 5.42.1
|
'@typescript-eslint/scope-manager': 5.42.1
|
||||||
'@typescript-eslint/types': 5.42.1
|
'@typescript-eslint/types': 5.42.1
|
||||||
'@typescript-eslint/typescript-estree': 5.42.1_typescript@4.8.4
|
'@typescript-eslint/typescript-estree': 5.42.1_typescript@4.8.4
|
||||||
eslint: 8.27.0
|
eslint: 8.32.0
|
||||||
eslint-scope: 5.1.1
|
eslint-scope: 5.1.1
|
||||||
eslint-utils: 3.0.0_eslint@8.27.0
|
eslint-utils: 3.0.0_eslint@8.32.0
|
||||||
|
semver: 7.3.8
|
||||||
|
transitivePeerDependencies:
|
||||||
|
- supports-color
|
||||||
|
- typescript
|
||||||
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/utils/5.48.2_yygwinqv3a2io74xmwofqb7uka:
|
||||||
|
resolution: {integrity: sha512-2h18c0d7jgkw6tdKTlNaM7wyopbLRBiit8oAxoP89YnuBOzCZ8g8aBCaCqq7h208qUTroL7Whgzam7UY3HVLow==}
|
||||||
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
peerDependencies:
|
||||||
|
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||||
|
dependencies:
|
||||||
|
'@types/json-schema': 7.0.11
|
||||||
|
'@types/semver': 7.3.12
|
||||||
|
'@typescript-eslint/scope-manager': 5.48.2
|
||||||
|
'@typescript-eslint/types': 5.48.2
|
||||||
|
'@typescript-eslint/typescript-estree': 5.48.2_typescript@4.8.4
|
||||||
|
eslint: 8.32.0
|
||||||
|
eslint-scope: 5.1.1
|
||||||
|
eslint-utils: 3.0.0_eslint@8.32.0
|
||||||
semver: 7.3.8
|
semver: 7.3.8
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -3281,6 +3409,14 @@ packages:
|
|||||||
eslint-visitor-keys: 3.3.0
|
eslint-visitor-keys: 3.3.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/@typescript-eslint/visitor-keys/5.48.2:
|
||||||
|
resolution: {integrity: sha512-z9njZLSkwmjFWUelGEwEbdf4NwKvfHxvGC0OcGN1Hp/XNDIcJ7D5DpPNPv6x6/mFvc1tQHsaWmpD/a4gOvvCJQ==}
|
||||||
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
|
dependencies:
|
||||||
|
'@typescript-eslint/types': 5.48.2
|
||||||
|
eslint-visitor-keys: 3.3.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/@vitejs/plugin-vue/4.0.0_vite@4.0.1+vue@3.2.45:
|
/@vitejs/plugin-vue/4.0.0_vite@4.0.1+vue@3.2.45:
|
||||||
resolution: {integrity: sha512-e0X4jErIxAB5oLtDqbHvHpJe/uWNkdpYV83AOG2xo2tEVSzCzewgJMtREZM30wXnM5ls90hxiOtAuVU6H5JgbA==}
|
resolution: {integrity: sha512-e0X4jErIxAB5oLtDqbHvHpJe/uWNkdpYV83AOG2xo2tEVSzCzewgJMtREZM30wXnM5ls90hxiOtAuVU6H5JgbA==}
|
||||||
engines: {node: ^14.18.0 || >=16.0.0}
|
engines: {node: ^14.18.0 || >=16.0.0}
|
||||||
@@ -3677,12 +3813,12 @@ packages:
|
|||||||
acorn: 8.8.0
|
acorn: 8.8.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/acorn-jsx/5.3.2_acorn@8.8.0:
|
/acorn-jsx/5.3.2_acorn@8.8.1:
|
||||||
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
resolution: {integrity: sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
|
acorn: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.8.0
|
acorn: 8.8.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/acorn-walk/7.2.0:
|
/acorn-walk/7.2.0:
|
||||||
@@ -3986,7 +4122,7 @@ packages:
|
|||||||
/axios/0.21.4_debug@4.3.2:
|
/axios/0.21.4_debug@4.3.2:
|
||||||
resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==}
|
resolution: {integrity: sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
follow-redirects: 1.15.2_debug@4.3.2
|
follow-redirects: 1.15.2
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- debug
|
- debug
|
||||||
dev: true
|
dev: true
|
||||||
@@ -4623,7 +4759,7 @@ packages:
|
|||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/concat-map/0.0.1:
|
/concat-map/0.0.1:
|
||||||
resolution: {integrity: sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==}
|
resolution: {integrity: sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/concurrently/7.5.0:
|
/concurrently/7.5.0:
|
||||||
@@ -5406,8 +5542,8 @@ packages:
|
|||||||
d3-zoom: 3.0.0
|
d3-zoom: 3.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/d3/7.7.0:
|
/d3/7.8.2:
|
||||||
resolution: {integrity: sha512-VEwHCMgMjD2WBsxeRGUE18RmzxT9Bn7ghDpzvTEvkLSBAKgTMydJjouZTjspgQfRHpPt/PB3EHWBa6SSyFQq4g==}
|
resolution: {integrity: sha512-WXty7qOGSHb7HR7CfOzwN1Gw04MUOzN8qh9ZUsvwycIMb4DYMpY9xczZ6jUorGtO6bR9BPMPaueIKwiDxu9uiQ==}
|
||||||
engines: {node: '>=12'}
|
engines: {node: '>=12'}
|
||||||
dependencies:
|
dependencies:
|
||||||
d3-array: 3.2.0
|
d3-array: 3.2.0
|
||||||
@@ -5442,10 +5578,10 @@ packages:
|
|||||||
d3-zoom: 3.0.0
|
d3-zoom: 3.0.0
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
/dagre-d3-es/7.0.6:
|
/dagre-d3-es/7.0.8:
|
||||||
resolution: {integrity: sha512-CaaE/nZh205ix+Up4xsnlGmpog5GGm81Upi2+/SBHxwNwrccBb3K51LzjZ1U6hgvOlAEUsVWf1xSTzCyKpJ6+Q==}
|
resolution: {integrity: sha512-eykdoYQ4FwCJinEYS0gPL2f2w+BPbSLvnQSJ3Ye1vAoPjdkq6xIMKBv+UkICd3qZE26wBKIn3p+6n0QC7R1LyA==}
|
||||||
dependencies:
|
dependencies:
|
||||||
d3: 7.7.0
|
d3: 7.8.2
|
||||||
lodash-es: 4.17.21
|
lodash-es: 4.17.21
|
||||||
dev: false
|
dev: false
|
||||||
|
|
||||||
@@ -6184,21 +6320,21 @@ packages:
|
|||||||
source-map: 0.6.1
|
source-map: 0.6.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/eslint-config-prettier/8.5.0_eslint@8.27.0:
|
/eslint-config-prettier/8.6.0_eslint@8.32.0:
|
||||||
resolution: {integrity: sha512-obmWKLUNCnhtQRKc+tmnYuQl0pFU1ibYJQ5BGhTVB08bHe9wC8qUeG7c08dj9XX+AuPj1YSGSQIHl1pnDHZR0Q==}
|
resolution: {integrity: sha512-bAF0eLpLVqP5oEVUFKpMA+NnRFICwn9X8B5jrR9FcqnYBuPbqWEjTEspPWMj5ye6czoSLDweCzSo3Ko7gGrZaA==}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: '>=7.0.0'
|
eslint: '>=7.0.0'
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 8.27.0
|
eslint: 8.32.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/eslint-plugin-cypress/2.12.1_eslint@8.27.0:
|
/eslint-plugin-cypress/2.12.1_eslint@8.32.0:
|
||||||
resolution: {integrity: sha512-c2W/uPADl5kospNDihgiLc7n87t5XhUbFDoTl6CfVkmG+kDAb5Ux10V9PoLPu9N+r7znpc+iQlcmAqT1A/89HA==}
|
resolution: {integrity: sha512-c2W/uPADl5kospNDihgiLc7n87t5XhUbFDoTl6CfVkmG+kDAb5Ux10V9PoLPu9N+r7znpc+iQlcmAqT1A/89HA==}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: '>= 3.2.1'
|
eslint: '>= 3.2.1'
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 8.27.0
|
eslint: 8.32.0
|
||||||
globals: 11.12.0
|
globals: 11.12.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@@ -6208,7 +6344,7 @@ packages:
|
|||||||
htmlparser2: 8.0.1
|
htmlparser2: 8.0.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/eslint-plugin-jest/27.1.5_kdswgjmqcx7mthqz7ow2zlfevy:
|
/eslint-plugin-jest/27.1.5_5rcd23qw3h5vuffwo2owxb3hw4:
|
||||||
resolution: {integrity: sha512-CK2dekZ5VBdzsOSOH5Fc1rwC+cWXjkcyrmf1RV714nDUDKu+o73TTJiDxpbILG8PtPPpAAl3ywzh5QA7Ft0mjA==}
|
resolution: {integrity: sha512-CK2dekZ5VBdzsOSOH5Fc1rwC+cWXjkcyrmf1RV714nDUDKu+o73TTJiDxpbILG8PtPPpAAl3ywzh5QA7Ft0mjA==}
|
||||||
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -6221,16 +6357,16 @@ packages:
|
|||||||
jest:
|
jest:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@typescript-eslint/eslint-plugin': 5.42.1_2udltptbznfmezdozpdoa2aemq
|
'@typescript-eslint/eslint-plugin': 5.48.2_iljmjqxcygjq3saipl7gerxpvi
|
||||||
'@typescript-eslint/utils': 5.42.1_rmayb2veg2btbq6mbmnyivgasy
|
'@typescript-eslint/utils': 5.42.1_yygwinqv3a2io74xmwofqb7uka
|
||||||
eslint: 8.27.0
|
eslint: 8.32.0
|
||||||
jest: 29.3.1_odkjkoia5xunhxkdrka32ib6vi
|
jest: 29.3.1_odkjkoia5xunhxkdrka32ib6vi
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
- typescript
|
- typescript
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/eslint-plugin-jsdoc/39.6.2_eslint@8.27.0:
|
/eslint-plugin-jsdoc/39.6.2_eslint@8.32.0:
|
||||||
resolution: {integrity: sha512-dvgY/W7eUFoAIIiaWHERIMI61ZWqcz9YFjEeyTzdPlrZc3TY/3aZm5aB91NUoTLWYZmO/vFlYSuQi15tF7uE5A==}
|
resolution: {integrity: sha512-dvgY/W7eUFoAIIiaWHERIMI61ZWqcz9YFjEeyTzdPlrZc3TY/3aZm5aB91NUoTLWYZmO/vFlYSuQi15tF7uE5A==}
|
||||||
engines: {node: ^14 || ^16 || ^17 || ^18 || ^19}
|
engines: {node: ^14 || ^16 || ^17 || ^18 || ^19}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -6240,7 +6376,7 @@ packages:
|
|||||||
comment-parser: 1.3.1
|
comment-parser: 1.3.1
|
||||||
debug: 4.3.4
|
debug: 4.3.4
|
||||||
escape-string-regexp: 4.0.0
|
escape-string-regexp: 4.0.0
|
||||||
eslint: 8.27.0
|
eslint: 8.32.0
|
||||||
esquery: 1.4.0
|
esquery: 1.4.0
|
||||||
semver: 7.3.8
|
semver: 7.3.8
|
||||||
spdx-expression-parse: 3.0.1
|
spdx-expression-parse: 3.0.1
|
||||||
@@ -6256,23 +6392,23 @@ packages:
|
|||||||
vscode-json-languageservice: 4.2.1
|
vscode-json-languageservice: 4.2.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/eslint-plugin-lodash/7.4.0_eslint@8.27.0:
|
/eslint-plugin-lodash/7.4.0_eslint@8.32.0:
|
||||||
resolution: {integrity: sha512-Tl83UwVXqe1OVeBRKUeWcfg6/pCW1GTRObbdnbEJgYwjxp5Q92MEWQaH9+dmzbRt6kvYU1Mp893E79nJiCSM8A==}
|
resolution: {integrity: sha512-Tl83UwVXqe1OVeBRKUeWcfg6/pCW1GTRObbdnbEJgYwjxp5Q92MEWQaH9+dmzbRt6kvYU1Mp893E79nJiCSM8A==}
|
||||||
engines: {node: '>=10'}
|
engines: {node: '>=10'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: '>=2'
|
eslint: '>=2'
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 8.27.0
|
eslint: 8.32.0
|
||||||
lodash: 4.17.21
|
lodash: 4.17.21
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/eslint-plugin-markdown/3.0.0_eslint@8.27.0:
|
/eslint-plugin-markdown/3.0.0_eslint@8.32.0:
|
||||||
resolution: {integrity: sha512-hRs5RUJGbeHDLfS7ELanT0e29Ocyssf/7kBM+p7KluY5AwngGkDf8Oyu4658/NZSGTTq05FZeWbkxXtbVyHPwg==}
|
resolution: {integrity: sha512-hRs5RUJGbeHDLfS7ELanT0e29Ocyssf/7kBM+p7KluY5AwngGkDf8Oyu4658/NZSGTTq05FZeWbkxXtbVyHPwg==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
eslint: ^6.0.0 || ^7.0.0 || ^8.0.0
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 8.27.0
|
eslint: 8.32.0
|
||||||
mdast-util-from-markdown: 0.8.5
|
mdast-util-from-markdown: 0.8.5
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- supports-color
|
- supports-color
|
||||||
@@ -6290,7 +6426,7 @@ packages:
|
|||||||
'@microsoft/tsdoc-config': 0.16.2
|
'@microsoft/tsdoc-config': 0.16.2
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/eslint-plugin-unicorn/45.0.0_eslint@8.27.0:
|
/eslint-plugin-unicorn/45.0.0_eslint@8.32.0:
|
||||||
resolution: {integrity: sha512-iP8cMRxXKHonKioOhnCoCcqVhoqhAp6rB+nsoLjXFDxTHz3btWMAp8xwzjHA0B1K6YV/U/Yvqn1bUXZt8sJPuQ==}
|
resolution: {integrity: sha512-iP8cMRxXKHonKioOhnCoCcqVhoqhAp6rB+nsoLjXFDxTHz3btWMAp8xwzjHA0B1K6YV/U/Yvqn1bUXZt8sJPuQ==}
|
||||||
engines: {node: '>=14.18'}
|
engines: {node: '>=14.18'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -6299,8 +6435,8 @@ packages:
|
|||||||
'@babel/helper-validator-identifier': 7.19.1
|
'@babel/helper-validator-identifier': 7.19.1
|
||||||
ci-info: 3.6.2
|
ci-info: 3.6.2
|
||||||
clean-regexp: 1.0.0
|
clean-regexp: 1.0.0
|
||||||
eslint: 8.27.0
|
eslint: 8.32.0
|
||||||
eslint-utils: 3.0.0_eslint@8.27.0
|
eslint-utils: 3.0.0_eslint@8.32.0
|
||||||
esquery: 1.4.0
|
esquery: 1.4.0
|
||||||
indent-string: 4.0.0
|
indent-string: 4.0.0
|
||||||
is-builtin-module: 3.2.0
|
is-builtin-module: 3.2.0
|
||||||
@@ -6331,13 +6467,13 @@ packages:
|
|||||||
estraverse: 5.3.0
|
estraverse: 5.3.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/eslint-utils/3.0.0_eslint@8.27.0:
|
/eslint-utils/3.0.0_eslint@8.32.0:
|
||||||
resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
|
resolution: {integrity: sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==}
|
||||||
engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
|
engines: {node: ^10.0.0 || ^12.0.0 || >= 14.0.0}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
eslint: '>=5'
|
eslint: '>=5'
|
||||||
dependencies:
|
dependencies:
|
||||||
eslint: 8.27.0
|
eslint: 8.32.0
|
||||||
eslint-visitor-keys: 2.1.0
|
eslint-visitor-keys: 2.1.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@@ -6351,13 +6487,13 @@ packages:
|
|||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/eslint/8.27.0:
|
/eslint/8.32.0:
|
||||||
resolution: {integrity: sha512-0y1bfG2ho7mty+SiILVf9PfuRA49ek4Nc60Wmmu62QlobNR+CeXa4xXIJgcuwSQgZiWaPH+5BDsctpIW0PR/wQ==}
|
resolution: {integrity: sha512-nETVXpnthqKPFyuY2FNjz/bEd6nbosRgKbkgS/y1C7LJop96gYHWpiguLecMHQ2XCPxn77DS0P+68WzG6vkZSQ==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
hasBin: true
|
hasBin: true
|
||||||
dependencies:
|
dependencies:
|
||||||
'@eslint/eslintrc': 1.3.3
|
'@eslint/eslintrc': 1.4.1
|
||||||
'@humanwhocodes/config-array': 0.11.7
|
'@humanwhocodes/config-array': 0.11.8
|
||||||
'@humanwhocodes/module-importer': 1.0.1
|
'@humanwhocodes/module-importer': 1.0.1
|
||||||
'@nodelib/fs.walk': 1.2.8
|
'@nodelib/fs.walk': 1.2.8
|
||||||
ajv: 6.12.6
|
ajv: 6.12.6
|
||||||
@@ -6367,7 +6503,7 @@ packages:
|
|||||||
doctrine: 3.0.0
|
doctrine: 3.0.0
|
||||||
escape-string-regexp: 4.0.0
|
escape-string-regexp: 4.0.0
|
||||||
eslint-scope: 7.1.1
|
eslint-scope: 7.1.1
|
||||||
eslint-utils: 3.0.0_eslint@8.27.0
|
eslint-utils: 3.0.0_eslint@8.32.0
|
||||||
eslint-visitor-keys: 3.3.0
|
eslint-visitor-keys: 3.3.0
|
||||||
espree: 9.4.0
|
espree: 9.4.0
|
||||||
esquery: 1.4.0
|
esquery: 1.4.0
|
||||||
@@ -6376,7 +6512,7 @@ packages:
|
|||||||
file-entry-cache: 6.0.1
|
file-entry-cache: 6.0.1
|
||||||
find-up: 5.0.0
|
find-up: 5.0.0
|
||||||
glob-parent: 6.0.2
|
glob-parent: 6.0.2
|
||||||
globals: 13.17.0
|
globals: 13.19.0
|
||||||
grapheme-splitter: 1.0.4
|
grapheme-splitter: 1.0.4
|
||||||
ignore: 5.2.0
|
ignore: 5.2.0
|
||||||
import-fresh: 3.3.0
|
import-fresh: 3.3.0
|
||||||
@@ -6403,8 +6539,8 @@ packages:
|
|||||||
resolution: {integrity: sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==}
|
resolution: {integrity: sha512-DQmnRpLj7f6TgN/NYb0MTzJXL+vJF9h3pHy4JhCIs3zwcgez8xmGg3sXHcEO97BrmO2OSvCwMdfdlyl+E9KjOw==}
|
||||||
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
|
||||||
dependencies:
|
dependencies:
|
||||||
acorn: 8.8.0
|
acorn: 8.8.1
|
||||||
acorn-jsx: 5.3.2_acorn@8.8.0
|
acorn-jsx: 5.3.2_acorn@8.8.1
|
||||||
eslint-visitor-keys: 3.3.0
|
eslint-visitor-keys: 3.3.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
@@ -6679,6 +6815,12 @@ packages:
|
|||||||
reusify: 1.0.4
|
reusify: 1.0.4
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/fault/2.0.1:
|
||||||
|
resolution: {integrity: sha512-WtySTkS4OKev5JtpHXnib4Gxiurzh5NCGvWrFaZ34m6JehfTUhKZvn9njTfw48t6JumVQOmrKqpmGcdwxnhqBQ==}
|
||||||
|
dependencies:
|
||||||
|
format: 0.2.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/faye-websocket/0.11.4:
|
/faye-websocket/0.11.4:
|
||||||
resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==}
|
resolution: {integrity: sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==}
|
||||||
engines: {node: '>=0.8.0'}
|
engines: {node: '>=0.8.0'}
|
||||||
@@ -6778,7 +6920,7 @@ packages:
|
|||||||
resolution: {integrity: sha512-XGozTsMPYkm+6b5QL3Z9wQcJjNYxp0CYn3U1gO7dwD6PAqU1SVWZxI9CCg3z+ml3YfqdPnrBehaBrnH2AGKbNA==}
|
resolution: {integrity: sha512-XGozTsMPYkm+6b5QL3Z9wQcJjNYxp0CYn3U1gO7dwD6PAqU1SVWZxI9CCg3z+ml3YfqdPnrBehaBrnH2AGKbNA==}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/follow-redirects/1.15.2_debug@4.3.2:
|
/follow-redirects/1.15.2:
|
||||||
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
|
resolution: {integrity: sha512-VQLG33o04KaQ8uYi2tVNbdrWp1QWxNNea+nmIB4EVM28v0hmP17z7aG1+wAkNzVq4KeXTq3221ye5qTJP91JwA==}
|
||||||
engines: {node: '>=4.0'}
|
engines: {node: '>=4.0'}
|
||||||
peerDependencies:
|
peerDependencies:
|
||||||
@@ -6786,8 +6928,6 @@ packages:
|
|||||||
peerDependenciesMeta:
|
peerDependenciesMeta:
|
||||||
debug:
|
debug:
|
||||||
optional: true
|
optional: true
|
||||||
dependencies:
|
|
||||||
debug: 4.3.2
|
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/foreground-child/2.0.0:
|
/foreground-child/2.0.0:
|
||||||
@@ -6829,6 +6969,11 @@ packages:
|
|||||||
mime-types: 2.1.35
|
mime-types: 2.1.35
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/format/0.2.2:
|
||||||
|
resolution: {integrity: sha512-wzsgA6WOq+09wrU1tsJ09udeR/YZRaeArL9e1wPbFg3GG2yDnC2ldKpxs4xunpFF9DgqCqOIra3bc1HWrJ37Ww==}
|
||||||
|
engines: {node: '>=0.4.x'}
|
||||||
|
dev: true
|
||||||
|
|
||||||
/forwarded/0.2.0:
|
/forwarded/0.2.0:
|
||||||
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
|
resolution: {integrity: sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==}
|
||||||
engines: {node: '>= 0.6'}
|
engines: {node: '>= 0.6'}
|
||||||
@@ -7066,8 +7211,8 @@ packages:
|
|||||||
engines: {node: '>=4'}
|
engines: {node: '>=4'}
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/globals/13.17.0:
|
/globals/13.19.0:
|
||||||
resolution: {integrity: sha512-1C+6nQRb1GwGMKm2dH/E7enFAMxGTmGI7/dEdhy/DNelv85w9B72t3uc5frtMNXIbzrarJJ/lTCjcaZwbLJmyw==}
|
resolution: {integrity: sha512-dkQ957uSRWHw7CFXLUtUHQI3g3aWApYhfNR2O6jn/907riyTYKVBmxYVROkBcY614FSSeSJh7Xm7SrUWCxvJMQ==}
|
||||||
engines: {node: '>=8'}
|
engines: {node: '>=8'}
|
||||||
dependencies:
|
dependencies:
|
||||||
type-fest: 0.20.2
|
type-fest: 0.20.2
|
||||||
@@ -7322,7 +7467,7 @@ packages:
|
|||||||
engines: {node: '>=8.0.0'}
|
engines: {node: '>=8.0.0'}
|
||||||
dependencies:
|
dependencies:
|
||||||
eventemitter3: 4.0.7
|
eventemitter3: 4.0.7
|
||||||
follow-redirects: 1.15.2_debug@4.3.2
|
follow-redirects: 1.15.2
|
||||||
requires-port: 1.0.0
|
requires-port: 1.0.0
|
||||||
transitivePeerDependencies:
|
transitivePeerDependencies:
|
||||||
- debug
|
- debug
|
||||||
@@ -8763,6 +8908,12 @@ packages:
|
|||||||
- supports-color
|
- supports-color
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/mdast-util-frontmatter/1.0.0:
|
||||||
|
resolution: {integrity: sha512-7itKvp0arEVNpCktOET/eLFAYaZ+0cNjVtFtIPxgQ5tV+3i+D4SDDTjTzPWl44LT59PC+xdx+glNTawBdF98Mw==}
|
||||||
|
dependencies:
|
||||||
|
micromark-extension-frontmatter: 1.0.0
|
||||||
|
dev: true
|
||||||
|
|
||||||
/mdast-util-gfm-autolink-literal/1.0.2:
|
/mdast-util-gfm-autolink-literal/1.0.2:
|
||||||
resolution: {integrity: sha512-FzopkOd4xTTBeGXhXSBU0OCDDh5lUj2rd+HQqG92Ld+jL4lpUfgX2AT2OHAVP9aEeDKp7G92fuooSZcYJA3cRg==}
|
resolution: {integrity: sha512-FzopkOd4xTTBeGXhXSBU0OCDDh5lUj2rd+HQqG92Ld+jL4lpUfgX2AT2OHAVP9aEeDKp7G92fuooSZcYJA3cRg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -8933,6 +9084,14 @@ packages:
|
|||||||
uvu: 0.5.6
|
uvu: 0.5.6
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/micromark-extension-frontmatter/1.0.0:
|
||||||
|
resolution: {integrity: sha512-EXjmRnupoX6yYuUJSQhrQ9ggK0iQtQlpi6xeJzVD5xscyAI+giqco5fdymayZhJMbIFecjnE2yz85S9NzIgQpg==}
|
||||||
|
dependencies:
|
||||||
|
fault: 2.0.1
|
||||||
|
micromark-util-character: 1.1.0
|
||||||
|
micromark-util-symbol: 1.0.1
|
||||||
|
dev: true
|
||||||
|
|
||||||
/micromark-extension-gfm-autolink-literal/1.0.3:
|
/micromark-extension-gfm-autolink-literal/1.0.3:
|
||||||
resolution: {integrity: sha512-i3dmvU0htawfWED8aHMMAzAVp/F0Z+0bPh3YrbTPPL1v4YAlCZpy5rBO5p0LPYiZo0zFVkoYh7vDU7yQSiCMjg==}
|
resolution: {integrity: sha512-i3dmvU0htawfWED8aHMMAzAVp/F0Z+0bPh3YrbTPPL1v4YAlCZpy5rBO5p0LPYiZo0zFVkoYh7vDU7yQSiCMjg==}
|
||||||
dependencies:
|
dependencies:
|
||||||
@@ -9267,13 +9426,9 @@ packages:
|
|||||||
ufo: 1.0.1
|
ufo: 1.0.1
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
/moment-mini/2.29.4:
|
|
||||||
resolution: {integrity: sha512-uhXpYwHFeiTbY9KSgPPRoo1nt8OxNVdMVoTBYHfSEKeRkIkwGpO+gERmhuhBtzfaeOyTkykSrm2+noJBgqt3Hg==}
|
|
||||||
dev: false
|
|
||||||
|
|
||||||
/moment/2.29.4:
|
/moment/2.29.4:
|
||||||
resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==}
|
resolution: {integrity: sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==}
|
||||||
dev: true
|
dev: false
|
||||||
|
|
||||||
/mri/1.2.0:
|
/mri/1.2.0:
|
||||||
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
resolution: {integrity: sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==}
|
||||||
@@ -10164,6 +10319,15 @@ packages:
|
|||||||
jsesc: 0.5.0
|
jsesc: 0.5.0
|
||||||
dev: true
|
dev: true
|
||||||
|
|
||||||
|
/remark-frontmatter/4.0.1:
|
||||||
|
resolution: {integrity: sha512-38fJrB0KnmD3E33a5jZC/5+gGAC2WKNiPw1/fdXJvijBlhA7RCsvJklrYJakS0HedninvaCYW8lQGf9C918GfA==}
|
||||||
|
dependencies:
|
||||||
|
'@types/mdast': 3.0.10
|
||||||
|
mdast-util-frontmatter: 1.0.0
|
||||||
|
micromark-extension-frontmatter: 1.0.0
|
||||||
|
unified: 10.1.2
|
||||||
|
dev: true
|
||||||
|
|
||||||
/remark-gfm/3.0.1:
|
/remark-gfm/3.0.1:
|
||||||
resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==}
|
resolution: {integrity: sha512-lEFDoi2PICJyNrACFOfDD3JlLkuSbOa5Wd8EPt06HUdptv8Gn0bxYTdbU/XXQ3swAPkEaGxxPN9cbnMHvVu1Ig==}
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
@@ -23,7 +23,7 @@ const lint = async (file: string): Promise<boolean> => {
|
|||||||
return result.errorCount === 0;
|
return result.errorCount === 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
(async () => {
|
const main = async () => {
|
||||||
const jisonFiles = await globby(['./packages/**/*.jison', '!./**/node_modules/**'], {
|
const jisonFiles = await globby(['./packages/**/*.jison', '!./**/node_modules/**'], {
|
||||||
dot: true,
|
dot: true,
|
||||||
});
|
});
|
||||||
@@ -31,4 +31,6 @@ const lint = async (file: string): Promise<boolean> => {
|
|||||||
if (lintResults.includes(false)) {
|
if (lintResults.includes(false)) {
|
||||||
process.exit(1);
|
process.exit(1);
|
||||||
}
|
}
|
||||||
})();
|
};
|
||||||
|
|
||||||
|
void main();
|
||||||
|
|||||||
@@ -13,8 +13,8 @@ const load = async () => {
|
|||||||
await mermaid.registerExternalDiagrams([mindmap]);
|
await mermaid.registerExternalDiagrams([mindmap]);
|
||||||
await render('info');
|
await render('info');
|
||||||
|
|
||||||
setTimeout(async () => {
|
setTimeout(() => {
|
||||||
await render(`mindmap
|
void render(`mindmap
|
||||||
root((mindmap))
|
root((mindmap))
|
||||||
Origins
|
Origins
|
||||||
Long history
|
Long history
|
||||||
@@ -35,4 +35,4 @@ const load = async () => {
|
|||||||
}, 2500);
|
}, 2500);
|
||||||
};
|
};
|
||||||
|
|
||||||
window.addEventListener('load', load, false);
|
window.addEventListener('load', () => void load(), false);
|
||||||
|
|||||||
9
tsconfig.eslint.json
Normal file
9
tsconfig.eslint.json
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
// extend your base config to share compilerOptions, etc
|
||||||
|
"extends": "./tsconfig.json",
|
||||||
|
"compilerOptions": {
|
||||||
|
// ensure that nobody can accidentally use this config for a build
|
||||||
|
"noEmit": true
|
||||||
|
},
|
||||||
|
"include": ["packages", "tests", "scripts", "cypress", "__mocks__", "./.eslintrc.cjs", "./*"]
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user