mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-26 15:44:12 +01:00
Compare commits
172 Commits
yash-singh
...
sidv/biome
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
94fa23514f | ||
|
|
8cbe3e073d | ||
|
|
ce3b0af03a | ||
|
|
c7c1218e02 | ||
|
|
422b8cd078 | ||
|
|
f5bdbf22e7 | ||
|
|
1ab23d137f | ||
|
|
cba968ccc0 | ||
|
|
0f3778aea8 | ||
|
|
ac5c61dbd4 | ||
|
|
48303a030d | ||
|
|
6c785c9316 | ||
|
|
054ed6c69c | ||
|
|
58483fb231 | ||
|
|
0d8c3fcf8c | ||
|
|
89e061aa51 | ||
|
|
a1badd5167 | ||
|
|
55a8e4cf7e | ||
|
|
e7577ed51e | ||
|
|
d2b42ebd74 | ||
|
|
ba34386a69 | ||
|
|
a23b891f20 | ||
|
|
3a5793f948 | ||
|
|
0a5315cd5a | ||
|
|
98f32bfdfe | ||
|
|
22a00a5f8b | ||
|
|
3381717e86 | ||
|
|
08dfdfed82 | ||
|
|
2c80d806cc | ||
|
|
9f375139d5 | ||
|
|
0c49d2b84e | ||
|
|
42414e85d1 | ||
|
|
1e43ad1ee3 | ||
|
|
cda41a1cdf | ||
|
|
1a199d630f | ||
|
|
51c07163aa | ||
|
|
9bbd3cab3c | ||
|
|
6f61a71dda | ||
|
|
3af4020cdc | ||
|
|
d65e78f9e2 | ||
|
|
82b120e567 | ||
|
|
d95c159b1f | ||
|
|
c468319869 | ||
|
|
4b21e1e745 | ||
|
|
fb1942c2cf | ||
|
|
81d8b9d02e | ||
|
|
6db070197a | ||
|
|
a331125187 | ||
|
|
66bc461fa1 | ||
|
|
df72febc00 | ||
|
|
5aced51f9e | ||
|
|
fe9fbd8618 | ||
|
|
b031c6f182 | ||
|
|
2f792e33d6 | ||
|
|
dc51a8f182 | ||
|
|
e8d18189ac | ||
|
|
a6276a94c3 | ||
|
|
85628f2148 | ||
|
|
1f70717a53 | ||
|
|
493bb8a80e | ||
|
|
788e7c96ff | ||
|
|
caa0ff340d | ||
|
|
44688a20b6 | ||
|
|
3f1bba407e | ||
|
|
91e8bcaba9 | ||
|
|
66cd0b9621 | ||
|
|
6382dcf7c8 | ||
|
|
5587011f75 | ||
|
|
0044aa3029 | ||
|
|
9c3bcec7f0 | ||
|
|
63f9e95795 | ||
|
|
8f00555bf5 | ||
|
|
029b3c1101 | ||
|
|
2340a3b836 | ||
|
|
d84b4403ab | ||
|
|
323f72ce33 | ||
|
|
ecee23d8ba | ||
|
|
7ee22de5e2 | ||
|
|
c904c7d21a | ||
|
|
ce3d0a23de | ||
|
|
1c4dd9b923 | ||
|
|
b285466130 | ||
|
|
3754ac0872 | ||
|
|
83ca6897bd | ||
|
|
d2d7f2bcb0 | ||
|
|
20f9abcc38 | ||
|
|
0417a8ddff | ||
|
|
46fe731379 | ||
|
|
0e63233845 | ||
|
|
d6ccd93cf2 | ||
|
|
cf20ccb126 | ||
|
|
ec7adb7e00 | ||
|
|
44f42b2a63 | ||
|
|
7bcba29493 | ||
|
|
8744008630 | ||
|
|
418d34cbee | ||
|
|
fcd5c2c21d | ||
|
|
e3c6281b26 | ||
|
|
ae5b886148 | ||
|
|
c5badf8341 | ||
|
|
da882de0d4 | ||
|
|
633febaeab | ||
|
|
bf9485c231 | ||
|
|
a722bdcd37 | ||
|
|
8a5fe53706 | ||
|
|
362e49aa2c | ||
|
|
6d2939c9b9 | ||
|
|
9a11cb7bb3 | ||
|
|
00eaebeac8 | ||
|
|
dd92aecdca | ||
|
|
e26dea6416 | ||
|
|
3b2b8dacd8 | ||
|
|
df94d3994d | ||
|
|
6f56d94c64 | ||
|
|
56c4f10607 | ||
|
|
dfa71317ad | ||
|
|
2df26ca323 | ||
|
|
b7cb9673b0 | ||
|
|
8d815f878c | ||
|
|
dab26df9c4 | ||
|
|
c7fe9a6465 | ||
|
|
4f26f3ae2e | ||
|
|
730fa89e4c | ||
|
|
0326d899c4 | ||
|
|
c993adfcdb | ||
|
|
4885b311f8 | ||
|
|
3274f673ab | ||
|
|
4f642428de | ||
|
|
954f5d7d42 | ||
|
|
4a12c46350 | ||
|
|
9eb64cd6db | ||
|
|
7b8e76c26f | ||
|
|
665be1ecfe | ||
|
|
edda73c7fc | ||
|
|
6413529a6e | ||
|
|
f5e1df08a0 | ||
|
|
bb2bbfdf92 | ||
|
|
22bd26272d | ||
|
|
da150e8767 | ||
|
|
1f64452716 | ||
|
|
10871af93b | ||
|
|
50c9ede69d | ||
|
|
ca4fa11859 | ||
|
|
9986b023d7 | ||
|
|
58af76384a | ||
|
|
e2ca8e820e | ||
|
|
1cbd730b8d | ||
|
|
6f1a553234 | ||
|
|
e68ba3f1df | ||
|
|
92f1941fb0 | ||
|
|
a536484408 | ||
|
|
76801ff564 | ||
|
|
c4ccfec316 | ||
|
|
1ac9244e68 | ||
|
|
f2d3ac1e7b | ||
|
|
edad740e15 | ||
|
|
18defaae6d | ||
|
|
128c69aa76 | ||
|
|
17fd681bdb | ||
|
|
e852156b9f | ||
|
|
7f33ae0f40 | ||
|
|
13aa3265e3 | ||
|
|
3b0687e557 | ||
|
|
357da0ca28 | ||
|
|
9b411fa8d4 | ||
|
|
087a5748c8 | ||
|
|
6105185d05 | ||
|
|
c993a817d1 | ||
|
|
002aa29f19 | ||
|
|
07de090723 | ||
|
|
8691874dbb | ||
|
|
db92b5a219 |
@@ -2,7 +2,7 @@ import { build } from 'esbuild';
|
||||
import { mkdir, writeFile } from 'node:fs/promises';
|
||||
import { packageOptions } from '../.build/common.js';
|
||||
import { generateLangium } from '../.build/generateLangium.js';
|
||||
import { MermaidBuildOptions, defaultOptions, getBuildConfig } from './util.js';
|
||||
import { type MermaidBuildOptions, defaultOptions, getBuildConfig } from './util.js';
|
||||
|
||||
const shouldVisualize = process.argv.includes('--visualize');
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { transformJison } from '../.build/jisonTransformer.js';
|
||||
import { Plugin } from 'esbuild';
|
||||
import type { Plugin } from 'esbuild';
|
||||
|
||||
export const jisonPlugin: Plugin = {
|
||||
name: 'jison',
|
||||
|
||||
@@ -56,7 +56,7 @@ export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
|
||||
const external: string[] = ['require', 'fs', 'path'];
|
||||
const { name, file, packageName } = packageOptions[entryName];
|
||||
const outFileName = getFileName(name, options);
|
||||
let output: BuildOptions = buildOptions({
|
||||
const output: BuildOptions = buildOptions({
|
||||
absWorkingDir: resolve(__dirname, `../packages/${packageName}`),
|
||||
entryPoints: {
|
||||
[outFileName]: `src/${file}`,
|
||||
|
||||
@@ -25,7 +25,7 @@ module.exports = {
|
||||
'plugin:json/recommended',
|
||||
'plugin:markdown/recommended-legacy',
|
||||
'plugin:@cspell/recommended',
|
||||
'prettier',
|
||||
'biome',
|
||||
],
|
||||
plugins: [
|
||||
'@typescript-eslint',
|
||||
|
||||
5
.github/lychee.toml
vendored
5
.github/lychee.toml
vendored
@@ -41,7 +41,10 @@ exclude = [
|
||||
"https://bundlephobia.com",
|
||||
|
||||
# Chrome webstore migration issue. Temporary
|
||||
"https://chromewebstore.google.com"
|
||||
"https://chromewebstore.google.com",
|
||||
|
||||
# Drupal 403
|
||||
"https://(www.)?drupal.org"
|
||||
]
|
||||
|
||||
# Exclude all private IPs from checking.
|
||||
|
||||
72
.github/workflows/e2e.yml
vendored
72
.github/workflows/e2e.yml
vendored
@@ -1,9 +1,3 @@
|
||||
# We use github cache to save snapshots between runs.
|
||||
# For PRs and MergeQueues, the target commit is used, and for push events, github.event.previous is used.
|
||||
# If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots.
|
||||
# These are then downloaded before running the E2E, providing the reference snapshots.
|
||||
# If there are any errors, the diff image is uploaded to artifacts, and the user is notified.
|
||||
|
||||
name: E2E
|
||||
|
||||
on:
|
||||
@@ -72,16 +66,6 @@ jobs:
|
||||
mkdir -p cypress/snapshots/stats/base
|
||||
mv stats cypress/snapshots/stats/base
|
||||
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@v6
|
||||
id: cypress-snapshot-gen
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
|
||||
with:
|
||||
install: false
|
||||
start: pnpm run dev
|
||||
wait-on: 'http://localhost:9000'
|
||||
browser: chrome
|
||||
|
||||
e2e:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
@@ -146,6 +130,10 @@ jobs:
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
VITEST_COVERAGE: true
|
||||
CYPRESS_COMMIT: ${{ github.sha }}
|
||||
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
|
||||
ARGOS_PARALLEL: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
|
||||
ARGOS_PARALLEL_TOTAL: 4
|
||||
ARGOS_PARALLEL_INDEX: ${{ matrix.containers }}
|
||||
|
||||
- name: Upload Coverage to Codecov
|
||||
uses: codecov/codecov-action@v4
|
||||
@@ -158,55 +146,3 @@ jobs:
|
||||
fail_ci_if_error: false
|
||||
verbose: true
|
||||
token: 6845cc80-77ee-4e17-85a1-026cd95e0766
|
||||
|
||||
# We upload the artifacts into numbered archives to prevent overwriting
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: snapshots-${{ matrix.containers }}
|
||||
retention-days: 1
|
||||
path: ./cypress/snapshots
|
||||
|
||||
combineArtifacts:
|
||||
needs: e2e
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ always() }}
|
||||
steps:
|
||||
# Download all snapshot artifacts and merge them into a single folder
|
||||
- name: Download All Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: snapshots
|
||||
pattern: snapshots-*
|
||||
merge-multiple: true
|
||||
|
||||
# For successful push events, we save the snapshots cache
|
||||
- name: Save snapshots cache
|
||||
id: cache-upload
|
||||
if: ${{ github.event_name == 'push' && needs.e2e.result != 'failure' }}
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ./snapshots
|
||||
key: ${{ runner.os }}-snapshots-${{ github.event.after }}
|
||||
|
||||
- name: Flatten images to a folder
|
||||
if: ${{ needs.e2e.result == 'failure' }}
|
||||
run: |
|
||||
mkdir errors
|
||||
cd snapshots
|
||||
find . -mindepth 2 -type d -name "*__diff_output__*" -exec sh -c 'mv "$0"/*.png ../errors/' {} \;
|
||||
|
||||
- name: Upload Error snapshots
|
||||
if: ${{ needs.e2e.result == 'failure' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
id: upload-artifacts
|
||||
with:
|
||||
name: error-snapshots
|
||||
retention-days: 10
|
||||
path: errors/
|
||||
|
||||
- name: Notify Users
|
||||
if: ${{ needs.e2e.result == 'failure' }}
|
||||
run: |
|
||||
echo "::error title=Visual tests failed::You can view images that failed by downloading the error-snapshots artifact: ${{ steps.upload-artifacts.outputs.artifact-url }}"
|
||||
|
||||
4
.github/workflows/lint.yml
vendored
4
.github/workflows/lint.yml
vendored
@@ -37,9 +37,9 @@ jobs:
|
||||
- name: Run Linting
|
||||
shell: bash
|
||||
run: |
|
||||
if ! pnpm run lint; then
|
||||
if ! pnpm run lint:ci; then
|
||||
# print a nice error message on lint failure
|
||||
ERROR_MESSAGE='Running `pnpm run lint` failed.'
|
||||
ERROR_MESSAGE='Running `pnpm run lint:ci` failed.'
|
||||
ERROR_MESSAGE+=' Running `pnpm -w 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`.'
|
||||
|
||||
3
.gitignore
vendored
3
.gitignore
vendored
@@ -48,6 +48,7 @@ demos/dev/**
|
||||
!/demos/dev/example.html
|
||||
!/demos/dev/reload.js
|
||||
tsx-0/**
|
||||
vite.config.ts.timestamp-*
|
||||
|
||||
# autogenereated by langium-cli
|
||||
generated/
|
||||
generated/
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
export default {
|
||||
'!(docs/**/*)*.{ts,js,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',
|
||||
'biome check --no-errors-on-unmatched --files-ignore-unknown=true --write',
|
||||
],
|
||||
'.cspell/*.txt': ['tsx scripts/fixCSpell.ts'],
|
||||
'**/*.jison': ['pnpm -w run lint:jison'],
|
||||
|
||||
@@ -1,18 +0,0 @@
|
||||
dist
|
||||
cypress/platform/xss3.html
|
||||
.cache
|
||||
.pnpm-store
|
||||
coverage
|
||||
# Autogenerated by PNPM
|
||||
pnpm-lock.yaml
|
||||
stats
|
||||
**/.vitepress/components.d.ts
|
||||
**/.vitepress/cache
|
||||
.nyc_output
|
||||
# Autogenerated by `pnpm run --filter mermaid types:build-config`
|
||||
packages/mermaid/src/config.type.ts
|
||||
# autogenereated by langium-cli
|
||||
generated/
|
||||
# Ignore the files creates in /demos/dev except for example.html
|
||||
demos/dev/**
|
||||
!/demos/dev/example.html
|
||||
@@ -1,8 +0,0 @@
|
||||
{
|
||||
"endOfLine": "auto",
|
||||
"printWidth": 100,
|
||||
"singleQuote": true,
|
||||
"useTabs": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
import { build, InlineConfig, type PluginOption } from 'vite';
|
||||
import { build, type InlineConfig, type PluginOption } from 'vite';
|
||||
import { resolve } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import jisonPlugin from './jisonPlugin.js';
|
||||
@@ -48,7 +48,7 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
|
||||
const external: (string | RegExp)[] = ['require', 'fs', 'path'];
|
||||
console.log(entryName, packageOptions[entryName]);
|
||||
const { name, file, packageName } = packageOptions[entryName];
|
||||
let output: OutputOptions = [
|
||||
const output: OutputOptions = [
|
||||
{
|
||||
name,
|
||||
format: 'esm',
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { PluginOption } from 'vite';
|
||||
import type { PluginOption } from 'vite';
|
||||
import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js';
|
||||
|
||||
/**
|
||||
|
||||
7
FUNDING.json
Normal file
7
FUNDING.json
Normal file
@@ -0,0 +1,7 @@
|
||||
{
|
||||
"drips": {
|
||||
"ethereum": {
|
||||
"ownedBy": "0x0831DDFe60d009d9448CC976157b539089aB821E"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -35,6 +35,7 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai
|
||||
[](https://www.npmjs.com/package/mermaid)
|
||||
[](https://discord.gg/AgrbSrBer3)
|
||||
[](https://twitter.com/mermaidjs_)
|
||||
[](https://argos-ci.com)
|
||||
|
||||
<img src="./img/header.png" alt="" />
|
||||
|
||||
|
||||
229
biome.json
Normal file
229
biome.json
Normal file
@@ -0,0 +1,229 @@
|
||||
{
|
||||
"$schema": "https://biomejs.dev/schemas/1.8.2/schema.json",
|
||||
"files": {
|
||||
"ignore": [
|
||||
"**/contributor-names.json",
|
||||
"**/generated/",
|
||||
"**/knsv*.html",
|
||||
"**/local*.html",
|
||||
"**/stats/",
|
||||
"**/user-avatars/*",
|
||||
"./.vscode/**",
|
||||
"cypress/platform/current.html",
|
||||
"cypress/platform/experimental.html",
|
||||
"cypress/platform/xss3.html",
|
||||
"cypress/screenshots/",
|
||||
"cypress/snapshots/",
|
||||
"demos/dev/**",
|
||||
"packages/mermaid/src/config.type.ts"
|
||||
]
|
||||
},
|
||||
"formatter": {
|
||||
"enabled": true,
|
||||
"formatWithErrors": false,
|
||||
"indentStyle": "space",
|
||||
"indentWidth": 2,
|
||||
"lineEnding": "lf",
|
||||
"lineWidth": 100,
|
||||
"attributePosition": "auto"
|
||||
},
|
||||
"organizeImports": { "enabled": false },
|
||||
"linter": {
|
||||
"enabled": true,
|
||||
"rules": {
|
||||
"recommended": false,
|
||||
"complexity": {
|
||||
"noBannedTypes": "error",
|
||||
"noExtraBooleanCast": "error",
|
||||
"noMultipleSpacesInRegularExpressionLiterals": "error",
|
||||
"noUselessCatch": "error",
|
||||
"noUselessThisAlias": "error",
|
||||
"noUselessTypeConstraint": "error",
|
||||
"noWith": "error",
|
||||
"useFlatMap": "error"
|
||||
},
|
||||
"correctness": {
|
||||
"noConstAssign": "error",
|
||||
"noConstantCondition": "error",
|
||||
"noEmptyCharacterClassInRegex": "error",
|
||||
"noEmptyPattern": "error",
|
||||
"noGlobalObjectCalls": "error",
|
||||
"noInnerDeclarations": "error",
|
||||
"noInvalidConstructorSuper": "error",
|
||||
"noNewSymbol": "error",
|
||||
"noNonoctalDecimalEscape": "error",
|
||||
"noPrecisionLoss": "error",
|
||||
"noSelfAssign": "error",
|
||||
"noSetterReturn": "error",
|
||||
"noSwitchDeclarations": "error",
|
||||
"noUndeclaredVariables": "error",
|
||||
"noUnreachable": "error",
|
||||
"noUnreachableSuper": "error",
|
||||
"noUnsafeFinally": "error",
|
||||
"noUnsafeOptionalChaining": "error",
|
||||
"noUnusedLabels": "error",
|
||||
"noUnusedVariables": "off",
|
||||
"useArrayLiterals": "off",
|
||||
"useIsNan": "error",
|
||||
"useValidForDirection": "error",
|
||||
"useYield": "error"
|
||||
},
|
||||
"style": {
|
||||
"noNamespace": "error",
|
||||
"useAsConstAssertion": "error",
|
||||
"useBlockStatements": "error",
|
||||
"useForOf": "error",
|
||||
"useImportType": "error",
|
||||
"useNamingConvention": {
|
||||
"level": "off",
|
||||
"options": { "strictCase": false }
|
||||
}
|
||||
},
|
||||
"suspicious": {
|
||||
"noAssignInExpressions": "warn",
|
||||
"noAsyncPromiseExecutor": "error",
|
||||
"noCatchAssign": "error",
|
||||
"noClassAssign": "error",
|
||||
"noCompareNegZero": "error",
|
||||
"noConsoleLog": "off",
|
||||
"noControlCharactersInRegex": "error",
|
||||
"noDebugger": "error",
|
||||
"noDuplicateCase": "error",
|
||||
"noDuplicateClassMembers": "error",
|
||||
"noDuplicateObjectKeys": "error",
|
||||
"noDuplicateParameters": "error",
|
||||
"noEmptyBlockStatements": "off",
|
||||
"noExplicitAny": "off",
|
||||
"noExtraNonNullAssertion": "error",
|
||||
"noFallthroughSwitchClause": "error",
|
||||
"noFunctionAssign": "error",
|
||||
"noGlobalAssign": "error",
|
||||
"noImportAssign": "error",
|
||||
"noMisleadingCharacterClass": "error",
|
||||
"noMisleadingInstantiator": "error",
|
||||
"noPrototypeBuiltins": "off",
|
||||
"noRedeclare": "error",
|
||||
"noShadowRestrictedNames": "error",
|
||||
"noUnsafeDeclarationMerging": "error",
|
||||
"noUnsafeNegation": "error",
|
||||
"useGetterReturn": "error",
|
||||
"useIsArray": "error",
|
||||
"useValidTypeof": "error"
|
||||
}
|
||||
}
|
||||
},
|
||||
"javascript": {
|
||||
"formatter": {
|
||||
"jsxQuoteStyle": "double",
|
||||
"quoteProperties": "asNeeded",
|
||||
"trailingCommas": "es5",
|
||||
"semicolons": "always",
|
||||
"arrowParentheses": "always",
|
||||
"bracketSpacing": true,
|
||||
"bracketSameLine": false,
|
||||
"quoteStyle": "single",
|
||||
"attributePosition": "auto"
|
||||
},
|
||||
"globals": [
|
||||
"it",
|
||||
"describe",
|
||||
"beforeEach",
|
||||
"beforeAll",
|
||||
"afterEach",
|
||||
"cy",
|
||||
"expect",
|
||||
"context",
|
||||
"Cypress"
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
{
|
||||
"include": ["cypress/**", "demos/**", "**/scripts"],
|
||||
"linter": { "rules": { "suspicious": { "noConsoleLog": "off" } } }
|
||||
},
|
||||
{ "include": ["*.{js,jsx,mjs,cjs}"], "linter": { "rules": {} } },
|
||||
{ "include": ["*.{ts,tsx}"], "linter": { "rules": {} } },
|
||||
{
|
||||
"include": ["*.spec.{ts,js}", "cypress/**", "demos/**", "**/docs/**"],
|
||||
"linter": {
|
||||
"rules": {
|
||||
"correctness": { "noUnusedVariables": "off" },
|
||||
"style": {
|
||||
"useNamingConvention": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"include": ["*.spec.{ts,js}", "tests/**", "cypress/**/*.js"],
|
||||
"linter": {
|
||||
"rules": {
|
||||
"style": {
|
||||
"useNamingConvention": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"include": ["*.html", "*.md", "**/*.md/*"],
|
||||
"linter": {
|
||||
"rules": {
|
||||
"correctness": {
|
||||
"noUndeclaredVariables": "off",
|
||||
"noUnusedVariables": "off"
|
||||
},
|
||||
"style": { "noVar": "error" }
|
||||
}
|
||||
}
|
||||
},
|
||||
{ "include": ["*.md"] },
|
||||
{
|
||||
"include": ["**/*.md/**"],
|
||||
"linter": {
|
||||
"rules": {
|
||||
"correctness": {
|
||||
"noUndeclaredVariables": "off",
|
||||
"noUnusedVariables": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"include": ["*.ts", "*.tsx", "*.mts", "*.cts"],
|
||||
"linter": {
|
||||
"rules": {
|
||||
"correctness": {
|
||||
"noConstAssign": "off",
|
||||
"noGlobalObjectCalls": "off",
|
||||
"noInvalidConstructorSuper": "off",
|
||||
"noNewSymbol": "off",
|
||||
"noSetterReturn": "off",
|
||||
"noUndeclaredVariables": "off",
|
||||
"noUnreachable": "off",
|
||||
"noUnreachableSuper": "off"
|
||||
},
|
||||
"style": {
|
||||
"noArguments": "error",
|
||||
"noVar": "error",
|
||||
"useConst": "error"
|
||||
},
|
||||
"suspicious": {
|
||||
"noDuplicateClassMembers": "off",
|
||||
"noDuplicateObjectKeys": "off",
|
||||
"noDuplicateParameters": "off",
|
||||
"noFunctionAssign": "off",
|
||||
"noImportAssign": "off",
|
||||
"noRedeclare": "off",
|
||||
"noUnsafeNegation": "off",
|
||||
"useGetterReturn": "off"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"vcs": {
|
||||
"enabled": true,
|
||||
"clientKind": "git",
|
||||
"useIgnoreFile": true
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,8 @@ import { defineConfig } from 'cypress';
|
||||
import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin';
|
||||
import coverage from '@cypress/code-coverage/task';
|
||||
import eyesPlugin from '@applitools/eyes-cypress';
|
||||
import { registerArgosTask } from '@argos-ci/cypress/task';
|
||||
|
||||
export default eyesPlugin(
|
||||
defineConfig({
|
||||
projectId: 'n2sma2',
|
||||
@@ -17,10 +19,17 @@ export default eyesPlugin(
|
||||
}
|
||||
return launchOptions;
|
||||
});
|
||||
addMatchImageSnapshotPlugin(on, config);
|
||||
// copy any needed variables from process.env to config.env
|
||||
config.env.useAppli = process.env.USE_APPLI ? true : false;
|
||||
config.env.useArgos = !!process.env.CI;
|
||||
|
||||
if (config.env.useArgos) {
|
||||
registerArgosTask(on, config, {
|
||||
token: 'fc3a35cf5200db928d65b2047861582d9444032b',
|
||||
});
|
||||
} else {
|
||||
addMatchImageSnapshotPlugin(on, config);
|
||||
}
|
||||
// do not forget to return the changed config object!
|
||||
return config;
|
||||
},
|
||||
|
||||
@@ -55,6 +55,7 @@ export const imgSnapshotTest = (
|
||||
const options: CypressMermaidConfig = {
|
||||
..._options,
|
||||
fontFamily: _options.fontFamily || 'courier',
|
||||
// @ts-ignore TODO: Fix type of fontSize
|
||||
fontSize: _options.fontSize || '16px',
|
||||
sequence: {
|
||||
...(_options.sequence || {}),
|
||||
@@ -94,19 +95,8 @@ export const openURLAndVerifyRendering = (
|
||||
options: CypressMermaidConfig,
|
||||
validation?: any
|
||||
): void => {
|
||||
const useAppli: boolean = Cypress.env('useAppli');
|
||||
const name: string = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
|
||||
|
||||
if (useAppli) {
|
||||
cy.log(`Opening eyes ${Cypress.spec.name} --- ${name}`);
|
||||
cy.eyesOpen({
|
||||
appName: 'Mermaid',
|
||||
testName: name,
|
||||
batchName: Cypress.spec.name,
|
||||
batchId: batchId + Cypress.spec.name,
|
||||
});
|
||||
}
|
||||
|
||||
cy.visit(url);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
cy.get('svg').should('be.visible');
|
||||
@@ -115,11 +105,27 @@ export const openURLAndVerifyRendering = (
|
||||
cy.get('svg').should(validation);
|
||||
}
|
||||
|
||||
verifyScreenshot(name);
|
||||
};
|
||||
|
||||
export const verifyScreenshot = (name: string): void => {
|
||||
const useAppli: boolean = Cypress.env('useAppli');
|
||||
const useArgos: boolean = Cypress.env('useArgos');
|
||||
|
||||
if (useAppli) {
|
||||
cy.log(`Opening eyes ${Cypress.spec.name} --- ${name}`);
|
||||
cy.eyesOpen({
|
||||
appName: 'Mermaid',
|
||||
testName: name,
|
||||
batchName: Cypress.spec.name,
|
||||
batchId: batchId + Cypress.spec.name,
|
||||
});
|
||||
cy.log(`Check eyes ${Cypress.spec.name}`);
|
||||
cy.eyesCheckWindow('Click!');
|
||||
cy.log(`Closing eyes ${Cypress.spec.name}`);
|
||||
cy.eyesClose();
|
||||
} else if (useArgos) {
|
||||
cy.argosScreenshot(name);
|
||||
} else {
|
||||
cy.matchImageSnapshot(name);
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { renderGraph } from '../../helpers/util.ts';
|
||||
import { renderGraph, verifyScreenshot } from '../../helpers/util.ts';
|
||||
describe('Configuration', () => {
|
||||
describe('arrowMarkerAbsolute', () => {
|
||||
it('should handle default value false of arrowMarkerAbsolute', () => {
|
||||
@@ -119,8 +119,7 @@ describe('Configuration', () => {
|
||||
const url = 'http://localhost:9000/regression/issue-1874.html';
|
||||
cy.visit(url);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
cy.get('svg').should('be.visible');
|
||||
cy.matchImageSnapshot(
|
||||
verifyScreenshot(
|
||||
'configuration.spec-should-not-taint-initial-configuration-when-using-multiple-directives'
|
||||
);
|
||||
});
|
||||
@@ -145,7 +144,7 @@ describe('Configuration', () => {
|
||||
// none of the diagrams should be error diagrams
|
||||
expect($svg).to.not.contain('Syntax error');
|
||||
});
|
||||
cy.matchImageSnapshot(
|
||||
verifyScreenshot(
|
||||
'configuration.spec-should-not-render-error-diagram-if-suppressErrorRendering-is-set'
|
||||
);
|
||||
});
|
||||
@@ -162,7 +161,7 @@ describe('Configuration', () => {
|
||||
// some of the diagrams should be error diagrams
|
||||
expect($svg).to.contain('Syntax error');
|
||||
});
|
||||
cy.matchImageSnapshot(
|
||||
verifyScreenshot(
|
||||
'configuration.spec-should-render-error-diagram-if-suppressErrorRendering-is-not-set'
|
||||
);
|
||||
});
|
||||
|
||||
@@ -10,7 +10,6 @@ describe('XSS', () => {
|
||||
cy.wait(1000).then(() => {
|
||||
cy.get('.mermaid').should('exist');
|
||||
});
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('should not allow tags in the css', () => {
|
||||
@@ -137,4 +136,9 @@ describe('XSS', () => {
|
||||
cy.wait(1000);
|
||||
cy.get('#the-malware').should('not.exist');
|
||||
});
|
||||
it('should sanitize backticks block diagram labels properly', () => {
|
||||
cy.visit('http://localhost:9000/xss25.html');
|
||||
cy.wait(1000);
|
||||
cy.get('#the-malware').should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -30,7 +30,6 @@ describe('C4 diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a simple C4Container diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -50,7 +49,6 @@ describe('C4 diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a simple C4Component diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -69,7 +67,6 @@ describe('C4 diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a simple C4Dynamic diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -93,7 +90,6 @@ describe('C4 diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a simple C4Deployment diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -117,6 +113,5 @@ describe('C4 diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32,7 +32,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{ logLevel: 1 }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('2: should render a simple class diagrams with cardinality', () => {
|
||||
@@ -61,7 +60,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('3: should render a simple class diagram with different visibilities', () => {
|
||||
@@ -79,7 +77,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('4: should render a simple class diagram with comments', () => {
|
||||
@@ -109,7 +106,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('5: should render a simple class diagram with abstract method', () => {
|
||||
@@ -121,7 +117,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('6: should render a simple class diagram with static method', () => {
|
||||
@@ -133,7 +128,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('7: should render a simple class diagram with Generic class', () => {
|
||||
@@ -153,7 +147,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('8: should render a simple class diagram with Generic class and relations', () => {
|
||||
@@ -174,7 +167,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('9: should render a simple class diagram with clickable link', () => {
|
||||
@@ -196,7 +188,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('10: should render a simple class diagram with clickable callback', () => {
|
||||
@@ -218,7 +209,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('11: should render a simple class diagram with return type on method', () => {
|
||||
@@ -233,7 +223,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('12: should render a simple class diagram with generic types', () => {
|
||||
@@ -249,7 +238,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('13: should render a simple class diagram with css classes applied', () => {
|
||||
@@ -267,7 +255,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('14: should render a simple class diagram with css classes applied directly', () => {
|
||||
@@ -283,7 +270,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('15: should render a simple class diagram with css classes applied to multiple classes', () => {
|
||||
@@ -298,7 +284,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('16: should render multiple class diagrams', () => {
|
||||
@@ -351,7 +336,6 @@ describe('Class diagram', () => {
|
||||
],
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
// it('17: should render a class diagram when useMaxWidth is true (default)', () => {
|
||||
@@ -421,7 +405,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{ logLevel: 1 }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('should render class diagram with newlines in title', () => {
|
||||
@@ -439,7 +422,6 @@ describe('Class diagram', () => {
|
||||
+quack()
|
||||
}
|
||||
`);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('should render class diagram with many newlines in title', () => {
|
||||
|
||||
@@ -218,7 +218,6 @@ describe('Entity Relationship Diagram', () => {
|
||||
`,
|
||||
{ loglevel: 1 }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('should render entities with keys', () => {
|
||||
|
||||
@@ -8,7 +8,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a complete quadrant chart', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -30,7 +29,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render without points', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -46,7 +44,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should able to render y-axix on right side', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -63,7 +60,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should able to render x-axix on bottom', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -80,7 +76,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should able to render x-axix on bottom and y-axis on right', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -97,7 +92,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render without title', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -112,7 +106,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should use all the config', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -135,7 +128,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should use all the theme variable', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -158,7 +150,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render x-axis labels in the center, if x-axis has two labels', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -180,7 +171,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render y-axis labels in the center, if y-axis has two labels', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -202,7 +192,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render both axes labels on the left and bottom, if both axes have only one label', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -224,7 +213,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('it should render data points with styles', () => {
|
||||
@@ -249,7 +237,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('it should render data points with styles + classes', () => {
|
||||
|
||||
@@ -44,6 +44,5 @@ describe('Requirement diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/// <reference types="Cypress" />
|
||||
// <reference types="Cypress" />
|
||||
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
@@ -68,6 +68,19 @@ context('Sequence diagram', () => {
|
||||
{ sequence: { actorFontFamily: 'courier' } }
|
||||
);
|
||||
});
|
||||
it('should render bidirectional arrows', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
Alice<<->>John: Hello John, how are you?
|
||||
Alice<<-->>John: Hi Alice, I can hear you!
|
||||
John<<->>Alice: This also works the other way
|
||||
John<<-->>Alice: Yes
|
||||
Alice->John: Test
|
||||
John->>Alice: Still works
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should handle different line breaks', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
@@ -464,6 +477,18 @@ context('Sequence diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should render notes over actors and participant', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
actor Alice
|
||||
participant Charlie
|
||||
note over Alice: some note
|
||||
note over Charlie: other note
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should render long messages from an actor to the left to one to the right', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
|
||||
@@ -8,7 +8,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 1, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a simple state diagrams', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -20,7 +19,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a long descriptions instead of id when available', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -32,7 +30,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a long descriptions with additional descriptions', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -44,7 +41,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a single state with short descriptions', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -55,7 +51,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a transition descriptions with new lines', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -69,7 +64,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a state with a note', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -83,7 +77,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a state with on the left side when so specified', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -97,7 +90,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a state with a note together with another state', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -113,7 +105,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a note with multiple lines in it', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -156,7 +147,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a simple state diagrams 2', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -169,7 +159,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a simple state diagrams with labels', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -185,7 +174,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render state descriptions', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -198,7 +186,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render composite states', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -217,7 +204,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render multiple composite states', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -287,7 +273,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render concurrency states', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -311,7 +296,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a state with states in it', () => {
|
||||
imgSnapshotTest(
|
||||
|
||||
@@ -10,7 +10,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a long descriptions instead of id when available', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -22,7 +21,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a long descriptions with additional descriptions', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -34,7 +32,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a single state with short descriptions', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -45,7 +42,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a transition descriptions with new lines', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -59,7 +55,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a state with a note', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -73,7 +68,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a state with on the left side when so specified', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -87,7 +81,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a state with a note together with another state', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -103,7 +96,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a note with multiple lines in it', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -146,7 +138,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a simple state diagrams 2', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -159,7 +150,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a simple state diagrams with labels', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -175,7 +165,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render state descriptions', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -188,7 +177,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render composite states', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -207,7 +195,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render multiple composit states', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -277,7 +264,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render concurrency states', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -301,7 +287,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a state with states in it', () => {
|
||||
imgSnapshotTest(
|
||||
|
||||
@@ -10,7 +10,6 @@ describe('themeCSS balancing, it', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should not allow unbalanced CSS definitions 2', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -21,7 +20,6 @@ describe('themeCSS balancing, it', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -45,7 +43,6 @@ describe('Pie Chart', () => {
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a flowchart diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -70,7 +67,6 @@ describe('Pie Chart', () => {
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a new flowchart diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -96,7 +92,6 @@ describe('Pie Chart', () => {
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a sequence diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -125,7 +120,6 @@ describe('Pie Chart', () => {
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('should render a class diagram', () => {
|
||||
@@ -175,7 +169,6 @@ describe('Pie Chart', () => {
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a state diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -210,7 +203,6 @@ stateDiagram
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a state diagram (v2)', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -245,7 +237,6 @@ stateDiagram-v2
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a er diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -266,7 +257,6 @@ erDiagram
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a user journey diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -287,7 +277,6 @@ erDiagram
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a gantt diagram', () => {
|
||||
cy.clock(new Date('2014-01-06').getTime());
|
||||
@@ -326,7 +315,6 @@ erDiagram
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -9,7 +9,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Should render a complete chart', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -35,7 +34,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('y-axis title not required', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -48,7 +46,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Should render a chart without y-axis with different range', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -60,7 +57,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('x axis title not required', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -72,7 +68,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Multiple plots can be rendered', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -87,7 +82,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Decimals and negative numbers are supported', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -98,7 +92,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Render spark line with "plotReservedSpacePercent"', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -116,7 +109,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Render spark bar without displaying other property', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -143,7 +135,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Should use all the config from directive', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -158,7 +149,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Should use all the config from yaml', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -199,7 +189,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Render with show axis title false', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -221,7 +210,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Render with show axis label false', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -243,7 +231,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Render with show axis tick false', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -265,7 +252,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Render with show axis line false', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -287,7 +273,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Render all the theme color', () => {
|
||||
imgSnapshotTest(
|
||||
@@ -317,6 +302,17 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should use the correct distances between data points', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
xychart-beta
|
||||
x-axis 0 --> 2
|
||||
line [0, 1, 0, 1]
|
||||
bar [1, 0, 1, 0]
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
});
|
||||
|
||||
108
cypress/platform/xss25.html
Normal file
108
cypress/platform/xss25.html
Normal file
@@ -0,0 +1,108 @@
|
||||
<html>
|
||||
<head>
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<style>
|
||||
body {
|
||||
/* background: rgb(221, 208, 208); */
|
||||
/* background:#333; */
|
||||
font-family: 'Arial';
|
||||
/* font-size: 18px !important; */
|
||||
}
|
||||
h1 {
|
||||
color: grey;
|
||||
}
|
||||
.mermaid2 {
|
||||
display: none;
|
||||
}
|
||||
.mermaid svg {
|
||||
/* font-size: 18px !important; */
|
||||
}
|
||||
.malware {
|
||||
position: fixed;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
height: 150px;
|
||||
background: red;
|
||||
color: black;
|
||||
display: flex;
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
font-family: monospace;
|
||||
font-size: 72px;
|
||||
}
|
||||
</style>
|
||||
<script>
|
||||
function xssAttack() {
|
||||
const div = document.createElement('div');
|
||||
div.id = 'the-malware';
|
||||
div.className = 'malware';
|
||||
div.innerHTML = 'XSS Succeeded';
|
||||
document.getElementsByTagName('body')[0].appendChild(div);
|
||||
throw new Error('XSS Succeeded');
|
||||
}
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<div>Security check</div>
|
||||
<div class="flex">
|
||||
<div id="diagram" class="mermaid"></div>
|
||||
<div id="res" class=""></div>
|
||||
</div>
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
mermaid.parseError = function (err, hash) {
|
||||
// console.error('Mermaid error: ', err);
|
||||
};
|
||||
mermaid.initialize({
|
||||
theme: 'forest',
|
||||
arrowMarkerAbsolute: true,
|
||||
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
|
||||
logLevel: 0,
|
||||
state: {
|
||||
defaultRenderer: 'dagre-wrapper',
|
||||
},
|
||||
flowchart: {
|
||||
// defaultRenderer: 'dagre-wrapper',
|
||||
nodeSpacing: 10,
|
||||
curve: 'cardinal',
|
||||
htmlLabels: true,
|
||||
},
|
||||
htmlLabels: false,
|
||||
// gantt: { axisFormat: '%m/%d/%Y' },
|
||||
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
|
||||
// sequenceDiagram: { actorMargin: 300 } // deprecated
|
||||
// fontFamily: '"times", sans-serif',
|
||||
// fontFamily: 'courier',
|
||||
fontSize: 18,
|
||||
curve: 'basis',
|
||||
securityLevel: 'strict',
|
||||
startOnLoad: false,
|
||||
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
|
||||
// themeVariables: {relationLabelColor: 'red'}
|
||||
});
|
||||
function callback() {
|
||||
alert('It worked');
|
||||
}
|
||||
|
||||
let diagram = 'block-beta\n';
|
||||
diagram += '`A-- "X<img src=x on';
|
||||
diagram += 'error=xssAttack()>" -->B';
|
||||
|
||||
console.log(diagram);
|
||||
// document.querySelector('#diagram').innerHTML = diagram;
|
||||
const { svg } = await mermaid.render('diagram', diagram);
|
||||
document.querySelector('#res').innerHTML = svg;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
import '@cypress/code-coverage/support';
|
||||
import '@applitools/eyes-cypress/commands';
|
||||
import '@argos-ci/cypress/support';
|
||||
// Import commands.js using ES2015 syntax:
|
||||
import './commands';
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"compilerOptions": {
|
||||
"target": "es2020",
|
||||
"lib": ["es2020", "dom"],
|
||||
"types": ["cypress", "node"],
|
||||
"types": ["cypress", "node", "@argos-ci/cypress/dist/support.d.ts"],
|
||||
"allowImportingTsExtensions": true,
|
||||
"noEmit": true
|
||||
},
|
||||
|
||||
@@ -238,6 +238,17 @@
|
||||
Alice-xJohn: Hello John, how are you?
|
||||
John--xAlice: Great!
|
||||
</pre>
|
||||
|
||||
<hr />
|
||||
|
||||
<pre class="mermaid">
|
||||
sequenceDiagram
|
||||
participant Alice
|
||||
participant Bob
|
||||
Alice<<->>Bob: Hello!
|
||||
Alice<<->>Bob: Wow, we said that at the same time!
|
||||
Bob<<-->>Alice: Bidirectional Arrows are so cool
|
||||
</pre>
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
mermaid.initialize({
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
version: '3.9'
|
||||
services:
|
||||
mermaid:
|
||||
build:
|
||||
@@ -8,7 +7,7 @@ services:
|
||||
tty: true
|
||||
working_dir: /mermaid
|
||||
mem_limit: '8G'
|
||||
entrypoint: docker-entrypoint.sh
|
||||
entrypoint: ./docker-entrypoint.sh
|
||||
environment:
|
||||
- NODE_OPTIONS=--max_old_space_size=8192
|
||||
volumes:
|
||||
@@ -16,6 +15,7 @@ services:
|
||||
- root_cache:/root/.cache
|
||||
- root_local:/root/.local
|
||||
- root_npm:/root/.npm
|
||||
- /tmp:/tmp
|
||||
ports:
|
||||
- 9000:9000
|
||||
- 3333:3333
|
||||
|
||||
@@ -56,7 +56,7 @@ The following commands must be sufficient enough to start with:
|
||||
|
||||
```bash
|
||||
curl -fsSL https://get.pnpm.io/install.sh | sh -
|
||||
pnpm env use --global 18
|
||||
pnpm env use --global 20
|
||||
```
|
||||
|
||||
You may also need to reload `.shrc` or `.bashrc` afterwards.
|
||||
|
||||
BIN
docs/config/img/mathMLDifferences.png
Normal file
BIN
docs/config/img/mathMLDifferences.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 15 KiB |
@@ -84,3 +84,13 @@ Example with legacy mode enabled (the latest version of KaTeX's stylesheet can b
|
||||
</body>
|
||||
</html>
|
||||
```
|
||||
|
||||
## Handling Rendering Differences
|
||||
|
||||
Due to differences between default fonts across operating systems and browser's MathML implementations, inconsistent results can be seen across platforms. If having consistent results are important, or the most optimal rendered results are desired, `forceLegacyMathML` can be enabled in the config.
|
||||
|
||||
This option will always use KaTeX's stylesheet instead of only when MathML is not supported (as with `legacyMathML`). Note that only `forceLegacyMathML` needs to be set.
|
||||
|
||||
If including KaTeX's stylesheet is not a concern, enabling this option is recommended to avoid scenarios where no MathML implementation within a browser provides the desired output (as seen below).
|
||||
|
||||

|
||||
|
||||
@@ -19,4 +19,4 @@ The `parseError` function will not be called.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:64](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L64)
|
||||
[mermaidAPI.ts:65](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L65)
|
||||
|
||||
@@ -18,4 +18,4 @@ The diagram type, e.g. 'flowchart', 'sequence', etc.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:71](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L71)
|
||||
[mermaidAPI.ts:72](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L72)
|
||||
|
||||
@@ -39,7 +39,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:94](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L94)
|
||||
[mermaidAPI.ts:95](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L95)
|
||||
|
||||
---
|
||||
|
||||
@@ -51,7 +51,7 @@ The diagram type, e.g. 'flowchart', 'sequence', etc.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:84](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L84)
|
||||
[mermaidAPI.ts:85](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L85)
|
||||
|
||||
---
|
||||
|
||||
@@ -63,4 +63,4 @@ The svg code for the rendered graph.
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:80](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L80)
|
||||
[mermaidAPI.ts:81](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L81)
|
||||
|
||||
@@ -26,7 +26,7 @@ Renames and re-exports [mermaidAPI](mermaidAPI.md#mermaidapi)
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:74](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L74)
|
||||
[mermaidAPI.ts:75](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L75)
|
||||
|
||||
## Variables
|
||||
|
||||
@@ -98,7 +98,7 @@ mermaid.initialize(config);
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:635](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L635)
|
||||
[mermaidAPI.ts:634](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L634)
|
||||
|
||||
## Functions
|
||||
|
||||
@@ -129,7 +129,7 @@ Return the last node appended
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:277](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L277)
|
||||
[mermaidAPI.ts:276](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L276)
|
||||
|
||||
---
|
||||
|
||||
@@ -167,10 +167,10 @@ Create the user styles
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type | Description |
|
||||
| :---------- | :------------------------------------------------------------------ | :------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `config` | `MermaidConfig` | configuration that has style and theme settings to use |
|
||||
| `classDefs` | `undefined` \| `null` \| `Record`<`string`, `DiagramStyleClassDef`> | the classDefs in the diagram text. Might be null if none were defined. Usually is the result of a call to getClasses(...) |
|
||||
| Name | Type | Description |
|
||||
| :---------- | :--------------------------------------------------------------- | :------------------------------------------------------------------------------------------------------------------------ |
|
||||
| `config` | `MermaidConfig` | configuration that has style and theme settings to use |
|
||||
| `classDefs` | `undefined` \| `null` \| `Map`<`string`, `DiagramStyleClassDef`> | the classDefs in the diagram text. Might be null if none were defined. Usually is the result of a call to getClasses(...) |
|
||||
|
||||
#### Returns
|
||||
|
||||
@@ -180,7 +180,7 @@ the string with all the user styles
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:153](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L153)
|
||||
[mermaidAPI.ts:154](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L154)
|
||||
|
||||
---
|
||||
|
||||
@@ -190,12 +190,12 @@ the string with all the user styles
|
||||
|
||||
#### Parameters
|
||||
|
||||
| Name | Type |
|
||||
| :---------- | :-------------------------------------------------------- |
|
||||
| `config` | `MermaidConfig` |
|
||||
| `graphType` | `string` |
|
||||
| `classDefs` | `undefined` \| `Record`<`string`, `DiagramStyleClassDef`> |
|
||||
| `svgId` | `string` |
|
||||
| Name | Type |
|
||||
| :---------- | :----------------------------------------------------- |
|
||||
| `config` | `MermaidConfig` |
|
||||
| `graphType` | `string` |
|
||||
| `classDefs` | `undefined` \| `Map`<`string`, `DiagramStyleClassDef`> |
|
||||
| `svgId` | `string` |
|
||||
|
||||
#### Returns
|
||||
|
||||
@@ -230,7 +230,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:138](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L138)
|
||||
[mermaidAPI.ts:139](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L139)
|
||||
|
||||
---
|
||||
|
||||
@@ -252,11 +252,10 @@ Put the svgCode into an iFrame. Return the iFrame code
|
||||
`string`
|
||||
|
||||
- the code with the iFrame that now contains the svgCode
|
||||
TODO replace btoa(). Replace with buf.toString('base64')?
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:254](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L254)
|
||||
[mermaidAPI.ts:253](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L253)
|
||||
|
||||
---
|
||||
|
||||
@@ -281,4 +280,4 @@ Remove any existing elements from the given document
|
||||
|
||||
#### Defined in
|
||||
|
||||
[mermaidAPI.ts:327](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L327)
|
||||
[mermaidAPI.ts:326](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L326)
|
||||
|
||||
@@ -240,6 +240,8 @@ Communication tools and platforms
|
||||
|
||||
### Other
|
||||
|
||||
- [Astro](https://astro.build/)
|
||||
- [Adding diagrams to your Astro site with MermaidJS and Playwright](https://agramont.net/blog/diagraming-with-mermaidjs-astro/)
|
||||
- [Bisheng](https://www.npmjs.com/package/bisheng)
|
||||
- [bisheng-plugin-mermaid](https://github.com/yct21/bisheng-plugin-mermaid)
|
||||
- [Blazorade Mermaid: Render Mermaid diagrams in Blazor applications](https://github.com/Blazorade/Blazorade-Mermaid/wiki)
|
||||
@@ -249,6 +251,7 @@ Communication tools and platforms
|
||||
- [Jekyll](https://jekyllrb.com/)
|
||||
- [jekyll-mermaid](https://rubygems.org/gems/jekyll-mermaid)
|
||||
- [jekyll-mermaid-diagrams](https://github.com/fuzhibo/jekyll-mermaid-diagrams)
|
||||
- [MarkChart: Preview Mermaid diagrams on macOS](https://markchart.app/)
|
||||
- [mermaid-isomorphic](https://github.com/remcohaszing/mermaid-isomorphic)
|
||||
- [mermaid-server: Generate diagrams using a HTTP request](https://github.com/TomWright/mermaid-server)
|
||||
- [NiceGUI: Let any browser be the frontend of your Python code](https://nicegui.io) ✅
|
||||
|
||||
@@ -6,6 +6,10 @@
|
||||
|
||||
# Mermaid Chart
|
||||
|
||||
The Future of Diagramming & Visual Collaboration
|
||||
|
||||
Try the Ultimate AI, Mermaid, and Visual Diagramming Suite by creating an account at [Mermaid Chart](https://www.mermaidchart.com/app/sign-up).
|
||||
|
||||
<br />
|
||||
|
||||
<a href="https://www.producthunt.com/posts/mermaid-chart?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-mermaid-chart" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=416671&theme=light" alt="Mermaid Chart - A smarter way to create diagrams | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
|
||||
@@ -18,22 +22,26 @@
|
||||
|
||||
- **Editor** - A web based editor for creating and editing Mermaid diagrams.
|
||||
|
||||
- **Presentation** - A presentation mode for viewing Mermaid diagrams in a slideshow format.
|
||||
- **Visual Editor** - The Visual Editor enables users of all skill levels to create diagrams easily and efficiently, with both GUI and code-based editing options.
|
||||
|
||||
- **Collaboration** - A web based collaboration feature for multi-user editing on Mermaid diagrams in real-time (Pro plan).
|
||||
- **AI Chat** - Use our embedded AI Chat to generate diagrams from natural language descriptions.
|
||||
|
||||
- **Plugins** - A plugin system for extending the functionality of Mermaid.
|
||||
|
||||
Plugins are available for:
|
||||
Official Mermaid Chart plugins:
|
||||
|
||||
- [ChatGPT](https://docs.mermaidchart.com/plugins/chatgpt)
|
||||
- [Mermaid Chart GPT](https://chat.openai.com/g/g-1IRFKwq4G-mermaid-chart)
|
||||
- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=MermaidChart.vscode-mermaid-chart)
|
||||
- [JetBrains IDE](https://plugins.jetbrains.com/plugin/23043-mermaid-chart)
|
||||
- [Microsoft PowerPoint and Word](https://appsource.microsoft.com/en-us/product/office/WA200006214?tab=Overview)
|
||||
- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=MermaidChart.vscode-mermaid-chart)
|
||||
|
||||
- **AI diagramming** - A feature for generating Mermaid diagrams from text using AI (Pro plan).
|
||||
Visit our [Plugins](https://www.mermaidchart.com/plugins) page for more information.
|
||||
|
||||
- **More** - To learn more, visit our [Product](https://www.mermaidchart.com/product) page.
|
||||
- **Collaboration** - A web based collaboration feature for multi-user editing on Mermaid diagrams in real-time (Pro and Enterprise plans).
|
||||
|
||||
- **Comments** - Enhance collaboration by adding comments to diagrams.
|
||||
|
||||
- **Presentations** - A presentation mode for viewing Mermaid diagrams in a slideshow format.
|
||||
|
||||
## Plans
|
||||
|
||||
@@ -43,11 +51,9 @@
|
||||
|
||||
- **Enterprise** - A paid plan for enterprise use that includes all Pro features, and more.
|
||||
|
||||
## Access
|
||||
To learn more, visit our [Pricing](https://mermaidchart.com/pricing) page.
|
||||
|
||||
Sign up for a free account at [Mermaid Chart](https://www.mermaidchart.com/app/sign-up).
|
||||
|
||||
Mermaid Chart is currently offering a 14-day free trial of our newly-launched Pro tier. To learn more, visit our [Pricing](https://mermaidchart.com/pricing) page.
|
||||
Mermaid Chart is currently offering a 14-day free trial on our Pro and Enterprise tiers. Sign up for a free account at [Mermaid Chart](https://www.mermaidchart.com/app/sign-up).
|
||||
|
||||
## Mermaid JS contributions
|
||||
|
||||
|
||||
@@ -157,7 +157,7 @@ For a list of Mermaid Plugins and Integrations, visit the [Integrations page](..
|
||||
|
||||
Mermaid Chart plugins are available for:
|
||||
|
||||
- [ChatGPT](https://docs.mermaidchart.com/plugins/chatgpt)
|
||||
- [ChatGPT](https://docs.mermaidchart.com/plugins/mermaid-chart-gpt)
|
||||
- [JetBrains IDE](https://docs.mermaidchart.com/plugins/jetbrains-ide)
|
||||
- [Microsoft PowerPoint](https://docs.mermaidchart.com/plugins/microsoft-powerpoint)
|
||||
- [Microsoft Word](https://docs.mermaidchart.com/plugins/microsoft-word)
|
||||
|
||||
@@ -6,6 +6,18 @@
|
||||
|
||||
# Blog
|
||||
|
||||
## [How to Choose the Right Documentation Software](https://www.mermaidchart.com/blog/posts/how-to-choose-the-right-documentation-software/)
|
||||
|
||||
7 May 2024 · 5 mins
|
||||
|
||||
How to Choose the Right Documentation Software. Reliable and efficient documentation software is crucial in the fast-paced world of software development.
|
||||
|
||||
## [AI in software diagramming: What trends will define the future?](https://www.mermaidchart.com/blog/posts/ai-in-software-diagramming/)
|
||||
|
||||
24 April 2024 · 5 mins
|
||||
|
||||
Artificial intelligence (AI) tools are changing the way developers work.
|
||||
|
||||
## [Mermaid Chart Unveils Visual Editor for Sequence Diagrams](https://www.mermaidchart.com/blog/posts/mermaid-chart-unveils-visual-editor-for-sequence-diagrams/)
|
||||
|
||||
8 April 2024 · 5 mins
|
||||
|
||||
@@ -881,7 +881,7 @@ Examples of tooltip usage below:
|
||||
|
||||
```html
|
||||
<script>
|
||||
const callback = function () {
|
||||
window.callback = function () {
|
||||
alert('A callback was triggered');
|
||||
};
|
||||
</script>
|
||||
@@ -913,7 +913,7 @@ flowchart LR
|
||||
|
||||
> **Success** The tooltip functionality and the ability to link to urls are available from version 0.5.2.
|
||||
|
||||
?> Due to limitations with how Docsify handles JavaScript callback functions, an alternate working demo for the above code can be viewed at [this jsfiddle](https://jsfiddle.net/Ogglas/2o73vdez/7).
|
||||
?> Due to limitations with how Docsify handles JavaScript callback functions, an alternate working demo for the above code can be viewed at [this jsfiddle](https://jsfiddle.net/yk4h7qou/2/).
|
||||
|
||||
Links are opened in the same browser tab/window by default. It is possible to change this by adding a link target to the click definition (`_self`, `_blank`, `_parent` and `_top` are supported):
|
||||
|
||||
@@ -957,7 +957,7 @@ Beginner's tip—a full example using interactive links in a html context:
|
||||
</pre>
|
||||
|
||||
<script>
|
||||
const callback = function () {
|
||||
window.callback = function () {
|
||||
alert('A callback was triggered');
|
||||
};
|
||||
const config = {
|
||||
|
||||
@@ -206,18 +206,20 @@ Messages can be of two displayed either solid or with a dotted line.
|
||||
[Actor][Arrow][Actor]:Message text
|
||||
```
|
||||
|
||||
There are six types of arrows currently supported:
|
||||
There are ten types of arrows currently supported:
|
||||
|
||||
| Type | Description |
|
||||
| ------ | ------------------------------------------------ |
|
||||
| `->` | Solid line without arrow |
|
||||
| `-->` | Dotted line without arrow |
|
||||
| `->>` | Solid line with arrowhead |
|
||||
| `-->>` | Dotted line with arrowhead |
|
||||
| `-x` | Solid line with a cross at the end |
|
||||
| `--x` | Dotted line with a cross at the end. |
|
||||
| `-)` | Solid line with an open arrow at the end (async) |
|
||||
| `--)` | Dotted line with a open arrow at the end (async) |
|
||||
| Type | Description |
|
||||
| -------- | ------------------------------------------------------------------------ |
|
||||
| `->` | Solid line without arrow |
|
||||
| `-->` | Dotted line without arrow |
|
||||
| `->>` | Solid line with arrowhead |
|
||||
| `-->>` | Dotted line with arrowhead |
|
||||
| `<<->>` | Solid line with bidirectional arrowheads (v\<MERMAID_RELEASE_VERSION>+) |
|
||||
| `<<-->>` | Dotted line with bidirectional arrowheads (v\<MERMAID_RELEASE_VERSION>+) |
|
||||
| `-x` | Solid line with a cross at the end |
|
||||
| `--x` | Dotted line with a cross at the end. |
|
||||
| `-)` | Solid line with an open arrow at the end (async) |
|
||||
| `--)` | Dotted line with a open arrow at the end (async) |
|
||||
|
||||
## Activations
|
||||
|
||||
@@ -304,17 +306,35 @@ sequenceDiagram
|
||||
Note over Alice,John: A typical interaction
|
||||
```
|
||||
|
||||
It is also possible to add a line break (applies to text input in general):
|
||||
## Line breaks
|
||||
|
||||
Line break can be added to Note and Message:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
Alice->John: Hello John, how are you?
|
||||
Alice->John: Hello John,<br/>how are you?
|
||||
Note over Alice,John: A typical interaction<br/>But now in two lines
|
||||
```
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
Alice->John: Hello John, how are you?
|
||||
Alice->John: Hello John,<br/>how are you?
|
||||
Note over Alice,John: A typical interaction<br/>But now in two lines
|
||||
```
|
||||
|
||||
Line breaks in Actor names requires aliases:
|
||||
|
||||
```mermaid-example
|
||||
sequenceDiagram
|
||||
participant Alice as Alice<br/>Johnson
|
||||
Alice->John: Hello John,<br/>how are you?
|
||||
Note over Alice,John: A typical interaction<br/>But now in two lines
|
||||
```
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Alice as Alice<br/>Johnson
|
||||
Alice->John: Hello John,<br/>how are you?
|
||||
Note over Alice,John: A typical interaction<br/>But now in two lines
|
||||
```
|
||||
|
||||
|
||||
30
package.json
30
package.json
@@ -4,7 +4,7 @@
|
||||
"version": "10.2.4",
|
||||
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
||||
"type": "module",
|
||||
"packageManager": "pnpm@8.15.7",
|
||||
"packageManager": "pnpm@9.4.0+sha512.f549b8a52c9d2b8536762f99c0722205efc5af913e77835dbccc3b0b0b2ca9e7dc8022b78062c17291c48e88749c70ce88eb5a74f1fa8c4bf5e18bb46c8bd83a",
|
||||
"keywords": [
|
||||
"diagram",
|
||||
"markdown",
|
||||
@@ -19,14 +19,15 @@
|
||||
"build:esbuild": "pnpm run -r clean && tsx .esbuild/build.ts",
|
||||
"build:mermaid": "pnpm build:esbuild --mermaid",
|
||||
"build:viz": "pnpm build:esbuild --visualize",
|
||||
"build:types": "tsx .build/types.ts",
|
||||
"build:types": "pnpm --filter mermaid types:build-config && tsx .build/types.ts",
|
||||
"build:types:watch": "tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly --watch",
|
||||
"dev": "tsx .esbuild/server.ts",
|
||||
"dev:vite": "tsx .vite/server.ts",
|
||||
"dev:coverage": "pnpm coverage:cypress:clean && VITE_COVERAGE=true pnpm dev:vite",
|
||||
"release": "pnpm build",
|
||||
"lint": "cross-env NODE_OPTIONS=--max_old_space_size=8192 eslint --cache --cache-strategy content . && pnpm lint:jison && prettier --cache --check .",
|
||||
"lint:fix": "cross-env NODE_OPTIONS=--max_old_space_size=8192 eslint --cache --cache-strategy content --fix . && prettier --write . && tsx scripts/fixCSpell.ts",
|
||||
"lint": "pnpm biome check && pnpm lint:jison",
|
||||
"lint:fix": "pnpm biome check --write",
|
||||
"lint:ci": "pnpm lint && cross-env NODE_OPTIONS=--max_old_space_size=16384 eslint --cache --cache-strategy content .",
|
||||
"lint:jison": "tsx ./scripts/jison/lint.mts",
|
||||
"contributors": "tsx scripts/updateContributors.ts",
|
||||
"cypress": "cypress run",
|
||||
@@ -51,17 +52,13 @@
|
||||
"author": "Knut Sveidqvist",
|
||||
"license": "MIT",
|
||||
"standard": {
|
||||
"ignore": [
|
||||
"**/parser/*.js",
|
||||
"dist/**/*.js",
|
||||
"cypress/**/*.js"
|
||||
],
|
||||
"globals": [
|
||||
"page"
|
||||
]
|
||||
"ignore": ["**/parser/*.js", "dist/**/*.js", "cypress/**/*.js"],
|
||||
"globals": ["page"]
|
||||
},
|
||||
"devDependencies": {
|
||||
"@applitools/eyes-cypress": "^3.42.3",
|
||||
"@argos-ci/cypress": "^2.0.5",
|
||||
"@biomejs/biome": "1.8.2",
|
||||
"@cspell/eslint-plugin": "^8.6.0",
|
||||
"@cypress/code-coverage": "^3.12.30",
|
||||
"@rollup/plugin-typescript": "^11.1.6",
|
||||
@@ -89,7 +86,7 @@
|
||||
"cypress-image-snapshot": "^4.0.1",
|
||||
"esbuild": "^0.20.2",
|
||||
"eslint": "^8.57.0",
|
||||
"eslint-config-prettier": "^9.1.0",
|
||||
"eslint-config-biome": "^1.7.3",
|
||||
"eslint-plugin-cypress": "^2.15.1",
|
||||
"eslint-plugin-html": "^8.0.0",
|
||||
"eslint-plugin-jest": "^27.9.0",
|
||||
@@ -107,7 +104,7 @@
|
||||
"jison": "^0.4.18",
|
||||
"js-yaml": "^4.1.0",
|
||||
"jsdom": "^24.0.0",
|
||||
"langium-cli": "3.0.1",
|
||||
"langium-cli": "3.0.3",
|
||||
"lint-staged": "^15.2.2",
|
||||
"markdown-table": "^3.0.3",
|
||||
"nyc": "^15.1.0",
|
||||
@@ -126,10 +123,5 @@
|
||||
},
|
||||
"nyc": {
|
||||
"report-dir": "coverage/cypress"
|
||||
},
|
||||
"pnpm": {
|
||||
"patchedDependencies": {
|
||||
"cytoscape@3.28.1": "patches/cytoscape@3.28.1.patch"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,7 @@
|
||||
},
|
||||
"./*": "./*"
|
||||
},
|
||||
"keywords": [
|
||||
"diagram",
|
||||
"markdown",
|
||||
"example",
|
||||
"mermaid"
|
||||
],
|
||||
"keywords": ["diagram", "markdown", "example", "mermaid"],
|
||||
"scripts": {
|
||||
"prepublishOnly": "pnpm -w run build"
|
||||
},
|
||||
@@ -28,14 +23,8 @@
|
||||
"author": "Knut Sveidqvist",
|
||||
"license": "MIT",
|
||||
"standard": {
|
||||
"ignore": [
|
||||
"**/parser/*.js",
|
||||
"dist/**/*.js",
|
||||
"cypress/**/*.js"
|
||||
],
|
||||
"globals": [
|
||||
"page"
|
||||
]
|
||||
"ignore": ["**/parser/*.js", "dist/**/*.js", "cypress/**/*.js"],
|
||||
"globals": ["page"]
|
||||
},
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^7.0.0",
|
||||
@@ -47,11 +36,6 @@
|
||||
"mermaid": "workspace:*",
|
||||
"rimraf": "^5.0.5"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
],
|
||||
"sideEffects": [
|
||||
"**/*.css",
|
||||
"**/*.scss"
|
||||
]
|
||||
"files": ["dist"],
|
||||
"sideEffects": ["**/*.css", "**/*.scss"]
|
||||
}
|
||||
|
||||
@@ -13,7 +13,7 @@ export const draw = (text, id, version) => {
|
||||
try {
|
||||
const conf = getConfig();
|
||||
log.debug('Rendering example diagram\n' + text, 'Conf: ');
|
||||
const THEME_COLOR_LIMIT = getConfig().themeVariables.THEME_COLOR_LIMIT;
|
||||
const themeColorLimit = getConfig().themeVariables.THEME_COLOR_LIMIT;
|
||||
const securityLevel = getConfig().securityLevel;
|
||||
// Handle root and Document for when rendering in sandbox mode
|
||||
let sandboxElement;
|
||||
@@ -30,7 +30,7 @@ export const draw = (text, id, version) => {
|
||||
const g = svg.append('g');
|
||||
|
||||
let i;
|
||||
for (i = 0; i < THEME_COLOR_LIMIT; i++) {
|
||||
for (i = 0; i < themeColorLimit; i++) {
|
||||
const section = g.append('g').attr('class', 'section-' + i);
|
||||
section
|
||||
.append('rect')
|
||||
|
||||
@@ -12,13 +12,7 @@
|
||||
},
|
||||
"./*": "./*"
|
||||
},
|
||||
"keywords": [
|
||||
"diagram",
|
||||
"markdown",
|
||||
"flowchart",
|
||||
"elk",
|
||||
"mermaid"
|
||||
],
|
||||
"keywords": ["diagram", "markdown", "flowchart", "elk", "mermaid"],
|
||||
"scripts": {
|
||||
"prepublishOnly": "pnpm -w run build"
|
||||
},
|
||||
@@ -39,7 +33,5 @@
|
||||
"mermaid": "workspace:^",
|
||||
"rimraf": "^5.0.5"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
]
|
||||
"files": ["dist"]
|
||||
}
|
||||
|
||||
@@ -39,6 +39,26 @@ describe('flowchart-elk detector', () => {
|
||||
).toBe(true);
|
||||
});
|
||||
|
||||
// The error from the issue was reproduced with mindmap, so this is just an example
|
||||
// what matters is the keyword somewhere inside graph definition
|
||||
it('should check only the beginning of the line in search of keywords', () => {
|
||||
expect(
|
||||
detector('mindmap ["Descendant node in flowchart"]', {
|
||||
flowchart: {
|
||||
defaultRenderer: 'elk',
|
||||
},
|
||||
})
|
||||
).toBe(false);
|
||||
|
||||
expect(
|
||||
detector('mindmap ["Descendant node in graph"]', {
|
||||
flowchart: {
|
||||
defaultRenderer: 'elk',
|
||||
},
|
||||
})
|
||||
).toBe(false);
|
||||
});
|
||||
|
||||
it('should detect flowchart-elk', () => {
|
||||
expect(detector('flowchart-elk')).toBe(true);
|
||||
});
|
||||
|
||||
@@ -11,7 +11,7 @@ const detector: DiagramDetector = (txt, config): boolean => {
|
||||
// If diagram explicitly states flowchart-elk
|
||||
/^\s*flowchart-elk/.test(txt) ||
|
||||
// If a flowchart/graph diagram has their default renderer set to elk
|
||||
(/^\s*flowchart|graph/.test(txt) && config?.flowchart?.defaultRenderer === 'elk')
|
||||
(/^\s*(flowchart|graph)/.test(txt) && config?.flowchart?.defaultRenderer === 'elk')
|
||||
) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -41,12 +41,12 @@ let nodeDb = {};
|
||||
export const addVertices = async function (vert, svgId, root, doc, diagObj, parentLookupDb, graph) {
|
||||
const svg = root.select(`[id="${svgId}"]`);
|
||||
const nodes = svg.insert('g').attr('class', 'nodes');
|
||||
const keys = Object.keys(vert);
|
||||
const keys = [...vert.keys()];
|
||||
|
||||
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
|
||||
await Promise.all(
|
||||
keys.map(async function (id) {
|
||||
const vertex = vert[id];
|
||||
const vertex = vert.get(id);
|
||||
|
||||
/**
|
||||
* Variable for storing the classes for the vertex
|
||||
@@ -445,18 +445,20 @@ export const addEdges = function (edges, diagObj, graph, svg) {
|
||||
edgeData.arrowTypeStart = 'arrow_open';
|
||||
edgeData.arrowTypeEnd = 'arrow_open';
|
||||
|
||||
/* eslint-disable no-fallthrough */
|
||||
switch (edge.type) {
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: Expected fallthrough
|
||||
case 'double_arrow_cross':
|
||||
edgeData.arrowTypeStart = 'arrow_cross';
|
||||
case 'arrow_cross':
|
||||
edgeData.arrowTypeEnd = 'arrow_cross';
|
||||
break;
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: Expected fallthrough
|
||||
case 'double_arrow_point':
|
||||
edgeData.arrowTypeStart = 'arrow_point';
|
||||
case 'arrow_point':
|
||||
edgeData.arrowTypeEnd = 'arrow_point';
|
||||
break;
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: Expected fallthrough
|
||||
case 'double_arrow_circle':
|
||||
edgeData.arrowTypeStart = 'arrow_circle';
|
||||
case 'arrow_circle':
|
||||
@@ -595,7 +597,7 @@ const addMarkersToEdge = function (svgPath, edgeData, diagramType, arrowMarkerAb
|
||||
*
|
||||
* @param text
|
||||
* @param diagObj
|
||||
* @returns {Record<string, import('../../mermaid/src/diagram-api/types.js').DiagramStyleClassDef>} ClassDef styles
|
||||
* @returns {Map<string, import('../../mermaid/src/diagram-api/types.js').DiagramStyleClassDef>} ClassDef styles
|
||||
*/
|
||||
export const getClasses = function (text, diagObj) {
|
||||
log.info('Extracting classes');
|
||||
|
||||
@@ -12,12 +12,7 @@
|
||||
},
|
||||
"./*": "./*"
|
||||
},
|
||||
"keywords": [
|
||||
"diagram",
|
||||
"markdown",
|
||||
"zenuml",
|
||||
"mermaid"
|
||||
],
|
||||
"keywords": ["diagram", "markdown", "zenuml", "mermaid"],
|
||||
"scripts": {
|
||||
"clean": "rimraf dist",
|
||||
"prepublishOnly": "pnpm -w run build"
|
||||
@@ -42,7 +37,5 @@
|
||||
"peerDependencies": {
|
||||
"mermaid": "workspace:>=10.0.0"
|
||||
},
|
||||
"files": [
|
||||
"dist"
|
||||
]
|
||||
"files": ["dist"]
|
||||
}
|
||||
|
||||
@@ -58,19 +58,13 @@
|
||||
"author": "Knut Sveidqvist",
|
||||
"license": "MIT",
|
||||
"standard": {
|
||||
"ignore": [
|
||||
"**/parser/*.js",
|
||||
"dist/**/*.js",
|
||||
"cypress/**/*.js"
|
||||
],
|
||||
"globals": [
|
||||
"page"
|
||||
]
|
||||
"ignore": ["**/parser/*.js", "dist/**/*.js", "cypress/**/*.js"],
|
||||
"globals": ["page"]
|
||||
},
|
||||
"dependencies": {
|
||||
"@braintree/sanitize-url": "^7.0.1",
|
||||
"@mermaid-js/parser": "workspace:^",
|
||||
"cytoscape": "^3.28.1",
|
||||
"cytoscape": "^3.29.2",
|
||||
"cytoscape-cose-bilkent": "^4.1.0",
|
||||
"d3": "^7.9.0",
|
||||
"d3-sankey": "^0.12.3",
|
||||
@@ -88,7 +82,7 @@
|
||||
},
|
||||
"devDependencies": {
|
||||
"@adobe/jsonschema2md": "^8.0.0",
|
||||
"@types/cytoscape": "^3.19.16",
|
||||
"@types/cytoscape": "^3.21.4",
|
||||
"@types/d3": "^7.4.3",
|
||||
"@types/d3-sankey": "^0.12.4",
|
||||
"@types/d3-scale": "^4.0.8",
|
||||
@@ -103,8 +97,6 @@
|
||||
"@types/prettier": "^3.0.0",
|
||||
"@types/stylis": "^4.2.5",
|
||||
"@types/uuid": "^9.0.8",
|
||||
"@typescript-eslint/eslint-plugin": "^7.3.1",
|
||||
"@typescript-eslint/parser": "^7.3.1",
|
||||
"ajv": "^8.12.0",
|
||||
"chokidar": "^3.6.0",
|
||||
"concurrently": "^8.2.2",
|
||||
@@ -132,10 +124,7 @@
|
||||
"vitepress": "^1.0.1",
|
||||
"vitepress-plugin-search": "1.0.4-alpha.22"
|
||||
},
|
||||
"files": [
|
||||
"dist/",
|
||||
"README.md"
|
||||
],
|
||||
"files": ["dist/", "README.md"],
|
||||
"sideEffects": false,
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
|
||||
@@ -10,17 +10,15 @@
|
||||
|
||||
/* eslint-disable no-console */
|
||||
|
||||
import { readFile, writeFile } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
import _Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js';
|
||||
import { JSON_SCHEMA, load } from 'js-yaml';
|
||||
import { compile, type JSONSchema } from 'json-schema-to-typescript';
|
||||
import assert from 'node:assert';
|
||||
import { execFile } from 'node:child_process';
|
||||
import { readFile, writeFile } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
import { promisify } from 'node:util';
|
||||
|
||||
import { load, JSON_SCHEMA } from 'js-yaml';
|
||||
import { compile, type JSONSchema } from 'json-schema-to-typescript';
|
||||
import prettier from 'prettier';
|
||||
|
||||
import _Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js';
|
||||
import { prettierConfig } from './prettier.js';
|
||||
|
||||
// Workaround for wrong AJV types, see
|
||||
// https://github.com/ajv-validator/ajv/issues/2132#issuecomment-1290409907
|
||||
@@ -34,28 +32,6 @@ const verifyOnly = process.argv.includes('--verify');
|
||||
/** If `true`, automatically `git add` any changes (i.e. during `pnpm run pre-commit`)*/
|
||||
const git = process.argv.includes('--git');
|
||||
|
||||
/**
|
||||
* All of the keys in the mermaid config that have a mermaid diagram config.
|
||||
*/
|
||||
const MERMAID_CONFIG_DIAGRAM_KEYS = [
|
||||
'flowchart',
|
||||
'sequence',
|
||||
'gantt',
|
||||
'journey',
|
||||
'class',
|
||||
'state',
|
||||
'er',
|
||||
'pie',
|
||||
'quadrantChart',
|
||||
'xyChart',
|
||||
'requirement',
|
||||
'mindmap',
|
||||
'timeline',
|
||||
'gitGraph',
|
||||
'c4',
|
||||
'sankey',
|
||||
];
|
||||
|
||||
/**
|
||||
* Loads the MermaidConfig JSON schema YAML file.
|
||||
*
|
||||
@@ -148,53 +124,9 @@ async function generateTypescript(mermaidConfigSchema: JSONSchemaType<MermaidCon
|
||||
return { ...schema, required: [] };
|
||||
}
|
||||
|
||||
/**
|
||||
* This is a temporary hack to control the order the types are generated in.
|
||||
*
|
||||
* By default, json-schema-to-typescript outputs the $defs in the order they
|
||||
* are used, then any unused schemas at the end.
|
||||
*
|
||||
* **The only purpose of this function is to make the `git diff` simpler**
|
||||
* **We should remove this later to simplify the code**
|
||||
*
|
||||
* @todo TODO: Remove this function in a future PR.
|
||||
* @param schema - The input schema.
|
||||
* @returns The schema with all `$ref`s removed.
|
||||
*/
|
||||
function unrefSubschemas(schema: JSONSchemaType<Record<string, any>>) {
|
||||
return {
|
||||
...schema,
|
||||
properties: Object.fromEntries(
|
||||
Object.entries(schema.properties).map(([key, propertySchema]) => {
|
||||
if (MERMAID_CONFIG_DIAGRAM_KEYS.includes(key)) {
|
||||
const { $ref, ...propertySchemaWithoutRef } = propertySchema as JSONSchemaType<unknown>;
|
||||
if ($ref === undefined) {
|
||||
throw Error(
|
||||
`subSchema ${key} is in MERMAID_CONFIG_DIAGRAM_KEYS but does not have a $ref field`
|
||||
);
|
||||
}
|
||||
const [
|
||||
_root, // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
_defs, // eslint-disable-line @typescript-eslint/no-unused-vars
|
||||
defName,
|
||||
] = $ref.split('/');
|
||||
return [
|
||||
key,
|
||||
{
|
||||
...propertySchemaWithoutRef,
|
||||
tsType: defName,
|
||||
},
|
||||
];
|
||||
}
|
||||
return [key, propertySchema];
|
||||
})
|
||||
),
|
||||
};
|
||||
}
|
||||
|
||||
assert.ok(mermaidConfigSchema.$defs);
|
||||
const modifiedSchema = {
|
||||
...unrefSubschemas(removeRequired(mermaidConfigSchema)),
|
||||
...removeRequired(mermaidConfigSchema),
|
||||
|
||||
$defs: Object.fromEntries(
|
||||
Object.entries(mermaidConfigSchema.$defs).map(([key, subSchema]) => {
|
||||
@@ -209,7 +141,7 @@ async function generateTypescript(mermaidConfigSchema: JSONSchemaType<MermaidCon
|
||||
{
|
||||
additionalProperties: false, // in JSON Schema 2019-09, these are called `unevaluatedProperties`
|
||||
unreachableDefinitions: true, // definition for FontConfig is unreachable
|
||||
style: (await prettier.resolveConfig('.')) ?? {},
|
||||
style: prettierConfig,
|
||||
}
|
||||
);
|
||||
|
||||
|
||||
@@ -52,6 +52,7 @@ import mm from 'micromatch';
|
||||
// @ts-ignore No typescript declaration file
|
||||
import flatmap from 'unist-util-flatmap';
|
||||
import { visit } from 'unist-util-visit';
|
||||
import { prettierConfig } from './prettier.js';
|
||||
|
||||
export const MERMAID_RELEASE_VERSION = JSON.parse(readFileSync('../mermaid/package.json', 'utf8'))
|
||||
.version as string;
|
||||
@@ -85,7 +86,6 @@ const LOGMSG_COPIED = `, and copied to ${FINAL_DOCS_DIR}`;
|
||||
|
||||
const WARN_DOCSDIR_DOESNT_MATCH = `Changed files were transformed in ${SOURCE_DOCS_DIR} but do not match the files in ${FINAL_DOCS_DIR}. Please run 'pnpm --filter mermaid run docs:build' after making changes to ${SOURCE_DOCS_DIR} to update the ${FINAL_DOCS_DIR} directory with the transformed files.`;
|
||||
|
||||
const prettierConfig = (await prettier.resolveConfig('.')) ?? {};
|
||||
// From https://github.com/vuejs/vitepress/blob/428eec3750d6b5648a77ac52d88128df0554d4d1/src/node/markdownToVue.ts#L20-L21
|
||||
const includesRE = /<!--\s*@include:\s*(.*?)\s*-->/g;
|
||||
const includedFiles: Set<string> = new Set();
|
||||
@@ -367,26 +367,26 @@ async function transformJsonSchema(file: string) {
|
||||
});
|
||||
|
||||
/** Location of the `schema.yaml` files */
|
||||
const SCHEMA_INPUT_DIR = 'src/schemas/';
|
||||
const schemaInputDir = 'src/schemas/';
|
||||
/**
|
||||
* Location to store the generated `schema.json` file for the website
|
||||
*
|
||||
* Because Vitepress doesn't handle bundling `.json` files properly, we need
|
||||
* to instead place it into a `public/` subdirectory.
|
||||
*/
|
||||
const SCHEMA_OUTPUT_DIR = 'src/docs/public/schemas/';
|
||||
const VITEPRESS_PUBLIC_DIR = 'src/docs/public';
|
||||
const schemaOutputDir = 'src/docs/public/schemas/';
|
||||
const vitepressPublicDir = 'src/docs/public';
|
||||
/**
|
||||
* Location to store the generated Schema Markdown docs.
|
||||
* Links to JSON Schemas should automatically be rewritten to point to
|
||||
* `SCHEMA_OUTPUT_DIR`.
|
||||
*/
|
||||
const SCHEMA_MARKDOWN_OUTPUT_DIR = join('src', 'docs', 'config', 'schema-docs');
|
||||
const schemaMarkdownOutputDir = join('src', 'docs', 'config', 'schema-docs');
|
||||
|
||||
// write .schema.json files
|
||||
const jsonFileName = file
|
||||
.replace('.schema.yaml', '.schema.json')
|
||||
.replace(SCHEMA_INPUT_DIR, SCHEMA_OUTPUT_DIR);
|
||||
.replace(schemaInputDir, schemaOutputDir);
|
||||
copyTransformedContents(jsonFileName, !verifyOnly, JSON.stringify(jsonSchema, undefined, 2));
|
||||
|
||||
const schemas = traverseSchemas([schemaLoader()(jsonFileName, jsonSchema)]);
|
||||
@@ -414,7 +414,7 @@ async function transformJsonSchema(file: string) {
|
||||
* @returns New absolute Vitepress path to schema
|
||||
*/
|
||||
rewritelinks: (origin: string) => {
|
||||
return `/${relative(VITEPRESS_PUBLIC_DIR, origin)}`;
|
||||
return `/${relative(vitepressPublicDir, origin)}`;
|
||||
},
|
||||
})(schemas);
|
||||
|
||||
@@ -458,7 +458,7 @@ async function transformJsonSchema(file: string) {
|
||||
parser: 'markdown',
|
||||
...prettierConfig,
|
||||
});
|
||||
const newFileName = join(SCHEMA_MARKDOWN_OUTPUT_DIR, `${name}.md`);
|
||||
const newFileName = join(schemaMarkdownOutputDir, `${name}.md`);
|
||||
copyTransformedContents(newFileName, !verifyOnly, formatted);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,11 +24,11 @@ describe('docs.mts', () => {
|
||||
|
||||
describe('is a code block', () => {
|
||||
const beforeCodeLine = 'test\n';
|
||||
const diagram_text = 'graph\n A --> B\n';
|
||||
const diagramText = 'graph\n A --> B\n';
|
||||
|
||||
describe('language = "mermaid-nocode"', () => {
|
||||
const lang_keyword = 'mermaid-nocode';
|
||||
const contents = beforeCodeLine + '```' + lang_keyword + '\n' + diagram_text + '\n```\n';
|
||||
const langKeyword = 'mermaid-nocode';
|
||||
const contents = beforeCodeLine + '```' + langKeyword + '\n' + diagramText + '\n```\n';
|
||||
|
||||
it('changes the language to "mermaid"', async () => {
|
||||
const result = (
|
||||
@@ -37,17 +37,16 @@ describe('docs.mts', () => {
|
||||
.process(contents)
|
||||
).toString();
|
||||
expect(result).toEqual(
|
||||
beforeCodeLine + '\n' + '```' + 'mermaid' + '\n' + diagram_text + '\n```\n'
|
||||
beforeCodeLine + '\n' + '```' + 'mermaid' + '\n' + diagramText + '\n```\n'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('language = "mermaid" | "mmd" | "mermaid-example"', () => {
|
||||
const mermaid_keywords = ['mermaid', 'mmd', 'mermaid-example'];
|
||||
const mermaidKeywords = ['mermaid', 'mmd', 'mermaid-example'];
|
||||
|
||||
mermaid_keywords.forEach((lang_keyword) => {
|
||||
const contents =
|
||||
beforeCodeLine + '```' + lang_keyword + '\n' + diagram_text + '\n```\n';
|
||||
mermaidKeywords.forEach((langKeyword) => {
|
||||
const contents = beforeCodeLine + '```' + langKeyword + '\n' + diagramText + '\n```\n';
|
||||
|
||||
it('changes the language to "mermaid-example" and adds a copy of the code block with language = "mermaid"', async () => {
|
||||
const result = (
|
||||
@@ -59,10 +58,10 @@ describe('docs.mts', () => {
|
||||
beforeCodeLine +
|
||||
'\n' +
|
||||
'```mermaid-example\n' +
|
||||
diagram_text +
|
||||
diagramText +
|
||||
'\n```\n' +
|
||||
'\n```mermaid\n' +
|
||||
diagram_text +
|
||||
diagramText +
|
||||
'\n```\n'
|
||||
);
|
||||
});
|
||||
@@ -70,9 +69,9 @@ describe('docs.mts', () => {
|
||||
});
|
||||
|
||||
it('calls transformToBlockQuote with the node information', async () => {
|
||||
const lang_keyword = 'note';
|
||||
const langKeyword = 'note';
|
||||
const contents =
|
||||
beforeCodeLine + '```' + lang_keyword + '\n' + 'This is the text\n' + '```\n';
|
||||
beforeCodeLine + '```' + langKeyword + '\n' + 'This is the text\n' + '```\n';
|
||||
|
||||
const result = (
|
||||
await remarkBuilder().use(transformMarkdownAst, { originalFilename }).process(contents)
|
||||
|
||||
8
packages/mermaid/scripts/prettier.ts
Normal file
8
packages/mermaid/scripts/prettier.ts
Normal file
@@ -0,0 +1,8 @@
|
||||
export const prettierConfig = {
|
||||
endOfLine: 'auto',
|
||||
printWidth: 100,
|
||||
singleQuote: true,
|
||||
useTabs: false,
|
||||
tabWidth: 2,
|
||||
trailingComma: 'es5',
|
||||
} as const;
|
||||
@@ -8,32 +8,32 @@ describe('when working with site config', () => {
|
||||
configApi.setSiteConfig({});
|
||||
});
|
||||
it('should set site config and config properly', () => {
|
||||
const config_0 = { fontFamily: 'foo-font', fontSize: 150 };
|
||||
configApi.setSiteConfig(config_0);
|
||||
const config_1 = configApi.getSiteConfig();
|
||||
const config_2 = configApi.getConfig();
|
||||
expect(config_1.fontFamily).toEqual(config_0.fontFamily);
|
||||
expect(config_1.fontSize).toEqual(config_0.fontSize);
|
||||
expect(config_1).toEqual(config_2);
|
||||
const config0 = { fontFamily: 'foo-font', fontSize: 150 };
|
||||
configApi.setSiteConfig(config0);
|
||||
const config1 = configApi.getSiteConfig();
|
||||
const config2 = configApi.getConfig();
|
||||
expect(config1.fontFamily).toEqual(config0.fontFamily);
|
||||
expect(config1.fontSize).toEqual(config0.fontSize);
|
||||
expect(config1).toEqual(config2);
|
||||
});
|
||||
it('should respect secure keys when applying directives', () => {
|
||||
const config_0: MermaidConfig = {
|
||||
const config0: MermaidConfig = {
|
||||
fontFamily: 'foo-font',
|
||||
securityLevel: 'strict', // can't be changed
|
||||
fontSize: 12345, // can't be changed
|
||||
secure: [...configApi.defaultConfig.secure!, 'fontSize'],
|
||||
};
|
||||
configApi.setSiteConfig(config_0);
|
||||
configApi.setSiteConfig(config0);
|
||||
const directive: MermaidConfig = {
|
||||
fontFamily: 'baf',
|
||||
// fontSize and securityLevel shouldn't be changed
|
||||
fontSize: 54321,
|
||||
securityLevel: 'loose',
|
||||
};
|
||||
const cfg: MermaidConfig = configApi.updateCurrentConfig(config_0, [directive]);
|
||||
const cfg: MermaidConfig = configApi.updateCurrentConfig(config0, [directive]);
|
||||
expect(cfg.fontFamily).toEqual(directive.fontFamily);
|
||||
expect(cfg.fontSize).toBe(config_0.fontSize);
|
||||
expect(cfg.securityLevel).toBe(config_0.securityLevel);
|
||||
expect(cfg.fontSize).toBe(config0.fontSize);
|
||||
expect(cfg.securityLevel).toBe(config0.securityLevel);
|
||||
});
|
||||
it('should allow setting partial options', () => {
|
||||
const defaultConfig = configApi.getConfig();
|
||||
@@ -52,30 +52,30 @@ describe('when working with site config', () => {
|
||||
);
|
||||
});
|
||||
it('should set reset config properly', () => {
|
||||
const config_0 = { fontFamily: 'foo-font', fontSize: 150 };
|
||||
configApi.setSiteConfig(config_0);
|
||||
const config_1 = { fontFamily: 'baf' };
|
||||
configApi.setConfig(config_1);
|
||||
const config_2 = configApi.getConfig();
|
||||
expect(config_2.fontFamily).toEqual(config_1.fontFamily);
|
||||
const config0 = { fontFamily: 'foo-font', fontSize: 150 };
|
||||
configApi.setSiteConfig(config0);
|
||||
const config1 = { fontFamily: 'baf' };
|
||||
configApi.setConfig(config1);
|
||||
const config2 = configApi.getConfig();
|
||||
expect(config2.fontFamily).toEqual(config1.fontFamily);
|
||||
configApi.reset();
|
||||
const config_3 = configApi.getConfig();
|
||||
expect(config_3.fontFamily).toEqual(config_0.fontFamily);
|
||||
const config_4 = configApi.getSiteConfig();
|
||||
expect(config_4.fontFamily).toEqual(config_0.fontFamily);
|
||||
const config3 = configApi.getConfig();
|
||||
expect(config3.fontFamily).toEqual(config0.fontFamily);
|
||||
const config4 = configApi.getSiteConfig();
|
||||
expect(config4.fontFamily).toEqual(config0.fontFamily);
|
||||
});
|
||||
it('should set global reset config properly', () => {
|
||||
const config_0 = { fontFamily: 'foo-font', fontSize: 150 };
|
||||
configApi.setSiteConfig(config_0);
|
||||
const config_1 = configApi.getSiteConfig();
|
||||
expect(config_1.fontFamily).toEqual(config_0.fontFamily);
|
||||
const config_2 = configApi.getConfig();
|
||||
expect(config_2.fontFamily).toEqual(config_0.fontFamily);
|
||||
const config0 = { fontFamily: 'foo-font', fontSize: 150 };
|
||||
configApi.setSiteConfig(config0);
|
||||
const config1 = configApi.getSiteConfig();
|
||||
expect(config1.fontFamily).toEqual(config0.fontFamily);
|
||||
const config2 = configApi.getConfig();
|
||||
expect(config2.fontFamily).toEqual(config0.fontFamily);
|
||||
configApi.setConfig({ altFontFamily: 'bar-font' });
|
||||
const config_3 = configApi.getConfig();
|
||||
expect(config_3.altFontFamily).toEqual('bar-font');
|
||||
const config3 = configApi.getConfig();
|
||||
expect(config3.altFontFamily).toEqual('bar-font');
|
||||
configApi.reset();
|
||||
const config_4 = configApi.getConfig();
|
||||
expect(config_4.altFontFamily).toBeUndefined();
|
||||
const config4 = configApi.getConfig();
|
||||
expect(config4.altFontFamily).toBeUndefined();
|
||||
});
|
||||
});
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -13,13 +13,13 @@ export default intersectPolygon;
|
||||
* @param point
|
||||
*/
|
||||
function intersectPolygon(node, polyPoints, point) {
|
||||
var x1 = node.x;
|
||||
var y1 = node.y;
|
||||
let x1 = node.x;
|
||||
let y1 = node.y;
|
||||
|
||||
var intersections = [];
|
||||
let intersections = [];
|
||||
|
||||
var minX = Number.POSITIVE_INFINITY;
|
||||
var minY = Number.POSITIVE_INFINITY;
|
||||
let minX = Number.POSITIVE_INFINITY;
|
||||
let minY = Number.POSITIVE_INFINITY;
|
||||
if (typeof polyPoints.forEach === 'function') {
|
||||
polyPoints.forEach(function (entry) {
|
||||
minX = Math.min(minX, entry.x);
|
||||
@@ -30,13 +30,13 @@ function intersectPolygon(node, polyPoints, point) {
|
||||
minY = Math.min(minY, polyPoints.y);
|
||||
}
|
||||
|
||||
var left = x1 - node.width / 2 - minX;
|
||||
var top = y1 - node.height / 2 - minY;
|
||||
let left = x1 - node.width / 2 - minX;
|
||||
let top = y1 - node.height / 2 - minY;
|
||||
|
||||
for (var i = 0; i < polyPoints.length; i++) {
|
||||
var p1 = polyPoints[i];
|
||||
var p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0];
|
||||
var intersect = intersectLine(
|
||||
for (let i = 0; i < polyPoints.length; i++) {
|
||||
let p1 = polyPoints[i];
|
||||
let p2 = polyPoints[i < polyPoints.length - 1 ? i + 1 : 0];
|
||||
let intersect = intersectLine(
|
||||
node,
|
||||
point,
|
||||
{ x: left + p1.x, y: top + p1.y },
|
||||
@@ -55,13 +55,13 @@ function intersectPolygon(node, polyPoints, point) {
|
||||
if (intersections.length > 1) {
|
||||
// More intersections, find the one nearest to edge end point
|
||||
intersections.sort(function (p, q) {
|
||||
var pdx = p.x - point.x;
|
||||
var pdy = p.y - point.y;
|
||||
var distp = Math.sqrt(pdx * pdx + pdy * pdy);
|
||||
let pdx = p.x - point.x;
|
||||
let pdy = p.y - point.y;
|
||||
let distp = Math.sqrt(pdx * pdx + pdy * pdy);
|
||||
|
||||
var qdx = q.x - point.x;
|
||||
var qdy = q.y - point.y;
|
||||
var distq = Math.sqrt(qdx * qdx + qdy * qdy);
|
||||
let qdx = q.x - point.x;
|
||||
let qdy = q.y - point.y;
|
||||
let distq = Math.sqrt(qdx * qdx + qdy * qdy);
|
||||
|
||||
return distp < distq ? -1 : distp === distq ? 0 : 1;
|
||||
});
|
||||
|
||||
@@ -119,7 +119,7 @@ const hexagon = async (parent, node) => {
|
||||
return shapeSvg;
|
||||
};
|
||||
|
||||
const block_arrow = async (parent, node) => {
|
||||
const blockArrow = async (parent, node) => {
|
||||
const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
|
||||
|
||||
const f = 2;
|
||||
@@ -140,7 +140,7 @@ const block_arrow = async (parent, node) => {
|
||||
return shapeSvg;
|
||||
};
|
||||
|
||||
const rect_left_inv_arrow = async (parent, node) => {
|
||||
const rectLeftInvArrow = async (parent, node) => {
|
||||
const { shapeSvg, bbox } = await labelHelper(
|
||||
parent,
|
||||
node,
|
||||
@@ -171,7 +171,7 @@ const rect_left_inv_arrow = async (parent, node) => {
|
||||
return shapeSvg;
|
||||
};
|
||||
|
||||
const lean_right = async (parent, node) => {
|
||||
const leanRight = async (parent, node) => {
|
||||
const { shapeSvg, bbox } = await labelHelper(parent, node, getClassesFromNode(node), true);
|
||||
|
||||
const w = bbox.width + node.padding;
|
||||
@@ -194,7 +194,7 @@ const lean_right = async (parent, node) => {
|
||||
return shapeSvg;
|
||||
};
|
||||
|
||||
const lean_left = async (parent, node) => {
|
||||
const leanLeft = async (parent, node) => {
|
||||
const { shapeSvg, bbox } = await labelHelper(
|
||||
parent,
|
||||
node,
|
||||
@@ -250,7 +250,7 @@ const trapezoid = async (parent, node) => {
|
||||
return shapeSvg;
|
||||
};
|
||||
|
||||
const inv_trapezoid = async (parent, node) => {
|
||||
const invTrapezoid = async (parent, node) => {
|
||||
const { shapeSvg, bbox } = await labelHelper(
|
||||
parent,
|
||||
node,
|
||||
@@ -278,7 +278,7 @@ const inv_trapezoid = async (parent, node) => {
|
||||
return shapeSvg;
|
||||
};
|
||||
|
||||
const rect_right_inv_arrow = async (parent, node) => {
|
||||
const rectRightInvArrow = async (parent, node) => {
|
||||
const { shapeSvg, bbox } = await labelHelper(
|
||||
parent,
|
||||
node,
|
||||
@@ -875,7 +875,7 @@ const end = (parent, node) => {
|
||||
return shapeSvg;
|
||||
};
|
||||
|
||||
const class_box = (parent, node) => {
|
||||
const classBox = (parent, node) => {
|
||||
const halfPadding = node.padding / 2;
|
||||
const rowPadding = 4;
|
||||
const lineHeight = 8;
|
||||
@@ -1111,13 +1111,13 @@ const shapes = {
|
||||
doublecircle,
|
||||
stadium,
|
||||
hexagon,
|
||||
block_arrow,
|
||||
rect_left_inv_arrow,
|
||||
lean_right,
|
||||
lean_left,
|
||||
block_arrow: blockArrow,
|
||||
rect_left_inv_arrow: rectLeftInvArrow,
|
||||
lean_right: leanRight,
|
||||
lean_left: leanLeft,
|
||||
trapezoid,
|
||||
inv_trapezoid,
|
||||
rect_right_inv_arrow,
|
||||
inv_trapezoid: invTrapezoid,
|
||||
rect_right_inv_arrow: rectRightInvArrow,
|
||||
cylinder,
|
||||
start,
|
||||
end,
|
||||
@@ -1125,7 +1125,7 @@ const shapes = {
|
||||
subroutine,
|
||||
fork: forkJoin,
|
||||
join: forkJoin,
|
||||
class_box,
|
||||
class_box: classBox,
|
||||
};
|
||||
|
||||
let nodeElems = {};
|
||||
|
||||
@@ -70,7 +70,7 @@ export interface DiagramRenderer {
|
||||
getClasses?: (
|
||||
text: string,
|
||||
diagram: Pick<DiagramDefinition, 'db'>
|
||||
) => Record<string, DiagramStyleClassDef>;
|
||||
) => Map<string, DiagramStyleClassDef>;
|
||||
}
|
||||
|
||||
export interface DiagramDefinition {
|
||||
|
||||
@@ -70,8 +70,9 @@ describe('diagram detection', () => {
|
||||
--------------^
|
||||
Expecting 'AMP', 'COLON', 'PIPE', 'TESTSTR', 'DOWN', 'DEFAULT', 'NUM', 'COMMA', 'NODE_STRING', 'BRKT', 'MINUS', 'MULT', 'UNICODE_TEXT', got 'EOF']
|
||||
`);
|
||||
await expect(Diagram.fromText('sequenceDiagram; A-->B')).rejects
|
||||
.toThrowErrorMatchingInlineSnapshot(`
|
||||
await expect(
|
||||
Diagram.fromText('sequenceDiagram; A-->B')
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`
|
||||
[Error: Parse error on line 1:
|
||||
...quenceDiagram; A-->B
|
||||
-----------------------^
|
||||
|
||||
@@ -1,21 +1,26 @@
|
||||
import clone from 'lodash-es/clone.js';
|
||||
import * as configApi from '../../config.js';
|
||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||
import type { DiagramDB } from '../../diagram-api/types.js';
|
||||
import { log } from '../../logger.js';
|
||||
import common from '../common/common.js';
|
||||
import { clear as commonClear } from '../common/commonDb.js';
|
||||
import type { Block, ClassDef } from './blockTypes.js';
|
||||
|
||||
// Initialize the node database for simple lookups
|
||||
let blockDatabase: Record<string, Block> = {};
|
||||
let blockDatabase: Map<string, Block> = new Map();
|
||||
let edgeList: Block[] = [];
|
||||
let edgeCount: Record<string, number> = {};
|
||||
let edgeCount: Map<string, number> = new Map();
|
||||
|
||||
const COLOR_KEYWORD = 'color';
|
||||
const FILL_KEYWORD = 'fill';
|
||||
const BG_FILL = 'bgFill';
|
||||
const STYLECLASS_SEP = ',';
|
||||
const config = getConfig();
|
||||
|
||||
let classes = {} as Record<string, ClassDef>;
|
||||
let classes: Map<string, ClassDef> = new Map();
|
||||
|
||||
const sanitizeText = (txt: string) => common.sanitizeText(txt, config);
|
||||
|
||||
/**
|
||||
* Called when the parser comes across a (style) class definition
|
||||
@@ -26,10 +31,11 @@ let classes = {} as Record<string, ClassDef>;
|
||||
*/
|
||||
export const addStyleClass = function (id: string, styleAttributes = '') {
|
||||
// create a new style class object with this id
|
||||
if (classes[id] === undefined) {
|
||||
classes[id] = { id: id, styles: [], textStyles: [] }; // This is a classDef
|
||||
let foundClass = classes.get(id);
|
||||
if (!foundClass) {
|
||||
foundClass = { id: id, styles: [], textStyles: [] };
|
||||
classes.set(id, foundClass); // This is a classDef
|
||||
}
|
||||
const foundClass = classes[id];
|
||||
if (styleAttributes !== undefined && styleAttributes !== null) {
|
||||
styleAttributes.split(STYLECLASS_SEP).forEach((attrib) => {
|
||||
// remove any trailing ;
|
||||
@@ -54,7 +60,7 @@ export const addStyleClass = function (id: string, styleAttributes = '') {
|
||||
* @param styles - the string with 1 or more style attributes (each separated by a comma)
|
||||
*/
|
||||
export const addStyle2Node = function (id: string, styles = '') {
|
||||
const foundBlock = blockDatabase[id];
|
||||
const foundBlock = blockDatabase.get(id)!;
|
||||
if (styles !== undefined && styles !== null) {
|
||||
foundBlock.styles = styles.split(STYLECLASS_SEP);
|
||||
}
|
||||
@@ -70,11 +76,11 @@ export const addStyle2Node = function (id: string, styles = '') {
|
||||
*/
|
||||
export const setCssClass = function (itemIds: string, cssClassName: string) {
|
||||
itemIds.split(',').forEach(function (id: string) {
|
||||
let foundBlock = blockDatabase[id];
|
||||
let foundBlock = blockDatabase.get(id);
|
||||
if (foundBlock === undefined) {
|
||||
const trimmedId = id.trim();
|
||||
blockDatabase[trimmedId] = { id: trimmedId, type: 'na', children: [] } as Block;
|
||||
foundBlock = blockDatabase[trimmedId];
|
||||
foundBlock = { id: trimmedId, type: 'na', children: [] } as Block;
|
||||
blockDatabase.set(trimmedId, foundBlock);
|
||||
}
|
||||
if (!foundBlock.classes) {
|
||||
foundBlock.classes = [];
|
||||
@@ -87,6 +93,9 @@ const populateBlockDatabase = (_blockList: Block[] | Block[][], parent: Block):
|
||||
const blockList = _blockList.flat();
|
||||
const children = [];
|
||||
for (const block of blockList) {
|
||||
if (block.label) {
|
||||
block.label = sanitizeText(block.label);
|
||||
}
|
||||
if (block.type === 'classDef') {
|
||||
addStyleClass(block.id, block.css);
|
||||
continue;
|
||||
@@ -104,12 +113,9 @@ const populateBlockDatabase = (_blockList: Block[] | Block[][], parent: Block):
|
||||
if (block.type === 'column-setting') {
|
||||
parent.columns = block.columns || -1;
|
||||
} else if (block.type === 'edge') {
|
||||
if (edgeCount[block.id]) {
|
||||
edgeCount[block.id]++;
|
||||
} else {
|
||||
edgeCount[block.id] = 1;
|
||||
}
|
||||
block.id = edgeCount[block.id] + '-' + block.id;
|
||||
const count = (edgeCount.get(block.id) ?? 0) + 1;
|
||||
edgeCount.set(block.id, count);
|
||||
block.id = count + '-' + block.id;
|
||||
edgeList.push(block);
|
||||
} else {
|
||||
if (!block.label) {
|
||||
@@ -120,16 +126,17 @@ const populateBlockDatabase = (_blockList: Block[] | Block[][], parent: Block):
|
||||
block.label = block.id;
|
||||
}
|
||||
}
|
||||
const newBlock = !blockDatabase[block.id];
|
||||
if (newBlock) {
|
||||
blockDatabase[block.id] = block;
|
||||
const existingBlock = blockDatabase.get(block.id);
|
||||
|
||||
if (existingBlock === undefined) {
|
||||
blockDatabase.set(block.id, block);
|
||||
} else {
|
||||
// Add newer relevant data to aggregated node
|
||||
if (block.type !== 'na') {
|
||||
blockDatabase[block.id].type = block.type;
|
||||
existingBlock.type = block.type;
|
||||
}
|
||||
if (block.label !== block.id) {
|
||||
blockDatabase[block.id].label = block.label;
|
||||
existingBlock.label = block.label;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -142,10 +149,10 @@ const populateBlockDatabase = (_blockList: Block[] | Block[][], parent: Block):
|
||||
for (let j = 0; j < w; j++) {
|
||||
const newBlock = clone(block);
|
||||
newBlock.id = newBlock.id + '-' + j;
|
||||
blockDatabase[newBlock.id] = newBlock;
|
||||
blockDatabase.set(newBlock.id, newBlock);
|
||||
children.push(newBlock);
|
||||
}
|
||||
} else if (newBlock) {
|
||||
} else if (existingBlock === undefined) {
|
||||
children.push(block);
|
||||
}
|
||||
}
|
||||
@@ -160,12 +167,12 @@ const clear = (): void => {
|
||||
log.debug('Clear called');
|
||||
commonClear();
|
||||
rootBlock = { id: 'root', type: 'composite', children: [], columns: -1 } as Block;
|
||||
blockDatabase = { root: rootBlock };
|
||||
blockDatabase = new Map([['root', rootBlock]]);
|
||||
blocks = [] as Block[];
|
||||
classes = {} as Record<string, ClassDef>;
|
||||
classes = new Map();
|
||||
|
||||
edgeList = [];
|
||||
edgeCount = {};
|
||||
edgeCount = new Map();
|
||||
};
|
||||
|
||||
export function typeStr2Type(typeStr: string) {
|
||||
@@ -241,7 +248,7 @@ const setHierarchy = (block: Block[]): void => {
|
||||
};
|
||||
|
||||
const getColumns = (blockId: string): number => {
|
||||
const block = blockDatabase[blockId];
|
||||
const block = blockDatabase.get(blockId);
|
||||
if (!block) {
|
||||
return -1;
|
||||
}
|
||||
@@ -259,7 +266,7 @@ const getColumns = (blockId: string): number => {
|
||||
* @returns
|
||||
*/
|
||||
const getBlocksFlat = () => {
|
||||
return [...Object.values(blockDatabase)];
|
||||
return [...blockDatabase.values()];
|
||||
};
|
||||
/**
|
||||
* Returns the hierarchy of blocks
|
||||
@@ -273,11 +280,11 @@ const getEdges = () => {
|
||||
return edgeList;
|
||||
};
|
||||
const getBlock = (id: string) => {
|
||||
return blockDatabase[id];
|
||||
return blockDatabase.get(id);
|
||||
};
|
||||
|
||||
const setBlock = (block: Block) => {
|
||||
blockDatabase[block.id] = block;
|
||||
blockDatabase.set(block.id, block);
|
||||
};
|
||||
|
||||
const getLogger = () => console;
|
||||
|
||||
@@ -388,7 +388,7 @@ describe('Block diagram', function () {
|
||||
const mc = blocks[0];
|
||||
expect(mc.classes).toContain('black');
|
||||
const classes = db.getClasses();
|
||||
const black = classes.black;
|
||||
const black = classes.get('black')!;
|
||||
expect(black.id).toBe('black');
|
||||
expect(black.styles[0]).toEqual('color:#ffffff');
|
||||
});
|
||||
@@ -406,4 +406,21 @@ columns 1
|
||||
expect(B.styles).toContain('fill:#f9F');
|
||||
});
|
||||
});
|
||||
|
||||
describe('prototype properties', function () {
|
||||
function validateProperty(prop: string) {
|
||||
expect(() => block.parse(`block-beta\n${prop}`)).not.toThrow();
|
||||
expect(() =>
|
||||
block.parse(`block-beta\nA; classDef ${prop} color:#ffffff,fill:#000000; class A ${prop}`)
|
||||
).not.toThrow();
|
||||
}
|
||||
|
||||
it('should work with a __proto__ property', function () {
|
||||
validateProperty('__proto__');
|
||||
});
|
||||
|
||||
it('should work with a constructor property', function () {
|
||||
validateProperty('constructor');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -256,7 +256,7 @@ boundaryStartStatement
|
||||
|
||||
boundaryStart
|
||||
: ENTERPRISE_BOUNDARY attributes {$2.splice(2, 0, 'ENTERPRISE'); yy.addPersonOrSystemBoundary(...$2); $$=$2;}
|
||||
| SYSTEM_BOUNDARY attributes {$2.splice(2, 0, 'ENTERPRISE'); yy.addPersonOrSystemBoundary(...$2); $$=$2;}
|
||||
| SYSTEM_BOUNDARY attributes {$2.splice(2, 0, 'SYSTEM'); yy.addPersonOrSystemBoundary(...$2); $$=$2;}
|
||||
| BOUNDARY attributes {yy.addPersonOrSystemBoundary(...$2); $$=$2;}
|
||||
| CONTAINER_BOUNDARY attributes {$2.splice(2, 0, 'CONTAINER'); yy.addContainerBoundary(...$2); $$=$2;}
|
||||
| NODE attributes {yy.addDeploymentNode('node', ...$2); $$=$2;}
|
||||
|
||||
@@ -26,10 +26,10 @@ import type {
|
||||
const MERMAID_DOM_ID_PREFIX = 'classId-';
|
||||
|
||||
let relations: ClassRelation[] = [];
|
||||
let classes: ClassMap = {};
|
||||
let classes: Map<string, ClassNode> = new Map();
|
||||
let notes: ClassNote[] = [];
|
||||
let classCounter = 0;
|
||||
let namespaces: NamespaceMap = {};
|
||||
let namespaces: Map<string, NamespaceNode> = new Map();
|
||||
let namespaceCounter = 0;
|
||||
|
||||
let functions: any[] = [];
|
||||
@@ -57,7 +57,7 @@ export const setClassLabel = function (_id: string, label: string) {
|
||||
}
|
||||
|
||||
const { className } = splitClassNameAndType(id);
|
||||
classes[className].label = label;
|
||||
classes.get(className)!.label = label;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -70,13 +70,13 @@ export const addClass = function (_id: string) {
|
||||
const id = common.sanitizeText(_id, getConfig());
|
||||
const { className, type } = splitClassNameAndType(id);
|
||||
// Only add class if not exists
|
||||
if (Object.hasOwn(classes, className)) {
|
||||
if (classes.has(className)) {
|
||||
return;
|
||||
}
|
||||
// alert('Adding class: ' + className);
|
||||
const name = common.sanitizeText(className, getConfig());
|
||||
// alert('Adding class after: ' + name);
|
||||
classes[name] = {
|
||||
classes.set(name, {
|
||||
id: name,
|
||||
type: type,
|
||||
label: name,
|
||||
@@ -86,7 +86,7 @@ export const addClass = function (_id: string) {
|
||||
annotations: [],
|
||||
styles: [],
|
||||
domId: MERMAID_DOM_ID_PREFIX + name + '-' + classCounter,
|
||||
} as ClassNode;
|
||||
} as ClassNode);
|
||||
|
||||
classCounter++;
|
||||
};
|
||||
@@ -99,25 +99,25 @@ export const addClass = function (_id: string) {
|
||||
*/
|
||||
export const lookUpDomId = function (_id: string): string {
|
||||
const id = common.sanitizeText(_id, getConfig());
|
||||
if (id in classes) {
|
||||
return classes[id].domId;
|
||||
if (classes.has(id)) {
|
||||
return classes.get(id)!.domId;
|
||||
}
|
||||
throw new Error('Class not found: ' + id);
|
||||
};
|
||||
|
||||
export const clear = function () {
|
||||
relations = [];
|
||||
classes = {};
|
||||
classes = new Map();
|
||||
notes = [];
|
||||
functions = [];
|
||||
functions.push(setupToolTips);
|
||||
namespaces = {};
|
||||
namespaces = new Map();
|
||||
namespaceCounter = 0;
|
||||
commonClear();
|
||||
};
|
||||
|
||||
export const getClass = function (id: string): ClassNode {
|
||||
return classes[id];
|
||||
return classes.get(id)!;
|
||||
};
|
||||
|
||||
export const getClasses = function (): ClassMap {
|
||||
@@ -157,7 +157,7 @@ export const addRelation = function (relation: ClassRelation) {
|
||||
*/
|
||||
export const addAnnotation = function (className: string, annotation: string) {
|
||||
const validatedClassName = splitClassNameAndType(className).className;
|
||||
classes[validatedClassName].annotations.push(annotation);
|
||||
classes.get(validatedClassName)!.annotations.push(annotation);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -173,7 +173,7 @@ export const addMember = function (className: string, member: string) {
|
||||
addClass(className);
|
||||
|
||||
const validatedClassName = splitClassNameAndType(className).className;
|
||||
const theClass = classes[validatedClassName];
|
||||
const theClass = classes.get(validatedClassName)!;
|
||||
|
||||
if (typeof member === 'string') {
|
||||
// Member can contain white spaces, we trim them out
|
||||
@@ -226,8 +226,9 @@ export const setCssClass = function (ids: string, className: string) {
|
||||
if (_id[0].match(/\d/)) {
|
||||
id = MERMAID_DOM_ID_PREFIX + id;
|
||||
}
|
||||
if (classes[id] !== undefined) {
|
||||
classes[id].cssClasses.push(className);
|
||||
const classNode = classes.get(id);
|
||||
if (classNode) {
|
||||
classNode.cssClasses.push(className);
|
||||
}
|
||||
});
|
||||
};
|
||||
@@ -241,17 +242,17 @@ export const setCssClass = function (ids: string, className: string) {
|
||||
const setTooltip = function (ids: string, tooltip?: string) {
|
||||
ids.split(',').forEach(function (id) {
|
||||
if (tooltip !== undefined) {
|
||||
classes[id].tooltip = sanitizeText(tooltip);
|
||||
classes.get(id)!.tooltip = sanitizeText(tooltip);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
export const getTooltip = function (id: string, namespace?: string) {
|
||||
if (namespace) {
|
||||
return namespaces[namespace].classes[id].tooltip;
|
||||
if (namespace && namespaces.has(namespace)) {
|
||||
return namespaces.get(namespace)!.classes.get(id)!.tooltip;
|
||||
}
|
||||
|
||||
return classes[id].tooltip;
|
||||
return classes.get(id)!.tooltip;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -268,14 +269,15 @@ export const setLink = function (ids: string, linkStr: string, target: string) {
|
||||
if (_id[0].match(/\d/)) {
|
||||
id = MERMAID_DOM_ID_PREFIX + id;
|
||||
}
|
||||
if (classes[id] !== undefined) {
|
||||
classes[id].link = utils.formatUrl(linkStr, config);
|
||||
const theClass = classes.get(id);
|
||||
if (theClass) {
|
||||
theClass.link = utils.formatUrl(linkStr, config);
|
||||
if (config.securityLevel === 'sandbox') {
|
||||
classes[id].linkTarget = '_top';
|
||||
theClass.linkTarget = '_top';
|
||||
} else if (typeof target === 'string') {
|
||||
classes[id].linkTarget = sanitizeText(target);
|
||||
theClass.linkTarget = sanitizeText(target);
|
||||
} else {
|
||||
classes[id].linkTarget = '_blank';
|
||||
theClass.linkTarget = '_blank';
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -292,7 +294,7 @@ export const setLink = function (ids: string, linkStr: string, target: string) {
|
||||
export const setClickEvent = function (ids: string, functionName: string, functionArgs: string) {
|
||||
ids.split(',').forEach(function (id) {
|
||||
setClickFunc(id, functionName, functionArgs);
|
||||
classes[id].haveCallback = true;
|
||||
classes.get(id)!.haveCallback = true;
|
||||
});
|
||||
setCssClass(ids, 'clickable');
|
||||
};
|
||||
@@ -308,7 +310,7 @@ const setClickFunc = function (_domId: string, functionName: string, functionArg
|
||||
}
|
||||
|
||||
const id = domId;
|
||||
if (classes[id] !== undefined) {
|
||||
if (classes.has(id)) {
|
||||
const elemId = lookUpDomId(id);
|
||||
let argList: string[] = [];
|
||||
if (typeof functionArgs === 'string') {
|
||||
@@ -417,22 +419,22 @@ const setDirection = (dir: string) => {
|
||||
* @public
|
||||
*/
|
||||
export const addNamespace = function (id: string) {
|
||||
if (namespaces[id] !== undefined) {
|
||||
if (namespaces.has(id)) {
|
||||
return;
|
||||
}
|
||||
|
||||
namespaces[id] = {
|
||||
namespaces.set(id, {
|
||||
id: id,
|
||||
classes: {},
|
||||
classes: new Map(),
|
||||
children: {},
|
||||
domId: MERMAID_DOM_ID_PREFIX + id + '-' + namespaceCounter,
|
||||
} as NamespaceNode;
|
||||
} as NamespaceNode);
|
||||
|
||||
namespaceCounter++;
|
||||
};
|
||||
|
||||
const getNamespace = function (name: string): NamespaceNode {
|
||||
return namespaces[name];
|
||||
return namespaces.get(name)!;
|
||||
};
|
||||
|
||||
const getNamespaces = function (): NamespaceMap {
|
||||
@@ -447,18 +449,18 @@ const getNamespaces = function (): NamespaceMap {
|
||||
* @public
|
||||
*/
|
||||
export const addClassesToNamespace = function (id: string, classNames: string[]) {
|
||||
if (namespaces[id] === undefined) {
|
||||
if (!namespaces.has(id)) {
|
||||
return;
|
||||
}
|
||||
for (const name of classNames) {
|
||||
const { className } = splitClassNameAndType(name);
|
||||
classes[className].parent = id;
|
||||
namespaces[id].classes[className] = classes[className];
|
||||
classes.get(className)!.parent = id;
|
||||
namespaces.get(id)!.classes.set(className, classes.get(className)!);
|
||||
}
|
||||
};
|
||||
|
||||
export const setCssStyle = function (id: string, styles: string[]) {
|
||||
const thisClass = classes[id];
|
||||
const thisClass = classes.get(id);
|
||||
if (!styles || !thisClass) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
import { parser } from './parser/classDiagram.jison';
|
||||
import classDb from './classDb.js';
|
||||
import { vi, describe, it, expect } from 'vitest';
|
||||
import type { ClassMap, NamespaceNode } from './classTypes.js';
|
||||
const spyOn = vi.spyOn;
|
||||
|
||||
const staticCssStyle = 'text-decoration:underline;';
|
||||
@@ -392,8 +393,8 @@ class C13["With Città foreign language"]
|
||||
Student "1" --o "1" IdCard : carries
|
||||
Student "1" --o "1" Bike : rides`);
|
||||
|
||||
expect(Object.keys(classDb.getClasses()).length).toBe(3);
|
||||
expect(classDb.getClasses().Student).toMatchInlineSnapshot(`
|
||||
expect(classDb.getClasses().size).toBe(3);
|
||||
expect(classDb.getClasses().get('Student')).toMatchInlineSnapshot(`
|
||||
{
|
||||
"annotations": [],
|
||||
"cssClasses": [],
|
||||
@@ -1539,12 +1540,12 @@ class Class2
|
||||
}`;
|
||||
parser.parse(str);
|
||||
|
||||
const testNamespace = parser.yy.getNamespace('Namespace1');
|
||||
const testClasses = parser.yy.getClasses();
|
||||
expect(Object.keys(testNamespace.classes).length).toBe(2);
|
||||
const testNamespace: NamespaceNode = parser.yy.getNamespace('Namespace1');
|
||||
const testClasses: ClassMap = parser.yy.getClasses();
|
||||
expect(testNamespace.classes.size).toBe(2);
|
||||
expect(Object.keys(testNamespace.children).length).toBe(0);
|
||||
expect(testNamespace.classes['Class1'].id).toBe('Class1');
|
||||
expect(Object.keys(testClasses).length).toBe(2);
|
||||
expect(testNamespace.classes.get('Class1')?.id).toBe('Class1');
|
||||
expect(testClasses.size).toBe(2);
|
||||
});
|
||||
|
||||
it('should add relations between classes of different namespaces', function () {
|
||||
@@ -1573,25 +1574,25 @@ class Class2
|
||||
const testNamespaceB = parser.yy.getNamespace('B');
|
||||
const testClasses = parser.yy.getClasses();
|
||||
const testRelations = parser.yy.getRelations();
|
||||
expect(Object.keys(testNamespaceA.classes).length).toBe(2);
|
||||
expect(testNamespaceA.classes['A1'].members[0].getDisplayDetails().displayText).toBe(
|
||||
expect(testNamespaceA.classes.size).toBe(2);
|
||||
expect(testNamespaceA.classes.get('A1').members[0].getDisplayDetails().displayText).toBe(
|
||||
'+foo : string'
|
||||
);
|
||||
expect(testNamespaceA.classes['A2'].members[0].getDisplayDetails().displayText).toBe(
|
||||
expect(testNamespaceA.classes.get('A2').members[0].getDisplayDetails().displayText).toBe(
|
||||
'+bar : int'
|
||||
);
|
||||
expect(Object.keys(testNamespaceB.classes).length).toBe(2);
|
||||
expect(testNamespaceB.classes['B1'].members[0].getDisplayDetails().displayText).toBe(
|
||||
expect(testNamespaceB.classes.size).toBe(2);
|
||||
expect(testNamespaceB.classes.get('B1').members[0].getDisplayDetails().displayText).toBe(
|
||||
'+foo : bool'
|
||||
);
|
||||
expect(testNamespaceB.classes['B2'].members[0].getDisplayDetails().displayText).toBe(
|
||||
expect(testNamespaceB.classes.get('B2').members[0].getDisplayDetails().displayText).toBe(
|
||||
'+bar : float'
|
||||
);
|
||||
expect(Object.keys(testClasses).length).toBe(4);
|
||||
expect(testClasses['A1'].parent).toBe('A');
|
||||
expect(testClasses['A2'].parent).toBe('A');
|
||||
expect(testClasses['B1'].parent).toBe('B');
|
||||
expect(testClasses['B2'].parent).toBe('B');
|
||||
expect(testClasses.size).toBe(4);
|
||||
expect(testClasses.get('A1').parent).toBe('A');
|
||||
expect(testClasses.get('A2').parent).toBe('A');
|
||||
expect(testClasses.get('B1').parent).toBe('B');
|
||||
expect(testClasses.get('B2').parent).toBe('B');
|
||||
expect(testRelations[0].id1).toBe('A1');
|
||||
expect(testRelations[0].id2).toBe('B1');
|
||||
expect(testRelations[1].id1).toBe('A2');
|
||||
|
||||
@@ -4,7 +4,7 @@ import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
|
||||
import { log } from '../../logger.js';
|
||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||
import { render } from '../../dagre-wrapper/index.js';
|
||||
import utils from '../../utils.js';
|
||||
import utils, { getEdgeId } from '../../utils.js';
|
||||
import { interpolateToCurve, getStylesFromArray } from '../../utils.js';
|
||||
import { setupGraphViewbox } from '../../setupGraphViewbox.js';
|
||||
import common from '../common/common.js';
|
||||
@@ -44,14 +44,11 @@ export const addNamespaces = function (
|
||||
_id: string,
|
||||
diagObj: any
|
||||
) {
|
||||
const keys = Object.keys(namespaces);
|
||||
log.info('keys:', keys);
|
||||
log.info('keys:', [...namespaces.keys()]);
|
||||
log.info(namespaces);
|
||||
|
||||
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
|
||||
keys.forEach(function (id) {
|
||||
const vertex = namespaces[id];
|
||||
|
||||
namespaces.forEach(function (vertex) {
|
||||
// parent node must be one of [rect, roundedWithTitle, noteGroup, divider]
|
||||
const shape = 'rect';
|
||||
|
||||
@@ -89,16 +86,13 @@ export const addClasses = function (
|
||||
diagObj: any,
|
||||
parent?: string
|
||||
) {
|
||||
const keys = Object.keys(classes);
|
||||
log.info('keys:', keys);
|
||||
log.info('keys:', [...classes.keys()]);
|
||||
log.info(classes);
|
||||
|
||||
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
|
||||
keys
|
||||
.filter((id) => classes[id].parent == parent)
|
||||
.forEach(function (id) {
|
||||
const vertex = classes[id];
|
||||
|
||||
[...classes.values()]
|
||||
.filter((vertex) => vertex.parent === parent)
|
||||
.forEach(function (vertex) {
|
||||
/**
|
||||
* Variable for storing the classes for the vertex
|
||||
*/
|
||||
@@ -187,7 +181,7 @@ export const addNotes = function (
|
||||
g.setNode(vertex.id, node);
|
||||
log.info('setNode', node);
|
||||
|
||||
if (!vertex.class || !(vertex.class in classes)) {
|
||||
if (!vertex.class || !classes.has(vertex.class)) {
|
||||
return;
|
||||
}
|
||||
const edgeId = startEdgeId + i;
|
||||
@@ -231,7 +225,10 @@ export const addRelations = function (relations: ClassRelation[], g: graphlib.Gr
|
||||
//Set relationship style and line type
|
||||
classes: 'relation',
|
||||
pattern: edge.relation.lineType == 1 ? 'dashed' : 'solid',
|
||||
id: `id_${edge.id1}_${edge.id2}_${cnt}`,
|
||||
id: getEdgeId(edge.id1, edge.id2, {
|
||||
prefix: 'id',
|
||||
counter: cnt,
|
||||
}),
|
||||
// Set link type for rendering
|
||||
arrowhead: edge.type === 'arrow_open' ? 'none' : 'normal',
|
||||
//Set edge extra labels
|
||||
@@ -346,7 +343,7 @@ export const draw = async function (text: string, id: string, _version: string,
|
||||
}
|
||||
const root =
|
||||
securityLevel === 'sandbox'
|
||||
? select(sandboxElement.nodes()[0].contentDocument.body)
|
||||
? select(sandboxElement!.nodes()[0]!.contentDocument.body)
|
||||
: select('body');
|
||||
const svg = root.select(`[id="${id}"]`);
|
||||
|
||||
@@ -366,7 +363,8 @@ export const draw = async function (text: string, id: string, _version: string,
|
||||
|
||||
// Add label rects for non html labels
|
||||
if (!conf?.htmlLabels) {
|
||||
const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
|
||||
const doc =
|
||||
securityLevel === 'sandbox' ? sandboxElement!.nodes()[0]!.contentDocument : document;
|
||||
const labels = doc.querySelectorAll('[id="' + id + '"] .edgeLabel .label');
|
||||
for (const label of labels) {
|
||||
// Get dimensions of label
|
||||
|
||||
@@ -175,10 +175,10 @@ export const draw = function (text, id, _version, diagObj) {
|
||||
});
|
||||
|
||||
const classes = diagObj.db.getClasses();
|
||||
const keys = Object.keys(classes);
|
||||
const keys = [...classes.keys()];
|
||||
|
||||
for (const key of keys) {
|
||||
const classDef = classes[key];
|
||||
const classDef = classes.get(key);
|
||||
const node = svgDraw.drawClass(diagram, classDef, conf, diagObj);
|
||||
idCache[node.id] = node;
|
||||
|
||||
@@ -216,7 +216,7 @@ export const draw = function (text, id, _version, diagObj) {
|
||||
// metadata about the node. In this case we're going to add labels to each of
|
||||
// our nodes.
|
||||
g.setNode(node.id, node);
|
||||
if (note.class && note.class in classes) {
|
||||
if (note.class && classes.has(note.class)) {
|
||||
g.setEdge(
|
||||
note.id,
|
||||
getGraphId(note.class),
|
||||
|
||||
@@ -161,5 +161,5 @@ export interface NamespaceNode {
|
||||
children: NamespaceMap;
|
||||
}
|
||||
|
||||
export type ClassMap = Record<string, ClassNode>;
|
||||
export type NamespaceMap = Record<string, NamespaceNode>;
|
||||
export type ClassMap = Map<string, ClassNode>;
|
||||
export type NamespaceMap = Map<string, NamespaceNode>;
|
||||
|
||||
16
packages/mermaid/src/diagrams/class/parser/class.spec.js
Normal file
16
packages/mermaid/src/diagrams/class/parser/class.spec.js
Normal file
@@ -0,0 +1,16 @@
|
||||
import { parser } from './classDiagram.jison';
|
||||
import classDb from '../classDb.js';
|
||||
|
||||
describe('class diagram', function () {
|
||||
beforeEach(function () {
|
||||
parser.yy = classDb;
|
||||
parser.yy.clear();
|
||||
});
|
||||
|
||||
describe('prototype properties', function () {
|
||||
it.each(['__proto__', 'constructor'])('should work with a %s property', function (prop) {
|
||||
expect(() => parser.parse(`classDiagram\nclass ${prop}`)).not.toThrow();
|
||||
expect(() => parser.parse(`classDiagram\nnamespace ${prop} {\n\tclass A\n}`)).not.toThrow();
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -78,28 +78,28 @@ export const drawEdge = function (elem, path, relation, conf, diagObj) {
|
||||
x = labelPosition.x;
|
||||
y = labelPosition.y;
|
||||
|
||||
let p1_card_x, p1_card_y;
|
||||
let p2_card_x, p2_card_y;
|
||||
let p1CardX, p1CardY;
|
||||
let p2CardX, p2CardY;
|
||||
|
||||
if (l % 2 !== 0 && l > 1) {
|
||||
let cardinality_1_point = utils.calcCardinalityPosition(
|
||||
let cardinality1Point = utils.calcCardinalityPosition(
|
||||
relation.relation.type1 !== 'none',
|
||||
path.points,
|
||||
path.points[0]
|
||||
);
|
||||
let cardinality_2_point = utils.calcCardinalityPosition(
|
||||
let cardinality2Point = utils.calcCardinalityPosition(
|
||||
relation.relation.type2 !== 'none',
|
||||
path.points,
|
||||
path.points[l - 1]
|
||||
);
|
||||
|
||||
log.debug('cardinality_1_point ' + JSON.stringify(cardinality_1_point));
|
||||
log.debug('cardinality_2_point ' + JSON.stringify(cardinality_2_point));
|
||||
log.debug('cardinality_1_point ' + JSON.stringify(cardinality1Point));
|
||||
log.debug('cardinality_2_point ' + JSON.stringify(cardinality2Point));
|
||||
|
||||
p1_card_x = cardinality_1_point.x;
|
||||
p1_card_y = cardinality_1_point.y;
|
||||
p2_card_x = cardinality_2_point.x;
|
||||
p2_card_y = cardinality_2_point.y;
|
||||
p1CardX = cardinality1Point.x;
|
||||
p1CardY = cardinality1Point.y;
|
||||
p2CardX = cardinality2Point.x;
|
||||
p2CardY = cardinality2Point.y;
|
||||
}
|
||||
|
||||
if (relation.title !== undefined) {
|
||||
@@ -129,8 +129,8 @@ export const drawEdge = function (elem, path, relation, conf, diagObj) {
|
||||
const g = elem.append('g').attr('class', 'cardinality');
|
||||
g.append('text')
|
||||
.attr('class', 'type1')
|
||||
.attr('x', p1_card_x)
|
||||
.attr('y', p1_card_y)
|
||||
.attr('x', p1CardX)
|
||||
.attr('y', p1CardY)
|
||||
.attr('fill', 'black')
|
||||
.attr('font-size', '6')
|
||||
.text(relation.relationTitle1);
|
||||
@@ -139,8 +139,8 @@ export const drawEdge = function (elem, path, relation, conf, diagObj) {
|
||||
const g = elem.append('g').attr('class', 'cardinality');
|
||||
g.append('text')
|
||||
.attr('class', 'type2')
|
||||
.attr('x', p2_card_x)
|
||||
.attr('y', p2_card_y)
|
||||
.attr('x', p2CardX)
|
||||
.attr('y', p2CardY)
|
||||
.attr('fill', 'black')
|
||||
.attr('font-size', '6')
|
||||
.text(relation.relationTitle2);
|
||||
|
||||
@@ -30,18 +30,18 @@ const setupDompurifyHooksIfNotSetup = (() => {
|
||||
})();
|
||||
|
||||
function setupDompurifyHooks() {
|
||||
const TEMPORARY_ATTRIBUTE = 'data-temp-href-target';
|
||||
const temporaryAttribute = 'data-temp-href-target';
|
||||
|
||||
DOMPurify.addHook('beforeSanitizeAttributes', (node: Element) => {
|
||||
if (node.tagName === 'A' && node.hasAttribute('target')) {
|
||||
node.setAttribute(TEMPORARY_ATTRIBUTE, node.getAttribute('target') || '');
|
||||
node.setAttribute(temporaryAttribute, node.getAttribute('target') || '');
|
||||
}
|
||||
});
|
||||
|
||||
DOMPurify.addHook('afterSanitizeAttributes', (node: Element) => {
|
||||
if (node.tagName === 'A' && node.hasAttribute(TEMPORARY_ATTRIBUTE)) {
|
||||
node.setAttribute('target', node.getAttribute(TEMPORARY_ATTRIBUTE) || '');
|
||||
node.removeAttribute(TEMPORARY_ATTRIBUTE);
|
||||
if (node.tagName === 'A' && node.hasAttribute(temporaryAttribute)) {
|
||||
node.setAttribute('target', node.getAttribute(temporaryAttribute) || '');
|
||||
node.removeAttribute(temporaryAttribute);
|
||||
if (node.getAttribute('target') === '_blank') {
|
||||
node.setAttribute('rel', 'noopener');
|
||||
}
|
||||
@@ -337,18 +337,20 @@ export const renderKatex = async (text: string, config: MermaidConfig): Promise<
|
||||
return text;
|
||||
}
|
||||
|
||||
if (!isMathMLSupported() && !config.legacyMathML) {
|
||||
if (!(isMathMLSupported() || config.legacyMathML || config.forceLegacyMathML)) {
|
||||
return text.replace(katexRegex, 'MathML is unsupported in this environment.');
|
||||
}
|
||||
|
||||
const { default: katex } = await import('katex');
|
||||
const outputMode =
|
||||
config.forceLegacyMathML || (!isMathMLSupported() && config.legacyMathML)
|
||||
? 'htmlAndMathml'
|
||||
: 'mathml';
|
||||
return text
|
||||
.split(lineBreakRegex)
|
||||
.map((line) =>
|
||||
hasKatex(line)
|
||||
? `<div style="display: flex; align-items: center; justify-content: center; white-space: nowrap;">
|
||||
${line}
|
||||
</div>`
|
||||
? `<div style="display: flex; align-items: center; justify-content: center; white-space: nowrap;">${line}</div>`
|
||||
: `<div>${line}</div>`
|
||||
)
|
||||
.join('')
|
||||
@@ -357,7 +359,7 @@ export const renderKatex = async (text: string, config: MermaidConfig): Promise<
|
||||
.renderToString(c, {
|
||||
throwOnError: true,
|
||||
displayMode: true,
|
||||
output: isMathMLSupported() ? 'mathml' : 'htmlAndMathml',
|
||||
output: outputMode,
|
||||
})
|
||||
.replace(/\n/g, ' ')
|
||||
.replace(/<annotation.*<\/annotation>/g, '')
|
||||
|
||||
@@ -11,7 +11,7 @@ import {
|
||||
getDiagramTitle,
|
||||
} from '../common/commonDb.js';
|
||||
|
||||
let entities = {};
|
||||
let entities = new Map();
|
||||
let relationships = [];
|
||||
|
||||
const Cardinality = {
|
||||
@@ -28,15 +28,15 @@ const Identification = {
|
||||
};
|
||||
|
||||
const addEntity = function (name, alias = undefined) {
|
||||
if (entities[name] === undefined) {
|
||||
entities[name] = { attributes: [], alias: alias };
|
||||
if (!entities.has(name)) {
|
||||
entities.set(name, { attributes: [], alias: alias });
|
||||
log.info('Added new entity :', name);
|
||||
} else if (entities[name] && !entities[name].alias && alias) {
|
||||
entities[name].alias = alias;
|
||||
} else if (entities.has(name) && !entities.get(name).alias && alias) {
|
||||
entities.get(name).alias = alias;
|
||||
log.info(`Add alias '${alias}' to entity '${name}'`);
|
||||
}
|
||||
|
||||
return entities[name];
|
||||
return entities.get(name);
|
||||
};
|
||||
|
||||
const getEntities = () => entities;
|
||||
@@ -75,7 +75,7 @@ const addRelationship = function (entA, rolA, entB, rSpec) {
|
||||
const getRelationships = () => relationships;
|
||||
|
||||
const clear = function () {
|
||||
entities = {};
|
||||
entities = new Map();
|
||||
relationships = [];
|
||||
commonClear();
|
||||
};
|
||||
|
||||
@@ -296,12 +296,12 @@ const drawAttributes = (groupNode, entityTextNode, attributes) => {
|
||||
* Use D3 to construct the svg elements for the entities
|
||||
*
|
||||
* @param svgNode The svg node that contains the diagram
|
||||
* @param entities The entities to be drawn
|
||||
* @param {Map<string, object>} entities The entities to be drawn
|
||||
* @param graph The graph that contains the vertex and edge definitions post-layout
|
||||
* @returns {object} The first entity that was inserted
|
||||
*/
|
||||
const drawEntities = function (svgNode, entities, graph) {
|
||||
const keys = Object.keys(entities);
|
||||
const keys = [...entities.keys()];
|
||||
let firstOne;
|
||||
|
||||
keys.forEach(function (entityName) {
|
||||
@@ -326,12 +326,12 @@ const drawEntities = function (svgNode, entities, graph) {
|
||||
.style('text-anchor', 'middle')
|
||||
.style('font-family', getConfig().fontFamily)
|
||||
.style('font-size', conf.fontSize + 'px')
|
||||
.text(entities[entityName].alias ?? entityName);
|
||||
.text(entities.get(entityName).alias ?? entityName);
|
||||
|
||||
const { width: entityWidth, height: entityHeight } = drawAttributes(
|
||||
groupNode,
|
||||
textNode,
|
||||
entities[entityName].attributes
|
||||
entities.get(entityName).attributes
|
||||
);
|
||||
|
||||
// Draw the rectangle - insert it before the text so that the text is not obscured
|
||||
|
||||
@@ -17,7 +17,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
const line2 = 'MAINLAND';
|
||||
erDiagram.parser.parse(`erDiagram\n${line1}\n${line2}`);
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(erDb.getRelationships().length).toBe(0);
|
||||
});
|
||||
|
||||
@@ -27,7 +27,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
expect(() => {
|
||||
erDiagram.parser.parse(`erDiagram\n ${name}\n`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(name)).toBe(false);
|
||||
expect(entities.has(name)).toBe(false);
|
||||
}).toThrow();
|
||||
});
|
||||
describe('has non A-Za-z0-9_- chars', function () {
|
||||
@@ -47,7 +47,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
expect(() => {
|
||||
erDiagram.parser.parse(`erDiagram\n ${name}\n`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(name)).toBe(false);
|
||||
expect(entities.has(name)).toBe(false);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
@@ -55,21 +55,21 @@ describe('when parsing ER diagram it...', function () {
|
||||
const name = singleOccurrence;
|
||||
erDiagram.parser.parse(`erDiagram\n "${name}"\n`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(name)).toBe(true);
|
||||
expect(entities.has(name)).toBe(true);
|
||||
});
|
||||
|
||||
it(`"${repeatedOccurrence}" repeated occurrence`, function () {
|
||||
const name = repeatedOccurrence;
|
||||
erDiagram.parser.parse(`erDiagram\n "${name}"\n`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(name)).toBe(true);
|
||||
expect(entities.has(name)).toBe(true);
|
||||
});
|
||||
|
||||
it(`"${singleOccurrence}" ends with`, function () {
|
||||
const name = endsWith;
|
||||
erDiagram.parser.parse(`erDiagram\n "${name}"\n`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(name)).toBe(true);
|
||||
expect(entities.has(name)).toBe(true);
|
||||
});
|
||||
|
||||
it(`"${cannontStartWith}" cannot start with the character`, function () {
|
||||
@@ -77,7 +77,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
expect(() => {
|
||||
erDiagram.parser.parse(`erDiagram\n "${name}"\n`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(name)).toBe(false);
|
||||
expect(entities.has(name)).toBe(false);
|
||||
}).toThrow();
|
||||
});
|
||||
});
|
||||
@@ -88,7 +88,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
const name = 'a' + allCombined;
|
||||
erDiagram.parser.parse(`erDiagram\n "${name}"\n`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(name)).toBe(true);
|
||||
expect(entities.has(name)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -96,14 +96,14 @@ describe('when parsing ER diagram it...', function () {
|
||||
expect(() => {
|
||||
erDiagram.parser.parse(`erDiagram\n "Blo%rf"\n`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(name)).toBe(false);
|
||||
expect(entities.has(name)).toBe(false);
|
||||
}).toThrow();
|
||||
});
|
||||
it('cannot contain \\ because it could start and escape code', function () {
|
||||
expect(() => {
|
||||
erDiagram.parser.parse(`erDiagram\n "Blo\\rf"\n`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(name)).toBe(false);
|
||||
expect(entities.has(name)).toBe(false);
|
||||
}).toThrow();
|
||||
});
|
||||
|
||||
@@ -114,7 +114,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
expect(() => {
|
||||
erDiagram.parser.parse(`erDiagram\n "${badName}"\n`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(badName)).toBe(false);
|
||||
expect(entities.has(badName)).toBe(false);
|
||||
}).toThrow();
|
||||
});
|
||||
});
|
||||
@@ -124,14 +124,14 @@ describe('when parsing ER diagram it...', function () {
|
||||
const beyondEnglishName = 'DUCK-àáâäæãåā';
|
||||
erDiagram.parser.parse(`erDiagram\n${beyondEnglishName}\n`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(beyondEnglishName)).toBe(true);
|
||||
expect(entities.has(beyondEnglishName)).toBe(true);
|
||||
});
|
||||
|
||||
it('can contain - _ without needing ""', function () {
|
||||
const hyphensUnderscore = 'DUCK-BILLED_PLATYPUS';
|
||||
erDiagram.parser.parse(`erDiagram\n${hyphensUnderscore}\n`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(hyphensUnderscore)).toBe(true);
|
||||
expect(entities.has(hyphensUnderscore)).toBe(true);
|
||||
});
|
||||
|
||||
it('can have an alias', function () {
|
||||
@@ -139,8 +139,8 @@ describe('when parsing ER diagram it...', function () {
|
||||
const alias = 'bar';
|
||||
erDiagram.parser.parse(`erDiagram\n${entity}["${alias}"]\n`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(entity)).toBe(true);
|
||||
expect(entities[entity].alias).toBe(alias);
|
||||
expect(entities.has(entity)).toBe(true);
|
||||
expect(entities.get(entity).alias).toBe(alias);
|
||||
});
|
||||
|
||||
it('can have an alias even if the relationship is defined before class', function () {
|
||||
@@ -151,10 +151,10 @@ describe('when parsing ER diagram it...', function () {
|
||||
`erDiagram\n${firstEntity} ||--o| ${secondEntity} : rel\nclass ${firstEntity}["${alias}"]\n`
|
||||
);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(firstEntity)).toBe(true);
|
||||
expect(entities.hasOwnProperty(secondEntity)).toBe(true);
|
||||
expect(entities[firstEntity].alias).toBe(alias);
|
||||
expect(entities[secondEntity].alias).toBeUndefined();
|
||||
expect(entities.has(firstEntity)).toBe(true);
|
||||
expect(entities.has(secondEntity)).toBe(true);
|
||||
expect(entities.get(firstEntity).alias).toBe(alias);
|
||||
expect(entities.get(secondEntity).alias).toBeUndefined();
|
||||
});
|
||||
|
||||
it('can have an alias even if the relationship is defined after class', function () {
|
||||
@@ -165,17 +165,17 @@ describe('when parsing ER diagram it...', function () {
|
||||
`erDiagram\nclass ${firstEntity}["${alias}"]\n${firstEntity} ||--o| ${secondEntity} : rel\n`
|
||||
);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(firstEntity)).toBe(true);
|
||||
expect(entities.hasOwnProperty(secondEntity)).toBe(true);
|
||||
expect(entities[firstEntity].alias).toBe(alias);
|
||||
expect(entities[secondEntity].alias).toBeUndefined();
|
||||
expect(entities.has(firstEntity)).toBe(true);
|
||||
expect(entities.has(secondEntity)).toBe(true);
|
||||
expect(entities.get(firstEntity).alias).toBe(alias);
|
||||
expect(entities.get(secondEntity).alias).toBeUndefined();
|
||||
});
|
||||
|
||||
it('can start with an underscore', function () {
|
||||
const entity = '_foo';
|
||||
erDiagram.parser.parse(`erDiagram\n${entity}\n`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty(entity)).toBe(true);
|
||||
expect(entities.has(entity)).toBe(true);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -191,11 +191,11 @@ describe('when parsing ER diagram it...', function () {
|
||||
);
|
||||
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)');
|
||||
expect(entities.size).toBe(1);
|
||||
expect(entities.get(entity).attributes.length).toBe(3);
|
||||
expect(entities.get(entity).attributes[0].attributeName).toBe('myBookTitle');
|
||||
expect(entities.get(entity).attributes[1].attributeName).toBe('MYBOOKSUBTITLE_1');
|
||||
expect(entities.get(entity).attributes[2].attributeName).toBe('author-ref[name](1)');
|
||||
});
|
||||
|
||||
it('should allow asterisk at the start of attribute name', function () {
|
||||
@@ -204,8 +204,8 @@ describe('when parsing ER diagram it...', function () {
|
||||
|
||||
erDiagram.parser.parse(`erDiagram\n${entity}{\n${attribute}}`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(Object.keys(entities).length).toBe(1);
|
||||
expect(entities[entity].attributes.length).toBe(1);
|
||||
expect(entities.size).toBe(1);
|
||||
expect(entities.get(entity).attributes.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should allow asterisks at the start of attribute declared with type and name', () => {
|
||||
@@ -214,8 +214,8 @@ describe('when parsing ER diagram it...', function () {
|
||||
|
||||
erDiagram.parser.parse(`erDiagram\n${entity} {\n${attribute}}`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(Object.keys(entities).length).toBe(1);
|
||||
expect(entities[entity].attributes.length).toBe(1);
|
||||
expect(entities.size).toBe(1);
|
||||
expect(entities.get(entity).attributes.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should not allow leading numbers, dashes or brackets', function () {
|
||||
@@ -236,8 +236,8 @@ describe('when parsing ER diagram it...', function () {
|
||||
|
||||
erDiagram.parser.parse(`erDiagram\n${entity} {\n${attribute}\n}`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(Object.keys(entities).length).toBe(1);
|
||||
expect(entities[entity].attributes.length).toBe(1);
|
||||
expect(entities.size).toBe(1);
|
||||
expect(entities.get(entity).attributes.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should allow an entity with a single attribute to be defined with a key', function () {
|
||||
@@ -246,8 +246,8 @@ describe('when parsing ER diagram it...', function () {
|
||||
|
||||
erDiagram.parser.parse(`erDiagram\n${entity} {\n${attribute}\n}`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(Object.keys(entities).length).toBe(1);
|
||||
expect(entities[entity].attributes.length).toBe(1);
|
||||
expect(entities.size).toBe(1);
|
||||
expect(entities.get(entity).attributes.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should allow an entity with a single attribute to be defined with a comment', function () {
|
||||
@@ -256,9 +256,9 @@ describe('when parsing ER diagram it...', function () {
|
||||
|
||||
erDiagram.parser.parse(`erDiagram\n${entity} {\n${attribute}\n}`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(Object.keys(entities).length).toBe(1);
|
||||
expect(entities[entity].attributes.length).toBe(1);
|
||||
expect(entities[entity].attributes[0].attributeComment).toBe('comment');
|
||||
expect(entities.size).toBe(1);
|
||||
expect(entities.get(entity).attributes.length).toBe(1);
|
||||
expect(entities.get(entity).attributes[0].attributeComment).toBe('comment');
|
||||
});
|
||||
|
||||
it('should allow an entity with a single attribute to be defined with a key and a comment', function () {
|
||||
@@ -267,8 +267,8 @@ describe('when parsing ER diagram it...', function () {
|
||||
|
||||
erDiagram.parser.parse(`erDiagram\n${entity} {\n${attribute}\n}`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(Object.keys(entities).length).toBe(1);
|
||||
expect(entities[entity].attributes.length).toBe(1);
|
||||
expect(entities.size).toBe(1);
|
||||
expect(entities.get(entity).attributes.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should allow an entity with attribute starting with fk, pk or uk and a comment', function () {
|
||||
@@ -282,7 +282,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
`erDiagram\n${entity} {\n${attribute1} \n\n${attribute2}\n${attribute3}\n${attribute4}\n}`
|
||||
);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities[entity].attributes.length).toBe(4);
|
||||
expect(entities.get(entity).attributes.length).toBe(4);
|
||||
});
|
||||
|
||||
it('should allow an entity with attributes that have many constraints and comments', function () {
|
||||
@@ -297,14 +297,14 @@ describe('when parsing ER diagram it...', function () {
|
||||
`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');
|
||||
expect(entities.get(entity).attributes[0].attributeKeyTypeList).toEqual(['PK', 'FK']);
|
||||
expect(entities.get(entity).attributes[0].attributeComment).toBe('comment1');
|
||||
expect(entities.get(entity).attributes[1].attributeKeyTypeList).toEqual(['PK', 'UK', 'FK']);
|
||||
expect(entities.get(entity).attributes[2].attributeKeyTypeList).toEqual(['PK', 'UK']);
|
||||
expect(entities.get(entity).attributes[2].attributeComment).toBe('comment3');
|
||||
expect(entities.get(entity).attributes[3].attributeKeyTypeList).toBeUndefined();
|
||||
expect(entities.get(entity).attributes[4].attributeKeyTypeList).toBeUndefined();
|
||||
expect(entities.get(entity).attributes[4].attributeComment).toBe('comment5');
|
||||
});
|
||||
|
||||
it('should allow an entity with attribute that has a generic type', function () {
|
||||
@@ -317,8 +317,8 @@ describe('when parsing ER diagram it...', function () {
|
||||
`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.size).toBe(1);
|
||||
expect(entities.get(entity).attributes.length).toBe(3);
|
||||
});
|
||||
|
||||
it('should allow an entity with attribute that is an array', function () {
|
||||
@@ -328,8 +328,8 @@ describe('when parsing ER diagram it...', function () {
|
||||
|
||||
erDiagram.parser.parse(`erDiagram\n${entity} {\n${attribute1}\n${attribute2}\n}`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(Object.keys(entities).length).toBe(1);
|
||||
expect(entities[entity].attributes.length).toBe(2);
|
||||
expect(entities.size).toBe(1);
|
||||
expect(entities.get(entity).attributes.length).toBe(2);
|
||||
});
|
||||
|
||||
it('should allow an entity with attribute that is a limited length string', function () {
|
||||
@@ -339,10 +339,10 @@ describe('when parsing ER diagram it...', function () {
|
||||
|
||||
erDiagram.parser.parse(`erDiagram\n${entity} {\n${attribute1}\n${attribute2}\n}`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(Object.keys(entities).length).toBe(1);
|
||||
expect(entities[entity].attributes.length).toBe(2);
|
||||
expect(entities[entity].attributes[0].attributeType).toBe('character(10)');
|
||||
expect(entities[entity].attributes[1].attributeType).toBe('varchar(5)');
|
||||
expect(entities.size).toBe(1);
|
||||
expect(entities.get(entity).attributes.length).toBe(2);
|
||||
expect(entities.get(entity).attributes[0].attributeType).toBe('character(10)');
|
||||
expect(entities.get(entity).attributes[1].attributeType).toBe('varchar(5)');
|
||||
});
|
||||
|
||||
it('should allow an entity with multiple attributes to be defined', function () {
|
||||
@@ -355,7 +355,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
`erDiagram\n${entity} {\n${attribute1}\n${attribute2}\n${attribute3}\n}`
|
||||
);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities[entity].attributes.length).toBe(3);
|
||||
expect(entities.get(entity).attributes.length).toBe(3);
|
||||
});
|
||||
|
||||
it('should allow attribute definitions to be split into multiple blocks', function () {
|
||||
@@ -368,7 +368,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
`erDiagram\n${entity} {\n${attribute1}\n}\n${entity} {\n${attribute2}\n${attribute3}\n}`
|
||||
);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities[entity].attributes.length).toBe(3);
|
||||
expect(entities.get(entity).attributes.length).toBe(3);
|
||||
});
|
||||
|
||||
it('should allow an empty attribute block', function () {
|
||||
@@ -376,8 +376,8 @@ describe('when parsing ER diagram it...', function () {
|
||||
|
||||
erDiagram.parser.parse(`erDiagram\n${entity} {}`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty('BOOK')).toBe(true);
|
||||
expect(entities[entity].attributes.length).toBe(0);
|
||||
expect(entities.has('BOOK')).toBe(true);
|
||||
expect(entities.get(entity).attributes.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should allow an attribute block to start immediately after the entity name', function () {
|
||||
@@ -385,8 +385,8 @@ describe('when parsing ER diagram it...', function () {
|
||||
|
||||
erDiagram.parser.parse(`erDiagram\n${entity}{}`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty('BOOK')).toBe(true);
|
||||
expect(entities[entity].attributes.length).toBe(0);
|
||||
expect(entities.has('BOOK')).toBe(true);
|
||||
expect(entities.get(entity).attributes.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should allow an attribute block to be separated from the entity name by spaces', function () {
|
||||
@@ -394,8 +394,8 @@ describe('when parsing ER diagram it...', function () {
|
||||
|
||||
erDiagram.parser.parse(`erDiagram\n${entity} {}`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(entities.hasOwnProperty('BOOK')).toBe(true);
|
||||
expect(entities[entity].attributes.length).toBe(0);
|
||||
expect(entities.has('BOOK')).toBe(true);
|
||||
expect(entities.get(entity).attributes.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should allow whitespace before and after attribute definitions', function () {
|
||||
@@ -404,8 +404,8 @@ describe('when parsing ER diagram it...', function () {
|
||||
|
||||
erDiagram.parser.parse(`erDiagram\n${entity} {\n \n\n ${attribute}\n\n \n}`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(Object.keys(entities).length).toBe(1);
|
||||
expect(entities[entity].attributes.length).toBe(1);
|
||||
expect(entities.size).toBe(1);
|
||||
expect(entities.get(entity).attributes.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should allow no whitespace before and after attribute definitions', function () {
|
||||
@@ -414,8 +414,8 @@ describe('when parsing ER diagram it...', function () {
|
||||
|
||||
erDiagram.parser.parse(`erDiagram\n${entity}{${attribute}}`);
|
||||
const entities = erDb.getEntities();
|
||||
expect(Object.keys(entities).length).toBe(1);
|
||||
expect(entities[entity].attributes.length).toBe(1);
|
||||
expect(entities.size).toBe(1);
|
||||
expect(entities.get(entity).attributes.length).toBe(1);
|
||||
});
|
||||
|
||||
it('should associate two entities correctly', function () {
|
||||
@@ -423,8 +423,8 @@ describe('when parsing ER diagram it...', function () {
|
||||
const entities = erDb.getEntities();
|
||||
const relationships = erDb.getRelationships();
|
||||
|
||||
expect(entities.hasOwnProperty('CAR')).toBe(true);
|
||||
expect(entities.hasOwnProperty('DRIVER')).toBe(true);
|
||||
expect(entities.has('CAR')).toBe(true);
|
||||
expect(entities.has('DRIVER')).toBe(true);
|
||||
expect(relationships.length).toBe(1);
|
||||
expect(relationships[0].relSpec.cardA).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
expect(relationships[0].relSpec.cardB).toBe(erDb.Cardinality.ONLY_ONE);
|
||||
@@ -437,7 +437,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse(`erDiagram\n${line1}\n${line2}`);
|
||||
const entities = erDb.getEntities();
|
||||
|
||||
expect(Object.keys(entities).length).toBe(3);
|
||||
expect(entities.size).toBe(3);
|
||||
});
|
||||
|
||||
it('should create the role specified', function () {
|
||||
@@ -451,7 +451,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
|
||||
it('should allow recursive relationships', function () {
|
||||
erDiagram.parser.parse('erDiagram\nNODE ||--o{ NODE : "leads to"');
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(1);
|
||||
expect(erDb.getEntities().size).toBe(1);
|
||||
});
|
||||
|
||||
describe('accessible title and description', () => {
|
||||
@@ -491,7 +491,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
const entities = erDb.getEntities();
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(entities).length).toBe(2);
|
||||
expect(entities.size).toBe(2);
|
||||
expect(rels.length).toBe(2);
|
||||
});
|
||||
|
||||
@@ -507,7 +507,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA ||--|{ B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ONE_OR_MORE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ONLY_ONE);
|
||||
@@ -517,7 +517,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA ||..o{ B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ONLY_ONE);
|
||||
@@ -527,7 +527,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA |o..o{ B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ZERO_OR_ONE);
|
||||
@@ -537,7 +537,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA |o--|{ B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ONE_OR_MORE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ZERO_OR_ONE);
|
||||
@@ -547,7 +547,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA }|--|| B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ONLY_ONE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ONE_OR_MORE);
|
||||
@@ -557,7 +557,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA }o--|| B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ONLY_ONE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
@@ -567,7 +567,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA }o..o| B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ZERO_OR_ONE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
@@ -577,7 +577,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA }|..o| B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ZERO_OR_ONE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ONE_OR_MORE);
|
||||
@@ -587,7 +587,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA |o..|| B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ONLY_ONE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ZERO_OR_ONE);
|
||||
@@ -597,7 +597,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA ||..|| B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ONLY_ONE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ONLY_ONE);
|
||||
@@ -607,7 +607,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA ||--o| B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ZERO_OR_ONE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ONLY_ONE);
|
||||
@@ -617,7 +617,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA |o..o| B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ZERO_OR_ONE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ZERO_OR_ONE);
|
||||
@@ -627,7 +627,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA }o--o{ B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
@@ -637,7 +637,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA }|..|{ B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ONE_OR_MORE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ONE_OR_MORE);
|
||||
@@ -647,7 +647,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA }o--|{ B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ONE_OR_MORE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
@@ -657,7 +657,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA }|..o{ B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ONE_OR_MORE);
|
||||
@@ -667,7 +667,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA one or zero to many B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ZERO_OR_ONE);
|
||||
@@ -677,7 +677,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA one or many optionally to zero or one B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ZERO_OR_ONE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ONE_OR_MORE);
|
||||
@@ -687,7 +687,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA zero or more to zero or many B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
@@ -697,7 +697,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA many(0) to many(1) B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ONE_OR_MORE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
@@ -707,7 +707,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA many optionally to one B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ONLY_ONE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
@@ -717,7 +717,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA only one optionally to 1+ B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ONE_OR_MORE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ONLY_ONE);
|
||||
@@ -727,7 +727,7 @@ describe('when parsing ER diagram it...', function () {
|
||||
erDiagram.parser.parse('erDiagram\nA 0+ optionally to 1 B : has');
|
||||
const rels = erDb.getRelationships();
|
||||
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ONLY_ONE);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
@@ -786,10 +786,21 @@ describe('when parsing ER diagram it...', function () {
|
||||
it('should represent parent-child relationship correctly', function () {
|
||||
erDiagram.parser.parse('erDiagram\nPROJECT u--o{ TEAM_MEMBER : "parent"');
|
||||
const rels = erDb.getRelationships();
|
||||
expect(Object.keys(erDb.getEntities()).length).toBe(2);
|
||||
expect(erDb.getEntities().size).toBe(2);
|
||||
expect(rels.length).toBe(1);
|
||||
expect(rels[0].relSpec.cardB).toBe(erDb.Cardinality.MD_PARENT);
|
||||
expect(rels[0].relSpec.cardA).toBe(erDb.Cardinality.ZERO_OR_MORE);
|
||||
});
|
||||
});
|
||||
|
||||
describe('prototype properties', function () {
|
||||
it.each(['__proto__', 'constructor', 'prototype'])(
|
||||
'should work with a %s property',
|
||||
function (prop) {
|
||||
expect(() =>
|
||||
erDiagram.parser.parse(`erDiagram\n${prop} ||--|{ ORDER : place`)
|
||||
).not.toThrow();
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -53,7 +53,7 @@ function hexagon(parent, bbox, node) {
|
||||
* @param bbox
|
||||
* @param node
|
||||
*/
|
||||
function rect_left_inv_arrow(parent, bbox, node) {
|
||||
function rectLeftInvArrow(parent, bbox, node) {
|
||||
const w = bbox.width;
|
||||
const h = bbox.height;
|
||||
const points = [
|
||||
@@ -75,7 +75,7 @@ function rect_left_inv_arrow(parent, bbox, node) {
|
||||
* @param bbox
|
||||
* @param node
|
||||
*/
|
||||
function lean_right(parent, bbox, node) {
|
||||
function leanRight(parent, bbox, node) {
|
||||
const w = bbox.width;
|
||||
const h = bbox.height;
|
||||
const points = [
|
||||
@@ -96,7 +96,7 @@ function lean_right(parent, bbox, node) {
|
||||
* @param bbox
|
||||
* @param node
|
||||
*/
|
||||
function lean_left(parent, bbox, node) {
|
||||
function leanLeft(parent, bbox, node) {
|
||||
const w = bbox.width;
|
||||
const h = bbox.height;
|
||||
const points = [
|
||||
@@ -138,7 +138,7 @@ function trapezoid(parent, bbox, node) {
|
||||
* @param bbox
|
||||
* @param node
|
||||
*/
|
||||
function inv_trapezoid(parent, bbox, node) {
|
||||
function invTrapezoid(parent, bbox, node) {
|
||||
const w = bbox.width;
|
||||
const h = bbox.height;
|
||||
const points = [
|
||||
@@ -159,7 +159,7 @@ function inv_trapezoid(parent, bbox, node) {
|
||||
* @param bbox
|
||||
* @param node
|
||||
*/
|
||||
function rect_right_inv_arrow(parent, bbox, node) {
|
||||
function rectRightInvArrow(parent, bbox, node) {
|
||||
const w = bbox.width;
|
||||
const h = bbox.height;
|
||||
const points = [
|
||||
@@ -308,22 +308,22 @@ export function addToRender(render) {
|
||||
render.shapes().cylinder = cylinder;
|
||||
|
||||
// Add custom shape for box with inverted arrow on left side
|
||||
render.shapes().rect_left_inv_arrow = rect_left_inv_arrow;
|
||||
render.shapes().rect_left_inv_arrow = rectLeftInvArrow;
|
||||
|
||||
// Add custom shape for box with inverted arrow on left side
|
||||
render.shapes().lean_right = lean_right;
|
||||
render.shapes().lean_right = leanRight;
|
||||
|
||||
// Add custom shape for box with inverted arrow on left side
|
||||
render.shapes().lean_left = lean_left;
|
||||
render.shapes().lean_left = leanLeft;
|
||||
|
||||
// Add custom shape for box with inverted arrow on left side
|
||||
render.shapes().trapezoid = trapezoid;
|
||||
|
||||
// Add custom shape for box with inverted arrow on left side
|
||||
render.shapes().inv_trapezoid = inv_trapezoid;
|
||||
render.shapes().inv_trapezoid = invTrapezoid;
|
||||
|
||||
// Add custom shape for box with inverted arrow on right side
|
||||
render.shapes().rect_right_inv_arrow = rect_right_inv_arrow;
|
||||
render.shapes().rect_right_inv_arrow = rectRightInvArrow;
|
||||
}
|
||||
|
||||
/** @param addShape */
|
||||
@@ -335,22 +335,22 @@ export function addToRenderV2(addShape) {
|
||||
addShape({ cylinder });
|
||||
|
||||
// Add custom shape for box with inverted arrow on left side
|
||||
addShape({ rect_left_inv_arrow });
|
||||
addShape({ rect_left_inv_arrow: rectLeftInvArrow });
|
||||
|
||||
// Add custom shape for box with inverted arrow on left side
|
||||
addShape({ lean_right });
|
||||
addShape({ lean_right: leanRight });
|
||||
|
||||
// Add custom shape for box with inverted arrow on left side
|
||||
addShape({ lean_left });
|
||||
addShape({ lean_left: leanLeft });
|
||||
|
||||
// Add custom shape for box with inverted arrow on left side
|
||||
addShape({ trapezoid });
|
||||
|
||||
// Add custom shape for box with inverted arrow on left side
|
||||
addShape({ inv_trapezoid });
|
||||
addShape({ inv_trapezoid: invTrapezoid });
|
||||
|
||||
// Add custom shape for box with inverted arrow on right side
|
||||
addShape({ rect_right_inv_arrow });
|
||||
addShape({ rect_right_inv_arrow: rectRightInvArrow });
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -51,17 +51,17 @@ describe('flow db addClass', () => {
|
||||
flowDb.addClass('a,b', ['stroke-width: 8px']);
|
||||
const classes = flowDb.getClasses();
|
||||
|
||||
expect(classes.hasOwnProperty('a')).toBe(true);
|
||||
expect(classes.hasOwnProperty('b')).toBe(true);
|
||||
expect(classes['a']['styles']).toEqual(['stroke-width: 8px']);
|
||||
expect(classes['b']['styles']).toEqual(['stroke-width: 8px']);
|
||||
expect(classes.has('a')).toBe(true);
|
||||
expect(classes.has('b')).toBe(true);
|
||||
expect(classes.get('a')?.styles).toEqual(['stroke-width: 8px']);
|
||||
expect(classes.get('b')?.styles).toEqual(['stroke-width: 8px']);
|
||||
});
|
||||
|
||||
it('should detect single class', () => {
|
||||
flowDb.addClass('a', ['stroke-width: 8px']);
|
||||
const classes = flowDb.getClasses();
|
||||
|
||||
expect(classes.hasOwnProperty('a')).toBe(true);
|
||||
expect(classes['a']['styles']).toEqual(['stroke-width: 8px']);
|
||||
expect(classes.has('a')).toBe(true);
|
||||
expect(classes.get('a')?.styles).toEqual(['stroke-width: 8px']);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -17,12 +17,12 @@ import type { FlowVertex, FlowClass, FlowSubGraph, FlowText, FlowEdge, FlowLink
|
||||
const MERMAID_DOM_ID_PREFIX = 'flowchart-';
|
||||
let vertexCounter = 0;
|
||||
let config = getConfig();
|
||||
let vertices: Record<string, FlowVertex> = {};
|
||||
let vertices: Map<string, FlowVertex> = new Map();
|
||||
let edges: FlowEdge[] & { defaultInterpolate?: string; defaultStyle?: string[] } = [];
|
||||
let classes: Record<string, FlowClass> = {};
|
||||
let classes: Map<string, FlowClass> = new Map();
|
||||
let subGraphs: FlowSubGraph[] = [];
|
||||
let subGraphLookup: Record<string, FlowSubGraph> = {};
|
||||
let tooltips: Record<string, string> = {};
|
||||
let subGraphLookup: Map<string, FlowSubGraph> = new Map();
|
||||
let tooltips: Map<string, string> = new Map();
|
||||
let subCount = 0;
|
||||
let firstGraphFlag = true;
|
||||
let direction: string;
|
||||
@@ -40,10 +40,9 @@ const sanitizeText = (txt: string) => common.sanitizeText(txt, config);
|
||||
* @param id - id of the node
|
||||
*/
|
||||
export const lookUpDomId = function (id: string) {
|
||||
const vertexKeys = Object.keys(vertices);
|
||||
for (const vertexKey of vertexKeys) {
|
||||
if (vertices[vertexKey].id === id) {
|
||||
return vertices[vertexKey].domId;
|
||||
for (const vertex of vertices.values()) {
|
||||
if (vertex.id === id) {
|
||||
return vertex.domId;
|
||||
}
|
||||
}
|
||||
return id;
|
||||
@@ -67,50 +66,53 @@ export const addVertex = function (
|
||||
}
|
||||
let txt;
|
||||
|
||||
if (vertices[id] === undefined) {
|
||||
vertices[id] = {
|
||||
let vertex = vertices.get(id);
|
||||
if (vertex === undefined) {
|
||||
vertex = {
|
||||
id,
|
||||
labelType: 'text',
|
||||
domId: MERMAID_DOM_ID_PREFIX + id + '-' + vertexCounter,
|
||||
styles: [],
|
||||
classes: [],
|
||||
};
|
||||
vertices.set(id, vertex);
|
||||
}
|
||||
vertexCounter++;
|
||||
|
||||
if (textObj !== undefined) {
|
||||
config = getConfig();
|
||||
txt = sanitizeText(textObj.text.trim());
|
||||
vertices[id].labelType = textObj.type;
|
||||
vertex.labelType = textObj.type;
|
||||
// strip quotes if string starts and ends with a quote
|
||||
if (txt[0] === '"' && txt[txt.length - 1] === '"') {
|
||||
txt = txt.substring(1, txt.length - 1);
|
||||
}
|
||||
vertices[id].text = txt;
|
||||
vertex.text = txt;
|
||||
} else {
|
||||
if (vertices[id].text === undefined) {
|
||||
vertices[id].text = id;
|
||||
if (vertex.text === undefined) {
|
||||
vertex.text = id;
|
||||
}
|
||||
}
|
||||
if (type !== undefined) {
|
||||
vertices[id].type = type;
|
||||
vertex.type = type;
|
||||
}
|
||||
if (style !== undefined && style !== null) {
|
||||
style.forEach(function (s) {
|
||||
vertices[id].styles.push(s);
|
||||
vertex.styles.push(s);
|
||||
});
|
||||
}
|
||||
if (classes !== undefined && classes !== null) {
|
||||
classes.forEach(function (s) {
|
||||
vertices[id].classes.push(s);
|
||||
vertex.classes.push(s);
|
||||
});
|
||||
}
|
||||
if (dir !== undefined) {
|
||||
vertices[id].dir = dir;
|
||||
vertex.dir = dir;
|
||||
}
|
||||
if (vertices[id].props === undefined) {
|
||||
vertices[id].props = props;
|
||||
if (vertex.props === undefined) {
|
||||
vertex.props = props;
|
||||
} else if (props !== undefined) {
|
||||
Object.assign(vertices[id].props, props);
|
||||
Object.assign(vertex.props, props);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -208,17 +210,19 @@ export const updateLink = function (positions: ('default' | number)[], style: st
|
||||
|
||||
export const addClass = function (ids: string, style: string[]) {
|
||||
ids.split(',').forEach(function (id) {
|
||||
if (classes[id] === undefined) {
|
||||
classes[id] = { id, styles: [], textStyles: [] };
|
||||
let classNode = classes.get(id);
|
||||
if (classNode === undefined) {
|
||||
classNode = { id, styles: [], textStyles: [] };
|
||||
classes.set(id, classNode);
|
||||
}
|
||||
|
||||
if (style !== undefined && style !== null) {
|
||||
style.forEach(function (s) {
|
||||
if (s.match('color')) {
|
||||
const newStyle = s.replace('fill', 'bgFill').replace('color', 'fill');
|
||||
classes[id].textStyles.push(newStyle);
|
||||
classNode.textStyles.push(newStyle);
|
||||
}
|
||||
classes[id].styles.push(s);
|
||||
classNode.styles.push(s);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -255,11 +259,13 @@ export const setDirection = function (dir: string) {
|
||||
*/
|
||||
export const setClass = function (ids: string, className: string) {
|
||||
for (const id of ids.split(',')) {
|
||||
if (vertices[id]) {
|
||||
vertices[id].classes.push(className);
|
||||
const vertex = vertices.get(id);
|
||||
if (vertex) {
|
||||
vertex.classes.push(className);
|
||||
}
|
||||
if (subGraphLookup[id]) {
|
||||
subGraphLookup[id].classes.push(className);
|
||||
const subGraph = subGraphLookup.get(id);
|
||||
if (subGraph) {
|
||||
subGraph.classes.push(className);
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -270,7 +276,7 @@ const setTooltip = function (ids: string, tooltip: string) {
|
||||
}
|
||||
tooltip = sanitizeText(tooltip);
|
||||
for (const id of ids.split(',')) {
|
||||
tooltips[version === 'gen-1' ? lookUpDomId(id) : id] = tooltip;
|
||||
tooltips.set(version === 'gen-1' ? lookUpDomId(id) : id, tooltip);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -303,8 +309,9 @@ const setClickFun = function (id: string, functionName: string, functionArgs: st
|
||||
argList.push(id);
|
||||
}
|
||||
|
||||
if (vertices[id] !== undefined) {
|
||||
vertices[id].haveCallback = true;
|
||||
const vertex = vertices.get(id);
|
||||
if (vertex) {
|
||||
vertex.haveCallback = true;
|
||||
funs.push(function () {
|
||||
const elem = document.querySelector(`[id="${domId}"]`);
|
||||
if (elem !== null) {
|
||||
@@ -329,19 +336,17 @@ const setClickFun = function (id: string, functionName: string, functionArgs: st
|
||||
*/
|
||||
export const setLink = function (ids: string, linkStr: string, target: string) {
|
||||
ids.split(',').forEach(function (id) {
|
||||
if (vertices[id] !== undefined) {
|
||||
vertices[id].link = utils.formatUrl(linkStr, config);
|
||||
vertices[id].linkTarget = target;
|
||||
const vertex = vertices.get(id);
|
||||
if (vertex !== undefined) {
|
||||
vertex.link = utils.formatUrl(linkStr, config);
|
||||
vertex.linkTarget = target;
|
||||
}
|
||||
});
|
||||
setClass(ids, 'clickable');
|
||||
};
|
||||
|
||||
export const getTooltip = function (id: string) {
|
||||
if (tooltips.hasOwnProperty(id)) {
|
||||
return tooltips[id];
|
||||
}
|
||||
return undefined;
|
||||
return tooltips.get(id);
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -435,14 +440,14 @@ funs.push(setupToolTips);
|
||||
*
|
||||
*/
|
||||
export const clear = function (ver = 'gen-1') {
|
||||
vertices = {};
|
||||
classes = {};
|
||||
vertices = new Map();
|
||||
classes = new Map();
|
||||
edges = [];
|
||||
funs = [setupToolTips];
|
||||
subGraphs = [];
|
||||
subGraphLookup = {};
|
||||
subGraphLookup = new Map();
|
||||
subCount = 0;
|
||||
tooltips = {};
|
||||
tooltips = new Map();
|
||||
firstGraphFlag = true;
|
||||
version = ver;
|
||||
config = getConfig();
|
||||
@@ -516,7 +521,7 @@ export const addSubGraph = function (
|
||||
// Remove the members in the new subgraph if they already belong to another subgraph
|
||||
subGraph.nodes = makeUniq(subGraph, subGraphs).nodes;
|
||||
subGraphs.push(subGraph);
|
||||
subGraphLookup[id] = subGraph;
|
||||
subGraphLookup.set(id, subGraph);
|
||||
return id;
|
||||
};
|
||||
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
|
||||
import { select, curveLinear, selectAll } from 'd3';
|
||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||
import utils from '../../utils.js';
|
||||
import utils, { getEdgeId } from '../../utils.js';
|
||||
import { render } from '../../dagre-wrapper/index.js';
|
||||
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';
|
||||
import { log } from '../../logger.js';
|
||||
@@ -29,11 +29,11 @@ export const setConf = function (cnf) {
|
||||
*/
|
||||
export const addVertices = async function (vert, g, svgId, root, doc, diagObj) {
|
||||
const svg = root.select(`[id="${svgId}"]`);
|
||||
const keys = Object.keys(vert);
|
||||
const keys = vert.keys();
|
||||
|
||||
// Iterate through each item in the vertex object (containing all the vertices found) in the graph definition
|
||||
for (const id of keys) {
|
||||
const vertex = vert[id];
|
||||
const vertex = vert.get(id);
|
||||
|
||||
/**
|
||||
* Variable for storing the classes for the vertex
|
||||
@@ -210,7 +210,11 @@ export const addEdges = async function (edges, g, diagObj) {
|
||||
cnt++;
|
||||
|
||||
// Identify Link
|
||||
const linkIdBase = 'L-' + edge.start + '-' + edge.end;
|
||||
const linkIdBase = getEdgeId(edge.start, edge.end, {
|
||||
counter: cnt,
|
||||
prefix: 'L',
|
||||
});
|
||||
|
||||
// count the links from+to the same node to give unique id
|
||||
if (linkIdCnt[linkIdBase] === undefined) {
|
||||
linkIdCnt[linkIdBase] = 0;
|
||||
@@ -219,7 +223,8 @@ export const addEdges = async function (edges, g, diagObj) {
|
||||
linkIdCnt[linkIdBase]++;
|
||||
log.info('abc78 new entry', linkIdBase, linkIdCnt[linkIdBase]);
|
||||
}
|
||||
let linkId = linkIdBase + '-' + linkIdCnt[linkIdBase];
|
||||
let linkId = `${linkIdBase}_${linkIdCnt[linkIdBase]}`;
|
||||
|
||||
log.info('abc78 new link id to be used is', linkIdBase, linkId, linkIdCnt[linkIdBase]);
|
||||
const linkNameStart = 'LS-' + edge.start;
|
||||
const linkNameEnd = 'LE-' + edge.end;
|
||||
@@ -239,18 +244,20 @@ export const addEdges = async function (edges, g, diagObj) {
|
||||
edgeData.arrowTypeStart = 'arrow_open';
|
||||
edgeData.arrowTypeEnd = 'arrow_open';
|
||||
|
||||
/* eslint-disable no-fallthrough */
|
||||
switch (edge.type) {
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: Expected fallthrough
|
||||
case 'double_arrow_cross':
|
||||
edgeData.arrowTypeStart = 'arrow_cross';
|
||||
case 'arrow_cross':
|
||||
edgeData.arrowTypeEnd = 'arrow_cross';
|
||||
break;
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: Expected fallthrough
|
||||
case 'double_arrow_point':
|
||||
edgeData.arrowTypeStart = 'arrow_point';
|
||||
case 'arrow_point':
|
||||
edgeData.arrowTypeEnd = 'arrow_point';
|
||||
break;
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: Expected fallthrough
|
||||
case 'double_arrow_circle':
|
||||
edgeData.arrowTypeStart = 'arrow_circle';
|
||||
case 'arrow_circle':
|
||||
@@ -336,7 +343,7 @@ export const addEdges = async function (edges, g, diagObj) {
|
||||
*
|
||||
* @param text
|
||||
* @param diagObj
|
||||
* @returns {Record<string, import('../../diagram-api/types.js').DiagramStyleClassDef>} ClassDef styles
|
||||
* @returns {Map<string, import('../../diagram-api/types.js').DiagramStyleClassDef>} ClassDef styles
|
||||
*/
|
||||
export const getClasses = function (text, diagObj) {
|
||||
return diagObj.db.getClasses();
|
||||
@@ -420,9 +427,9 @@ export const draw = async function (text, id, _version, diagObj) {
|
||||
|
||||
selectAll('cluster').append('text');
|
||||
|
||||
for (let j = 0; j < subG.nodes.length; j++) {
|
||||
log.info('Setting up subgraphs', subG.nodes[j], subG.id);
|
||||
g.setParent(subG.nodes[j], subG.id);
|
||||
for (const node of subG.nodes) {
|
||||
log.info('Setting up subgraphs', node, subG.id);
|
||||
g.setParent(node, subG.id);
|
||||
}
|
||||
}
|
||||
await addVertices(vert, g, id, root, doc, diagObj);
|
||||
@@ -463,9 +470,9 @@ export const draw = async function (text, id, _version, diagObj) {
|
||||
}
|
||||
|
||||
// If node has a link, wrap it in an anchor SVG object.
|
||||
const keys = Object.keys(vert);
|
||||
keys.forEach(function (key) {
|
||||
const vertex = vert[key];
|
||||
const keys = [...vert.keys()];
|
||||
keys.forEach((key) => {
|
||||
const vertex = vert.get(key);
|
||||
|
||||
if (vertex.link) {
|
||||
const node = select('#' + id + ' [id="' + key + '"]');
|
||||
|
||||
@@ -6,7 +6,7 @@ import { applyStyle } from 'dagre-d3-es/src/dagre-js/util.js';
|
||||
import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';
|
||||
import { log } from '../../logger.js';
|
||||
import common, { evaluate, renderKatex } from '../common/common.js';
|
||||
import { interpolateToCurve, getStylesFromArray } from '../../utils.js';
|
||||
import { interpolateToCurve, getStylesFromArray, getEdgeId } from '../../utils.js';
|
||||
import { setupGraphViewbox } from '../../setupGraphViewbox.js';
|
||||
import flowChartShapes from './flowChartShapes.js';
|
||||
import { replaceIconSubstring } from '../../rendering-util/createText.js';
|
||||
@@ -175,7 +175,10 @@ export const addEdges = async function (edges, g, diagObj) {
|
||||
cnt++;
|
||||
|
||||
// Identify Link
|
||||
const linkId = 'L-' + edge.start + '-' + edge.end;
|
||||
const linkId = getEdgeId(edge.start, edge.end, {
|
||||
counter: cnt,
|
||||
prefix: 'L',
|
||||
});
|
||||
const linkNameStart = 'LS-' + edge.start;
|
||||
const linkNameEnd = 'LE-' + edge.end;
|
||||
|
||||
@@ -265,7 +268,7 @@ export const addEdges = async function (edges, g, diagObj) {
|
||||
*
|
||||
* @param text
|
||||
* @param diagObj
|
||||
* @returns {Record<string, import('../../diagram-api/types.js').DiagramStyleClassDef>} ClassDef styles
|
||||
* @returns {Map<string, import('../../diagram-api/types.js').DiagramStyleClassDef>} ClassDef styles
|
||||
*/
|
||||
export const getClasses = function (text, diagObj) {
|
||||
log.info('Extracting classes');
|
||||
@@ -336,14 +339,14 @@ export const draw = async function (text, id, _version, diagObj) {
|
||||
|
||||
selectAll('cluster').append('text');
|
||||
|
||||
for (let j = 0; j < subG.nodes.length; j++) {
|
||||
for (const subGNode of subG.nodes) {
|
||||
log.warn(
|
||||
'Setting subgraph',
|
||||
subG.nodes[j],
|
||||
diagObj.db.lookUpDomId(subG.nodes[j]),
|
||||
subGNode,
|
||||
diagObj.db.lookUpDomId(subGNode),
|
||||
diagObj.db.lookUpDomId(subG.id)
|
||||
);
|
||||
g.setParent(diagObj.db.lookUpDomId(subG.nodes[j]), diagObj.db.lookUpDomId(subG.id));
|
||||
g.setParent(diagObj.db.lookUpDomId(subGNode), diagObj.db.lookUpDomId(subG.id));
|
||||
}
|
||||
}
|
||||
await addVertices(vert, g, id, root, doc, diagObj);
|
||||
@@ -426,8 +429,8 @@ export const draw = async function (text, id, _version, diagObj) {
|
||||
te.attr('transform', `translate(${xPos + _width / 2}, ${yPos + 14})`);
|
||||
te.attr('id', id + 'Text');
|
||||
|
||||
for (let j = 0; j < subG.classes.length; j++) {
|
||||
clusterEl[0].classList.add(subG.classes[j]);
|
||||
for (const subGClass of subG.classes) {
|
||||
clusterEl[0].classList.add(subGClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -452,9 +455,9 @@ export const draw = async function (text, id, _version, diagObj) {
|
||||
setupGraphViewbox(g, svg, conf.diagramPadding, conf.useMaxWidth);
|
||||
|
||||
// If node has a link, wrap it in an anchor SVG object.
|
||||
const keys = Object.keys(vert);
|
||||
const keys = [...vert.keys()];
|
||||
keys.forEach(function (key) {
|
||||
const vertex = vert[key];
|
||||
const vertex = vert.get(key);
|
||||
|
||||
if (vertex.link) {
|
||||
const node = root.select('#' + id + ' [id="' + diagObj.db.lookUpDomId(key) + '"]');
|
||||
|
||||
@@ -18,8 +18,8 @@ describe('[Arrows] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -38,8 +38,8 @@ describe('[Arrows] when parsing', () => {
|
||||
|
||||
expect(direction).toBe('LR');
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -58,8 +58,8 @@ describe('[Arrows] when parsing', () => {
|
||||
|
||||
expect(direction).toBe('RL');
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -78,8 +78,8 @@ describe('[Arrows] when parsing', () => {
|
||||
|
||||
expect(direction).toBe('BT');
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -99,8 +99,8 @@ describe('[Arrows] when parsing', () => {
|
||||
|
||||
expect(direction).toBe('TB');
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -116,8 +116,8 @@ describe('[Arrows] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -133,8 +133,8 @@ describe('[Arrows] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -150,8 +150,8 @@ describe('[Arrows] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(2);
|
||||
expect(edges[1].start).toBe('B');
|
||||
expect(edges[1].end).toBe('C');
|
||||
@@ -169,8 +169,8 @@ describe('[Arrows] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -186,8 +186,8 @@ describe('[Arrows] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -203,8 +203,8 @@ describe('[Arrows] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -220,8 +220,8 @@ describe('[Arrows] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -237,8 +237,8 @@ describe('[Arrows] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -254,8 +254,8 @@ describe('[Arrows] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
|
||||
@@ -19,8 +19,8 @@ describe('[Comments] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -34,8 +34,8 @@ describe('[Comments] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -49,8 +49,8 @@ describe('[Comments] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -64,8 +64,8 @@ describe('[Comments] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -79,8 +79,8 @@ describe('[Comments] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -94,8 +94,8 @@ describe('[Comments] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -109,8 +109,8 @@ describe('[Comments] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -124,8 +124,8 @@ describe('[Comments] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -143,8 +143,8 @@ describe('[Comments] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
|
||||
@@ -48,8 +48,6 @@ describe('[Edges] when parsing', () => {
|
||||
|
||||
it('should handle open ended edges', function () {
|
||||
const res = flow.parser.parse('graph TD;A---B;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges[0].type).toBe('arrow_open');
|
||||
@@ -57,8 +55,6 @@ describe('[Edges] when parsing', () => {
|
||||
|
||||
it('should handle cross ended edges', function () {
|
||||
const res = flow.parser.parse('graph TD;A--xB;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges[0].type).toBe('arrow_cross');
|
||||
@@ -66,8 +62,6 @@ describe('[Edges] when parsing', () => {
|
||||
|
||||
it('should handle open ended edges', function () {
|
||||
const res = flow.parser.parse('graph TD;A--oB;');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges[0].type).toBe('arrow_circle');
|
||||
@@ -81,8 +75,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -99,8 +93,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -119,8 +113,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -139,8 +133,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(2);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -164,8 +158,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -183,8 +177,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -202,8 +196,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -221,8 +215,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -240,8 +234,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -259,8 +253,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -278,8 +272,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -297,8 +291,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -316,8 +310,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -335,8 +329,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -354,8 +348,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -373,8 +367,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -392,8 +386,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -411,8 +405,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -430,8 +424,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -449,8 +443,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -468,8 +462,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -487,8 +481,8 @@ describe('[Edges] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(1);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
|
||||
@@ -23,7 +23,7 @@ describe('[Text] when parsing', () => {
|
||||
|
||||
expect(edges[0].type).toBe('arrow_point');
|
||||
expect(edges.length).toBe(47917);
|
||||
expect(Object.keys(vert).length).toBe(2);
|
||||
expect(vert.size).toBe(2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -19,12 +19,12 @@ A["\`The cat in **the** hat\`"]-- "\`The *bat* in the chat\`" -->B["The dog in t
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['A'].text).toBe('The cat in **the** hat');
|
||||
expect(vert['A'].labelType).toBe('markdown');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert['B'].text).toBe('The dog in the hog');
|
||||
expect(vert['B'].labelType).toBe('string');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('A').text).toBe('The cat in **the** hat');
|
||||
expect(vert.get('A').labelType).toBe('markdown');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(vert.get('B').text).toBe('The dog in the hog');
|
||||
expect(vert.get('B').labelType).toBe('string');
|
||||
expect(edges.length).toBe(2);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
|
||||
@@ -43,7 +43,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['A'].styles.length).toBe(0);
|
||||
expect(vert.get('A').styles.length).toBe(0);
|
||||
});
|
||||
it('should handle a single node with white space after it (SN1)', function () {
|
||||
// Silly but syntactically correct
|
||||
@@ -53,7 +53,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['A'].styles.length).toBe(0);
|
||||
expect(vert.get('A').styles.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle a single square node', function () {
|
||||
@@ -64,8 +64,8 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['a'].styles.length).toBe(0);
|
||||
expect(vert['a'].type).toBe('square');
|
||||
expect(vert.get('a').styles.length).toBe(0);
|
||||
expect(vert.get('a').type).toBe('square');
|
||||
});
|
||||
|
||||
it('should handle a single round square node', function () {
|
||||
@@ -76,8 +76,8 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['a'].styles.length).toBe(0);
|
||||
expect(vert['a'].type).toBe('square');
|
||||
expect(vert.get('a').styles.length).toBe(0);
|
||||
expect(vert.get('a').type).toBe('square');
|
||||
});
|
||||
|
||||
it('should handle a single circle node', function () {
|
||||
@@ -88,7 +88,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['a'].type).toBe('circle');
|
||||
expect(vert.get('a').type).toBe('circle');
|
||||
});
|
||||
|
||||
it('should handle a single round node', function () {
|
||||
@@ -99,7 +99,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['a'].type).toBe('round');
|
||||
expect(vert.get('a').type).toBe('round');
|
||||
});
|
||||
|
||||
it('should handle a single odd node', function () {
|
||||
@@ -110,7 +110,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['a'].type).toBe('odd');
|
||||
expect(vert.get('a').type).toBe('odd');
|
||||
});
|
||||
|
||||
it('should handle a single diamond node', function () {
|
||||
@@ -121,7 +121,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['a'].type).toBe('diamond');
|
||||
expect(vert.get('a').type).toBe('diamond');
|
||||
});
|
||||
|
||||
it('should handle a single diamond node with whitespace after it', function () {
|
||||
@@ -132,7 +132,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['a'].type).toBe('diamond');
|
||||
expect(vert.get('a').type).toBe('diamond');
|
||||
});
|
||||
|
||||
it('should handle a single diamond node with html in it (SN3)', function () {
|
||||
@@ -143,8 +143,8 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['a'].type).toBe('diamond');
|
||||
expect(vert['a'].text).toBe('A <br> end');
|
||||
expect(vert.get('a').type).toBe('diamond');
|
||||
expect(vert.get('a').text).toBe('A <br> end');
|
||||
});
|
||||
|
||||
it('should handle a single hexagon node', function () {
|
||||
@@ -155,7 +155,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['a'].type).toBe('hexagon');
|
||||
expect(vert.get('a').type).toBe('hexagon');
|
||||
});
|
||||
|
||||
it('should handle a single hexagon node with html in it', function () {
|
||||
@@ -166,8 +166,8 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['a'].type).toBe('hexagon');
|
||||
expect(vert['a'].text).toBe('A <br> end');
|
||||
expect(vert.get('a').type).toBe('hexagon');
|
||||
expect(vert.get('a').text).toBe('A <br> end');
|
||||
});
|
||||
|
||||
it('should handle a single round node with html in it', function () {
|
||||
@@ -178,8 +178,8 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['a'].type).toBe('round');
|
||||
expect(vert['a'].text).toBe('A <br> end');
|
||||
expect(vert.get('a').type).toBe('round');
|
||||
expect(vert.get('a').text).toBe('A <br> end');
|
||||
});
|
||||
|
||||
it('should handle a single double circle node', function () {
|
||||
@@ -190,7 +190,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['a'].type).toBe('doublecircle');
|
||||
expect(vert.get('a').type).toBe('doublecircle');
|
||||
});
|
||||
|
||||
it('should handle a single double circle node with whitespace after it', function () {
|
||||
@@ -201,7 +201,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['a'].type).toBe('doublecircle');
|
||||
expect(vert.get('a').type).toBe('doublecircle');
|
||||
});
|
||||
|
||||
it('should handle a single double circle node with html in it (SN3)', function () {
|
||||
@@ -212,8 +212,8 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['a'].type).toBe('doublecircle');
|
||||
expect(vert['a'].text).toBe('A <br> end');
|
||||
expect(vert.get('a').type).toBe('doublecircle');
|
||||
expect(vert.get('a').text).toBe('A <br> end');
|
||||
});
|
||||
|
||||
it('should handle a single node with alphanumerics starting on a char', function () {
|
||||
@@ -224,7 +224,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['id1'].styles.length).toBe(0);
|
||||
expect(vert.get('id1').styles.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle a single node with a single digit', function () {
|
||||
@@ -235,7 +235,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['1'].text).toBe('1');
|
||||
expect(vert.get('1').text).toBe('1');
|
||||
});
|
||||
|
||||
it('should handle a single node with a single digit in a subgraph', function () {
|
||||
@@ -247,7 +247,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['1'].text).toBe('1');
|
||||
expect(vert.get('1').text).toBe('1');
|
||||
});
|
||||
|
||||
it('should handle a single node with alphanumerics starting on a num', function () {
|
||||
@@ -258,7 +258,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['1id'].styles.length).toBe(0);
|
||||
expect(vert.get('1id').styles.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle a single node with alphanumerics containing a minus sign', function () {
|
||||
@@ -269,7 +269,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['i-d'].styles.length).toBe(0);
|
||||
expect(vert.get('i-d').styles.length).toBe(0);
|
||||
});
|
||||
|
||||
it('should handle a single node with alphanumerics containing a underscore sign', function () {
|
||||
@@ -280,33 +280,33 @@ describe('[Singlenodes] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges.length).toBe(0);
|
||||
expect(vert['i_d'].styles.length).toBe(0);
|
||||
expect(vert.get('i_d').styles.length).toBe(0);
|
||||
});
|
||||
|
||||
it.each(keywords)('should handle keywords between dashes "-"', function (keyword) {
|
||||
const res = flow.parser.parse(`graph TD;a-${keyword}-node;`);
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
expect(vert[`a-${keyword}-node`].text).toBe(`a-${keyword}-node`);
|
||||
expect(vert.get(`a-${keyword}-node`).text).toBe(`a-${keyword}-node`);
|
||||
});
|
||||
|
||||
it.each(keywords)('should handle keywords between periods "."', function (keyword) {
|
||||
const res = flow.parser.parse(`graph TD;a.${keyword}.node;`);
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
expect(vert[`a.${keyword}.node`].text).toBe(`a.${keyword}.node`);
|
||||
expect(vert.get(`a.${keyword}.node`).text).toBe(`a.${keyword}.node`);
|
||||
});
|
||||
|
||||
it.each(keywords)('should handle keywords between underscores "_"', function (keyword) {
|
||||
const res = flow.parser.parse(`graph TD;a_${keyword}_node;`);
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
expect(vert[`a_${keyword}_node`].text).toBe(`a_${keyword}_node`);
|
||||
expect(vert.get(`a_${keyword}_node`).text).toBe(`a_${keyword}_node`);
|
||||
});
|
||||
|
||||
it.each(keywords)('should handle nodes ending in %s', function (keyword) {
|
||||
const res = flow.parser.parse(`graph TD;node_${keyword};node.${keyword};node-${keyword};`);
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
expect(vert[`node_${keyword}`].text).toBe(`node_${keyword}`);
|
||||
expect(vert[`node.${keyword}`].text).toBe(`node.${keyword}`);
|
||||
expect(vert[`node-${keyword}`].text).toBe(`node-${keyword}`);
|
||||
expect(vert.get(`node_${keyword}`).text).toBe(`node_${keyword}`);
|
||||
expect(vert.get(`node.${keyword}`).text).toBe(`node.${keyword}`);
|
||||
expect(vert.get(`node-${keyword}`).text).toBe(`node-${keyword}`);
|
||||
});
|
||||
|
||||
const errorKeywords = [
|
||||
@@ -337,9 +337,9 @@ describe('[Singlenodes] when parsing', () => {
|
||||
it.each(workingKeywords)('should parse node beginning with %s', function (keyword) {
|
||||
flow.parser.parse(`graph TD; ${keyword}.node;${keyword}-node;${keyword}/node;`);
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
expect(vert[`${keyword}.node`].text).toBe(`${keyword}.node`);
|
||||
expect(vert[`${keyword}-node`].text).toBe(`${keyword}-node`);
|
||||
expect(vert[`${keyword}/node`].text).toBe(`${keyword}/node`);
|
||||
expect(vert.get(`${keyword}.node`).text).toBe(`${keyword}.node`);
|
||||
expect(vert.get(`${keyword}-node`).text).toBe(`${keyword}-node`);
|
||||
expect(vert.get(`${keyword}/node`).text).toBe(`${keyword}/node`);
|
||||
});
|
||||
|
||||
it.each(specialChars)(
|
||||
@@ -347,7 +347,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
function (specialChar) {
|
||||
flow.parser.parse(`graph TD; ${specialChar} --> A`);
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
expect(vert[`${specialChar}`].text).toBe(`${specialChar}`);
|
||||
expect(vert.get(`${specialChar}`).text).toBe(`${specialChar}`);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -356,7 +356,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
function (specialChar) {
|
||||
flow.parser.parse(`graph TD; ${specialChar}node --> A`);
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
expect(vert[`${specialChar}node`].text).toBe(`${specialChar}node`);
|
||||
expect(vert.get(`${specialChar}node`).text).toBe(`${specialChar}node`);
|
||||
}
|
||||
);
|
||||
|
||||
@@ -365,7 +365,7 @@ describe('[Singlenodes] when parsing', () => {
|
||||
function (specialChar) {
|
||||
flow.parser.parse(`graph TD; node${specialChar} --> A`);
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
expect(vert[`node${specialChar}`].text).toBe(`node${specialChar}`);
|
||||
expect(vert.get(`node${specialChar}`).text).toBe(`node${specialChar}`);
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
@@ -20,10 +20,8 @@ describe('[Style] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
const style = vert['Q'].styles[0];
|
||||
|
||||
expect(vert['Q'].styles.length).toBe(1);
|
||||
expect(vert['Q'].styles[0]).toBe('background:#fff');
|
||||
expect(vert.get('Q').styles.length).toBe(1);
|
||||
expect(vert.get('Q').styles[0]).toBe('background:#fff');
|
||||
});
|
||||
|
||||
it('should handle multiple styles for a vortex', function () {
|
||||
@@ -32,9 +30,9 @@ describe('[Style] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['R'].styles.length).toBe(2);
|
||||
expect(vert['R'].styles[0]).toBe('background:#fff');
|
||||
expect(vert['R'].styles[1]).toBe('border:1px solid red');
|
||||
expect(vert.get('R').styles.length).toBe(2);
|
||||
expect(vert.get('R').styles[0]).toBe('background:#fff');
|
||||
expect(vert.get('R').styles[1]).toBe('border:1px solid red');
|
||||
});
|
||||
|
||||
it('should handle multiple styles in a graph', function () {
|
||||
@@ -45,11 +43,11 @@ describe('[Style] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['S'].styles.length).toBe(1);
|
||||
expect(vert['T'].styles.length).toBe(2);
|
||||
expect(vert['S'].styles[0]).toBe('background:#aaa');
|
||||
expect(vert['T'].styles[0]).toBe('background:#bbb');
|
||||
expect(vert['T'].styles[1]).toBe('border:1px solid red');
|
||||
expect(vert.get('S').styles.length).toBe(1);
|
||||
expect(vert.get('T').styles.length).toBe(2);
|
||||
expect(vert.get('S').styles[0]).toBe('background:#aaa');
|
||||
expect(vert.get('T').styles[0]).toBe('background:#bbb');
|
||||
expect(vert.get('T').styles[1]).toBe('border:1px solid red');
|
||||
});
|
||||
|
||||
it('should handle styles and graph definitions in a graph', function () {
|
||||
@@ -60,11 +58,11 @@ describe('[Style] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['S'].styles.length).toBe(1);
|
||||
expect(vert['T'].styles.length).toBe(2);
|
||||
expect(vert['S'].styles[0]).toBe('background:#aaa');
|
||||
expect(vert['T'].styles[0]).toBe('background:#bbb');
|
||||
expect(vert['T'].styles[1]).toBe('border:1px solid red');
|
||||
expect(vert.get('S').styles.length).toBe(1);
|
||||
expect(vert.get('T').styles.length).toBe(2);
|
||||
expect(vert.get('S').styles[0]).toBe('background:#aaa');
|
||||
expect(vert.get('T').styles[0]).toBe('background:#bbb');
|
||||
expect(vert.get('T').styles[1]).toBe('border:1px solid red');
|
||||
});
|
||||
|
||||
it('should handle styles and graph definitions in a graph', function () {
|
||||
@@ -73,9 +71,9 @@ describe('[Style] when parsing', () => {
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
||||
expect(vert['T'].styles.length).toBe(2);
|
||||
expect(vert['T'].styles[0]).toBe('background:#bbb');
|
||||
expect(vert['T'].styles[1]).toBe('border:1px solid red');
|
||||
expect(vert.get('T').styles.length).toBe(2);
|
||||
expect(vert.get('T').styles[0]).toBe('background:#bbb');
|
||||
expect(vert.get('T').styles[1]).toBe('border:1px solid red');
|
||||
});
|
||||
|
||||
it('should keep node label text (if already defined) when a style is applied', function () {
|
||||
@@ -85,10 +83,10 @@ describe('[Style] when parsing', () => {
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
||||
expect(vert['A'].text).toBe('');
|
||||
expect(vert['B'].text).toBe('Test');
|
||||
expect(vert['C'].text).toBe('C');
|
||||
expect(vert['D'].text).toBe('D');
|
||||
expect(vert.get('A').text).toBe('');
|
||||
expect(vert.get('B').text).toBe('Test');
|
||||
expect(vert.get('C').text).toBe('C');
|
||||
expect(vert.get('D').text).toBe('D');
|
||||
});
|
||||
|
||||
it('should be possible to declare a class', function () {
|
||||
@@ -99,9 +97,9 @@ describe('[Style] when parsing', () => {
|
||||
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
|
||||
expect(classes['exClass'].styles.length).toBe(2);
|
||||
expect(classes['exClass'].styles[0]).toBe('background:#bbb');
|
||||
expect(classes['exClass'].styles[1]).toBe('border:1px solid red');
|
||||
expect(classes.get('exClass').styles.length).toBe(2);
|
||||
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
|
||||
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
|
||||
});
|
||||
|
||||
it('should be possible to declare multiple classes', function () {
|
||||
@@ -111,13 +109,13 @@ describe('[Style] when parsing', () => {
|
||||
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
|
||||
expect(classes['firstClass'].styles.length).toBe(2);
|
||||
expect(classes['firstClass'].styles[0]).toBe('background:#bbb');
|
||||
expect(classes['firstClass'].styles[1]).toBe('border:1px solid red');
|
||||
expect(classes.get('firstClass').styles.length).toBe(2);
|
||||
expect(classes.get('firstClass').styles[0]).toBe('background:#bbb');
|
||||
expect(classes.get('firstClass').styles[1]).toBe('border:1px solid red');
|
||||
|
||||
expect(classes['secondClass'].styles.length).toBe(2);
|
||||
expect(classes['secondClass'].styles[0]).toBe('background:#bbb');
|
||||
expect(classes['secondClass'].styles[1]).toBe('border:1px solid red');
|
||||
expect(classes.get('secondClass').styles.length).toBe(2);
|
||||
expect(classes.get('secondClass').styles[0]).toBe('background:#bbb');
|
||||
expect(classes.get('secondClass').styles[1]).toBe('border:1px solid red');
|
||||
});
|
||||
|
||||
it('should be possible to declare a class with a dot in the style', function () {
|
||||
@@ -128,9 +126,9 @@ describe('[Style] when parsing', () => {
|
||||
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
|
||||
expect(classes['exClass'].styles.length).toBe(2);
|
||||
expect(classes['exClass'].styles[0]).toBe('background:#bbb');
|
||||
expect(classes['exClass'].styles[1]).toBe('border:1.5px solid red');
|
||||
expect(classes.get('exClass').styles.length).toBe(2);
|
||||
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
|
||||
expect(classes.get('exClass').styles[1]).toBe('border:1.5px solid red');
|
||||
});
|
||||
it('should be possible to declare a class with a space in the style', function () {
|
||||
const res = flow.parser.parse(
|
||||
@@ -140,9 +138,9 @@ describe('[Style] when parsing', () => {
|
||||
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
|
||||
expect(classes['exClass'].styles.length).toBe(2);
|
||||
expect(classes['exClass'].styles[0]).toBe('background: #bbb');
|
||||
expect(classes['exClass'].styles[1]).toBe('border:1.5px solid red');
|
||||
expect(classes.get('exClass').styles.length).toBe(2);
|
||||
expect(classes.get('exClass').styles[0]).toBe('background: #bbb');
|
||||
expect(classes.get('exClass').styles[1]).toBe('border:1.5px solid red');
|
||||
});
|
||||
it('should be possible to apply a class to a vertex', function () {
|
||||
let statement = '';
|
||||
@@ -156,9 +154,9 @@ describe('[Style] when parsing', () => {
|
||||
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
|
||||
expect(classes['exClass'].styles.length).toBe(2);
|
||||
expect(classes['exClass'].styles[0]).toBe('background:#bbb');
|
||||
expect(classes['exClass'].styles[1]).toBe('border:1px solid red');
|
||||
expect(classes.get('exClass').styles.length).toBe(2);
|
||||
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
|
||||
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
|
||||
});
|
||||
it('should be possible to apply a class to a vertex with an id containing _', function () {
|
||||
let statement = '';
|
||||
@@ -172,9 +170,9 @@ describe('[Style] when parsing', () => {
|
||||
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
|
||||
expect(classes['exClass'].styles.length).toBe(2);
|
||||
expect(classes['exClass'].styles[0]).toBe('background:#bbb');
|
||||
expect(classes['exClass'].styles[1]).toBe('border:1px solid red');
|
||||
expect(classes.get('exClass').styles.length).toBe(2);
|
||||
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
|
||||
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
|
||||
});
|
||||
it('should be possible to apply a class to a vertex directly', function () {
|
||||
let statement = '';
|
||||
@@ -187,10 +185,10 @@ describe('[Style] when parsing', () => {
|
||||
const vertices = flow.parser.yy.getVertices();
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
|
||||
expect(classes['exClass'].styles.length).toBe(2);
|
||||
expect(vertices['b'].classes[0]).toBe('exClass');
|
||||
expect(classes['exClass'].styles[0]).toBe('background:#bbb');
|
||||
expect(classes['exClass'].styles[1]).toBe('border:1px solid red');
|
||||
expect(classes.get('exClass').styles.length).toBe(2);
|
||||
expect(vertices.get('b').classes[0]).toBe('exClass');
|
||||
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
|
||||
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
|
||||
});
|
||||
|
||||
it('should be possible to apply a class to a vertex directly : usecase A[text].class ', function () {
|
||||
@@ -204,10 +202,10 @@ describe('[Style] when parsing', () => {
|
||||
const vertices = flow.parser.yy.getVertices();
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
|
||||
expect(classes['exClass'].styles.length).toBe(2);
|
||||
expect(vertices['b'].classes[0]).toBe('exClass');
|
||||
expect(classes['exClass'].styles[0]).toBe('background:#bbb');
|
||||
expect(classes['exClass'].styles[1]).toBe('border:1px solid red');
|
||||
expect(classes.get('exClass').styles.length).toBe(2);
|
||||
expect(vertices.get('b').classes[0]).toBe('exClass');
|
||||
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
|
||||
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
|
||||
});
|
||||
|
||||
it('should be possible to apply a class to a vertex directly : usecase A[text].class-->B[test2] ', function () {
|
||||
@@ -221,10 +219,10 @@ describe('[Style] when parsing', () => {
|
||||
const vertices = flow.parser.yy.getVertices();
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
|
||||
expect(classes['exClass'].styles.length).toBe(2);
|
||||
expect(vertices['A'].classes[0]).toBe('exClass');
|
||||
expect(classes['exClass'].styles[0]).toBe('background:#bbb');
|
||||
expect(classes['exClass'].styles[1]).toBe('border:1px solid red');
|
||||
expect(classes.get('exClass').styles.length).toBe(2);
|
||||
expect(vertices.get('A').classes[0]).toBe('exClass');
|
||||
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
|
||||
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
|
||||
});
|
||||
|
||||
it('should be possible to apply a class to a vertex directly 2', function () {
|
||||
@@ -238,10 +236,10 @@ describe('[Style] when parsing', () => {
|
||||
const vertices = flow.parser.yy.getVertices();
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
|
||||
expect(classes['exClass'].styles.length).toBe(2);
|
||||
expect(vertices['b'].classes[0]).toBe('exClass');
|
||||
expect(classes['exClass'].styles[0]).toBe('background:#bbb');
|
||||
expect(classes['exClass'].styles[1]).toBe('border:1px solid red');
|
||||
expect(classes.get('exClass').styles.length).toBe(2);
|
||||
expect(vertices.get('b').classes[0]).toBe('exClass');
|
||||
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
|
||||
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
|
||||
});
|
||||
it('should be possible to apply a class to a comma separated list of vertices', function () {
|
||||
let statement = '';
|
||||
@@ -256,11 +254,11 @@ describe('[Style] when parsing', () => {
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
const vertices = flow.parser.yy.getVertices();
|
||||
|
||||
expect(classes['exClass'].styles.length).toBe(2);
|
||||
expect(classes['exClass'].styles[0]).toBe('background:#bbb');
|
||||
expect(classes['exClass'].styles[1]).toBe('border:1px solid red');
|
||||
expect(vertices['a'].classes[0]).toBe('exClass');
|
||||
expect(vertices['b'].classes[0]).toBe('exClass');
|
||||
expect(classes.get('exClass').styles.length).toBe(2);
|
||||
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
|
||||
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
|
||||
expect(vertices.get('a').classes[0]).toBe('exClass');
|
||||
expect(vertices.get('b').classes[0]).toBe('exClass');
|
||||
});
|
||||
|
||||
it('should handle style definitions with more then 1 digit in a row', function () {
|
||||
@@ -364,9 +362,9 @@ describe('[Style] when parsing', () => {
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
||||
expect(vert['A'].classes.length).toBe(0);
|
||||
expect(vert['B'].classes[0]).toBe('C1');
|
||||
expect(vert['D'].classes[0]).toBe('C1');
|
||||
expect(vert['E'].classes[0]).toBe('C2');
|
||||
expect(vert.get('A').classes.length).toBe(0);
|
||||
expect(vert.get('B').classes[0]).toBe('C1');
|
||||
expect(vert.get('D').classes[0]).toBe('C1');
|
||||
expect(vert.get('E').classes[0]).toBe('C2');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -113,7 +113,7 @@ describe('[Text] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges[0].type).toBe('arrow_cross');
|
||||
expect(vert['v'].text).toBe('my text');
|
||||
expect(vert.get('v').text).toBe('my text');
|
||||
});
|
||||
it('should handle v in node ids v at end', function () {
|
||||
// v at end
|
||||
@@ -123,7 +123,7 @@ describe('[Text] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges[0].type).toBe('arrow_cross');
|
||||
expect(vert['csv'].text).toBe('my text');
|
||||
expect(vert.get('csv').text).toBe('my text');
|
||||
});
|
||||
it('should handle v in node ids v in middle', function () {
|
||||
// v in middle
|
||||
@@ -133,7 +133,7 @@ describe('[Text] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges[0].type).toBe('arrow_cross');
|
||||
expect(vert['ava'].text).toBe('my text');
|
||||
expect(vert.get('ava').text).toBe('my text');
|
||||
});
|
||||
it('should handle v in node ids, v at start', function () {
|
||||
// v at start
|
||||
@@ -143,7 +143,7 @@ describe('[Text] when parsing', () => {
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(edges[0].type).toBe('arrow_cross');
|
||||
expect(vert['va'].text).toBe('my text');
|
||||
expect(vert.get('va').text).toBe('my text');
|
||||
});
|
||||
it('should handle keywords', function () {
|
||||
const res = flow.parser.parse('graph TD;A--x|text including graph space|B;');
|
||||
@@ -157,7 +157,7 @@ describe('[Text] when parsing', () => {
|
||||
const res = flow.parser.parse('graph TD;V-->a[v]');
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
expect(vert['a'].text).toBe('v');
|
||||
expect(vert.get('a').text).toBe('v');
|
||||
});
|
||||
it('should handle quoted text', function () {
|
||||
const res = flow.parser.parse('graph TD;V-- "test string()" -->a[v]');
|
||||
@@ -302,8 +302,8 @@ describe('[Text] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['C'].type).toBe('round');
|
||||
expect(vert['C'].text).toBe('Chimpansen hoppar');
|
||||
expect(vert.get('C').type).toBe('round');
|
||||
expect(vert.get('C').text).toBe('Chimpansen hoppar');
|
||||
});
|
||||
|
||||
const keywords = [
|
||||
@@ -353,8 +353,8 @@ describe('[Text] when parsing', () => {
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
expect(vert['B'].type).toBe(`${shape.name}`);
|
||||
expect(vert['B'].text).toBe(`This node has a ${keyword} as text`);
|
||||
expect(vert.get('B').type).toBe(`${shape.name}`);
|
||||
expect(vert.get('B').text).toBe(`This node has a ${keyword} as text`);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -365,24 +365,24 @@ describe('[Text] when parsing', () => {
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
expect(vert['B'].type).toBe('rect');
|
||||
expect(vert['B'].text).toBe(`This node has a ${keyword} as text`);
|
||||
expect(vert.get('B').type).toBe('rect');
|
||||
expect(vert.get('B').text).toBe(`This node has a ${keyword} as text`);
|
||||
});
|
||||
|
||||
it('should handle edge case for odd vertex with node id ending with minus', function () {
|
||||
const res = flow.parser.parse('graph TD;A_node-->odd->Vertex Text];');
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
||||
expect(vert['odd-'].type).toBe('odd');
|
||||
expect(vert['odd-'].text).toBe('Vertex Text');
|
||||
expect(vert.get('odd-').type).toBe('odd');
|
||||
expect(vert.get('odd-').text).toBe('Vertex Text');
|
||||
});
|
||||
it('should allow forward slashes in lean_right vertices', function () {
|
||||
const rest = flow.parser.parse(`graph TD;A_node-->B[/This node has a / as text/];`);
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
expect(vert['B'].type).toBe('lean_right');
|
||||
expect(vert['B'].text).toBe(`This node has a / as text`);
|
||||
expect(vert.get('B').type).toBe('lean_right');
|
||||
expect(vert.get('B').text).toBe(`This node has a / as text`);
|
||||
});
|
||||
|
||||
it('should allow back slashes in lean_left vertices', function () {
|
||||
@@ -390,8 +390,8 @@ describe('[Text] when parsing', () => {
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
expect(vert['B'].type).toBe('lean_left');
|
||||
expect(vert['B'].text).toBe(`This node has a \\ as text`);
|
||||
expect(vert.get('B').type).toBe('lean_left');
|
||||
expect(vert.get('B').text).toBe(`This node has a \\ as text`);
|
||||
});
|
||||
|
||||
it('should handle åäö and minus', function () {
|
||||
@@ -400,8 +400,8 @@ describe('[Text] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['C'].type).toBe('diamond');
|
||||
expect(vert['C'].text).toBe('Chimpansen hoppar åäö-ÅÄÖ');
|
||||
expect(vert.get('C').type).toBe('diamond');
|
||||
expect(vert.get('C').text).toBe('Chimpansen hoppar åäö-ÅÄÖ');
|
||||
});
|
||||
|
||||
it('should handle with åäö, minus and space and br', function () {
|
||||
@@ -410,8 +410,8 @@ describe('[Text] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['C'].type).toBe('round');
|
||||
expect(vert['C'].text).toBe('Chimpansen hoppar åäö <br> - ÅÄÖ');
|
||||
expect(vert.get('C').type).toBe('round');
|
||||
expect(vert.get('C').text).toBe('Chimpansen hoppar åäö <br> - ÅÄÖ');
|
||||
});
|
||||
// it.skip('should handle åäö, minus and space and br',function(){
|
||||
// const res = flow.parser.parse('graph TD; A[Object(foo,bar)]-->B(Thing);');
|
||||
@@ -419,22 +419,22 @@ describe('[Text] when parsing', () => {
|
||||
// const vert = flow.parser.yy.getVertices();
|
||||
// const edges = flow.parser.yy.getEdges();
|
||||
//
|
||||
// expect(vert['C'].type).toBe('round');
|
||||
// expect(vert['C'].text).toBe(' A[Object(foo,bar)]-->B(Thing);');
|
||||
// expect(vert.get('C').type).toBe('round');
|
||||
// expect(vert.get('C').text).toBe(' A[Object(foo,bar)]-->B(Thing);');
|
||||
// });
|
||||
it('should handle unicode chars', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(Начало);');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
||||
expect(vert['C'].text).toBe('Начало');
|
||||
expect(vert.get('C').text).toBe('Начало');
|
||||
});
|
||||
it('should handle backslask', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(c:\\windows);');
|
||||
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
|
||||
expect(vert['C'].text).toBe('c:\\windows');
|
||||
expect(vert.get('C').text).toBe('c:\\windows');
|
||||
});
|
||||
it('should handle CAPS', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(some CAPS);');
|
||||
@@ -442,8 +442,8 @@ describe('[Text] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['C'].type).toBe('round');
|
||||
expect(vert['C'].text).toBe('some CAPS');
|
||||
expect(vert.get('C').type).toBe('round');
|
||||
expect(vert.get('C').text).toBe('some CAPS');
|
||||
});
|
||||
it('should handle directions', function () {
|
||||
const res = flow.parser.parse('graph TD;A-->C(some URL);');
|
||||
@@ -451,8 +451,8 @@ describe('[Text] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['C'].type).toBe('round');
|
||||
expect(vert['C'].text).toBe('some URL');
|
||||
expect(vert.get('C').type).toBe('round');
|
||||
expect(vert.get('C').text).toBe('some URL');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -464,9 +464,9 @@ describe('[Text] when parsing', () => {
|
||||
|
||||
expect(edges[0].type).toBe('arrow_circle');
|
||||
expect(edges[1].type).toBe('arrow_point');
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert['C'].id).toBe('C');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(vert.get('C').id).toBe('C');
|
||||
expect(edges.length).toBe(2);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -482,8 +482,8 @@ describe('[Text] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].type).toBe('square');
|
||||
expect(vert['A'].text).toBe('chimpansen hoppar');
|
||||
expect(vert.get('A').type).toBe('square');
|
||||
expect(vert.get('A').text).toBe('chimpansen hoppar');
|
||||
});
|
||||
|
||||
it('should handle text in vertices with space with spaces between vertices and link', function () {
|
||||
@@ -492,8 +492,8 @@ describe('[Text] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].type).toBe('square');
|
||||
expect(vert['A'].text).toBe('chimpansen hoppar');
|
||||
expect(vert.get('A').type).toBe('square');
|
||||
expect(vert.get('A').text).toBe('chimpansen hoppar');
|
||||
});
|
||||
it('should handle text including _ in vertices', function () {
|
||||
const res = flow.parser.parse('graph TD;A[chimpansen_hoppar] --> C;');
|
||||
@@ -501,8 +501,8 @@ describe('[Text] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].type).toBe('square');
|
||||
expect(vert['A'].text).toBe('chimpansen_hoppar');
|
||||
expect(vert.get('A').type).toBe('square');
|
||||
expect(vert.get('A').text).toBe('chimpansen_hoppar');
|
||||
});
|
||||
|
||||
it('should handle quoted text in vertices ', function () {
|
||||
@@ -511,8 +511,8 @@ describe('[Text] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].type).toBe('square');
|
||||
expect(vert['A'].text).toBe('chimpansen hoppar ()[]');
|
||||
expect(vert.get('A').type).toBe('square');
|
||||
expect(vert.get('A').text).toBe('chimpansen hoppar ()[]');
|
||||
});
|
||||
|
||||
it('should handle text in circle vertices with space', function () {
|
||||
@@ -521,8 +521,8 @@ describe('[Text] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].type).toBe('circle');
|
||||
expect(vert['A'].text).toBe('chimpansen hoppar');
|
||||
expect(vert.get('A').type).toBe('circle');
|
||||
expect(vert.get('A').text).toBe('chimpansen hoppar');
|
||||
});
|
||||
|
||||
it('should handle text in ellipse vertices', function () {
|
||||
@@ -531,8 +531,8 @@ describe('[Text] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].type).toBe('ellipse');
|
||||
expect(vert['A'].text).toBe('this is an ellipse');
|
||||
expect(vert.get('A').type).toBe('ellipse');
|
||||
expect(vert.get('A').text).toBe('this is an ellipse');
|
||||
});
|
||||
|
||||
it('should not freeze when ellipse text has a `(`', function () {
|
||||
@@ -545,8 +545,8 @@ describe('[Text] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].type).toBe('round');
|
||||
expect(vert['A'].text).toBe('chimpansen hoppar');
|
||||
expect(vert.get('A').type).toBe('round');
|
||||
expect(vert.get('A').text).toBe('chimpansen hoppar');
|
||||
});
|
||||
|
||||
it('should handle text in with ?', function () {
|
||||
@@ -555,7 +555,7 @@ describe('[Text] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].text).toBe('?');
|
||||
expect(vert.get('A').text).toBe('?');
|
||||
expect(edges[0].text).toBe('?');
|
||||
});
|
||||
it('should handle text in with éèêàçô', function () {
|
||||
@@ -564,7 +564,7 @@ describe('[Text] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].text).toBe('éèêàçô');
|
||||
expect(vert.get('A').text).toBe('éèêàçô');
|
||||
expect(edges[0].text).toBe('éèêàçô');
|
||||
});
|
||||
|
||||
@@ -574,7 +574,7 @@ describe('[Text] when parsing', () => {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].text).toBe(',.?!+-*');
|
||||
expect(vert.get('A').text).toBe(',.?!+-*');
|
||||
expect(edges[0].text).toBe(',.?!+-*');
|
||||
});
|
||||
|
||||
@@ -591,7 +591,7 @@ describe('[Text] when parsing', () => {
|
||||
|
||||
it('should throw error for escaping quotes in text state', function () {
|
||||
//prettier-ignore
|
||||
const str = 'graph TD; A[This is a \"()\" in text];'; //eslint-disable-line no-useless-escape
|
||||
const str = 'graph TD; A[This is a "()" in text];'; //eslint-disable-line no-useless-escape
|
||||
|
||||
expect(() => flow.parser.parse(str)).toThrowError("got 'STR'");
|
||||
});
|
||||
|
||||
@@ -22,9 +22,9 @@ describe('when parsing flowcharts', function () {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert['C'].id).toBe('C');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(vert.get('C').id).toBe('C');
|
||||
expect(edges.length).toBe(2);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -44,9 +44,9 @@ describe('when parsing flowcharts', function () {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert['C'].id).toBe('C');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(vert.get('C').id).toBe('C');
|
||||
expect(edges.length).toBe(2);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('C');
|
||||
@@ -66,9 +66,9 @@ describe('when parsing flowcharts', function () {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert['C'].id).toBe('C');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(vert.get('C').id).toBe('C');
|
||||
expect(edges.length).toBe(2);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -88,10 +88,10 @@ describe('when parsing flowcharts', function () {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert['C'].id).toBe('C');
|
||||
expect(vert['D'].id).toBe('D');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(vert.get('C').id).toBe('C');
|
||||
expect(vert.get('D').id).toBe('D');
|
||||
expect(edges.length).toBe(4);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('C');
|
||||
@@ -119,10 +119,10 @@ describe('when parsing flowcharts', function () {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert['C'].id).toBe('C');
|
||||
expect(vert['D'].id).toBe('D');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(vert.get('C').id).toBe('C');
|
||||
expect(vert.get('D').id).toBe('D');
|
||||
expect(edges.length).toBe(4);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('C');
|
||||
@@ -150,11 +150,11 @@ describe('when parsing flowcharts', function () {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert['B2'].id).toBe('B2');
|
||||
expect(vert['C'].id).toBe('C');
|
||||
expect(vert['D2'].id).toBe('D2');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(vert.get('B2').id).toBe('B2');
|
||||
expect(vert.get('C').id).toBe('C');
|
||||
expect(vert.get('D2').id).toBe('D2');
|
||||
expect(edges.length).toBe(6);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -193,14 +193,14 @@ describe('when parsing flowcharts', function () {
|
||||
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
|
||||
expect(classes['exClass'].styles.length).toBe(2);
|
||||
expect(classes['exClass'].styles[0]).toBe('background:#bbb');
|
||||
expect(classes['exClass'].styles[1]).toBe('border:1px solid red');
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert['B'].classes[0]).toBe('exClass');
|
||||
expect(vert['C'].id).toBe('C');
|
||||
expect(vert['D'].id).toBe('D');
|
||||
expect(classes.get('exClass').styles.length).toBe(2);
|
||||
expect(classes.get('exClass').styles[0]).toBe('background:#bbb');
|
||||
expect(classes.get('exClass').styles[1]).toBe('border:1px solid red');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(vert.get('B').classes[0]).toBe('exClass');
|
||||
expect(vert.get('C').id).toBe('C');
|
||||
expect(vert.get('D').id).toBe('D');
|
||||
expect(edges.length).toBe(4);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
|
||||
@@ -19,8 +19,8 @@ describe('parsing a flow chart', function () {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
expect(edges.length).toBe(2);
|
||||
expect(edges[0].start).toBe('A');
|
||||
expect(edges[0].end).toBe('B');
|
||||
@@ -34,8 +34,8 @@ describe('parsing a flow chart', function () {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['endpoint'].id).toBe('endpoint');
|
||||
expect(vert['sender'].id).toBe('sender');
|
||||
expect(vert.get('endpoint').id).toBe('endpoint');
|
||||
expect(vert.get('sender').id).toBe('sender');
|
||||
expect(edges[0].start).toBe('endpoint');
|
||||
expect(edges[0].end).toBe('sender');
|
||||
});
|
||||
@@ -46,8 +46,8 @@ describe('parsing a flow chart', function () {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['blend'].id).toBe('blend');
|
||||
expect(vert['monograph'].id).toBe('monograph');
|
||||
expect(vert.get('blend').id).toBe('blend');
|
||||
expect(vert.get('monograph').id).toBe('monograph');
|
||||
expect(edges[0].start).toBe('blend');
|
||||
expect(edges[0].end).toBe('monograph');
|
||||
});
|
||||
@@ -58,8 +58,8 @@ describe('parsing a flow chart', function () {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['default'].id).toBe('default');
|
||||
expect(vert['monograph'].id).toBe('monograph');
|
||||
expect(vert.get('default').id).toBe('default');
|
||||
expect(vert.get('monograph').id).toBe('monograph');
|
||||
expect(edges[0].start).toBe('default');
|
||||
expect(edges[0].end).toBe('monograph');
|
||||
});
|
||||
@@ -71,12 +71,12 @@ describe('parsing a flow chart', function () {
|
||||
const vert = flow.parser.yy.getVertices();
|
||||
const edges = flow.parser.yy.getEdges();
|
||||
|
||||
expect(vert['A'].id).toBe('A');
|
||||
expect(vert['B'].id).toBe('B');
|
||||
expect(vert.get('A').id).toBe('A');
|
||||
expect(vert.get('B').id).toBe('B');
|
||||
if (result) {
|
||||
expect(vert['A'].text).toBe(result);
|
||||
expect(vert.get('A').text).toBe(result);
|
||||
} else {
|
||||
expect(vert['A'].text).toBe(char);
|
||||
expect(vert.get('A').text).toBe(char);
|
||||
}
|
||||
flow.parser.yy.clear();
|
||||
};
|
||||
@@ -135,7 +135,7 @@ describe('parsing a flow chart', function () {
|
||||
const res = flow.parser.parse(statement);
|
||||
const vertices = flow.parser.yy.getVertices();
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
expect(vertices['node1TB'].id).toBe('node1TB');
|
||||
expect(vertices.get('node1TB').id).toBe('node1TB');
|
||||
});
|
||||
|
||||
it('should be possible to use direction in node ids', function () {
|
||||
@@ -145,7 +145,7 @@ describe('parsing a flow chart', function () {
|
||||
const res = flow.parser.parse(statement);
|
||||
const vertices = flow.parser.yy.getVertices();
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
expect(vertices['A'].id).toBe('A');
|
||||
expect(vertices.get('A').id).toBe('A');
|
||||
});
|
||||
|
||||
it('should be possible to use numbers as labels', function () {
|
||||
@@ -154,8 +154,8 @@ describe('parsing a flow chart', function () {
|
||||
statement = statement + 'graph TB;subgraph "number as labels";1;end;';
|
||||
const res = flow.parser.parse(statement);
|
||||
const vertices = flow.parser.yy.getVertices();
|
||||
const classes = flow.parser.yy.getClasses();
|
||||
expect(vertices['1'].id).toBe('1');
|
||||
|
||||
expect(vertices.get('1').id).toBe('1');
|
||||
});
|
||||
|
||||
it('should add accTitle and accDescr to flow chart', function () {
|
||||
@@ -194,4 +194,47 @@ describe('parsing a flow chart', function () {
|
||||
with a second line`
|
||||
);
|
||||
});
|
||||
|
||||
for (const unsafeProp of ['__proto__', 'constructor']) {
|
||||
it(`should work with node id ${unsafeProp}`, function () {
|
||||
const flowChart = `graph LR
|
||||
${unsafeProp} --> A;`;
|
||||
|
||||
expect(() => {
|
||||
flow.parser.parse(flowChart);
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it(`should work with tooltip id ${unsafeProp}`, function () {
|
||||
const flowChart = `graph LR
|
||||
click ${unsafeProp} callback "${unsafeProp}";`;
|
||||
|
||||
expect(() => {
|
||||
flow.parser.parse(flowChart);
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it(`should work with class id ${unsafeProp}`, function () {
|
||||
const flowChart = `graph LR
|
||||
${unsafeProp} --> A;
|
||||
classDef ${unsafeProp} color:#ffffff,fill:#000000;
|
||||
class ${unsafeProp} ${unsafeProp};`;
|
||||
|
||||
expect(() => {
|
||||
flow.parser.parse(flowChart);
|
||||
}).not.toThrow();
|
||||
});
|
||||
|
||||
it(`should work with subgraph id ${unsafeProp}`, function () {
|
||||
const flowChart = `graph LR
|
||||
${unsafeProp} --> A;
|
||||
subgraph ${unsafeProp}
|
||||
C --> D;
|
||||
end;`;
|
||||
|
||||
expect(() => {
|
||||
flow.parser.parse(flowChart);
|
||||
}).not.toThrow();
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
@@ -28,7 +28,7 @@ let tickInterval = undefined;
|
||||
let todayMarker = '';
|
||||
let includes = [];
|
||||
let excludes = [];
|
||||
let links = {};
|
||||
let links = new Map();
|
||||
let sections = [];
|
||||
let tasks = [];
|
||||
let currentSection = '';
|
||||
@@ -62,7 +62,7 @@ export const clear = function () {
|
||||
inclusiveEndDates = false;
|
||||
topAxis = false;
|
||||
lastOrder = 0;
|
||||
links = {};
|
||||
links = new Map();
|
||||
commonClear();
|
||||
weekday = 'sunday';
|
||||
weekend = 'saturday';
|
||||
@@ -639,7 +639,7 @@ export const setLink = function (ids, _linkStr) {
|
||||
pushFun(id, () => {
|
||||
window.open(linkStr, '_self');
|
||||
});
|
||||
links[id] = linkStr;
|
||||
links.set(id, linkStr);
|
||||
}
|
||||
});
|
||||
setClass(ids, 'clickable');
|
||||
|
||||
@@ -475,14 +475,14 @@ export const draw = function (text, id, version, diagObj) {
|
||||
|
||||
rectangles
|
||||
.filter(function (d) {
|
||||
return links[d.id] !== undefined;
|
||||
return links.has(d.id);
|
||||
})
|
||||
.each(function (o) {
|
||||
var taskRect = doc.querySelector('#' + o.id);
|
||||
var taskText = doc.querySelector('#' + o.id + '-text');
|
||||
const oldParent = taskRect.parentNode;
|
||||
var Link = doc.createElement('a');
|
||||
Link.setAttribute('xlink:href', links[o.id]);
|
||||
Link.setAttribute('xlink:href', links.get(o.id));
|
||||
Link.setAttribute('target', '_top');
|
||||
oldParent.appendChild(Link);
|
||||
Link.appendChild(taskRect);
|
||||
@@ -724,6 +724,7 @@ export const draw = function (text, id, version, diagObj) {
|
||||
.attr('x', 10)
|
||||
.attr('y', function (d, i) {
|
||||
if (i > 0) {
|
||||
// biome-ignore lint/correctness/noUnreachable: <explanation>
|
||||
for (let j = 0; j < i; j++) {
|
||||
prevGap += numOccurrences[i - 1][1];
|
||||
return (d[1] * theGap) / 2 + prevGap * theGap + theTopPad;
|
||||
|
||||
@@ -157,30 +157,40 @@ describe('when parsing a gantt diagram it', function () {
|
||||
${'crit'} | ${false} | ${false} | ${true} | ${false}
|
||||
${'active'} | ${false} | ${false} | ${false} | ${true}
|
||||
${'crit,milestone,done'} | ${true} | ${true} | ${true} | ${false}
|
||||
`)('should handle a task with tags $tags', ({ tags, milestone, done, crit, active }) => {
|
||||
const str =
|
||||
'gantt\n' +
|
||||
'dateFormat YYYY-MM-DD\n' +
|
||||
'title Adding gantt diagram functionality to mermaid\n' +
|
||||
'section Documentation\n' +
|
||||
'test task:' +
|
||||
tags +
|
||||
', 2014-01-01, 2014-01-04';
|
||||
`)(
|
||||
'should handle a task with tags $tags',
|
||||
({
|
||||
tags,
|
||||
// Do not remove, these are used in eval.
|
||||
milestone,
|
||||
done,
|
||||
crit,
|
||||
active,
|
||||
}) => {
|
||||
const str =
|
||||
'gantt\n' +
|
||||
'dateFormat YYYY-MM-DD\n' +
|
||||
'title Adding gantt diagram functionality to mermaid\n' +
|
||||
'section Documentation\n' +
|
||||
'test task:' +
|
||||
tags +
|
||||
', 2014-01-01, 2014-01-04';
|
||||
|
||||
const allowedTags = ['active', 'done', 'crit', 'milestone'];
|
||||
const allowedTags = ['active', 'done', 'crit', 'milestone'];
|
||||
|
||||
expect(parserFnConstructor(str)).not.toThrow();
|
||||
expect(parserFnConstructor(str)).not.toThrow();
|
||||
|
||||
const tasks = parser.yy.getTasks();
|
||||
const tasks = parser.yy.getTasks();
|
||||
|
||||
allowedTags.forEach(function (t) {
|
||||
if (eval(t)) {
|
||||
expect(tasks[0][t]).toBeTruthy();
|
||||
} else {
|
||||
expect(tasks[0][t]).toBeFalsy();
|
||||
}
|
||||
});
|
||||
});
|
||||
allowedTags.forEach(function (t) {
|
||||
if (eval(t)) {
|
||||
expect(tasks[0][t]).toBeTruthy();
|
||||
} else {
|
||||
expect(tasks[0][t]).toBeFalsy();
|
||||
}
|
||||
});
|
||||
}
|
||||
);
|
||||
it('should parse callback specifier with no args', function () {
|
||||
spyOn(ganttDb, 'setClickEvent');
|
||||
const str =
|
||||
@@ -207,7 +217,6 @@ describe('when parsing a gantt diagram it', function () {
|
||||
'click cl2 call ganttTestClick("test0", test1, test2)\n';
|
||||
|
||||
expect(parserFnConstructor(str)).not.toThrow();
|
||||
const args = '"test1", "test2", "test3"';
|
||||
expect(ganttDb.setClickEvent).toHaveBeenCalledWith(
|
||||
'cl2',
|
||||
'ganttTestClick',
|
||||
@@ -256,4 +265,15 @@ row2`;
|
||||
expect(ganttDb.getWeekday()).toBe(day);
|
||||
}
|
||||
);
|
||||
|
||||
it.each(['__proto__', 'constructor'])('should allow for a link to %s id', (prop) => {
|
||||
expect(() =>
|
||||
parser.parse(`gantt
|
||||
dateFormat YYYY-MM-DD
|
||||
section Section
|
||||
A task :${prop}, 2024-10-01, 3d
|
||||
click ${prop} href "https://mermaid.js.org/"
|
||||
`)
|
||||
).not.toThrow();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -14,12 +14,12 @@ import {
|
||||
|
||||
let mainBranchName = getConfig().gitGraph.mainBranchName;
|
||||
let mainBranchOrder = getConfig().gitGraph.mainBranchOrder;
|
||||
let commits = {};
|
||||
let commits = new Map();
|
||||
let head = null;
|
||||
let branchesConfig = {};
|
||||
branchesConfig[mainBranchName] = { name: mainBranchName, order: mainBranchOrder };
|
||||
let branches = {};
|
||||
branches[mainBranchName] = head;
|
||||
let branchesConfig = new Map();
|
||||
branchesConfig.set(mainBranchName, { name: mainBranchName, order: mainBranchOrder });
|
||||
let branches = new Map();
|
||||
branches.set(mainBranchName, head);
|
||||
let curBranch = mainBranchName;
|
||||
let direction = 'LR';
|
||||
let seq = 0;
|
||||
@@ -46,11 +46,11 @@ function getId() {
|
||||
// if (Array.isArray(otherCommit.parent)) {
|
||||
// log.debug('In merge commit:', otherCommit.parent);
|
||||
// return (
|
||||
// isFastForwardable(currentCommit, commits[otherCommit.parent[0]]) ||
|
||||
// isFastForwardable(currentCommit, commits[otherCommit.parent[1]])
|
||||
// isFastForwardable(currentCommit, commits.get(otherCommit.parent[0])) ||
|
||||
// isFastForwardable(currentCommit, commits.get(otherCommit.parent[1]))
|
||||
// );
|
||||
// } else {
|
||||
// otherCommit = commits[otherCommit.parent];
|
||||
// otherCommit = commits.get(otherCommit.parent);
|
||||
// }
|
||||
// }
|
||||
// log.debug(currentCommit.id, otherCommit.id);
|
||||
@@ -118,16 +118,16 @@ export const commit = function (msg, id, type, tag) {
|
||||
branch: curBranch,
|
||||
};
|
||||
head = commit;
|
||||
commits[commit.id] = commit;
|
||||
branches[curBranch] = commit.id;
|
||||
commits.set(commit.id, commit);
|
||||
branches.set(curBranch, commit.id);
|
||||
log.debug('in pushCommit ' + commit.id);
|
||||
};
|
||||
|
||||
export const branch = function (name, order) {
|
||||
name = common.sanitizeText(name, getConfig());
|
||||
if (branches[name] === undefined) {
|
||||
branches[name] = head != null ? head.id : null;
|
||||
branchesConfig[name] = { name, order: order ? parseInt(order, 10) : null };
|
||||
if (!branches.has(name)) {
|
||||
branches.set(name, head != null ? head.id : null);
|
||||
branchesConfig.set(name, { name, order: order ? parseInt(order, 10) : null });
|
||||
checkout(name);
|
||||
log.debug('in createBranch');
|
||||
} else {
|
||||
@@ -147,12 +147,12 @@ export const branch = function (name, order) {
|
||||
}
|
||||
};
|
||||
|
||||
export const merge = function (otherBranch, custom_id, override_type, custom_tag) {
|
||||
export const merge = function (otherBranch, customId, overrideType, customTag) {
|
||||
otherBranch = common.sanitizeText(otherBranch, getConfig());
|
||||
custom_id = common.sanitizeText(custom_id, getConfig());
|
||||
customId = common.sanitizeText(customId, getConfig());
|
||||
|
||||
const currentCommit = commits[branches[curBranch]];
|
||||
const otherCommit = commits[branches[otherBranch]];
|
||||
const currentCommit = commits.get(branches.get(curBranch));
|
||||
const otherCommit = commits.get(branches.get(otherBranch));
|
||||
if (curBranch === otherBranch) {
|
||||
let error = new Error('Incorrect usage of "merge". Cannot merge a branch to itself');
|
||||
error.hash = {
|
||||
@@ -175,7 +175,7 @@ export const merge = function (otherBranch, custom_id, override_type, custom_tag
|
||||
expected: ['commit'],
|
||||
};
|
||||
throw error;
|
||||
} else if (branches[otherBranch] === undefined) {
|
||||
} else if (!branches.has(otherBranch)) {
|
||||
let error = new Error(
|
||||
'Incorrect usage of "merge". Branch to be merged (' + otherBranch + ') does not exist'
|
||||
);
|
||||
@@ -209,19 +209,19 @@ export const merge = function (otherBranch, custom_id, override_type, custom_tag
|
||||
expected: ['branch abc'],
|
||||
};
|
||||
throw error;
|
||||
} else if (custom_id && commits[custom_id] !== undefined) {
|
||||
} else if (customId && commits.has(customId)) {
|
||||
let error = new Error(
|
||||
'Incorrect usage of "merge". Commit with id:' +
|
||||
custom_id +
|
||||
customId +
|
||||
' already exists, use different custom Id'
|
||||
);
|
||||
error.hash = {
|
||||
text: 'merge ' + otherBranch + custom_id + override_type + custom_tag,
|
||||
token: 'merge ' + otherBranch + custom_id + override_type + custom_tag,
|
||||
text: 'merge ' + otherBranch + customId + overrideType + customTag,
|
||||
token: 'merge ' + otherBranch + customId + overrideType + customTag,
|
||||
line: '1',
|
||||
loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 },
|
||||
expected: [
|
||||
'merge ' + otherBranch + ' ' + custom_id + '_UNIQUE ' + override_type + ' ' + custom_tag,
|
||||
'merge ' + otherBranch + ' ' + customId + '_UNIQUE ' + overrideType + ' ' + customTag,
|
||||
],
|
||||
};
|
||||
|
||||
@@ -232,24 +232,24 @@ export const merge = function (otherBranch, custom_id, override_type, custom_tag
|
||||
// return;
|
||||
// }
|
||||
// if (isFastForwardable(currentCommit, otherCommit)) {
|
||||
// branches[curBranch] = branches[otherBranch];
|
||||
// head = commits[branches[curBranch]];
|
||||
// branches.set(curBranch, branches.get(otherBranch));
|
||||
// head = commits.get(branches.get(curBranch));
|
||||
// } else {
|
||||
// create merge commit
|
||||
const commit = {
|
||||
id: custom_id ? custom_id : seq + '-' + getId(),
|
||||
id: customId ? customId : seq + '-' + getId(),
|
||||
message: 'merged branch ' + otherBranch + ' into ' + curBranch,
|
||||
seq: seq++,
|
||||
parents: [head == null ? null : head.id, branches[otherBranch]],
|
||||
parents: [head == null ? null : head.id, branches.get(otherBranch)],
|
||||
branch: curBranch,
|
||||
type: commitType.MERGE,
|
||||
customType: override_type,
|
||||
customId: custom_id ? true : false,
|
||||
tag: custom_tag ? custom_tag : '',
|
||||
customType: overrideType,
|
||||
customId: customId ? true : false,
|
||||
tag: customTag ? customTag : '',
|
||||
};
|
||||
head = commit;
|
||||
commits[commit.id] = commit;
|
||||
branches[curBranch] = commit.id;
|
||||
commits.set(commit.id, commit);
|
||||
branches.set(curBranch, commit.id);
|
||||
// }
|
||||
log.debug(branches);
|
||||
log.debug('in mergeBranch');
|
||||
@@ -262,7 +262,7 @@ export const cherryPick = function (sourceId, targetId, tag, parentCommitId) {
|
||||
tag = common.sanitizeText(tag, getConfig());
|
||||
parentCommitId = common.sanitizeText(parentCommitId, getConfig());
|
||||
|
||||
if (!sourceId || commits[sourceId] === undefined) {
|
||||
if (!sourceId || !commits.has(sourceId)) {
|
||||
let error = new Error(
|
||||
'Incorrect usage of "cherryPick". Source commit id should exist and provided'
|
||||
);
|
||||
@@ -275,7 +275,7 @@ export const cherryPick = function (sourceId, targetId, tag, parentCommitId) {
|
||||
};
|
||||
throw error;
|
||||
}
|
||||
let sourceCommit = commits[sourceId];
|
||||
let sourceCommit = commits.get(sourceId);
|
||||
let sourceCommitBranch = sourceCommit.branch;
|
||||
if (
|
||||
parentCommitId &&
|
||||
@@ -292,7 +292,7 @@ export const cherryPick = function (sourceId, targetId, tag, parentCommitId) {
|
||||
);
|
||||
throw error;
|
||||
}
|
||||
if (!targetId || commits[targetId] === undefined) {
|
||||
if (!targetId || !commits.has(targetId)) {
|
||||
// cherry-pick source commit to current branch
|
||||
|
||||
if (sourceCommitBranch === curBranch) {
|
||||
@@ -308,7 +308,7 @@ export const cherryPick = function (sourceId, targetId, tag, parentCommitId) {
|
||||
};
|
||||
throw error;
|
||||
}
|
||||
const currentCommit = commits[branches[curBranch]];
|
||||
const currentCommit = commits.get(branches.get(curBranch));
|
||||
if (currentCommit === undefined || !currentCommit) {
|
||||
let error = new Error(
|
||||
'Incorrect usage of "cherry-pick". Current branch (' + curBranch + ')has no commits'
|
||||
@@ -336,15 +336,15 @@ export const cherryPick = function (sourceId, targetId, tag, parentCommitId) {
|
||||
}`,
|
||||
};
|
||||
head = commit;
|
||||
commits[commit.id] = commit;
|
||||
branches[curBranch] = commit.id;
|
||||
commits.set(commit.id, commit);
|
||||
branches.set(curBranch, commit.id);
|
||||
log.debug(branches);
|
||||
log.debug('in cherryPick');
|
||||
}
|
||||
};
|
||||
export const checkout = function (branch) {
|
||||
branch = common.sanitizeText(branch, getConfig());
|
||||
if (branches[branch] === undefined) {
|
||||
if (!branches.has(branch)) {
|
||||
let error = new Error(
|
||||
'Trying to checkout branch which is not yet created. (Help try using "branch ' + branch + '")'
|
||||
);
|
||||
@@ -360,8 +360,8 @@ export const checkout = function (branch) {
|
||||
//log.debug('in createBranch');
|
||||
} else {
|
||||
curBranch = branch;
|
||||
const id = branches[curBranch];
|
||||
head = commits[id];
|
||||
const id = branches.get(curBranch);
|
||||
head = commits.get(id);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -369,10 +369,10 @@ export const checkout = function (branch) {
|
||||
// log.debug('in reset', commitRef);
|
||||
// const ref = commitRef.split(':')[0];
|
||||
// let parentCount = parseInt(commitRef.split(':')[1]);
|
||||
// let commit = ref === 'HEAD' ? head : commits[branches[ref]];
|
||||
// let commit = ref === 'HEAD' ? head : commits.get(branches.get(ref));
|
||||
// log.debug(commit, parentCount);
|
||||
// while (parentCount > 0) {
|
||||
// commit = commits[commit.parent];
|
||||
// commit = commits.get(commit.parent);
|
||||
// parentCount--;
|
||||
// if (!commit) {
|
||||
// const err = 'Critical error - unique parent commit not found during reset';
|
||||
@@ -416,19 +416,19 @@ function prettyPrintCommitHistory(commitArr) {
|
||||
});
|
||||
const label = [line, commit.id, commit.seq];
|
||||
for (let branch in branches) {
|
||||
if (branches[branch] === commit.id) {
|
||||
if (branches.get(branch) === commit.id) {
|
||||
label.push(branch);
|
||||
}
|
||||
}
|
||||
log.debug(label.join(' '));
|
||||
if (commit.parents && commit.parents.length == 2) {
|
||||
const newCommit = commits[commit.parents[0]];
|
||||
const newCommit = commits.get(commit.parents[0]);
|
||||
upsert(commitArr, commit, newCommit);
|
||||
commitArr.push(commits[commit.parents[1]]);
|
||||
commitArr.push(commits.get(commit.parents[1]));
|
||||
} else if (commit.parents.length == 0) {
|
||||
return;
|
||||
} else {
|
||||
const nextCommit = commits[commit.parents];
|
||||
const nextCommit = commits.get(commit.parents);
|
||||
upsert(commitArr, commit, nextCommit);
|
||||
}
|
||||
commitArr = uniqBy(commitArr, (c) => c.id);
|
||||
@@ -442,21 +442,21 @@ export const prettyPrint = function () {
|
||||
};
|
||||
|
||||
export const clear = function () {
|
||||
commits = {};
|
||||
commits = new Map();
|
||||
head = null;
|
||||
let mainBranch = getConfig().gitGraph.mainBranchName;
|
||||
let mainBranchOrder = getConfig().gitGraph.mainBranchOrder;
|
||||
branches = {};
|
||||
branches[mainBranch] = null;
|
||||
branchesConfig = {};
|
||||
branchesConfig[mainBranch] = { name: mainBranch, order: mainBranchOrder };
|
||||
branches = new Map();
|
||||
branches.set(mainBranch, null);
|
||||
branchesConfig = new Map();
|
||||
branchesConfig.set(mainBranch, { name: mainBranch, order: mainBranchOrder });
|
||||
curBranch = mainBranch;
|
||||
seq = 0;
|
||||
commonClear();
|
||||
};
|
||||
|
||||
export const getBranchesAsObjArray = function () {
|
||||
const branchesArray = Object.values(branchesConfig)
|
||||
const branchesArray = [...branchesConfig.values()]
|
||||
.map((branchConfig, i) => {
|
||||
if (branchConfig.order !== null) {
|
||||
return branchConfig;
|
||||
@@ -479,9 +479,7 @@ export const getCommits = function () {
|
||||
return commits;
|
||||
};
|
||||
export const getCommitsArray = function () {
|
||||
const commitArr = Object.keys(commits).map(function (key) {
|
||||
return commits[key];
|
||||
});
|
||||
const commitArr = [...commits.values()];
|
||||
commitArr.forEach(function (o) {
|
||||
log.debug(o.id);
|
||||
});
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user