mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-08-15 14:29:25 +02:00
Compare commits
17 Commits
mermaid@11
...
sidv/biome
Author | SHA1 | Date | |
---|---|---|---|
![]() |
83fb2d933c | ||
![]() |
48303a030d | ||
![]() |
054ed6c69c | ||
![]() |
89e061aa51 | ||
![]() |
a1badd5167 | ||
![]() |
55a8e4cf7e | ||
![]() |
e7577ed51e | ||
![]() |
d2b42ebd74 | ||
![]() |
ba34386a69 | ||
![]() |
a23b891f20 | ||
![]() |
3a5793f948 | ||
![]() |
0a5315cd5a | ||
![]() |
98f32bfdfe | ||
![]() |
22a00a5f8b | ||
![]() |
3381717e86 | ||
![]() |
08dfdfed82 | ||
![]() |
2c80d806cc |
@@ -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}`,
|
||||
|
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`.'
|
||||
|
@@ -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';
|
||||
|
||||
/**
|
||||
|
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
|
||||
}
|
||||
}
|
16
package.json
16
package.json
@@ -25,8 +25,9 @@
|
||||
"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": "cross-env NODE_OPTIONS=--max_old_space_size=8192 eslint --cache --cache-strategy content . && pnpm lint",
|
||||
"lint:jison": "tsx ./scripts/jison/lint.mts",
|
||||
"contributors": "tsx scripts/updateContributors.ts",
|
||||
"cypress": "cypress run",
|
||||
@@ -51,18 +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",
|
||||
|
@@ -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"]
|
||||
}
|
||||
|
@@ -447,16 +447,19 @@ export const addEdges = function (edges, diagObj, graph, svg) {
|
||||
|
||||
/* eslint-disable no-fallthrough */
|
||||
switch (edge.type) {
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: <explanation>
|
||||
case 'double_arrow_cross':
|
||||
edgeData.arrowTypeStart = 'arrow_cross';
|
||||
case 'arrow_cross':
|
||||
edgeData.arrowTypeEnd = 'arrow_cross';
|
||||
break;
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: <explanation>
|
||||
case 'double_arrow_point':
|
||||
edgeData.arrowTypeStart = 'arrow_point';
|
||||
case 'arrow_point':
|
||||
edgeData.arrowTypeEnd = 'arrow_point';
|
||||
break;
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: <explanation>
|
||||
case 'double_arrow_circle':
|
||||
edgeData.arrowTypeStart = 'arrow_circle';
|
||||
case 'arrow_circle':
|
||||
|
@@ -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,14 +58,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.1",
|
||||
@@ -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"
|
||||
|
@@ -18,7 +18,7 @@ import { execFile } from 'node:child_process';
|
||||
import { readFile, writeFile } from 'node:fs/promises';
|
||||
import { join } from 'node:path';
|
||||
import { promisify } from 'node:util';
|
||||
import prettier from 'prettier';
|
||||
import { prettierConfig } from './prettier.js';
|
||||
|
||||
// Workaround for wrong AJV types, see
|
||||
// https://github.com/ajv-validator/ajv/issues/2132#issuecomment-1290409907
|
||||
@@ -141,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();
|
||||
});
|
||||
});
|
||||
|
@@ -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,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
|
||||
-----------------------^
|
||||
|
@@ -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');
|
||||
}
|
||||
|
@@ -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 });
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -246,16 +246,19 @@ export const addEdges = async function (edges, g, diagObj) {
|
||||
|
||||
/* eslint-disable no-fallthrough */
|
||||
switch (edge.type) {
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: <explanation>
|
||||
case 'double_arrow_cross':
|
||||
edgeData.arrowTypeStart = 'arrow_cross';
|
||||
case 'arrow_cross':
|
||||
edgeData.arrowTypeEnd = 'arrow_cross';
|
||||
break;
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: <explanation>
|
||||
case 'double_arrow_point':
|
||||
edgeData.arrowTypeStart = 'arrow_point';
|
||||
case 'arrow_point':
|
||||
edgeData.arrowTypeEnd = 'arrow_point';
|
||||
break;
|
||||
// biome-ignore lint/suspicious/noFallthroughSwitchClause: <explanation>
|
||||
case 'double_arrow_circle':
|
||||
edgeData.arrowTypeStart = 'arrow_circle';
|
||||
case 'arrow_circle':
|
||||
@@ -425,9 +428,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);
|
||||
|
@@ -339,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);
|
||||
@@ -429,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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -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'");
|
||||
});
|
||||
|
@@ -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',
|
||||
|
@@ -147,9 +147,9 @@ 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.get(branches.get(curBranch));
|
||||
const otherCommit = commits.get(branches.get(otherBranch));
|
||||
@@ -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.has(custom_id)) {
|
||||
} 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,
|
||||
],
|
||||
};
|
||||
|
||||
@@ -237,15 +237,15 @@ export const merge = function (otherBranch, custom_id, override_type, custom_tag
|
||||
// } 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.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.set(commit.id, commit);
|
||||
|
@@ -405,11 +405,11 @@ const drawCommits = (svg, commits, modifyGraph) => {
|
||||
text.attr('transform', 'rotate(' + -45 + ', ' + x + ', ' + y + ')');
|
||||
labelBkg.attr('transform', 'rotate(' + -45 + ', ' + x + ', ' + y + ')');
|
||||
} else {
|
||||
let r_x = -7.5 - ((bbox.width + 10) / 25) * 9.5;
|
||||
let r_y = 10 + (bbox.width / 25) * 8.5;
|
||||
let rX = -7.5 - ((bbox.width + 10) / 25) * 9.5;
|
||||
let rY = 10 + (bbox.width / 25) * 8.5;
|
||||
wrapper.attr(
|
||||
'transform',
|
||||
'translate(' + r_x + ', ' + r_y + ') rotate(' + -45 + ', ' + pos + ', ' + y + ')'
|
||||
'translate(' + rX + ', ' + rY + ') rotate(' + -45 + ', ' + pos + ', ' + y + ')'
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@@ -40,9 +40,9 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
|
||||
const db = diagObj.db as PieDB;
|
||||
const globalConfig: MermaidConfig = getConfig();
|
||||
const pieConfig: Required<PieDiagramConfig> = cleanAndMerge(db.getConfig(), globalConfig.pie);
|
||||
const MARGIN = 40;
|
||||
const LEGEND_RECT_SIZE = 18;
|
||||
const LEGEND_SPACING = 4;
|
||||
const margin = 40;
|
||||
const legendRectSize = 18;
|
||||
const legendSpacing = 4;
|
||||
const height = 450;
|
||||
const pieWidth: number = height;
|
||||
const svg: SVG = selectSvgElement(id);
|
||||
@@ -54,7 +54,7 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
|
||||
outerStrokeWidth ??= 2;
|
||||
|
||||
const textPosition: number = pieConfig.textPosition;
|
||||
const radius: number = Math.min(pieWidth, height) / 2 - MARGIN;
|
||||
const radius: number = Math.min(pieWidth, height) / 2 - margin;
|
||||
// Shape helper to build arcs:
|
||||
const arcGenerator: d3.Arc<unknown, d3.PieArcDatum<D3Section>> = arc<d3.PieArcDatum<D3Section>>()
|
||||
.innerRadius(0)
|
||||
@@ -139,25 +139,25 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
|
||||
.append('g')
|
||||
.attr('class', 'legend')
|
||||
.attr('transform', (_datum, index: number): string => {
|
||||
const height = LEGEND_RECT_SIZE + LEGEND_SPACING;
|
||||
const height = legendRectSize + legendSpacing;
|
||||
const offset = (height * color.domain().length) / 2;
|
||||
const horizontal = 12 * LEGEND_RECT_SIZE;
|
||||
const horizontal = 12 * legendRectSize;
|
||||
const vertical = index * height - offset;
|
||||
return 'translate(' + horizontal + ',' + vertical + ')';
|
||||
});
|
||||
|
||||
legend
|
||||
.append('rect')
|
||||
.attr('width', LEGEND_RECT_SIZE)
|
||||
.attr('height', LEGEND_RECT_SIZE)
|
||||
.attr('width', legendRectSize)
|
||||
.attr('height', legendRectSize)
|
||||
.style('fill', color)
|
||||
.style('stroke', color);
|
||||
|
||||
legend
|
||||
.data(arcs)
|
||||
.append('text')
|
||||
.attr('x', LEGEND_RECT_SIZE + LEGEND_SPACING)
|
||||
.attr('y', LEGEND_RECT_SIZE - LEGEND_SPACING)
|
||||
.attr('x', legendRectSize + legendSpacing)
|
||||
.attr('y', legendRectSize - legendSpacing)
|
||||
.text((datum: d3.PieArcDatum<D3Section>): string => {
|
||||
const { label, value } = datum.data;
|
||||
if (db.getShowData()) {
|
||||
@@ -173,7 +173,7 @@ export const draw: DrawDefinition = (text, id, _version, diagObj) => {
|
||||
.map((node) => (node as Element)?.getBoundingClientRect().width ?? 0)
|
||||
);
|
||||
|
||||
const totalWidth = pieWidth + MARGIN + LEGEND_RECT_SIZE + LEGEND_SPACING + longestTextWidth;
|
||||
const totalWidth = pieWidth + margin + legendRectSize + legendSpacing + longestTextWidth;
|
||||
|
||||
// Set viewBox
|
||||
svg.attr('viewBox', `0 0 ${totalWidth} ${height}`);
|
||||
|
@@ -45,13 +45,13 @@ class SankeyNode {
|
||||
constructor(public ID: string) {}
|
||||
}
|
||||
|
||||
const findOrCreateNode = (ID: string): SankeyNode => {
|
||||
ID = common.sanitizeText(ID, getConfig());
|
||||
const findOrCreateNode = (id: string): SankeyNode => {
|
||||
id = common.sanitizeText(id, getConfig());
|
||||
|
||||
let node = nodesMap.get(ID);
|
||||
let node = nodesMap.get(id);
|
||||
if (node === undefined) {
|
||||
node = new SankeyNode(ID);
|
||||
nodesMap.set(ID, node);
|
||||
node = new SankeyNode(id);
|
||||
nodesMap.set(id, node);
|
||||
nodes.push(node);
|
||||
}
|
||||
return node;
|
||||
|
@@ -49,11 +49,11 @@ export const drawPopup = function (elem, actor, minMenuWidth, textAttrs, forceMe
|
||||
rectElem.attr('height', rectData.height);
|
||||
rectElem.attr('rx', rectData.rx);
|
||||
rectElem.attr('ry', rectData.ry);
|
||||
let linkY = 20;
|
||||
if (links != null) {
|
||||
var linkY = 20;
|
||||
for (let key in links) {
|
||||
var linkElem = g.append('a');
|
||||
var sanitizedLink = sanitizeUrl(links[key]);
|
||||
const linkElem = g.append('a');
|
||||
const sanitizedLink = sanitizeUrl(links[key]);
|
||||
linkElem.attr('xlink:href', sanitizedLink);
|
||||
linkElem.attr('target', '_blank');
|
||||
|
||||
|
@@ -88,9 +88,9 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
expect(classes.get('exampleStyleClass').styles[0]).toEqual('background:#bbb');
|
||||
expect(classes.get('exampleStyleClass').styles[1]).toEqual('border:1px solid red');
|
||||
|
||||
const state_a = stateDb.getState('a');
|
||||
expect(state_a.classes.length).toEqual(1);
|
||||
expect(state_a.classes[0]).toEqual('exampleStyleClass');
|
||||
const stateA = stateDb.getState('a');
|
||||
expect(stateA.classes.length).toEqual(1);
|
||||
expect(stateA.classes[0]).toEqual('exampleStyleClass');
|
||||
});
|
||||
|
||||
it('can be applied to a state with an id containing _', function () {
|
||||
@@ -109,9 +109,9 @@ describe('ClassDefs and classes when parsing a State diagram', () => {
|
||||
expect(classes.get('exampleStyleClass').styles[0]).toBe('background:#bbb');
|
||||
expect(classes.get('exampleStyleClass').styles[1]).toBe('border:1px solid red');
|
||||
|
||||
const state_a_a = stateDiagram.parser.yy.getState('a_a');
|
||||
expect(state_a_a.classes.length).toEqual(1);
|
||||
expect(state_a_a.classes[0]).toEqual('exampleStyleClass');
|
||||
const stateAA = stateDiagram.parser.yy.getState('a_a');
|
||||
expect(stateAA.classes.length).toEqual(1);
|
||||
expect(stateAA.classes[0]).toEqual('exampleStyleClass');
|
||||
});
|
||||
|
||||
describe('::: syntax', () => {
|
||||
|
@@ -130,12 +130,12 @@ describe('state diagram V2, ', function () {
|
||||
stateDiagram.parser.yy.extract(stateDiagram.parser.yy.getRootDocV2());
|
||||
|
||||
const rels = stateDb.getRelations();
|
||||
const rel_1_2 = rels.find((rel) => rel.id1 === 'State1' && rel.id2 === 'State2');
|
||||
expect(rel_1_2.relationTitle).toEqual('Transition 1');
|
||||
const rel_1_3 = rels.find((rel) => rel.id1 === 'State1' && rel.id2 === 'State3');
|
||||
expect(rel_1_3.relationTitle).toEqual('Transition 2');
|
||||
const rel_1_4 = rels.find((rel) => rel.id1 === 'State1' && rel.id2 === 'State4');
|
||||
expect(rel_1_4.relationTitle).toEqual('Transition 3');
|
||||
const rel12 = rels.find((rel) => rel.id1 === 'State1' && rel.id2 === 'State2');
|
||||
expect(rel12.relationTitle).toEqual('Transition 1');
|
||||
const rel13 = rels.find((rel) => rel.id1 === 'State1' && rel.id2 === 'State3');
|
||||
expect(rel13.relationTitle).toEqual('Transition 2');
|
||||
const rel14 = rels.find((rel) => rel.id1 === 'State1' && rel.id2 === 'State4');
|
||||
expect(rel14.relationTitle).toEqual('Transition 3');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -408,10 +408,10 @@ describe('state diagram V2, ', function () {
|
||||
expect(states.get('Active').doc[0].id).toEqual('Idle');
|
||||
|
||||
const rels = stateDb.getRelations();
|
||||
const rel_Inactive_Idle = rels.find((rel) => rel.id1 === 'Inactive' && rel.id2 === 'Idle');
|
||||
expect(rel_Inactive_Idle.relationTitle).toEqual('ACT');
|
||||
const rel_Active_Active = rels.find((rel) => rel.id1 === 'Active' && rel.id2 === 'Active');
|
||||
expect(rel_Active_Active.relationTitle).toEqual('LOG');
|
||||
const relInactiveIdle = rels.find((rel) => rel.id1 === 'Inactive' && rel.id2 === 'Idle');
|
||||
expect(relInactiveIdle.relationTitle).toEqual('ACT');
|
||||
const relActiveActive = rels.find((rel) => rel.id1 === 'Active' && rel.id2 === 'Active');
|
||||
expect(relActiveActive.relationTitle).toEqual('LOG');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -362,8 +362,7 @@ const setupDoc = (g, parentParsedItem, doc, diagramStates, diagramDb, altFlag) =
|
||||
const getDir = (parsedItem, defaultDir = DEFAULT_NESTED_DOC_DIR) => {
|
||||
let dir = defaultDir;
|
||||
if (parsedItem.doc) {
|
||||
for (let i = 0; i < parsedItem.doc.length; i++) {
|
||||
const parsedItemDoc = parsedItem.doc[i];
|
||||
for (const parsedItemDoc of parsedItem.doc) {
|
||||
if (parsedItemDoc.stmt === 'dir') {
|
||||
dir = parsedItemDoc.value;
|
||||
}
|
||||
|
@@ -15,9 +15,7 @@ const genSections = (options) => {
|
||||
for (let i = 0; i < options.THEME_COLOR_LIMIT; i++) {
|
||||
const sw = '' + (17 - 3 * i);
|
||||
sections += `
|
||||
.section-${i - 1} rect, .section-${i - 1} path, .section-${i - 1} circle, .section-${
|
||||
i - 1
|
||||
} path {
|
||||
.section-${i - 1} rect, .section-${i - 1} path, .section-${i - 1} circle, .section-${i - 1} path {
|
||||
fill: ${options['cScale' + i]};
|
||||
}
|
||||
.section-${i - 1} text {
|
||||
|
@@ -29,7 +29,7 @@ export const draw = function (text: string, id: string, version: string, diagObj
|
||||
//1. Fetch the configuration
|
||||
const conf = getConfig();
|
||||
// @ts-expect-error - wrong config?
|
||||
const LEFT_MARGIN = conf.leftMargin ?? 50;
|
||||
const leftMargin = conf.leftMargin ?? 50;
|
||||
|
||||
log.debug('timeline', diagObj.db);
|
||||
|
||||
@@ -68,7 +68,7 @@ export const draw = function (text: string, id: string, version: string, diagObj
|
||||
//let sectionBeginX = 0;
|
||||
let depthY = 0;
|
||||
let sectionBeginY = 0;
|
||||
let masterX = 50 + LEFT_MARGIN;
|
||||
let masterX = 50 + leftMargin;
|
||||
//sectionBeginX = masterX;
|
||||
let masterY = 50;
|
||||
sectionBeginY = 50;
|
||||
@@ -115,8 +115,7 @@ export const draw = function (text: string, id: string, version: string, diagObj
|
||||
maxEventCount = Math.max(maxEventCount, task.events.length);
|
||||
//calculate maxEventLineLength
|
||||
let maxEventLineLengthTemp = 0;
|
||||
for (let j = 0; j < task.events.length; j++) {
|
||||
const event = task.events[j];
|
||||
for (const event of task.events) {
|
||||
const eventNode = {
|
||||
descr: event,
|
||||
section: task.section,
|
||||
@@ -203,7 +202,7 @@ export const draw = function (text: string, id: string, version: string, diagObj
|
||||
svg
|
||||
.append('text')
|
||||
.text(title)
|
||||
.attr('x', box.width / 2 - LEFT_MARGIN)
|
||||
.attr('x', box.width / 2 - leftMargin)
|
||||
.attr('font-size', '4ex')
|
||||
.attr('font-weight', 'bold')
|
||||
.attr('y', 20);
|
||||
@@ -215,9 +214,9 @@ export const draw = function (text: string, id: string, version: string, diagObj
|
||||
// Draw activity line
|
||||
lineWrapper
|
||||
.append('line')
|
||||
.attr('x1', LEFT_MARGIN)
|
||||
.attr('x1', leftMargin)
|
||||
.attr('y1', depthY) // One section head + one task + margins
|
||||
.attr('x2', box.width + 3 * LEFT_MARGIN) // Subtract stroke width so arrow point is retained
|
||||
.attr('x2', box.width + 3 * leftMargin) // Subtract stroke width so arrow point is retained
|
||||
.attr('y2', depthY)
|
||||
.attr('stroke-width', 4)
|
||||
.attr('stroke', 'black')
|
||||
|
@@ -75,8 +75,8 @@ function textSanitizer(text: string) {
|
||||
return sanitizeText(text.trim(), config);
|
||||
}
|
||||
|
||||
function setTmpSVGG(SVGG: Group) {
|
||||
tmpSVGGroup = SVGG;
|
||||
function setTmpSVGG(svgg: Group) {
|
||||
tmpSVGGroup = svgg;
|
||||
}
|
||||
function setOrientation(orientation: string) {
|
||||
if (orientation === 'horizontal') {
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { defineConfig, MarkdownOptions } from 'vitepress';
|
||||
import { defineConfig, type MarkdownOptions } from 'vitepress';
|
||||
import { version } from '../../../package.json';
|
||||
import MermaidExample from './mermaid-markdown-all.js';
|
||||
|
||||
|
@@ -1,5 +1,5 @@
|
||||
import contributorUsernamesJson from './contributor-names.json';
|
||||
import { CoreTeam, knut, plainTeamMembers } from './teamMembers.js';
|
||||
import { type CoreTeam, knut, plainTeamMembers } from './teamMembers.js';
|
||||
|
||||
const contributorUsernames: string[] = contributorUsernamesJson;
|
||||
|
||||
|
@@ -32,7 +32,7 @@ async function fetchAvatars() {
|
||||
});
|
||||
|
||||
contributors = JSON.parse(await readFile(pathContributors, { encoding: 'utf-8' }));
|
||||
let avatars = contributors.map((name) => {
|
||||
const avatars = contributors.map((name) => {
|
||||
download(`https://github.com/${name}.png?size=100`, getAvatarPath(name));
|
||||
});
|
||||
|
||||
|
@@ -61,7 +61,7 @@ onMounted(async () => {
|
||||
|
||||
//refresh images on first render
|
||||
const hasImages = /<img([\w\W]+?)>/.exec(code.value)?.length > 0;
|
||||
if (hasImages)
|
||||
if (hasImages) {
|
||||
setTimeout(() => {
|
||||
let imgElements = document.getElementsByTagName('img');
|
||||
let imgs = Array.from(imgElements);
|
||||
@@ -80,6 +80,7 @@ onMounted(async () => {
|
||||
});
|
||||
}
|
||||
}, 100);
|
||||
}
|
||||
});
|
||||
|
||||
onUnmounted(() => mut.disconnect());
|
||||
|
@@ -170,8 +170,9 @@ describe('when using mermaid and ', () => {
|
||||
).resolves.not.toThrow();
|
||||
});
|
||||
it('should throw for an invalid flow definition', async () => {
|
||||
await expect(mermaid.parse('graph TQ;A--x|text including URL space|B;')).rejects
|
||||
.toThrowErrorMatchingInlineSnapshot(`
|
||||
await expect(
|
||||
mermaid.parse('graph TQ;A--x|text including URL space|B;')
|
||||
).rejects.toThrowErrorMatchingInlineSnapshot(`
|
||||
[Error: Lexical error on line 1. Unrecognized text.
|
||||
graph TQ;A--x|text includ
|
||||
-----^]
|
||||
|
@@ -98,7 +98,7 @@ const run = async function (
|
||||
}
|
||||
) {
|
||||
try {
|
||||
await runThrowsErrors(options);
|
||||
await runThrowsErrors(42);
|
||||
} catch (e) {
|
||||
if (isDetailedError(e)) {
|
||||
log.error(e.str);
|
||||
|
@@ -207,7 +207,7 @@ describe('mermaidAPI', () => {
|
||||
});
|
||||
|
||||
it('uses the height and appends px from the svgElement given', () => {
|
||||
const faux_svgElement = {
|
||||
const fauxSvgElement = {
|
||||
viewBox: {
|
||||
baseVal: {
|
||||
height: 42,
|
||||
@@ -215,7 +215,7 @@ describe('mermaidAPI', () => {
|
||||
},
|
||||
};
|
||||
|
||||
const result = putIntoIFrame(inputSvgCode, faux_svgElement);
|
||||
const result = putIntoIFrame(inputSvgCode, fauxSvgElement);
|
||||
expect(result).toMatch(/style="(.*)height:42px;/);
|
||||
});
|
||||
});
|
||||
@@ -226,54 +226,54 @@ describe('mermaidAPI', () => {
|
||||
|
||||
describe('appendDivSvgG', () => {
|
||||
const fauxGNode = new MockedD3();
|
||||
const parent_append_spy = vi.spyOn(fauxParentNode, 'append').mockReturnValue(fauxEnclosingDiv);
|
||||
const div_append_spy = vi.spyOn(fauxEnclosingDiv, 'append').mockReturnValue(fauxSvgNode);
|
||||
const parentAppendSpy = vi.spyOn(fauxParentNode, 'append').mockReturnValue(fauxEnclosingDiv);
|
||||
const divAppendSpy = vi.spyOn(fauxEnclosingDiv, 'append').mockReturnValue(fauxSvgNode);
|
||||
// @ts-ignore @todo TODO why is this getting a type error?
|
||||
const div_attr_spy = vi.spyOn(fauxEnclosingDiv, 'attr').mockReturnValue(fauxEnclosingDiv);
|
||||
const svg_append_spy = vi.spyOn(fauxSvgNode, 'append').mockReturnValue(fauxGNode);
|
||||
const divAttrSpy = vi.spyOn(fauxEnclosingDiv, 'attr').mockReturnValue(fauxEnclosingDiv);
|
||||
const svgAppendSpy = vi.spyOn(fauxSvgNode, 'append').mockReturnValue(fauxGNode);
|
||||
// @ts-ignore @todo TODO why is this getting a type error?
|
||||
const svg_attr_spy = vi.spyOn(fauxSvgNode, 'attr').mockReturnValue(fauxSvgNode);
|
||||
const svgAttrSpy = vi.spyOn(fauxSvgNode, 'attr').mockReturnValue(fauxSvgNode);
|
||||
|
||||
// cspell:ignore dthe
|
||||
|
||||
it('appends a div node', () => {
|
||||
appendDivSvgG(fauxParentNode, 'theId', 'dtheId');
|
||||
expect(parent_append_spy).toHaveBeenCalledWith('div');
|
||||
expect(div_append_spy).toHaveBeenCalledWith('svg');
|
||||
expect(parentAppendSpy).toHaveBeenCalledWith('div');
|
||||
expect(divAppendSpy).toHaveBeenCalledWith('svg');
|
||||
});
|
||||
it('the id for the div is "d" with the id appended', () => {
|
||||
appendDivSvgG(fauxParentNode, 'theId', 'dtheId');
|
||||
expect(div_attr_spy).toHaveBeenCalledWith('id', 'dtheId');
|
||||
expect(divAttrSpy).toHaveBeenCalledWith('id', 'dtheId');
|
||||
});
|
||||
|
||||
it('sets the style for the div if one is given', () => {
|
||||
appendDivSvgG(fauxParentNode, 'theId', 'dtheId', 'given div style', 'given x link');
|
||||
expect(div_attr_spy).toHaveBeenCalledWith('style', 'given div style');
|
||||
expect(divAttrSpy).toHaveBeenCalledWith('style', 'given div style');
|
||||
});
|
||||
|
||||
it('appends a svg node to the div node', () => {
|
||||
appendDivSvgG(fauxParentNode, 'theId', 'dtheId');
|
||||
expect(div_attr_spy).toHaveBeenCalledWith('id', 'dtheId');
|
||||
expect(divAttrSpy).toHaveBeenCalledWith('id', 'dtheId');
|
||||
});
|
||||
it('sets the svg width to 100%', () => {
|
||||
appendDivSvgG(fauxParentNode, 'theId', 'dtheId');
|
||||
expect(svg_attr_spy).toHaveBeenCalledWith('width', '100%');
|
||||
expect(svgAttrSpy).toHaveBeenCalledWith('width', '100%');
|
||||
});
|
||||
it('the svg id is the id', () => {
|
||||
appendDivSvgG(fauxParentNode, 'theId', 'dtheId');
|
||||
expect(svg_attr_spy).toHaveBeenCalledWith('id', 'theId');
|
||||
expect(svgAttrSpy).toHaveBeenCalledWith('id', 'theId');
|
||||
});
|
||||
it('the svg xml namespace is the 2000 standard', () => {
|
||||
appendDivSvgG(fauxParentNode, 'theId', 'dtheId');
|
||||
expect(svg_attr_spy).toHaveBeenCalledWith('xmlns', 'http://www.w3.org/2000/svg');
|
||||
expect(svgAttrSpy).toHaveBeenCalledWith('xmlns', 'http://www.w3.org/2000/svg');
|
||||
});
|
||||
it('sets the svg xlink if one is given', () => {
|
||||
appendDivSvgG(fauxParentNode, 'theId', 'dtheId', 'div style', 'given x link');
|
||||
expect(svg_attr_spy).toHaveBeenCalledWith('xmlns:xlink', 'given x link');
|
||||
expect(svgAttrSpy).toHaveBeenCalledWith('xmlns:xlink', 'given x link');
|
||||
});
|
||||
it('appends a g (group) node to the svg node', () => {
|
||||
appendDivSvgG(fauxParentNode, 'theId', 'dtheId');
|
||||
expect(svg_append_spy).toHaveBeenCalledWith('g');
|
||||
expect(svgAppendSpy).toHaveBeenCalledWith('g');
|
||||
});
|
||||
it('returns the given parentRoot d3 nodes', () => {
|
||||
expect(appendDivSvgG(fauxParentNode, 'theId', 'dtheId')).toEqual(fauxParentNode);
|
||||
@@ -283,7 +283,7 @@ describe('mermaidAPI', () => {
|
||||
describe('createCssStyles', () => {
|
||||
const serif = 'serif';
|
||||
const sansSerif = 'sans-serif';
|
||||
const mocked_config_with_htmlLabels: MermaidConfig = {
|
||||
const mockedConfigWithHtmlLabels: MermaidConfig = {
|
||||
themeCSS: 'default',
|
||||
fontFamily: serif,
|
||||
altFontFamily: sansSerif,
|
||||
@@ -291,15 +291,15 @@ describe('mermaidAPI', () => {
|
||||
};
|
||||
|
||||
it('gets the cssStyles from the theme', () => {
|
||||
const styles = createCssStyles(mocked_config_with_htmlLabels, null);
|
||||
const styles = createCssStyles(mockedConfigWithHtmlLabels, null);
|
||||
expect(styles).toMatch(/^\ndefault(.*)/);
|
||||
});
|
||||
it('gets the fontFamily from the config', () => {
|
||||
const styles = createCssStyles(mocked_config_with_htmlLabels, new Map());
|
||||
const styles = createCssStyles(mockedConfigWithHtmlLabels, new Map());
|
||||
expect(styles).toMatch(/(.*)\n:root { --mermaid-font-family: serif(.*)/);
|
||||
});
|
||||
it('gets the alt fontFamily from the config', () => {
|
||||
const styles = createCssStyles(mocked_config_with_htmlLabels, undefined);
|
||||
const styles = createCssStyles(mockedConfigWithHtmlLabels, undefined);
|
||||
expect(styles).toMatch(/(.*)\n:root { --mermaid-alt-font-family: sans-serif(.*)/);
|
||||
});
|
||||
|
||||
@@ -310,13 +310,13 @@ describe('mermaidAPI', () => {
|
||||
const classDefs = { classDef1, classDef2, classDef3 };
|
||||
|
||||
describe('the graph supports classDefs', () => {
|
||||
const REGEXP_SPECIALS = ['^', '$', '?', '(', '{', '[', '.', '*', '!'];
|
||||
const regexpSpecials = ['^', '$', '?', '(', '{', '[', '.', '*', '!'];
|
||||
|
||||
// prefix any special RegExp characters in the given string with a \ so we can use the literal character in a RegExp
|
||||
function escapeForRegexp(str: string) {
|
||||
const strChars = [...str]; // split into array of every char
|
||||
const strEscaped = strChars.map((char) => {
|
||||
if (REGEXP_SPECIALS.includes(char)) {
|
||||
if (regexpSpecials.includes(char)) {
|
||||
return `\\${char}`;
|
||||
} else {
|
||||
return char;
|
||||
@@ -326,7 +326,7 @@ describe('mermaidAPI', () => {
|
||||
}
|
||||
|
||||
// Common test expecting given styles to have .classDef1 and .classDef2 statements but not .classDef3
|
||||
function expect_styles_matchesHtmlElements(styles: string, htmlElement: string) {
|
||||
function expectStylesMatchesHtmlElements(styles: string, htmlElement: string) {
|
||||
expect(styles).toMatch(
|
||||
new RegExp(
|
||||
`\\.classDef1 ${escapeForRegexp(
|
||||
@@ -344,7 +344,7 @@ describe('mermaidAPI', () => {
|
||||
}
|
||||
|
||||
// Common test expecting given textStyles to have .classDef2 and .classDef3 statements but not .classDef1
|
||||
function expect_textStyles_matchesHtmlElements(textStyles: string, htmlElement: string) {
|
||||
function expectTextStylesMatchesHtmlElements(textStyles: string, htmlElement: string) {
|
||||
expect(textStyles).toMatch(
|
||||
new RegExp(
|
||||
`\\.classDef2 ${escapeForRegexp(htmlElement)} \\{ textStyle2-1 !important; }`
|
||||
@@ -367,7 +367,7 @@ describe('mermaidAPI', () => {
|
||||
}
|
||||
|
||||
// common suite and tests to verify that the right styles are created with the right htmlElements
|
||||
function expect_correct_styles_with_htmlElements(mocked_config: MermaidConfig) {
|
||||
function expectCorrectStylesWithHtmlElements(mockedConfig: MermaidConfig) {
|
||||
describe('creates styles for "> *" and "span" elements', () => {
|
||||
const htmlElements = ['> *', 'span'];
|
||||
|
||||
@@ -375,21 +375,21 @@ describe('mermaidAPI', () => {
|
||||
// @todo TODO Can't figure out how to spy on the cssImportantStyles method.
|
||||
// That would be a much better approach than manually checking the result
|
||||
|
||||
const styles = createCssStyles(mocked_config, new Map(Object.entries(classDefs)));
|
||||
const styles = createCssStyles(mockedConfig, new Map(Object.entries(classDefs)));
|
||||
htmlElements.forEach((htmlElement) => {
|
||||
expect_styles_matchesHtmlElements(styles, htmlElement);
|
||||
expectStylesMatchesHtmlElements(styles, htmlElement);
|
||||
});
|
||||
expect_textStyles_matchesHtmlElements(styles, 'tspan');
|
||||
expectTextStylesMatchesHtmlElements(styles, 'tspan');
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
it('there are htmlLabels in the configuration', () => {
|
||||
expect_correct_styles_with_htmlElements(mocked_config_with_htmlLabels);
|
||||
expectCorrectStylesWithHtmlElements(mockedConfigWithHtmlLabels);
|
||||
});
|
||||
|
||||
it('there are flowchart.htmlLabels in the configuration', () => {
|
||||
const mocked_config_flowchart_htmlLabels: MermaidConfig = {
|
||||
const mockedConfigFlowchartHtmlLabels: MermaidConfig = {
|
||||
themeCSS: 'default',
|
||||
fontFamily: 'serif',
|
||||
altFontFamily: 'sans-serif',
|
||||
@@ -397,11 +397,11 @@ describe('mermaidAPI', () => {
|
||||
htmlLabels: true,
|
||||
},
|
||||
};
|
||||
expect_correct_styles_with_htmlElements(mocked_config_flowchart_htmlLabels);
|
||||
expectCorrectStylesWithHtmlElements(mockedConfigFlowchartHtmlLabels);
|
||||
});
|
||||
|
||||
describe('no htmlLabels in the configuration', () => {
|
||||
const mocked_config_no_htmlLabels = {
|
||||
const mockedConfigNoHtmlLabels = {
|
||||
themeCSS: 'default',
|
||||
fontFamily: 'serif',
|
||||
altFontFamily: 'sans-serif',
|
||||
@@ -414,13 +414,13 @@ describe('mermaidAPI', () => {
|
||||
// TODO Can't figure out how to spy on the cssImportantStyles method. That would be a much better approach than manually checking the result.
|
||||
|
||||
const styles = createCssStyles(
|
||||
mocked_config_no_htmlLabels,
|
||||
mockedConfigNoHtmlLabels,
|
||||
new Map(Object.entries(classDefs))
|
||||
);
|
||||
htmlElements.forEach((htmlElement) => {
|
||||
expect_styles_matchesHtmlElements(styles, htmlElement);
|
||||
expectStylesMatchesHtmlElements(styles, htmlElement);
|
||||
});
|
||||
expect_textStyles_matchesHtmlElements(styles, 'tspan');
|
||||
expectTextStylesMatchesHtmlElements(styles, 'tspan');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -692,8 +692,9 @@ describe('mermaidAPI', () => {
|
||||
).resolves.toBe(false);
|
||||
});
|
||||
it('resolves for valid definition', async () => {
|
||||
await expect(mermaidAPI.parse('graph TD;A--x|text including URL space|B;')).resolves
|
||||
.toMatchInlineSnapshot(`
|
||||
await expect(
|
||||
mermaidAPI.parse('graph TD;A--x|text including URL space|B;')
|
||||
).resolves.toMatchInlineSnapshot(`
|
||||
{
|
||||
"diagramType": "flowchart-v2",
|
||||
}
|
||||
@@ -748,15 +749,12 @@ describe('mermaidAPI', () => {
|
||||
const expectedDiagramType = testedDiagram.expectedType;
|
||||
|
||||
it('should set aria-roledescription to the diagram type AND should call addSVGa11yTitleDescription', async () => {
|
||||
const a11yDiagramInfo_spy = vi.spyOn(accessibility, 'setA11yDiagramInfo');
|
||||
const a11yTitleDesc_spy = vi.spyOn(accessibility, 'addSVGa11yTitleDescription');
|
||||
const a11yDiagramInfoSpy = vi.spyOn(accessibility, 'setA11yDiagramInfo');
|
||||
const a11yTitleDescSpy = vi.spyOn(accessibility, 'addSVGa11yTitleDescription');
|
||||
const result = await mermaidAPI.render(id, diagramText);
|
||||
expect(result.diagramType).toBe(expectedDiagramType);
|
||||
expect(a11yDiagramInfo_spy).toHaveBeenCalledWith(
|
||||
expect.anything(),
|
||||
expectedDiagramType
|
||||
);
|
||||
expect(a11yTitleDesc_spy).toHaveBeenCalled();
|
||||
expect(a11yDiagramInfoSpy).toHaveBeenCalledWith(expect.anything(), expectedDiagramType);
|
||||
expect(a11yTitleDescSpy).toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -363,14 +363,14 @@ const render = async function (
|
||||
|
||||
const idSelector = '#' + id;
|
||||
const iFrameID = 'i' + id;
|
||||
const iFrameID_selector = '#' + iFrameID;
|
||||
const iFrameIdSelector = '#' + iFrameID;
|
||||
const enclosingDivID = 'd' + id;
|
||||
const enclosingDivID_selector = '#' + enclosingDivID;
|
||||
const enclosingDivIdSelector = '#' + enclosingDivID;
|
||||
|
||||
const removeTempElements = () => {
|
||||
// -------------------------------------------------------------------------------
|
||||
// Remove the temporary HTML element if appropriate
|
||||
const tmpElementSelector = isSandboxed ? iFrameID_selector : enclosingDivID_selector;
|
||||
const tmpElementSelector = isSandboxed ? iFrameIdSelector : enclosingDivIdSelector;
|
||||
const node = select(tmpElementSelector).node();
|
||||
if (node && 'remove' in node) {
|
||||
node.remove();
|
||||
@@ -442,7 +442,7 @@ const render = async function (
|
||||
}
|
||||
|
||||
// Get the temporary div element containing the svg
|
||||
const element = root.select(enclosingDivID_selector).node();
|
||||
const element = root.select(enclosingDivIdSelector).node();
|
||||
const diagramType = diag.type;
|
||||
|
||||
// -------------------------------------------------------------------------------
|
||||
@@ -473,7 +473,7 @@ const render = async function (
|
||||
}
|
||||
|
||||
// This is the d3 node for the svg element
|
||||
const svgNode = root.select(`${enclosingDivID_selector} svg`);
|
||||
const svgNode = root.select(`${enclosingDivIdSelector} svg`);
|
||||
const a11yTitle: string | undefined = diag.db.getAccTitle?.();
|
||||
const a11yDescr: string | undefined = diag.db.getAccDescription?.();
|
||||
addA11yInfo(diagramType, svgNode, a11yTitle, a11yDescr);
|
||||
@@ -482,13 +482,13 @@ const render = async function (
|
||||
root.select(`[id="${id}"]`).selectAll('foreignobject > *').attr('xmlns', XMLNS_XHTML_STD);
|
||||
|
||||
// Fix for when the base tag is used
|
||||
let svgCode: string = root.select(enclosingDivID_selector).node().innerHTML;
|
||||
let svgCode: string = root.select(enclosingDivIdSelector).node().innerHTML;
|
||||
|
||||
log.debug('config.arrowMarkerAbsolute', config.arrowMarkerAbsolute);
|
||||
svgCode = cleanUpSvgCode(svgCode, isSandboxed, evaluate(config.arrowMarkerAbsolute));
|
||||
|
||||
if (isSandboxed) {
|
||||
const svgEl = root.select(enclosingDivID_selector + ' svg').node();
|
||||
const svgEl = root.select(enclosingDivIdSelector + ' svg').node();
|
||||
svgCode = putIntoIFrame(svgCode, svgEl);
|
||||
} else if (!isLooseSecurityLevel) {
|
||||
// Sanitize the svgCode using DOMPurify
|
||||
|
@@ -74,6 +74,7 @@ export class MockedD3 {
|
||||
attr(attrName: string): undefined | string;
|
||||
attr(attrName: string, attrValue: string): MockedD3;
|
||||
attr(attrName: string, attrValue?: string): undefined | string | MockedD3 {
|
||||
// biome-ignore lint/style/noArguments: <explanation>
|
||||
if (arguments.length === 1) {
|
||||
return this.attribs.get(attrName);
|
||||
} else {
|
||||
@@ -105,8 +106,8 @@ export class MockedD3 {
|
||||
// Real implementation returns an HTML Element
|
||||
public node = vi.fn().mockImplementation(() => {
|
||||
const topElem = this._containingHTMLdoc.createElement('svg');
|
||||
const elem_svgChild = this._containingHTMLdoc.createElement('svg'); // another svg element
|
||||
topElem.appendChild(elem_svgChild);
|
||||
const elemSvgChild = this._containingHTMLdoc.createElement('svg'); // another svg element
|
||||
topElem.appendChild(elemSvgChild);
|
||||
return topElem;
|
||||
});
|
||||
|
||||
|
@@ -11,51 +11,51 @@ addDiagrams();
|
||||
|
||||
describe('when assignWithDepth: should merge objects within objects', function () {
|
||||
it('should handle simple, depth:1 types (identity)', function () {
|
||||
const config_0 = { foo: 'bar', bar: 0 };
|
||||
const config_1 = { foo: 'bar', bar: 0 };
|
||||
const result = assignWithDepth(config_0, config_1);
|
||||
expect(result).toEqual(config_1);
|
||||
const config0 = { foo: 'bar', bar: 0 };
|
||||
const config1 = { foo: 'bar', bar: 0 };
|
||||
const result = assignWithDepth(config0, config1);
|
||||
expect(result).toEqual(config1);
|
||||
});
|
||||
it('should handle simple, depth:1 types (dst: undefined)', function () {
|
||||
const config_0 = undefined;
|
||||
const config_1 = { foo: 'bar', bar: 0 };
|
||||
const result = assignWithDepth(config_0, config_1);
|
||||
expect(result).toEqual(config_1);
|
||||
const config0 = undefined;
|
||||
const config1 = { foo: 'bar', bar: 0 };
|
||||
const result = assignWithDepth(config0, config1);
|
||||
expect(result).toEqual(config1);
|
||||
});
|
||||
it('should handle simple, depth:1 types (src: undefined)', function () {
|
||||
const config_0 = { foo: 'bar', bar: 0 };
|
||||
const config_1 = undefined;
|
||||
const result = assignWithDepth(config_0, config_1);
|
||||
expect(result).toEqual(config_0);
|
||||
const config0 = { foo: 'bar', bar: 0 };
|
||||
const config1 = undefined;
|
||||
const result = assignWithDepth(config0, config1);
|
||||
expect(result).toEqual(config0);
|
||||
});
|
||||
it('should handle simple, depth:1 types (merge)', function () {
|
||||
const config_0 = { foo: 'bar', bar: 0 };
|
||||
const config_1 = { foo: 'foo' };
|
||||
const result = assignWithDepth(config_0, config_1);
|
||||
const config0 = { foo: 'bar', bar: 0 };
|
||||
const config1 = { foo: 'foo' };
|
||||
const result = assignWithDepth(config0, config1);
|
||||
expect(result).toEqual({ foo: 'foo', bar: 0 });
|
||||
});
|
||||
it('should handle depth:2 types (dst: orphan)', function () {
|
||||
const config_0 = { foo: 'bar', bar: { foo: 'bar' } };
|
||||
const config_1 = { foo: 'bar' };
|
||||
const result = assignWithDepth(config_0, config_1);
|
||||
expect(result).toEqual(config_0);
|
||||
const config0 = { foo: 'bar', bar: { foo: 'bar' } };
|
||||
const config1 = { foo: 'bar' };
|
||||
const result = assignWithDepth(config0, config1);
|
||||
expect(result).toEqual(config0);
|
||||
});
|
||||
it('should handle depth:2 types (dst: object, src: simple type)', function () {
|
||||
const config_0 = { foo: 'bar', bar: { foo: 'bar' } };
|
||||
const config_1 = { foo: 'foo', bar: 'should NOT clobber' };
|
||||
const result = assignWithDepth(config_0, config_1);
|
||||
const config0 = { foo: 'bar', bar: { foo: 'bar' } };
|
||||
const config1 = { foo: 'foo', bar: 'should NOT clobber' };
|
||||
const result = assignWithDepth(config0, config1);
|
||||
expect(result).toEqual({ foo: 'foo', bar: { foo: 'bar' } });
|
||||
});
|
||||
it('should handle depth:2 types (src: orphan)', function () {
|
||||
const config_0 = { foo: 'bar' };
|
||||
const config_1 = { foo: 'bar', bar: { foo: 'bar' } };
|
||||
const result = assignWithDepth(config_0, config_1);
|
||||
expect(result).toEqual(config_1);
|
||||
const config0 = { foo: 'bar' };
|
||||
const config1 = { foo: 'bar', bar: { foo: 'bar' } };
|
||||
const result = assignWithDepth(config0, config1);
|
||||
expect(result).toEqual(config1);
|
||||
});
|
||||
it('should handle depth:2 types (merge)', function () {
|
||||
const config_0 = { foo: 'bar', bar: { foo: 'bar' }, boofar: 1 };
|
||||
const config_1 = { foo: 'foo', bar: { bar: 0 }, foobar: 'foobar' };
|
||||
const result = assignWithDepth(config_0, config_1);
|
||||
const config0 = { foo: 'bar', bar: { foo: 'bar' }, boofar: 1 };
|
||||
const config1 = { foo: 'foo', bar: { bar: 0 }, foobar: 'foobar' };
|
||||
const result = assignWithDepth(config0, config1);
|
||||
expect(result).toEqual({
|
||||
foo: 'foo',
|
||||
bar: { foo: 'bar', bar: 0 },
|
||||
@@ -64,17 +64,17 @@ describe('when assignWithDepth: should merge objects within objects', function (
|
||||
});
|
||||
});
|
||||
it('should handle depth:3 types (merge with clobber because assignWithDepth::depth == 2)', function () {
|
||||
const config_0 = {
|
||||
const config0 = {
|
||||
foo: 'bar',
|
||||
bar: { foo: 'bar', bar: { foo: { message: 'this', willbe: 'clobbered' } } },
|
||||
boofar: 1,
|
||||
};
|
||||
const config_1 = {
|
||||
const config1 = {
|
||||
foo: 'foo',
|
||||
bar: { foo: 'foo', bar: { foo: { message: 'clobbered other foo' } } },
|
||||
foobar: 'foobar',
|
||||
};
|
||||
const result = assignWithDepth(config_0, config_1);
|
||||
const result = assignWithDepth(config0, config1);
|
||||
expect(result).toEqual({
|
||||
foo: 'foo',
|
||||
bar: { foo: 'foo', bar: { foo: { message: 'clobbered other foo' } } },
|
||||
@@ -83,7 +83,7 @@ describe('when assignWithDepth: should merge objects within objects', function (
|
||||
});
|
||||
});
|
||||
it('should handle depth:3 types (merge with clobber because assignWithDepth::depth == 1)', function () {
|
||||
const config_0 = {
|
||||
const config0 = {
|
||||
foo: 'bar',
|
||||
bar: {
|
||||
foo: 'bar',
|
||||
@@ -91,12 +91,12 @@ describe('when assignWithDepth: should merge objects within objects', function (
|
||||
},
|
||||
boofar: 1,
|
||||
};
|
||||
const config_1 = {
|
||||
const config1 = {
|
||||
foo: 'foo',
|
||||
bar: { foo: 'foo', bar: { foo: { message: 'this' } } },
|
||||
foobar: 'foobar',
|
||||
};
|
||||
const result = assignWithDepth(config_0, config_1, { depth: 1 });
|
||||
const result = assignWithDepth(config0, config1, { depth: 1 });
|
||||
expect(result).toEqual({
|
||||
foo: 'foo',
|
||||
bar: { foo: 'foo', bar: { foo: { message: 'this' } } },
|
||||
@@ -105,17 +105,17 @@ describe('when assignWithDepth: should merge objects within objects', function (
|
||||
});
|
||||
});
|
||||
it('should handle depth:3 types (merge with no clobber because assignWithDepth::depth == 3)', function () {
|
||||
const config_0 = {
|
||||
const config0 = {
|
||||
foo: 'bar',
|
||||
bar: { foo: 'bar', bar: { foo: { message: '', willbe: 'present' } } },
|
||||
boofar: 1,
|
||||
};
|
||||
const config_1 = {
|
||||
const config1 = {
|
||||
foo: 'foo',
|
||||
bar: { foo: 'foo', bar: { foo: { message: 'this' } } },
|
||||
foobar: 'foobar',
|
||||
};
|
||||
const result = assignWithDepth(config_0, config_1, { depth: 3 });
|
||||
const result = assignWithDepth(config0, config1, { depth: 3 });
|
||||
expect(result).toEqual({
|
||||
foo: 'foo',
|
||||
bar: { foo: 'foo', bar: { foo: { message: 'this', willbe: 'present' } } },
|
||||
|
@@ -173,6 +173,7 @@ export const detectDirective = function (
|
||||
);
|
||||
let match: RegExpExecArray | null;
|
||||
const result: Directive[] = [];
|
||||
// biome-ignore lint/suspicious/noAssignInExpressions: <explanation>
|
||||
while ((match = directiveRegex.exec(text)) !== null) {
|
||||
// This is necessary to avoid infinite loops with zero-width matches
|
||||
if (match.index === directiveRegex.lastIndex) {
|
||||
@@ -443,7 +444,10 @@ function calcTerminalLabelPosition(
|
||||
* @param arr - Declarations
|
||||
* @returns The styles grouped as strings
|
||||
*/
|
||||
export function getStylesFromArray(arr: string[]): { style: string; labelStyle: string } {
|
||||
export function getStylesFromArray(arr: string[]): {
|
||||
style: string;
|
||||
labelStyle: string;
|
||||
} {
|
||||
let style = '';
|
||||
let labelStyle = '';
|
||||
|
||||
|
@@ -3,7 +3,7 @@ import * as configApi from '../config.js';
|
||||
|
||||
describe('getSubGraphTitleMargins', () => {
|
||||
it('should get subgraph title margins after config has been set', () => {
|
||||
const config_0 = {
|
||||
const config0 = {
|
||||
flowchart: {
|
||||
subGraphTitleMargin: {
|
||||
top: 10,
|
||||
@@ -12,8 +12,8 @@ describe('getSubGraphTitleMargins', () => {
|
||||
},
|
||||
};
|
||||
|
||||
configApi.setSiteConfig(config_0);
|
||||
expect(getSubGraphTitleMargins(config_0)).toEqual({
|
||||
configApi.setSiteConfig(config0);
|
||||
expect(getSubGraphTitleMargins(config0)).toEqual({
|
||||
subGraphTitleTopMargin: 10,
|
||||
subGraphTitleBottomMargin: 5,
|
||||
subGraphTitleTotalMargin: 15,
|
||||
|
@@ -3,10 +3,7 @@
|
||||
"version": "0.1.0-rc.1",
|
||||
"description": "MermaidJS parser",
|
||||
"author": "Yokozuna59",
|
||||
"contributors": [
|
||||
"Yokozuna59",
|
||||
"Sidharth Vinod (https://sidharth.dev)"
|
||||
],
|
||||
"contributors": ["Yokozuna59", "Sidharth Vinod (https://sidharth.dev)"],
|
||||
"homepage": "https://github.com/mermaid-js/mermaid/tree/develop/packages/mermaid/parser/#readme",
|
||||
"types": "dist/src/index.d.ts",
|
||||
"type": "module",
|
||||
@@ -28,20 +25,14 @@
|
||||
"directory": "packages/parser"
|
||||
},
|
||||
"license": "MIT",
|
||||
"keywords": [
|
||||
"mermaid",
|
||||
"parser",
|
||||
"ast"
|
||||
],
|
||||
"keywords": ["mermaid", "parser", "ast"],
|
||||
"dependencies": {
|
||||
"langium": "3.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"chevrotain": "^11.0.3"
|
||||
},
|
||||
"files": [
|
||||
"dist/"
|
||||
],
|
||||
"files": ["dist/"],
|
||||
"publishConfig": {
|
||||
"access": "public"
|
||||
}
|
||||
|
97
pnpm-lock.yaml
generated
97
pnpm-lock.yaml
generated
@@ -14,6 +14,9 @@ importers:
|
||||
'@argos-ci/cypress':
|
||||
specifier: ^2.0.5
|
||||
version: 2.0.5(cypress@13.7.3)
|
||||
'@biomejs/biome':
|
||||
specifier: 1.8.2
|
||||
version: 1.8.2
|
||||
'@cspell/eslint-plugin':
|
||||
specifier: ^8.6.0
|
||||
version: 8.7.0(eslint@8.57.0)
|
||||
@@ -300,12 +303,6 @@ importers:
|
||||
'@types/uuid':
|
||||
specifier: ^9.0.8
|
||||
version: 9.0.8
|
||||
'@typescript-eslint/eslint-plugin':
|
||||
specifier: ^7.3.1
|
||||
version: 7.6.0(@typescript-eslint/parser@7.6.0(eslint@8.57.0)(typescript@5.4.5))(eslint@8.57.0)(typescript@5.4.5)
|
||||
'@typescript-eslint/parser':
|
||||
specifier: ^7.3.1
|
||||
version: 7.6.0(eslint@8.57.0)(typescript@5.4.5)
|
||||
ajv:
|
||||
specifier: ^8.12.0
|
||||
version: 8.12.0
|
||||
@@ -1517,6 +1514,59 @@ packages:
|
||||
'@bcoe/v8-coverage@0.2.3':
|
||||
resolution: {integrity: sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==}
|
||||
|
||||
'@biomejs/biome@1.8.2':
|
||||
resolution: {integrity: sha512-XafCzLgs0xbH0bCjYKxQ63ig2V86fZQMq1jiy5pyLToWk9aHxA8GAUxyBtklPHtPYZPGEPOYglQHj4jyfUp+Iw==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
hasBin: true
|
||||
|
||||
'@biomejs/cli-darwin-arm64@1.8.2':
|
||||
resolution: {integrity: sha512-l9msLsTcSIAPqMsPIhodQmb50sEfaXPLQ0YW4cdj6INmd8iaOh/V9NceQb2366vACTJgcWDQ2RzlvURek1T68g==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [arm64]
|
||||
os: [darwin]
|
||||
|
||||
'@biomejs/cli-darwin-x64@1.8.2':
|
||||
resolution: {integrity: sha512-Fc4y/FuIxRSiB3TJ+y27vFDE/HJt4QgBuymktsIKEcBZvnKfsRjxvzVDunccRn4xbKgepnp+fn6BoS+ZIg/I3Q==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [x64]
|
||||
os: [darwin]
|
||||
|
||||
'@biomejs/cli-linux-arm64-musl@1.8.2':
|
||||
resolution: {integrity: sha512-WpT41QJJvkZa1eZq0WmD513zkC6AYaMI39HJKmKeiUeX2NZirG+bxv1YRDhqkns1NbBqo3+qrJqBkPmOW+xAVA==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@biomejs/cli-linux-arm64@1.8.2':
|
||||
resolution: {integrity: sha512-Q99qwP0qibkZxm2kfnt37OxeIlliDYf5ogi3zX9ij2DULzc+KtPA9Uj0wCljcJofOBsBYaHc7597Q+Bf/251ww==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [arm64]
|
||||
os: [linux]
|
||||
|
||||
'@biomejs/cli-linux-x64-musl@1.8.2':
|
||||
resolution: {integrity: sha512-rk1Wj4d3LIlAlIAS1m2jlyfOjkNbuY1lfwKvWIAeZC51yDMzwhRD7cReE5PE+jqLDtq60PX38hDPeKd7nA1S6A==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@biomejs/cli-linux-x64@1.8.2':
|
||||
resolution: {integrity: sha512-bjhhUVFchFid2gOjrvBe4fg8BShcpyFQTHuB/QQnfGxs1ddrGP30yq3fHfc6S6MoCcz9Tjd3Zzq1EfWfyy5iHA==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [x64]
|
||||
os: [linux]
|
||||
|
||||
'@biomejs/cli-win32-arm64@1.8.2':
|
||||
resolution: {integrity: sha512-EUbqmCmNWT5xhnxHrCAEBzJB1AnLqxTYoRjlxiCMzGvsy5jQzhCanJ8CT9kNsApW3pfPWBWkoTa7qrwWmwnEGA==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [arm64]
|
||||
os: [win32]
|
||||
|
||||
'@biomejs/cli-win32-x64@1.8.2':
|
||||
resolution: {integrity: sha512-n9H5oRUCk1uNezMgyJh9+hZdtfD8PXLLeq8DUzTycIhl0I1BulIoZ/uxWgRVDFDwAR1JHu1AykISCRFNGnc4iA==}
|
||||
engines: {node: '>=14.21.3'}
|
||||
cpu: [x64]
|
||||
os: [win32]
|
||||
|
||||
'@braintree/sanitize-url@7.0.1':
|
||||
resolution: {integrity: sha512-URg8UM6lfC9ZYqFipItRSxYJdgpU5d2Z4KnjsJ+rj6tgAmGme7E+PQNCiud8g0HDaZKMovu2qjfa0f5Ge0Vlsg==}
|
||||
|
||||
@@ -11061,6 +11111,41 @@ snapshots:
|
||||
|
||||
'@bcoe/v8-coverage@0.2.3': {}
|
||||
|
||||
'@biomejs/biome@1.8.2':
|
||||
optionalDependencies:
|
||||
'@biomejs/cli-darwin-arm64': 1.8.2
|
||||
'@biomejs/cli-darwin-x64': 1.8.2
|
||||
'@biomejs/cli-linux-arm64': 1.8.2
|
||||
'@biomejs/cli-linux-arm64-musl': 1.8.2
|
||||
'@biomejs/cli-linux-x64': 1.8.2
|
||||
'@biomejs/cli-linux-x64-musl': 1.8.2
|
||||
'@biomejs/cli-win32-arm64': 1.8.2
|
||||
'@biomejs/cli-win32-x64': 1.8.2
|
||||
|
||||
'@biomejs/cli-darwin-arm64@1.8.2':
|
||||
optional: true
|
||||
|
||||
'@biomejs/cli-darwin-x64@1.8.2':
|
||||
optional: true
|
||||
|
||||
'@biomejs/cli-linux-arm64-musl@1.8.2':
|
||||
optional: true
|
||||
|
||||
'@biomejs/cli-linux-arm64@1.8.2':
|
||||
optional: true
|
||||
|
||||
'@biomejs/cli-linux-x64-musl@1.8.2':
|
||||
optional: true
|
||||
|
||||
'@biomejs/cli-linux-x64@1.8.2':
|
||||
optional: true
|
||||
|
||||
'@biomejs/cli-win32-arm64@1.8.2':
|
||||
optional: true
|
||||
|
||||
'@biomejs/cli-win32-x64@1.8.2':
|
||||
optional: true
|
||||
|
||||
'@braintree/sanitize-url@7.0.1': {}
|
||||
|
||||
'@chevrotain/cst-dts-gen@11.0.3':
|
||||
|
@@ -1,4 +1,5 @@
|
||||
{
|
||||
"$schema": "https://docs.renovatebot.com/renovate-schema.json",
|
||||
"extends": [
|
||||
"config:base",
|
||||
":rebaseStalePrs",
|
||||
@@ -7,7 +8,8 @@
|
||||
":automergeTesters",
|
||||
":automergeLinters",
|
||||
":automergeTypes",
|
||||
":automergePatch"
|
||||
":automergePatch",
|
||||
"customManagers:biomeVersions"
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
|
@@ -1,8 +1,6 @@
|
||||
{
|
||||
// extend your base config to share compilerOptions, etc
|
||||
"extends": "./tsconfig.json",
|
||||
"compilerOptions": {
|
||||
// ensure that nobody can accidentally use this config for a build
|
||||
"noEmit": true
|
||||
},
|
||||
"include": [
|
||||
|
Reference in New Issue
Block a user