Compare commits

..

2 Commits

Author SHA1 Message Date
Sidharth Vinod
8a8893beaa try pixelmatch 2024-01-19 13:05:23 +05:30
Sidharth Vinod
2de72f6629 test 2024-01-19 12:50:00 +05:30
761 changed files with 28399 additions and 70150 deletions

View File

@@ -1,36 +0,0 @@
export interface PackageOptions {
name: string;
packageName: string;
file: string;
}
/**
* Shared common options for both ESBuild and Vite
*/
export const packageOptions = {
parser: {
name: 'mermaid-parser',
packageName: 'parser',
file: 'index.ts',
},
mermaid: {
name: 'mermaid',
packageName: 'mermaid',
file: 'mermaid.ts',
},
'mermaid-example-diagram': {
name: 'mermaid-example-diagram',
packageName: 'mermaid-example-diagram',
file: 'detector.ts',
},
'mermaid-zenuml': {
name: 'mermaid-zenuml',
packageName: 'mermaid-zenuml',
file: 'detector.ts',
},
'mermaid-layout-elk': {
name: 'mermaid-layout-elk',
packageName: 'mermaid-layout-elk',
file: 'layouts.ts',
},
} as const satisfies Record<string, PackageOptions>;

View File

@@ -1,5 +0,0 @@
import { generate } from 'langium-cli';
export async function generateLangium() {
await generate({ file: `./packages/parser/langium-config.json` });
}

View File

@@ -1,126 +0,0 @@
import { load, JSON_SCHEMA } from 'js-yaml';
import assert from 'node:assert';
import Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js';
import type { MermaidConfig, BaseDiagramConfig } from '../packages/mermaid/src/config.type.js';
/**
* All of the keys in the mermaid config that have a mermaid diagram config.
*/
const MERMAID_CONFIG_DIAGRAM_KEYS = [
'flowchart',
'sequence',
'gantt',
'journey',
'class',
'state',
'er',
'pie',
'quadrantChart',
'xyChart',
'requirement',
'mindmap',
'kanban',
'timeline',
'gitGraph',
'c4',
'sankey',
'block',
'packet',
'architecture',
] as const;
/**
* Generate default values from the JSON Schema.
*
* AJV does not support nested default values yet (or default values with $ref),
* so we need to manually find them (this may be fixed in ajv v9).
*
* @param mermaidConfigSchema - The Mermaid JSON Schema to use.
* @returns The default mermaid config object.
*/
function generateDefaults(mermaidConfigSchema: JSONSchemaType<MermaidConfig>) {
const ajv = new Ajv2019({
useDefaults: true,
allowUnionTypes: true,
strict: true,
});
ajv.addKeyword({
keyword: 'meta:enum', // used by jsonschema2md
errors: false,
});
ajv.addKeyword({
keyword: 'tsType', // used by json-schema-to-typescript
errors: false,
});
// ajv currently doesn't support nested default values, see https://github.com/ajv-validator/ajv/issues/1718
// (may be fixed in v9) so we need to manually use sub-schemas
const mermaidDefaultConfig = {};
assert.ok(mermaidConfigSchema.$defs);
const baseDiagramConfig = mermaidConfigSchema.$defs.BaseDiagramConfig;
for (const key of MERMAID_CONFIG_DIAGRAM_KEYS) {
const subSchemaRef = mermaidConfigSchema.properties[key].$ref;
const [root, defs, defName] = subSchemaRef.split('/');
assert.strictEqual(root, '#');
assert.strictEqual(defs, '$defs');
const subSchema = {
$schema: mermaidConfigSchema.$schema,
$defs: mermaidConfigSchema.$defs,
...mermaidConfigSchema.$defs[defName],
} as JSONSchemaType<BaseDiagramConfig>;
const validate = ajv.compile(subSchema);
mermaidDefaultConfig[key] = {};
for (const required of subSchema.required ?? []) {
if (subSchema.properties[required] === undefined && baseDiagramConfig.properties[required]) {
mermaidDefaultConfig[key][required] = baseDiagramConfig.properties[required].default;
}
}
if (!validate(mermaidDefaultConfig[key])) {
throw new Error(
`schema for subconfig ${key} does not have valid defaults! Errors were ${JSON.stringify(
validate.errors,
undefined,
2
)}`
);
}
}
const validate = ajv.compile(mermaidConfigSchema);
if (!validate(mermaidDefaultConfig)) {
throw new Error(
`Mermaid config JSON Schema does not have valid defaults! Errors were ${JSON.stringify(
validate.errors,
undefined,
2
)}`
);
}
return mermaidDefaultConfig;
}
export const loadSchema = (src: string, filename: string): JSONSchemaType<MermaidConfig> => {
const jsonSchema = load(src, {
filename,
// only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
// e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
schema: JSON_SCHEMA,
}) as JSONSchemaType<MermaidConfig>;
return jsonSchema;
};
export const getDefaults = (schema: JSONSchemaType<MermaidConfig>) => {
return `export default ${JSON.stringify(generateDefaults(schema), undefined, 2)};`;
};
export const getSchema = (schema: JSONSchemaType<MermaidConfig>) => {
return `export default ${JSON.stringify(schema, undefined, 2)};`;
};

View File

@@ -1,25 +0,0 @@
/* eslint-disable no-console */
import { packageOptions } from './common.js';
import { execSync } from 'child_process';
const buildType = (packageName: string) => {
console.log(`Building types for ${packageName}`);
try {
const out = execSync(`tsc -p ./packages/${packageName}/tsconfig.json --emitDeclarationOnly`);
if (out.length > 0) {
console.log(out.toString());
}
} catch (e) {
console.error(e);
if (e.stdout.length > 0) {
console.error(e.stdout.toString());
}
if (e.stderr.length > 0) {
console.error(e.stderr.toString());
}
}
};
for (const { packageName } of Object.values(packageOptions)) {
buildType(packageName);
}

View File

@@ -1,8 +0,0 @@
# Changesets
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
with multi-package repos, or single-package repos to help you version and publish your code. You can
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
We have a quick list of common questions to get you started engaging with this project in
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)

View File

@@ -1,12 +0,0 @@
{
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
"changelog": ["@changesets/changelog-github", { "repo": "mermaid-js/mermaid" }],
"commit": false,
"fixed": [],
"linked": [],
"access": "public",
"baseBranch": "master",
"updateInternalDependencies": "patch",
"bumpVersionsWithWorkspaceProtocolOnly": true,
"ignore": ["@mermaid-js/docs", "@mermaid-js/webpack-test", "@mermaid-js/mermaid-example-diagram"]
}

3
.commitlintrc.json Normal file
View File

@@ -0,0 +1,3 @@
{
"extends": ["@commitlint/config-conventional"]
}

View File

@@ -1,152 +0,0 @@
# This file contains coding related terms
ALPHANUM
antiscript
APPLYCLASS
ARROWHEADSTYLE
ARROWTYPE
autonumber
axisl-line
Bigdecimal
birel
BIREL
bqstring
BQUOTE
bramp
BRKT
brotli
callbackargs
callbackname
classdef
classdefid
classentity
classname
COLONSEP
COMPOSIT_STATE
concat
controlx
controly
CSSCLASS
curv
CYLINDEREND
CYLINDERSTART
DAGA
datakey
DEND
descr
distp
distq
divs
docref
DOMID
doublecircle
DOUBLECIRCLEEND
DOUBLECIRCLESTART
DQUOTE
DSTART
edgesep
EMPTYSTR
enddate
ERDIAGRAM
flatmap
forwardable
frontmatter
funs
gantt
GENERICTYPE
getBoundarys
grammr
graphtype
halign
iife
interp
introdcued
INVTRAPEND
INVTRAPSTART
JDBC
jison
Kaufmann
keyify
LABELPOS
LABELTYPE
layoutstop
lcov
LEFTOF
Lexa
linebreak
LINETYPE
LINKSTYLE
LLABEL
loglevel
LOGMSG
lookaheads
mdast
metafile
minlen
Mstartx
MULT
NODIR
NSTR
outdir
Qcontrolx
reinit
rels
reqs
rewritelinks
rgba
RIGHTOF
roughjs
sankey
sequencenumber
shrc
signaltype
someclass
SPACELINE
SPACELIST
STADIUMEND
STADIUMSTART
startdate
startx
starty
STMNT
stopx
stopy
strikethrough
stringifying
struct
STYLECLASS
STYLEDEF
STYLEOPTS
subcomponent
subcomponents
subconfig
SUBROUTINEEND
SUBROUTINESTART
Subschemas
substr
SVGG
SVGSVG
TAGEND
TAGSTART
techn
TESTSTR
TEXTDATA
TEXTLENGTH
titlevalue
topbar
TRAPEND
TRAPSTART
treemap
ts-nocheck
tsdoc
typeof
typestr
unshift
urlsafe
verifymethod
VERIFYMTHD
WARN_DOCSDIR_DOESNT_MATCH
xhost
yaxis
yfunc
yytext
zenuml

View File

@@ -1,9 +0,0 @@
# Contributors to mermaidjs, one per line
Ashish Jain
cpettitt
Dong Cai
Nikolay Rozhkov
Peng Xiao
Per Brolin
subhash-halder
Vinod Sidharth

View File

@@ -1,55 +0,0 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json
$schema: https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json
dictionaryDefinitions:
- name: code-terms
path: ./code-terms.txt
description: A list of coding related terms.
addWords: true
- name: mermaid-terms
path: ./mermaid-terms.txt
description: A list of terms related to the mermaid project.
addWords: true
- name: misc-terms
path: ./misc-terms.txt
description: A list of miscellaneous terms.
- name: 3rd-party-terms
path: ./libraries.txt
description: A list of 3rd party terms from dependencies.
addWords: true
- name: contributors
path: ./contributors.txt
description: A list of contributors to the mermaid project.
type: 'W'
addWords: true
# cspell:disable
- name: suggestions
words:
- none
- disp
- subproc
- tria
suggestWords:
- seperator:separator
- vertice:vertex
# cspell:enable
patterns:
- name: character-set-cyrillic
pattern: '/\p{Script_Extensions=Cyrillic}+/gu'
- name: svg-block
pattern: '<svg[\S\s]+?</svg>'
- name: json-property
pattern: '/"[\w/@-]+":/g'
dictionaries:
- mermaid-terms
- suggestions
- contributors
ignorePaths:
- '*.txt' # do not spell check local dictionaries
# cspell:dictionary misc-terms

View File

@@ -1,78 +0,0 @@
# Add third party library terms below
acyclicer
Antlr
Appli
applitools
Asciidoctor
Astah
automerge
bilkent
bisheng
Blazor
codedoc
Codemia
codepaths
csstree
cytoscape
cytoscape-cose-bilkent
dagre
dagre-d3
Deepdwn
Docsify
Docsy
Doctave
DokuWiki
dompurify
elkjs
fcose
fontawesome
Foswiki
Gitea
graphlib
Grav
icones
iconify
Inkdrop
jiti
jsdocs
jsfiddle
jsonschema
katex
khroma
langium
mathml
matplotlib
mdbook
Mermerd
mkdocs
Nextra
nodenext
npmjs
pageview
pathe
phpbb
pixelmatch
Podlite
presetAttributify
pyplot
redmine
rehype
roughjs
rscratch
shiki
Slidev
sparkline
sphinxcontrib
ssim
stylis
Swimm
tsbuildinfo
tseslint
Tuleap
Typora
unocss
unplugin
unstub
vite
vitest
Zune

View File

@@ -1,45 +0,0 @@
Adamiecki
arrowend
Bendpoints
bmatrix
braintree
catmull
compositTitleSize
curv
doublecircle
elems
gantt
gitgraph
gzipped
handDrawn
kanban
knsv
Knut
marginx
marginy
Markdownish
mermaidjs
mindmap
mindmaps
mrtree
multigraph
nodesep
NOTEGROUP
Pinterest
procs
rankdir
ranksep
rect
rects
sandboxed
siebling
statediagram
substate
Sveidqvist
unfixable
Viewbox
viewports
visio
vitepress
xlink
xychart

View File

@@ -1,7 +0,0 @@
BRANDES
circo
handDrawn
KOEPF
neato
newbranch
validify

View File

@@ -1,70 +0,0 @@
import { build } from 'esbuild';
import { mkdir, writeFile } from 'node:fs/promises';
import { packageOptions } from '../.build/common.js';
import { generateLangium } from '../.build/generateLangium.js';
import type { MermaidBuildOptions } from './util.js';
import { defaultOptions, getBuildConfig } from './util.js';
const shouldVisualize = process.argv.includes('--visualize');
const buildPackage = async (entryName: keyof typeof packageOptions) => {
const commonOptions: MermaidBuildOptions = {
...defaultOptions,
options: packageOptions[entryName],
} as const;
const buildConfigs: MermaidBuildOptions[] = [
// package.mjs
{ ...commonOptions },
// package.min.mjs
{
...commonOptions,
minify: true,
metafile: shouldVisualize,
},
// package.core.mjs
{ ...commonOptions, core: true },
];
if (entryName === 'mermaid') {
const iifeOptions: MermaidBuildOptions = { ...commonOptions, format: 'iife' };
buildConfigs.push(
// mermaid.js
{ ...iifeOptions },
// mermaid.min.js
{ ...iifeOptions, minify: true, metafile: shouldVisualize }
);
}
const results = await Promise.all(buildConfigs.map((option) => build(getBuildConfig(option))));
if (shouldVisualize) {
for (const { metafile } of results) {
if (!metafile?.outputs) {
continue;
}
const fileName = Object.keys(metafile.outputs)
.find((file) => !file.includes('chunks') && file.endsWith('js'))!
.replace('dist/', '');
// Upload metafile into https://esbuild.github.io/analyze/
await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile));
}
}
};
const handler = (e) => {
// eslint-disable-next-line no-console
console.error(e);
process.exit(1);
};
const main = async () => {
await generateLangium();
await mkdir('stats', { recursive: true });
const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[];
// it should build `parser` before `mermaid` because it's a dependency
for (const pkg of packageNames) {
await buildPackage(pkg).catch(handler);
}
};
void main();

View File

@@ -1,15 +0,0 @@
import { readFile } from 'node:fs/promises';
import { transformJison } from '../.build/jisonTransformer.js';
import type { Plugin } from 'esbuild';
export const jisonPlugin: Plugin = {
name: 'jison',
setup(build) {
build.onLoad({ filter: /\.jison$/ }, async (args) => {
// Load the file from the file system
const source = await readFile(args.path, 'utf8');
const contents = transformJison(source);
return { contents, warnings: [] };
});
},
};

View File

@@ -1,35 +0,0 @@
import type { JSONSchemaType } from 'ajv/dist/2019.js';
import type { MermaidConfig } from '../packages/mermaid/src/config.type.js';
import { readFile } from 'node:fs/promises';
import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js';
/**
* ESBuild plugin that handles JSON Schemas saved as a `.schema.yaml` file.
*
* Use `my-example.schema.yaml?only-defaults=true` to only load the default values.
*/
export const jsonSchemaPlugin = {
name: 'json-schema-plugin',
setup(build) {
let schema: JSONSchemaType<MermaidConfig> | undefined = undefined;
let content = '';
build.onLoad({ filter: /config\.schema\.yaml$/ }, async (args) => {
// Load the file from the file system
const source = await readFile(args.path, 'utf8');
const resolvedSchema: JSONSchemaType<MermaidConfig> =
content === source && schema ? schema : loadSchema(source, args.path);
if (content !== source) {
content = source;
schema = resolvedSchema;
}
const contents = args.suffix.includes('only-defaults')
? getDefaults(resolvedSchema)
: getSchema(resolvedSchema);
return { contents, warnings: [] };
});
},
};
export default jsonSchemaPlugin;

View File

@@ -1,122 +0,0 @@
/* eslint-disable no-console */
import chokidar from 'chokidar';
import cors from 'cors';
import { context } from 'esbuild';
import type { Request, Response } from 'express';
import express from 'express';
import { packageOptions } from '../.build/common.js';
import { generateLangium } from '../.build/generateLangium.js';
import { defaultOptions, getBuildConfig } from './util.js';
const configs = Object.values(packageOptions).map(({ packageName }) =>
getBuildConfig({
...defaultOptions,
minify: false,
core: false,
options: packageOptions[packageName],
})
);
const mermaidIIFEConfig = getBuildConfig({
...defaultOptions,
minify: false,
core: false,
options: packageOptions.mermaid,
format: 'iife',
});
configs.push(mermaidIIFEConfig);
const contexts = await Promise.all(
configs.map(async (config) => ({ config, context: await context(config) }))
);
let rebuildCounter = 1;
const rebuildAll = async () => {
const buildNumber = rebuildCounter++;
const timeLabel = `Rebuild ${buildNumber} Time (total)`;
console.time(timeLabel);
await Promise.all(
contexts.map(async ({ config, context }) => {
const buildVariant = `Rebuild ${buildNumber} Time (${Object.keys(config.entryPoints!)[0]} ${config.format})`;
console.time(buildVariant);
await context.rebuild();
console.timeEnd(buildVariant);
})
).catch((e) => console.error(e));
console.timeEnd(timeLabel);
};
let clients: { id: number; response: Response }[] = [];
function eventsHandler(request: Request, response: Response) {
const headers = {
'Content-Type': 'text/event-stream',
Connection: 'keep-alive',
'Cache-Control': 'no-cache',
};
response.writeHead(200, headers);
const clientId = Date.now();
clients.push({
id: clientId,
response,
});
request.on('close', () => {
clients = clients.filter((client) => client.id !== clientId);
});
}
let timeoutID: NodeJS.Timeout | undefined = undefined;
/**
* Debounce file change events to avoid rebuilding multiple times.
*/
function handleFileChange() {
if (timeoutID !== undefined) {
clearTimeout(timeoutID);
}
// eslint-disable-next-line @typescript-eslint/no-misused-promises
timeoutID = setTimeout(async () => {
await rebuildAll();
sendEventsToAll();
timeoutID = undefined;
}, 100);
}
function sendEventsToAll() {
clients.forEach(({ response }) => response.write(`data: ${Date.now()}\n\n`));
}
async function createServer() {
await generateLangium();
handleFileChange();
const app = express();
chokidar
.watch('**/src/**/*.{js,ts,langium,yaml,json}', {
ignoreInitial: true,
ignored: [/node_modules/, /dist/, /docs/, /coverage/],
})
// eslint-disable-next-line @typescript-eslint/no-misused-promises
.on('all', async (event, path) => {
// Ignore other events.
if (!['add', 'change'].includes(event)) {
return;
}
console.log(`${path} changed. Rebuilding...`);
if (path.endsWith('.langium')) {
await generateLangium();
}
handleFileChange();
});
app.use(cors());
app.get('/events', eventsHandler);
for (const { packageName } of Object.values(packageOptions)) {
app.use(express.static(`./packages/${packageName}/dist`));
}
app.use(express.static('demos'));
app.use(express.static('cypress/platform'));
app.listen(9000, () => {
console.log(`Listening on http://localhost:9000`);
});
}
void createServer();

View File

@@ -1,106 +0,0 @@
import { resolve } from 'path';
import { fileURLToPath } from 'url';
import type { BuildOptions } from 'esbuild';
import { readFileSync } from 'fs';
import jsonSchemaPlugin from './jsonSchemaPlugin.js';
import type { PackageOptions } from '../.build/common.js';
import { jisonPlugin } from './jisonPlugin.js';
const __dirname = fileURLToPath(new URL('.', import.meta.url));
export interface MermaidBuildOptions extends BuildOptions {
minify: boolean;
core: boolean;
metafile: boolean;
format: 'esm' | 'iife';
options: PackageOptions;
}
export const defaultOptions: Omit<MermaidBuildOptions, 'entryName' | 'options'> = {
minify: false,
metafile: false,
core: false,
format: 'esm',
} as const;
const buildOptions = (override: BuildOptions): BuildOptions => {
return {
bundle: true,
minify: true,
keepNames: true,
platform: 'browser',
tsconfig: 'tsconfig.json',
resolveExtensions: ['.ts', '.js', '.json', '.jison', '.yaml'],
external: ['require', 'fs', 'path'],
outdir: 'dist',
plugins: [jisonPlugin, jsonSchemaPlugin],
sourcemap: 'external',
...override,
};
};
const getFileName = (fileName: string, { core, format, minify }: MermaidBuildOptions) => {
if (core) {
fileName += '.core';
} else if (format === 'esm') {
fileName += '.esm';
}
if (minify) {
fileName += '.min';
}
return fileName;
};
export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
const {
core,
metafile,
format,
minify,
options: { name, file, packageName },
} = options;
const external: string[] = ['require', 'fs', 'path'];
const outFileName = getFileName(name, options);
const output: BuildOptions = buildOptions({
absWorkingDir: resolve(__dirname, `../packages/${packageName}`),
entryPoints: {
[outFileName]: `src/${file}`,
},
metafile,
minify,
logLevel: 'info',
chunkNames: `chunks/${outFileName}/[name]-[hash]`,
define: {
'import.meta.vitest': 'undefined',
},
});
if (core) {
const { dependencies } = JSON.parse(
readFileSync(resolve(__dirname, `../packages/${packageName}/package.json`), 'utf-8')
);
// Core build is used to generate file without bundled dependencies.
// This is used by downstream projects to bundle dependencies themselves.
// Ignore dependencies and any dependencies of dependencies
external.push(...Object.keys(dependencies));
output.external = external;
}
if (format === 'iife') {
output.format = 'iife';
output.splitting = false;
output.globalName = '__esbuild_esm_mermaid';
// Workaround for removing the .default access in esbuild IIFE.
// https://github.com/mermaid-js/mermaid/pull/4109#discussion_r1292317396
output.footer = {
js: 'globalThis.mermaid = globalThis.__esbuild_esm_mermaid.default;',
};
output.outExtension = { '.js': '.js' };
} else {
output.format = 'esm';
output.splitting = true;
output.outExtension = { '.js': '.mjs' };
}
return output;
};

8
.eslintignore Normal file
View File

@@ -0,0 +1,8 @@
dist/**
.github/**
docs/Setup.md
cypress.config.js
cypress/plugins/index.js
coverage
*.json
node_modules

165
.eslintrc.cjs Normal file
View File

@@ -0,0 +1,165 @@
module.exports = {
env: {
browser: true,
es6: true,
'jest/globals': true,
node: true,
},
root: true,
parser: '@typescript-eslint/parser',
parserOptions: {
ecmaFeatures: {
experimentalObjectRestSpread: true,
jsx: true,
},
tsconfigRootDir: __dirname,
sourceType: 'module',
ecmaVersion: 2020,
allowAutomaticSingleRunInference: true,
project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'],
parser: '@typescript-eslint/parser',
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:json/recommended',
'plugin:markdown/recommended',
'plugin:@cspell/recommended',
'prettier',
],
plugins: [
'@typescript-eslint',
'no-only-tests',
'html',
'jest',
'jsdoc',
'json',
'@cspell',
'lodash',
'unicorn',
],
ignorePatterns: [
// this file is automatically generated by `pnpm run --filter mermaid types:build-config`
'packages/mermaid/src/config.type.ts',
],
rules: {
curly: 'error',
'no-console': 'error',
'no-prototype-builtins': 'off',
'no-unused-vars': 'off',
'cypress/no-async-tests': 'off',
'@typescript-eslint/consistent-type-imports': 'error',
'@typescript-eslint/no-explicit-any': 'warn',
'@typescript-eslint/no-floating-promises': 'error',
'@typescript-eslint/no-misused-promises': 'error',
'@typescript-eslint/no-unused-vars': 'warn',
'@typescript-eslint/ban-ts-comment': [
'error',
{
'ts-expect-error': 'allow-with-description',
'ts-ignore': 'allow-with-description',
'ts-nocheck': 'allow-with-description',
'ts-check': 'allow-with-description',
minimumDescriptionLength: 10,
},
],
'json/*': ['error', 'allowComments'],
'@cspell/spellchecker': [
'error',
{
checkIdentifiers: false,
checkStrings: false,
checkStringTemplates: false,
},
],
'no-empty': [
'error',
{
allowEmptyCatch: true,
},
],
'no-only-tests/no-only-tests': 'error',
'lodash/import-scope': ['error', 'method'],
'unicorn/better-regex': 'error',
'unicorn/no-abusive-eslint-disable': 'error',
'unicorn/no-array-push-push': 'error',
'unicorn/no-for-loop': 'error',
'unicorn/no-instanceof-array': 'error',
'unicorn/no-typeof-undefined': 'error',
'unicorn/no-unnecessary-await': 'error',
'unicorn/no-unsafe-regex': 'warn',
'unicorn/no-useless-promise-resolve-reject': 'error',
'unicorn/prefer-array-find': 'error',
'unicorn/prefer-array-flat-map': 'error',
'unicorn/prefer-array-index-of': 'error',
'unicorn/prefer-array-some': 'error',
'unicorn/prefer-default-parameters': 'error',
'unicorn/prefer-includes': 'error',
'unicorn/prefer-negative-index': 'error',
'unicorn/prefer-object-from-entries': 'error',
'unicorn/prefer-string-starts-ends-with': 'error',
'unicorn/prefer-string-trim-start-end': 'error',
'unicorn/string-content': 'error',
'unicorn/prefer-spread': 'error',
'unicorn/no-lonely-if': 'error',
},
overrides: [
{
files: ['cypress/**', 'demos/**'],
rules: {
'no-console': 'off',
},
},
{
files: ['*.{js,jsx,mjs,cjs}'],
extends: ['plugin:jsdoc/recommended'],
rules: {
'jsdoc/check-indentation': 'off',
'jsdoc/check-alignment': 'off',
'jsdoc/check-line-alignment': 'off',
'jsdoc/multiline-blocks': 'off',
'jsdoc/newline-after-description': 'off',
'jsdoc/tag-lines': 'off',
'jsdoc/require-param-description': 'off',
'jsdoc/require-param-type': 'off',
'jsdoc/require-returns': 'off',
'jsdoc/require-returns-description': 'off',
},
},
{
files: ['*.{ts,tsx}'],
plugins: ['tsdoc'],
rules: {
'no-restricted-syntax': [
'error',
{
selector: 'TSEnumDeclaration',
message:
'Prefer using TypeScript union types over TypeScript enum, since TypeScript enums have a bunch of issues, see https://dev.to/dvddpl/whats-the-problem-with-typescript-enums-2okj',
},
],
'tsdoc/syntax': 'error',
},
},
{
files: ['*.spec.{ts,js}', 'cypress/**', 'demos/**', '**/docs/**'],
rules: {
'jsdoc/require-jsdoc': 'off',
'@typescript-eslint/no-unused-vars': 'off',
},
},
{
files: ['*.html', '*.md', '**/*.md/*'],
rules: {
'no-var': 'error',
'no-undef': 'off',
'@typescript-eslint/no-unused-vars': 'off',
'@typescript-eslint/no-floating-promises': 'off',
'@typescript-eslint/no-misused-promises': 'off',
},
parserOptions: {
project: null,
},
},
],
};

View File

@@ -3,9 +3,9 @@ contact_links:
- name: GitHub Discussions
url: https://github.com/mermaid-js/mermaid/discussions
about: Ask the Community questions or share your own graphs in our discussions.
- name: Discord
url: https://discord.gg/AgrbSrBer3
about: Join our Community on Discord for Help and a casual chat.
- name: Slack
url: https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE
about: Join our Community on Slack for Help and a casual chat.
- name: Documentation
url: https://mermaid.js.org
about: Read our documentation for all that Mermaid.js can offer.

View File

@@ -15,4 +15,3 @@ coverage:
# Turing off for now as code coverage isn't stable and causes unnecessary build failures.
# default:
# threshold: 2%
patch: off

16
.github/lychee.toml vendored
View File

@@ -34,20 +34,8 @@ exclude = [
# Don't check files that are generated during the build via `pnpm docs:code`
'packages/mermaid/src/docs/config/setup/*',
# Ignore Discord invite
"https://discord.gg",
# BundlePhobia has frequent downtime
"https://bundlephobia.com",
# Chrome webstore migration issue. Temporary
"https://chromewebstore.google.com",
# Drupal 403
"https://(www.)?drupal.org",
# Swimm returns 404, eventhough the link is valid
"https://docs.swimm.io"
# Ignore slack invite
"https://join.slack.com/"
]
# Exclude all private IPs from checking.

View File

@@ -12,7 +12,7 @@ Describe the way your implementation works or what design decisions you made if
Make sure you
- [ ] :book: have read the [contribution guidelines](https://mermaid.js.org/community/contributing.html)
- [ ] :book: have read the [contribution guidelines](https://github.com/mermaid-js/mermaid/blob/develop/CONTRIBUTING.md)
- [ ] :computer: have added necessary unit/e2e tests.
- [ ] :notebook: have added documentation. Make sure [`MERMAID_RELEASE_VERSION`](https://mermaid.js.org/community/contributing.html#update-documentation) is used for all new features.
- [ ] :butterfly: If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. Changesets that add features should be `minor` and those that fix bugs should be `patch`. Please prefix changeset messages with `feat:`, `fix:`, or `chore:`.
- [ ] :notebook: have added documentation. Make sure [`MERMAID_RELEASE_VERSION`](https://github.com/mermaid-js/mermaid/blob/develop/packages/mermaid/src/docs/community/contributing.md#update-documentation) is used for all new features.
- [ ] :bookmark: targeted `develop` branch

36
.github/release-drafter.yml vendored Normal file
View File

@@ -0,0 +1,36 @@
name-template: '$NEXT_PATCH_VERSION'
tag-template: '$NEXT_PATCH_VERSION'
categories:
- title: '🚨 **Breaking Changes**'
labels:
- 'Breaking Change'
- title: '🚀 Features'
labels:
- 'Type: Enhancement'
- 'feature' # deprecated, new PRs shouldn't have this
- title: '🐛 Bug Fixes'
labels:
- 'Type: Bug / Error'
- 'fix' # deprecated, new PRs shouldn't have this
- title: '🧰 Maintenance'
labels:
- 'Type: Other'
- 'chore' # deprecated, new PRs shouldn't have this
- title: '⚡️ Performance'
labels:
- 'Type: Performance'
- title: '📚 Documentation'
labels:
- 'Area: Documentation'
change-template: '- $TITLE (#$NUMBER) @$AUTHOR'
sort-by: title
sort-direction: ascending
exclude-labels:
- 'Skip changelog'
no-changes-template: 'This release contains minor changes and bugfixes.'
template: |
# Release Notes
$CHANGES
🎉 **Thanks to all contributors helping with this release!** 🎉

View File

@@ -1,45 +0,0 @@
name: autofix.ci # needed to securely identify the workflow
on:
pull_request:
branches-ignore:
- 'renovate/**'
permissions:
contents: read
concurrency: ${{ github.workflow }}-${{ github.ref }}
jobs:
autofix:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
cache: pnpm
node-version-file: '.node-version'
- name: Install Packages
run: |
pnpm install --frozen-lockfile
env:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Fix Linting
shell: bash
run: pnpm -w run lint:fix
- name: Sync `./src/config.type.ts` with `./src/schemas/config.schema.yaml`
shell: bash
run: pnpm run --filter mermaid types:build-config
- name: Build Docs
working-directory: ./packages/mermaid
run: pnpm run docs:build
- uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c # main

View File

@@ -8,8 +8,6 @@ on:
pull_request:
merge_group:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: read
@@ -18,15 +16,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: pnpm/action-setup@v2
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
uses: actions/setup-node@v4
with:
cache: pnpm
node-version-file: '.node-version'
node-version: 18
- name: Install Packages
run: pnpm install --frozen-lockfile

52
.github/workflows/build.yml vendored Normal file
View File

@@ -0,0 +1,52 @@
name: Build
on:
push: {}
merge_group:
pull_request:
types:
- opened
- synchronize
- ready_for_review
permissions:
contents: read
jobs:
build-mermaid:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
steps:
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
cache: pnpm
node-version: ${{ matrix.node-version }}
- name: Install Packages
run: |
pnpm install --frozen-lockfile
env:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Run Build
run: pnpm run build
- name: Upload Mermaid Build as Artifact
uses: actions/upload-artifact@v3
with:
name: mermaid-build
path: packages/mermaid/dist
- name: Upload Mermaid Mindmap Build as Artifact
uses: actions/upload-artifact@v3
with:
name: mermaid-mindmap-build
path: packages/mermaid-mindmap/dist

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v4
- name: Check for difference in README.md and docs/README.md
run: |

26
.github/workflows/checks.yml vendored Normal file
View File

@@ -0,0 +1,26 @@
on:
push:
merge_group:
pull_request:
types:
- opened
- synchronize
- ready_for_review
name: Static analysis on Test files
jobs:
check-tests:
runs-on: ubuntu-latest
name: check tests
if: github.repository_owner == 'mermaid-js'
steps:
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: testomatio/check-tests@stable
with:
framework: cypress
tests: './cypress/e2e/**/**.spec.js'
token: ${{ secrets.GITHUB_TOKEN }}
has-tests-label: true

View File

@@ -11,9 +11,6 @@ on:
- synchronize
- ready_for_review
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs:
analyze:
name: Analyze
@@ -32,11 +29,11 @@ jobs:
steps:
- name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/init@v2
with:
config-file: ./.github/codeql/codeql-config.yml
languages: ${{ matrix.language }}
@@ -48,7 +45,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/autobuild@v2
# Command-line programs to run using the OS shell.
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -62,4 +59,4 @@ jobs:
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
uses: github/codeql-action/analyze@v2

View File

@@ -15,6 +15,6 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: 'Checkout Repository'
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v4
- name: 'Dependency Review'
uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4
uses: actions/dependency-review-action@v3

View File

@@ -11,8 +11,6 @@ on:
default: master
description: 'Parent branch to use for PRs'
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: read
@@ -23,24 +21,24 @@ env:
jobs:
e2e-applitools:
runs-on: ubuntu-latest
container:
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1
options: --user 1001
strategy:
matrix:
node-version: [18.x]
steps:
- if: ${{ ! env.USE_APPLI }}
name: Warn if not using Applitools
run: |
echo "::error,title=Not using Applitools::APPLITOOLS_API_KEY is empty, disabling Applitools for this run."
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version-file: '.node-version'
node-version: ${{ matrix.node-version }}
- if: ${{ env.USE_APPLI }}
name: Notify applitools of new batch
@@ -54,7 +52,7 @@ jobs:
APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com'
- name: Cypress run
uses: cypress-io/github-action@d79d2d530a66e641eb4a5f227e13bc985c60b964 # v4.2.2
uses: cypress-io/github-action@v4
id: cypress
with:
start: pnpm run dev

View File

@@ -1,53 +0,0 @@
name: E2E - Generate Timings
on:
# run this workflow every night at 3am
schedule:
- cron: '28 3 * * *'
# or when the user triggers it from GitHub Actions page
workflow_dispatch:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: write
jobs:
timings:
runs-on: ubuntu-latest
container:
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1
options: --user 1001
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version-file: '.node-version'
- name: Install dependencies
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
with:
runTests: false
- name: Cypress run
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
id: cypress
with:
install: false
start: pnpm run dev:coverage
wait-on: 'http://localhost:9000'
browser: chrome
publish-summary: false
env:
VITEST_COVERAGE: true
CYPRESS_COMMIT: ${{ github.sha }}
SPLIT: 1
SPLIT_INDEX: 0
SPLIT_FILE: 'cypress/timings.json'
- name: Commit changes
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4
with:
add: 'cypress/timings.json'
author_name: 'github-actions[bot]'
author_email: '41898282+github-actions[bot]@users.noreply.github.com'
message: 'chore: update E2E timings'

View File

@@ -2,144 +2,95 @@ name: E2E
on:
push:
branches:
- develop
- master
- release/**
pull_request:
merge_group:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: read
env:
# For PRs and MergeQueues, the target commit is used, and for push events to non-develop branches, github.event.previous is used if available. Otherwise, 'develop' is used.
targetHash: >-
${{
github.event.pull_request.base.sha ||
github.event.merge_group.base_sha ||
(
(
(github.event_name == 'push' && github.ref == 'refs/heads/develop') ||
github.event.before == '0000000000000000000000000000000000000000'
) && 'develop'
) ||
github.event.before
}}
jobs:
cache:
runs-on: ubuntu-latest
container:
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1
options: --user 1001
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: actions/checkout@v4
- uses: pnpm/action-setup@v2
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
uses: actions/setup-node@v4
with:
node-version-file: '.node-version'
node-version: 18.x
- name: Cache snapshots
id: cache-snapshot
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache@v4
with:
save-always: true
path: ./cypress/snapshots
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
key: ${{ runner.os }}-snapshots
# If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots.
- name: Switch to base branch
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v4
with:
ref: ${{ env.targetHash }}
ref: ${{ github.event_name == 'pull_request' && github.event.pull_request.base.sha || github.event_name == 'merge_group' && github.event.merge_group.base.sha || 'develop' }}
- name: Install dependencies
- name: Cypress run
uses: cypress-io/github-action@v4
id: cypress-snapshot-gen
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
with:
# just perform install
runTests: false
- name: Calculate bundle size
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true'}}
run: |
pnpm run build:viz
mkdir -p cypress/snapshots/stats/base
mv stats cypress/snapshots/stats/base
start: pnpm run dev
wait-on: 'http://localhost:9000'
browser: chrome
e2e:
runs-on: ubuntu-latest
container:
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1
options: --user 1001
needs: cache
strategy:
fail-fast: false
matrix:
containers: [1, 2, 3, 4, 5]
node-version: [18.x]
containers: [1, 2, 3, 4]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version-file: '.node-version'
node-version: ${{ matrix.node-version }}
# These cached snapshots are downloaded, providing the reference snapshots.
- name: Cache snapshots
id: cache-snapshot
uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache/restore@v3
with:
path: ./cypress/snapshots
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
- name: Install dependencies
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
with:
runTests: false
- name: Output size diff
if: ${{ matrix.containers == 1 }}
run: |
pnpm run build:viz
mv stats cypress/snapshots/stats/head
echo '## Bundle size difference' >> "$GITHUB_STEP_SUMMARY"
echo '' >> "$GITHUB_STEP_SUMMARY"
npx tsx scripts/size.ts >> "$GITHUB_STEP_SUMMARY"
key: ${{ runner.os }}-snapshots
# Install NPM dependencies, cache them correctly
# and run all Cypress tests
- name: Cypress run
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
uses: cypress-io/github-action@v4
id: cypress
# If CYPRESS_RECORD_KEY is set, run in parallel on all containers
# Otherwise (e.g. if running from fork), we run on a single container only
if: ${{ ( env.CYPRESS_RECORD_KEY != '' ) || ( matrix.containers == 1 ) }}
with:
install: false
start: pnpm run dev:coverage
wait-on: 'http://localhost:9000'
browser: chrome
# Disable recording if we don't have an API key
# e.g. if this action was run from a fork
record: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
parallel: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
VITEST_COVERAGE: true
CYPRESS_COMMIT: ${{ github.sha }}
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
ARGOS_PARALLEL: true
ARGOS_PARALLEL_TOTAL: ${{ strategy.job-total }}
ARGOS_PARALLEL_INDEX: ${{ matrix.containers }}
SPLIT: ${{ strategy.job-total }}
SPLIT_INDEX: ${{ strategy.job-index }}
SPLIT_FILE: 'cypress/timings.json'
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
uses: codecov/codecov-action@v3
# Run step only pushes to develop and pull_requests
if: ${{ steps.cypress.conclusion == 'success' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/develop')}}
with:
@@ -149,3 +100,10 @@ jobs:
fail_ci_if_error: false
verbose: true
token: 6845cc80-77ee-4e17-85a1-026cd95e0766
- name: Upload Artifacts
uses: actions/upload-artifact@v3
if: ${{ failure() && steps.cypress.conclusion == 'failure' }}
with:
name: error-snapshots
path: cypress/snapshots/**/__diff_output__/*

View File

@@ -4,17 +4,11 @@ on:
issues:
types: [opened]
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs:
triage:
permissions:
issues: write # for andymckay/labeler to label issues
pull-requests: write # for andymckay/labeler to label PRs
runs-on: ubuntu-latest
steps:
- uses: andymckay/labeler@e6c4322d0397f3240f0e7e30a33b5c5df2d39e90 # 1.0.4
- uses: andymckay/labeler@1.0.4
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'
add-labels: 'Status: Triage'

View File

@@ -19,9 +19,6 @@ on:
# * is a special character in YAML so you have to quote this string
- cron: '30 8 * * *'
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs:
link-checker:
runs-on: ubuntu-latest
@@ -29,17 +26,17 @@ jobs:
# lychee only uses the GITHUB_TOKEN to avoid rate-limiting
contents: read
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v4
- name: Restore lychee cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2
uses: actions/cache@v3
with:
path: .lycheecache
key: cache-lychee-${{ github.sha }}
restore-keys: cache-lychee-
- name: Link Checker
uses: lycheeverse/lychee-action@c053181aa0c3d17606addfe97a9075a32723548a # v1.9.3
uses: lycheeverse/lychee-action@v1.9.1
with:
args: >-
--config .github/lychee.toml

View File

@@ -4,35 +4,32 @@ on:
push:
merge_group:
pull_request:
types:
- opened
- synchronize
- ready_for_review
workflow_dispatch:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions:
contents: write
jobs:
docker-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: hadolint/hadolint-action@54c9adbab1582c2ef04b2016b760714a4bfde3cf # v3.1.0
with:
verbose: true
lint:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
cache: pnpm
node-version-file: '.node-version'
node-version: ${{ matrix.node-version }}
- name: Install Packages
run: |
@@ -89,9 +86,14 @@ jobs:
continue-on-error: ${{ github.event_name == 'push' }}
run: pnpm run docs:verify
- uses: testomatio/check-tests@0ea638fcec1820cf2e7b9854fdbdd04128a55bd4 # stable
- name: Rebuild Docs
if: ${{ steps.verifyDocs.outcome == 'failure' && github.event_name == 'push' }}
working-directory: ./packages/mermaid
run: pnpm run docs:build
- name: Commit changes
uses: EndBug/add-and-commit@v9
if: ${{ steps.verifyDocs.outcome == 'failure' && github.event_name == 'push' }}
with:
framework: cypress
tests: './cypress/e2e/**/**.spec.js'
token: ${{ secrets.GITHUB_TOKEN }}
has-tests-label: true
message: 'Update docs'
add: 'docs/*'

View File

@@ -22,7 +22,7 @@ jobs:
pull-requests: write # write permission is required to label PRs
steps:
- name: Label PR
uses: release-drafter/release-drafter@3f0f87098bd6b5c5b9a36d49c41d998ea58f9348 # v6.0.0
uses: release-drafter/release-drafter@v5
with:
config-name: pr-labeler.yml
disable-autolabeler: false

View File

@@ -23,27 +23,27 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: pnpm/action-setup@v2
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
uses: actions/setup-node@v4
with:
cache: pnpm
node-version-file: '.node-version'
node-version: 18
- name: Install Packages
run: pnpm install --frozen-lockfile
- name: Setup Pages
uses: actions/configure-pages@1f0c5cde4bc74cd7e1254d0cb4de8d49e9068c7d # v4.0.0
uses: actions/configure-pages@v3
- name: Run Build
run: pnpm --filter mermaid run docs:build:vitepress
- name: Upload artifact
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1
uses: actions/upload-pages-artifact@v1
with:
path: packages/mermaid/src/vitepress/.vitepress/dist
@@ -56,4 +56,4 @@ jobs:
steps:
- name: Deploy to GitHub Pages
id: deployment
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
uses: actions/deploy-pages@v2

23
.github/workflows/release-draft.yml vendored Normal file
View File

@@ -0,0 +1,23 @@
name: Draft Release
on:
push:
branches:
- master
permissions:
contents: read
jobs:
draft-release:
runs-on: ubuntu-latest
permissions:
contents: write # write permission is required to create a github release
pull-requests: read # required to read PR titles/labels
steps:
- name: Draft Release
uses: release-drafter/release-drafter@v5
with:
disable-autolabeler: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -9,17 +9,17 @@ jobs:
publish-preview:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v4
with:
fetch-depth: 0
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: pnpm/action-setup@v2
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
uses: actions/setup-node@v4
with:
cache: pnpm
node-version-file: '.node-version'
node-version: 18.x
- name: Install Packages
run: |
@@ -28,7 +28,7 @@ jobs:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Install Json
run: npm i json@11.0.0 --global
run: npm i json --global
- name: Publish
working-directory: ./packages/mermaid

View File

@@ -1,43 +0,0 @@
name: Preview release
on:
pull_request:
branches: [develop]
types: [opened, synchronize, labeled, ready_for_review]
concurrency:
group: ${{ github.workflow }}-${{ github.event.number }}
cancel-in-progress: true
permissions:
contents: read
actions: write
jobs:
preview:
if: ${{ github.repository_owner == 'mermaid-js' }}
runs-on: ubuntu-latest
permissions:
contents: read
id-token: write
issues: write
pull-requests: write
name: Publish preview release
timeout-minutes: 5
steps:
- name: Checkout Repo
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
cache: pnpm
node-version-file: '.node-version'
- name: Install Packages
run: pnpm install --frozen-lockfile
- name: Publish packages
run: pnpx pkg-pr-new publish --pnpm './packages/*'

47
.github/workflows/release-publish.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
name: Publish release
on:
release:
types: [published]
jobs:
publish:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: fregante/setup-git-user@v2
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js v18
uses: actions/setup-node@v4
with:
cache: pnpm
node-version: 18.x
- name: Install Packages
run: |
pnpm install --frozen-lockfile
npm i json --global
env:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Prepare release
run: |
VERSION=${GITHUB_REF:10}
echo "Preparing release $VERSION"
git checkout -t origin/release/$VERSION
npm version --no-git-tag-version --allow-same-version $VERSION
git add package.json
git commit -nm "Bump version $VERSION"
git checkout -t origin/master
git merge -m "Release $VERSION" --no-ff release/$VERSION
git push --no-verify
- name: Publish
run: |
npm set //registry.npmjs.org/:_authToken $NPM_TOKEN
npm publish
env:
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}

View File

@@ -1,46 +0,0 @@
name: Release
on:
push:
branches:
- master
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs:
release:
if: github.repository == 'mermaid-js/mermaid'
permissions:
contents: write # to create release (changesets/action)
id-token: write # OpenID Connect token needed for provenance
pull-requests: write # to create pull request (changesets/action)
name: Release
runs-on: ubuntu-latest
steps:
- name: Checkout Repo
uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
cache: pnpm
node-version-file: '.node-version'
- name: Install Packages
run: pnpm install --frozen-lockfile
- name: Create Release Pull Request or Publish to npm
id: changesets
uses: changesets/action@3de3850952bec538fde60aac71731376e57b9b57 # v1.4.8
with:
version: pnpm changeset:version
publish: pnpm changeset:publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true

View File

@@ -1,37 +0,0 @@
name: Scorecard supply-chain security
on:
branch_protection_rule:
push:
branches:
- develop
schedule:
- cron: 29 15 * * 0
permissions: read-all
jobs:
analysis:
name: Scorecard analysis
permissions:
id-token: write
security-events: write
runs-on: ubuntu-latest
steps:
- name: Checkout code
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
persist-credentials: false
- name: Run analysis
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
with:
results_file: results.sarif
results_format: sarif
publish_results: true
- name: Upload artifact
uses: actions/upload-artifact@97a0fba1372883ab732affbe8f94b823f91727db # v3.pre.node20
with:
name: SARIF file
path: results.sarif
retention-days: 5
- name: Upload to code-scanning
uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
with:
sarif_file: results.sarif

View File

@@ -8,17 +8,20 @@ permissions:
jobs:
unit-test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x]
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
- name: Setup Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
cache: pnpm
node-version-file: '.node-version'
node-version: ${{ matrix.node-version }}
- name: Install Packages
run: |
@@ -38,12 +41,8 @@ jobs:
run: |
pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts --coverage
- name: Verify out-of-tree build with TypeScript
run: |
pnpm test:check:tsc
- name: Upload Coverage to Codecov
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0
uses: codecov/codecov-action@v3
# Run step only pushes to develop and pull_requests
if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' }}
with:

View File

@@ -8,6 +8,6 @@ jobs:
triage:
runs-on: ubuntu-latest
steps:
- uses: Dunning-Kruger/unlock-issues@b06b7f7e5c3f2eaa1c6d5d89f40930e4d6d9699e # v1
- uses: Dunning-Kruger/unlock-issues@v1
with:
repo-token: '${{ secrets.GITHUB_TOKEN }}'

View File

@@ -8,18 +8,11 @@ jobs:
update-browser-list:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- run: npx update-browserslist-db@latest
- uses: actions/checkout@v4
- run: npx browserslist@latest --update-db
- name: Commit changes
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4
uses: EndBug/add-and-commit@v9
with:
author_name: ${{ github.actor }}
author_email: ${{ github.actor }}@users.noreply.github.com
message: 'chore: update browsers list'
push: false
- name: Create Pull Request
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6.1.0
with:
branch: update-browserslist
title: Update Browserslist

7
.gitignore vendored
View File

@@ -35,7 +35,7 @@ cypress/snapshots/
.tsbuildinfo
tsconfig.tsbuildinfo
#knsv*.html
knsv*.html
local*.html
stats/
@@ -46,9 +46,4 @@ stats/
demos/dev/**
!/demos/dev/example.html
!/demos/dev/reload.js
tsx-0/**
vite.config.ts.timestamp-*
# autogenereated by langium-cli
generated/

View File

@@ -1,2 +0,0 @@
ignored:
- DL3002 # TODO: Last USER should not be root

4
.husky/commit-msg Executable file
View File

@@ -0,0 +1,4 @@
#!/bin/sh
# . "$(dirname "$0")/_/husky.sh"
# npx --no-install commitlint --edit $1

View File

@@ -1,2 +1,4 @@
#!/usr/bin/env sh
NODE_OPTIONS="--max_old_space_size=8192" pnpm run pre-commit
#!/bin/sh
. "$(dirname "$0")/_/husky.sh"
pnpm run pre-commit

View File

@@ -6,6 +6,6 @@ export default {
// https://prettier.io/docs/en/cli.html#--cache
'prettier --write',
],
'.cspell/*.txt': ['tsx scripts/fixCSpell.ts'],
'cSpell.json': ['tsx scripts/fixCSpell.ts'],
'**/*.jison': ['pnpm -w run lint:jison'],
};

View File

@@ -1 +0,0 @@
20.12.2

1
.npmrc
View File

@@ -1,4 +1,3 @@
registry=https://registry.npmjs.org
auto-install-peers=true
strict-peer-dependencies=false
package-import-method=clone-or-copy

View File

@@ -1,7 +1,6 @@
dist
cypress/platform/xss3.html
.cache
.pnpm-store
coverage
# Autogenerated by PNPM
pnpm-lock.yaml
@@ -11,10 +10,6 @@ stats
.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
# TODO: Lots of errors to fix
cypress/platform/state-refactor.html
!/demos/dev/example.html

View File

@@ -3,6 +3,5 @@
"printWidth": 100,
"singleQuote": true,
"useTabs": false,
"tabWidth": 2,
"trailingComma": "es5"
"tabWidth": 2
}

View File

@@ -1,15 +1,13 @@
import type { InlineConfig } from 'vite';
import { build, type PluginOption } from 'vite';
import { build, InlineConfig, type PluginOption } from 'vite';
import { resolve } from 'path';
import { fileURLToPath } from 'url';
import jisonPlugin from './jisonPlugin.js';
import jsonSchemaPlugin from './jsonSchemaPlugin.js';
import { readFileSync } from 'fs';
import typescript from '@rollup/plugin-typescript';
import { visualizer } from 'rollup-plugin-visualizer';
import type { TemplateType } from 'rollup-plugin-visualizer/dist/plugin/template-types.js';
import istanbul from 'vite-plugin-istanbul';
import { packageOptions } from '../.build/common.js';
import { generateLangium } from '../.build/generateLangium.js';
const visualize = process.argv.includes('--visualize');
const watch = process.argv.includes('--watch');
@@ -38,6 +36,24 @@ const visualizerOptions = (packageName: string, core = false): PluginOption[] =>
);
};
const packageOptions = {
mermaid: {
name: 'mermaid',
packageName: 'mermaid',
file: 'mermaid.ts',
},
'mermaid-example-diagram': {
name: 'mermaid-example-diagram',
packageName: 'mermaid-example-diagram',
file: 'detector.ts',
},
'mermaid-zenuml': {
name: 'mermaid-zenuml',
packageName: 'mermaid-zenuml',
file: 'detector.ts',
},
};
interface BuildOptions {
minify: boolean | 'esbuild';
core?: boolean;
@@ -47,18 +63,43 @@ interface BuildOptions {
export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions): InlineConfig => {
const external: (string | RegExp)[] = ['require', 'fs', 'path'];
// eslint-disable-next-line no-console
console.log(entryName, packageOptions[entryName]);
const { name, file, packageName } = packageOptions[entryName];
const output: OutputOptions = [
let output: OutputOptions = [
{
name,
format: 'esm',
sourcemap,
entryFileNames: `${name}.esm${minify ? '.min' : ''}.mjs`,
},
{
name,
format: 'umd',
sourcemap,
entryFileNames: `${name}${minify ? '.min' : ''}.js`,
},
];
if (core) {
const { dependencies } = JSON.parse(
readFileSync(resolve(__dirname, `../packages/${packageName}/package.json`), 'utf-8')
);
// Core build is used to generate file without bundled dependencies.
// This is used by downstream projects to bundle dependencies themselves.
// Ignore dependencies and any dependencies of dependencies
// Adapted from the RegEx used by `rollup-plugin-node`
external.push(new RegExp('^(?:' + Object.keys(dependencies).join('|') + ')(?:/.+)?$'));
// This needs to be an array. Otherwise vite will build esm & umd with same name and overwrite esm with umd.
output = [
{
name,
format: 'esm',
sourcemap,
entryFileNames: `${name}.core.mjs`,
},
];
}
const config: InlineConfig = {
configFile: false,
build: {
@@ -85,9 +126,10 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
plugins: [
jisonPlugin(),
jsonSchemaPlugin(), // handles `.schema.yaml` files
// @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite
typescript({ compilerOptions: { declaration: false } }),
istanbul({
exclude: ['node_modules', 'test/', '__mocks__', 'generated'],
exclude: ['node_modules', 'test/', '__mocks__'],
extension: ['.js', '.ts'],
requireEnv: true,
forceBuildInstrument: coverage,
@@ -107,28 +149,24 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
const buildPackage = async (entryName: keyof typeof packageOptions) => {
await build(getBuildConfig({ minify: false, entryName }));
await build(getBuildConfig({ minify: 'esbuild', entryName }));
await build(getBuildConfig({ minify: false, core: true, entryName }));
};
const main = async () => {
const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[];
for (const pkg of packageNames.filter(
(pkg) => !mermaidOnly || pkg === 'mermaid' || pkg === 'parser'
)) {
for (const pkg of packageNames.filter((pkg) => !mermaidOnly || pkg === 'mermaid')) {
await buildPackage(pkg);
}
};
await generateLangium();
if (watch) {
await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' }));
void build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' }));
build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' }));
if (!mermaidOnly) {
void build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' }));
void build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-zenuml' }));
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' }));
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-zenuml' }));
}
} else if (visualize) {
await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' }));
await build(getBuildConfig({ minify: false, core: true, entryName: 'mermaid' }));
await build(getBuildConfig({ minify: false, core: false, entryName: 'mermaid' }));
} else {

View File

@@ -1,10 +1,10 @@
import { transformJison } from '../.build/jisonTransformer.js';
import { transformJison } from './jisonTransformer.js';
const fileRegex = /\.(jison)$/;
export default function jison() {
return {
name: 'jison',
transform(src: string, id: string) {
if (fileRegex.test(id)) {
return {

View File

@@ -1,7 +1,6 @@
import jison from 'jison';
export const transformJison = (src: string): string => {
// @ts-ignore - Jison is not typed properly
const parser = new jison.Generator(src, {
moduleType: 'js',
'token-stack': true,

View File

@@ -1,5 +1,109 @@
import type { PluginOption } from 'vite';
import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js';
import { load, JSON_SCHEMA } from 'js-yaml';
import assert from 'node:assert';
import Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js';
import { PluginOption } from 'vite';
import type { MermaidConfig, BaseDiagramConfig } from '../packages/mermaid/src/config.type.js';
/**
* All of the keys in the mermaid config that have a mermaid diagram config.
*/
const MERMAID_CONFIG_DIAGRAM_KEYS = [
'flowchart',
'sequence',
'gantt',
'journey',
'class',
'state',
'er',
'pie',
'quadrantChart',
'xyChart',
'requirement',
'mindmap',
'timeline',
'gitGraph',
'c4',
'sankey',
] as const;
/**
* Generate default values from the JSON Schema.
*
* AJV does not support nested default values yet (or default values with $ref),
* so we need to manually find them (this may be fixed in ajv v9).
*
* @param mermaidConfigSchema - The Mermaid JSON Schema to use.
* @returns The default mermaid config object.
*/
function generateDefaults(mermaidConfigSchema: JSONSchemaType<MermaidConfig>) {
const ajv = new Ajv2019({
useDefaults: true,
allowUnionTypes: true,
strict: true,
});
ajv.addKeyword({
keyword: 'meta:enum', // used by jsonschema2md
errors: false,
});
ajv.addKeyword({
keyword: 'tsType', // used by json-schema-to-typescript
errors: false,
});
// ajv currently doesn't support nested default values, see https://github.com/ajv-validator/ajv/issues/1718
// (may be fixed in v9) so we need to manually use sub-schemas
const mermaidDefaultConfig = {};
assert.ok(mermaidConfigSchema.$defs);
const baseDiagramConfig = mermaidConfigSchema.$defs.BaseDiagramConfig;
for (const key of MERMAID_CONFIG_DIAGRAM_KEYS) {
const subSchemaRef = mermaidConfigSchema.properties[key].$ref;
const [root, defs, defName] = subSchemaRef.split('/');
assert.strictEqual(root, '#');
assert.strictEqual(defs, '$defs');
const subSchema = {
$schema: mermaidConfigSchema.$schema,
$defs: mermaidConfigSchema.$defs,
...mermaidConfigSchema.$defs[defName],
} as JSONSchemaType<BaseDiagramConfig>;
const validate = ajv.compile(subSchema);
mermaidDefaultConfig[key] = {};
for (const required of subSchema.required ?? []) {
if (subSchema.properties[required] === undefined && baseDiagramConfig.properties[required]) {
mermaidDefaultConfig[key][required] = baseDiagramConfig.properties[required].default;
}
}
if (!validate(mermaidDefaultConfig[key])) {
throw new Error(
`schema for subconfig ${key} does not have valid defaults! Errors were ${JSON.stringify(
validate.errors,
undefined,
2
)}`
);
}
}
const validate = ajv.compile(mermaidConfigSchema);
if (!validate(mermaidDefaultConfig)) {
throw new Error(
`Mermaid config JSON Schema does not have valid defaults! Errors were ${JSON.stringify(
validate.errors,
undefined,
2
)}`
);
}
return mermaidDefaultConfig;
}
/**
* Vite plugin that handles JSON Schemas saved as a `.schema.yaml` file.
@@ -16,13 +120,32 @@ export default function jsonSchemaPlugin(): PluginOption {
return;
}
const jsonSchema = loadSchema(src, idAsUrl.pathname);
return {
code: idAsUrl.searchParams.get('only-defaults')
? getDefaults(jsonSchema)
: getSchema(jsonSchema),
map: null, // no source map
};
if (idAsUrl.searchParams.get('only-defaults')) {
const jsonSchema = load(src, {
filename: idAsUrl.pathname,
// only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
// e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
schema: JSON_SCHEMA,
}) as JSONSchemaType<MermaidConfig>;
return {
code: `export default ${JSON.stringify(generateDefaults(jsonSchema), undefined, 2)};`,
map: null, // no source map
};
} else {
return {
code: `export default ${JSON.stringify(
load(src, {
filename: idAsUrl.pathname,
// only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
// e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
schema: JSON_SCHEMA,
}),
undefined,
2
)};`,
map: null, // provide source map if available
};
}
},
};
}

View File

@@ -1,7 +1,6 @@
import express from 'express';
import cors from 'cors';
import { createServer as createViteServer } from 'vite';
import { packageOptions } from '../.build/common.js';
async function createServer() {
const app = express();
@@ -15,17 +14,16 @@ async function createServer() {
});
app.use(cors());
for (const { packageName } of Object.values(packageOptions)) {
app.use(express.static(`./packages/${packageName}/dist`));
}
app.use(express.static('./packages/mermaid/dist'));
app.use(express.static('./packages/mermaid-zenuml/dist'));
app.use(express.static('./packages/mermaid-example-diagram/dist'));
app.use(vite.middlewares);
app.use(express.static('demos'));
app.use(express.static('cypress/platform'));
app.listen(9000, () => {
// eslint-disable-next-line no-console
console.log(`Listening on http://localhost:9000`);
});
}
void createServer();
createServer();

View File

@@ -2,7 +2,7 @@
"recommendations": [
"dbaeumer.vscode-eslint",
"esbenp.prettier-vscode",
"vitest.explorer",
"zixuanchen.vitest-explorer",
"luniclynx.bison"
]
}

View File

@@ -1,13 +1,2 @@
FROM node:20.12.2-alpine3.19@sha256:7a91aa397f2e2dfbfcdad2e2d72599f374e0b0172be1d86eeb73f1d33f36a4b2
USER 0:0
RUN corepack enable \
&& corepack enable pnpm
RUN apk add --no-cache git~=2.43.4 \
&& git config --add --system safe.directory /mermaid
ENV NODE_OPTIONS="--max_old_space_size=8192"
EXPOSE 9000 3333
FROM node:18.19.0-alpine3.18 AS base
RUN wget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.shrc" SHELL="$(which sh)" sh -

View File

@@ -1,7 +0,0 @@
{
"drips": {
"ethereum": {
"ownedBy": "0x0831DDFe60d009d9448CC976157b539089aB821E"
}
}
}

View File

@@ -15,7 +15,7 @@ Generate diagrams from markdown-like text.
<a href="https://mermaid.live/"><b>Live Editor!</b></a>
</p>
<p align="center">
<a href="https://mermaid.js.org">📖 Documentation</a> | <a href="https://mermaid.js.org/intro/">🚀 Getting Started</a> | <a href="https://www.jsdelivr.com/package/npm/mermaid">🌐 CDN</a> | <a href="https://discord.gg/AgrbSrBer3" title="Discord invite">🙌 Join Us</a>
<a href="https://mermaid.js.org">📖 Documentation</a> | <a href="https://mermaid.js.org/intro/">🚀 Getting Started</a> | <a href="https://www.jsdelivr.com/package/npm/mermaid">🌐 CDN</a> | <a href="https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE" title="Slack invite">🙌 Join Us</a>
</p>
<p align="center">
<a href="./README.zh-CN.md">简体中文</a>
@@ -33,10 +33,8 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai
[![Coverage Status](https://codecov.io/github/mermaid-js/mermaid/branch/develop/graph/badge.svg)](https://app.codecov.io/github/mermaid-js/mermaid/tree/develop)
[![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid)
[![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid)
[![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/AgrbSrBer3)
[![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
[![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_)
[![Covered by Argos Visual Testing](https://argos-ci.com/badge.svg)](https://argos-ci.com?utm_source=mermaid&utm_campaign=oss)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/mermaid-js/mermaid/badge)](https://securityscorecards.dev/viewer/?uri=github.com/mermaid-js/mermaid)
<img src="./img/header.png" alt="" />
@@ -44,7 +42,7 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai
**Thanks to all involved, people committing pull requests, people answering questions! 🙏**
<a href="https://mermaid.js.org/landing/"><img src="https://github.com/mermaid-js/mermaid/blob/master/docs/intro/img/book-banner-post-release.jpg" alt="Explore Mermaid.js in depth, with real-world examples, tips & tricks from the creator... The first official book on Mermaid is available for purchase. Check it out!"></a>
<a href="https://mermaid-js.github.io/mermaid/landing/"><img src="https://github.com/mermaid-js/mermaid/blob/master/docs/intro/img/book-banner-post-release.jpg" alt="Explore Mermaid.js in depth, with real-world examples, tips & tricks from the creator... The first official book on Mermaid is available for purchase. Check it out!"></a>
## Table of content
@@ -55,7 +53,7 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai
- [Examples](#examples)
- [Release](#release)
- [Related projects](#related-projects)
- [Contributors](#contributors---)
- [Contributors](#contributors)
- [Security and safe diagrams](#security-and-safe-diagrams)
- [Reporting vulnerabilities](#reporting-vulnerabilities)
- [Appreciation](#appreciation)
@@ -76,16 +74,12 @@ Mermaid addresses this problem by enabling users to create easily modifiable dia
<br/>
Mermaid allows even non-programmers to easily create detailed diagrams through the [Mermaid Live Editor](https://mermaid.live/).<br/>
For video tutorials, visit our [Tutorials](https://mermaid.js.org/ecosystem/tutorials.html) page.
Use Mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](https://mermaid.js.org/ecosystem/integrations-community.html).
For video tutorials, visit our [Tutorials](./docs/ecosystem/tutorials.md) page.
Use Mermaid with your favorite applications, check out the list of [Integrations and Usages of Mermaid](./docs/ecosystem/integrations-community.md).
You can also use Mermaid within [GitHub](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/) as well many of your other favorite applications—check out the list of [Integrations and Usages of Mermaid](https://mermaid.js.org/ecosystem/integrations-community.html).
You can also use Mermaid within [GitHub](https://github.blog/2022-02-14-include-diagrams-markdown-files-mermaid/) as well many of your other favorite applications—check out the list of [Integrations and Usages of Mermaid](./docs/ecosystem/integrations-community.md).
For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](https://mermaid.js.org/intro/getting-started.html), [Usage](https://mermaid.js.org/config/usage.html) and [Tutorials](https://mermaid.js.org/ecosystem/tutorials.html).
Our PR Visual Regression Testing is powered by [Argos](https://argos-ci.com/?utm_source=mermaid&utm_campaign=oss) with their generous Open Source plan. It makes the process of reviewing PRs with visual changes a breeze.
[![Covered by Argos Visual Testing](https://argos-ci.com/badge-large.svg)](https://argos-ci.com?utm_source=mermaid&utm_campaign=oss)
For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](./docs/intro/getting-started.md), [Usage](./docs/config/usage.md) and [Tutorials](./docs/ecosystem/tutorials.md).
In our release process we rely heavily on visual regression tests using [applitools](https://applitools.com/). Applitools is a great service which has been easy to use and integrate with our tests.
@@ -97,11 +91,11 @@ In our release process we rely heavily on visual regression tests using [applito
## Examples
**The following are some examples of the diagrams, charts and graphs that can be made using Mermaid. Click here to jump into the [text syntax](https://mermaid.js.org/intro/syntax-reference.html).**
**The following are some examples of the diagrams, charts and graphs that can be made using Mermaid. Click here to jump into the [text syntax](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference).**
<!-- <Flowchart> -->
### Flowchart [<a href="https://mermaid.js.org/syntax/flowchart.html">docs</a> - <a href="https://mermaid.live/edit#pako:eNpNkMtqwzAQRX9FzKqFJK7t1km8KDQP6KJQSLOLvZhIY1tgS0GWmgbb_165IaFaiXvOFTPqgGtBkEJR6zOv0Fj2scsU8-ft8I5G5Gw6fe339GN7tnrYaafE45WvRsLW3Ya4bKVWwzVe_xU-FfVsc9hR62rLwvw_2591z7Y3FuUwgYZMg1L4ObrRzMBW1FAGqb8KKtCLGWRq8Ko7CbS0FdJqA2mBdUsTQGf110VxSK1xdJM2EkuDzd2qNQrypQ7s5TQuXcrW-ie5VoUsx9yZ2seVtac2DYIRz0ppK3eccd0ErRTjD1XfyyRIomSBUUzJPMaXOBb8GC4XRfQcFmL-FEYIwzD8AggvcHE">live editor</a>]
### Flowchart [<a href="https://mermaid-js.github.io/mermaid/#/flowchart">docs</a> - <a href="https://mermaid.live/edit#pako:eNpNkMtqwzAQRX9FzKqFJK7t1km8KDQP6KJQSLOLvZhIY1tgS0GWmgbb_165IaFaiXvOFTPqgGtBkEJR6zOv0Fj2scsU8-ft8I5G5Gw6fe339GN7tnrYaafE45WvRsLW3Ya4bKVWwzVe_xU-FfVsc9hR62rLwvw_2591z7Y3FuUwgYZMg1L4ObrRzMBW1FAGqb8KKtCLGWRq8Ko7CbS0FdJqA2mBdUsTQGf110VxSK1xdJM2EkuDzd2qNQrypQ7s5TQuXcrW-ie5VoUsx9yZ2seVtac2DYIRz0ppK3eccd0ErRTjD1XfyyRIomSBUUzJPMaXOBb8GC4XRfQcFmL-FEYIwzD8AggvcHE">live editor</a>]
```
flowchart LR
@@ -121,12 +115,12 @@ C -->|One| D[Result 1]
C -->|Two| E[Result 2]
```
### Sequence diagram [<a href="https://mermaid.js.org/syntax/sequenceDiagram.html">docs</a> - <a href="https://mermaid.live/edit#pako:eNo9kMluwjAQhl_F-AykQMuSA1WrbuLQQ3v1ZbAnsVXHkzrjVhHi3etQwKfRv4w-z0FqMihL2eF3wqDxyUEdoVHhwTuNk-12RzaU4g29JzHMY2HpV0BE0VO6V8ETtdkGz1Zb1F8qiPyG5LX84mrLAmpwoWNh-5a0pWCiAxUwGBXeiVHEU4oq8V_6AHYUwAu2lLLTjVQ4bc1rT2yleI0IfJG320faZ9ABbk-Jz3hZnFxBduR9L2oiM5Jj2WBswJn8-cMArSRbbFDJMo8GK0ielVThmKOpNcD4bBxTlGUFvsOxhMT02QctS44JL6HzAS-iJzCYOwfJfTscunYd542aQuXqQU_RZ9kyt11ZFIM9rR3btJ9qaorOGQuR7c9mWSznyzXMF7hcLeBusTB6P9usq_ntrDKrm9kc5PF4_AMJE56Z">live editor</a>]
### Sequence diagram [<a href="https://mermaid-js.github.io/mermaid/#/sequenceDiagram">docs</a> - <a href="https://mermaid.live/edit#pako:eNo9kMluwjAQhl_F-AykQMuSA1WrbuLQQ3v1ZbAnsVXHkzrjVhHi3etQwKfRv4w-z0FqMihL2eF3wqDxyUEdoVHhwTuNk-12RzaU4g29JzHMY2HpV0BE0VO6V8ETtdkGz1Zb1F8qiPyG5LX84mrLAmpwoWNh-5a0pWCiAxUwGBXeiVHEU4oq8V_6AHYUwAu2lLLTjVQ4bc1rT2yleI0IfJG320faZ9ABbk-Jz3hZnFxBduR9L2oiM5Jj2WBswJn8-cMArSRbbFDJMo8GK0ielVThmKOpNcD4bBxTlGUFvsOxhMT02QctS44JL6HzAS-iJzCYOwfJfTscunYd542aQuXqQU_RZ9kyt11ZFIM9rR3btJ9qaorOGQuR7c9mWSznyzXMF7hcLeBusTB6P9usq_ntrDKrm9kc5PF4_AMJE56Z">live editor</a>]
```
sequenceDiagram
Alice->>John: Hello John, how are you?
loop HealthCheck
loop Healthcheck
John->>John: Fight against hypochondria
end
Note right of John: Rational thoughts!
@@ -138,7 +132,7 @@ Bob-->>John: Jolly good!
```mermaid
sequenceDiagram
Alice->>John: Hello John, how are you?
loop HealthCheck
loop Healthcheck
John->>John: Fight against hypochondria
end
Note right of John: Rational thoughts!
@@ -147,7 +141,7 @@ John->>Bob: How about you?
Bob-->>John: Jolly good!
```
### Gantt chart [<a href="https://mermaid.js.org/syntax/gantt.html">docs</a> - <a href="https://mermaid.live/edit#pako:eNp90cGOgyAQBuBXIZxtFbG29bbZ3fsmvXKZylhJEAyOTZrGd1_sto3xsHMBhu-HBO689hp5xS_giJQbsCbjHTv9jcp9-q63SKhZpb3DhMXSOIiE5ZkoNpnYZGXynh6U-4jBK7JnVfBYJo9QvgjtEya1cj8QwFq0TMz4lZqxTBg0hOF5m1jifI2Lf7Bc490CyxUu1rhc4GLGPOEdhg6Mjq92V44xxanFDhWv4lRjA6MlxZWbIh17DYTf2pAPvGrADphwGMmfbq7mFYURX-jLwCVA91bWg8YYunO69Y8vMgPFI2vvGnOZ-2Owsd0S9UOVpvP29mKoHc_b2nfpYHQLgdrrsUzLvDxALrHcS9hJqeuzOB6avBCN3mciBz5N0y_wxZ0J">live editor</a>]
### Gantt chart [<a href="https://mermaid-js.github.io/mermaid/#/gantt">docs</a> - <a href="https://mermaid.live/edit#pako:eNp90cGOgyAQBuBXIZxtFbG29bbZ3fsmvXKZylhJEAyOTZrGd1_sto3xsHMBhu-HBO689hp5xS_giJQbsCbjHTv9jcp9-q63SKhZpb3DhMXSOIiE5ZkoNpnYZGXynh6U-4jBK7JnVfBYJo9QvgjtEya1cj8QwFq0TMz4lZqxTBg0hOF5m1jifI2Lf7Bc490CyxUu1rhc4GLGPOEdhg6Mjq92V44xxanFDhWv4lRjA6MlxZWbIh17DYTf2pAPvGrADphwGMmfbq7mFYURX-jLwCVA91bWg8YYunO69Y8vMgPFI2vvGnOZ-2Owsd0S9UOVpvP29mKoHc_b2nfpYHQLgdrrsUzLvDxALrHcS9hJqeuzOB6avBCN3mciBz5N0y_wxZ0J">live editor</a>]
```
gantt
@@ -171,7 +165,7 @@ gantt
Parallel 4 : des6, after des4, 1d
```
### Class diagram [<a href="https://mermaid.js.org/syntax/classDiagram.html">docs</a> - <a href="https://mermaid.live/edit#pako:eNpdkTFPwzAQhf-K5QlQ2zQJJG1UBaGWDYmBgYEwXO1LYuTEwXYqlZL_jt02asXm--690zvfgTLFkWaUSTBmI6DS0BTt2lfzkKx-p1PytEO9f1FtdaQkI2ulZNGuVqK1qEtgmOfk7BitSzKdOhg59XuNGgk0RDxed-_IOr6uf8cZ6UhTZ8bvHqS5ub1mr9svZPbjk6DEBlu7AQuXyBkx4gcvDk9cUMJq0XT_YaW0kNK5j-ufAoRzcihaQvLcoN4Jv50vvVxw_xrnD3RCG9QNCO4-8OgpqK1dpoJm7smxhF7agp6kfcfB4jMXVmmalW4tnFDorXrbt4xmVvc4is53GKFUwNF5DtTuO3-sShjrJjLVlqLyvNfS4drazmRB4NuzSti6386YagIjeA3a1rtlEiRRsoAoxiSN4SGOOduGy0UZ3YclT-dhBHQYhj8dc6_I">live editor</a>]
### Class diagram [<a href="https://mermaid-js.github.io/mermaid/#/classDiagram">docs</a> - <a href="https://mermaid.live/edit#pako:eNpdkTFPwzAQhf-K5QlQ2zQJJG1UBaGWDYmBgYEwXO1LYuTEwXYqlZL_jt02asXm--690zvfgTLFkWaUSTBmI6DS0BTt2lfzkKx-p1PytEO9f1FtdaQkI2ulZNGuVqK1qEtgmOfk7BitSzKdOhg59XuNGgk0RDxed-_IOr6uf8cZ6UhTZ8bvHqS5ub1mr9svZPbjk6DEBlu7AQuXyBkx4gcvDk9cUMJq0XT_YaW0kNK5j-ufAoRzcihaQvLcoN4Jv50vvVxw_xrnD3RCG9QNCO4-8OgpqK1dpoJm7smxhF7agp6kfcfB4jMXVmmalW4tnFDorXrbt4xmVvc4is53GKFUwNF5DtTuO3-sShjrJjLVlqLyvNfS4drazmRB4NuzSti6386YagIjeA3a1rtlEiRRsoAoxiSN4SGOOduGy0UZ3YclT-dhBHQYhj8dc6_I">live editor</a>]
```
classDiagram
@@ -213,7 +207,7 @@ class Class10 {
```
### State diagram [<a href="https://mermaid.js.org/syntax/stateDiagram.html">docs</a> - <a href="https://mermaid.live/edit#pako:eNpdkEFvgzAMhf8K8nEqpYSNthx22Xbcqcexg0sCiZQQlDhIFeK_L8A6TfXp6fOz9ewJGssFVOAJSbwr7ByadGR1n8T6evpO0vQ1uZDSekOrXGFsPqJPO6q-2-imH8f_0TeHXm50lfelsAMjnEHFY6xpMdRAUhhRQxUlFy0GTTXU_RytYeAx-AdXZB1ULWovdoCB7OXWN1CRC-Ju-r3uz6UtchGHJqDbsPygU57iysb2reoWHpyOWBINvsqypb3vFMlw3TfWZF5xiY7keC6zkpUnZIUojwW-FAVvrvn51LLnvOXHQ84Q5nn-AVtLcwk">live editor</a>]
### State diagram [<a href="https://mermaid-js.github.io/mermaid/#/stateDiagram">docs</a> - <a href="https://mermaid.live/edit#pako:eNpdkEFvgzAMhf8K8nEqpYSNthx22Xbcqcexg0sCiZQQlDhIFeK_L8A6TfXp6fOz9ewJGssFVOAJSbwr7ByadGR1n8T6evpO0vQ1uZDSekOrXGFsPqJPO6q-2-imH8f_0TeHXm50lfelsAMjnEHFY6xpMdRAUhhRQxUlFy0GTTXU_RytYeAx-AdXZB1ULWovdoCB7OXWN1CRC-Ju-r3uz6UtchGHJqDbsPygU57iysb2reoWHpyOWBINvsqypb3vFMlw3TfWZF5xiY7keC6zkpUnZIUojwW-FAVvrvn51LLnvOXHQ84Q5nn-AVtLcwk">live editor</a>]
```
stateDiagram-v2
@@ -235,7 +229,7 @@ Moving --> Crash
Crash --> [*]
```
### Pie chart [<a href="https://mermaid.js.org/syntax/pie.html">docs</a> - <a href="https://mermaid.live/edit#pako:eNo9jsFugzAMhl8F-VzBgEEh13Uv0F1zcYkTIpEEBadShXj3BU3dzf_n77e8wxQUgYDVkvQSbsFsEgpRtEN_5i_kvzx05XiC-xvUHVzAUXRoVe7v0heFBJ7JkQSRR0Ua08ISpD-ymlaFTN_KcoggNC4bXQATh5-Xn0BwTPSWbhZNRPdvLQEV5dIO_FrPZ43dOJ-cgtfWnDzFJeOZed1EVZ3r0lie06Ocgqs2q2aMPD_HvuqbfsCmpf7aYte2anrU46Cbz1qr60fdIBzH8QvW9lkl">live editor</a>]
### Pie chart [<a href="https://mermaid-js.github.io/mermaid/#/pie">docs</a> - <a href="https://mermaid.live/edit#pako:eNo9jsFugzAMhl8F-VzBgEEh13Uv0F1zcYkTIpEEBadShXj3BU3dzf_n77e8wxQUgYDVkvQSbsFsEgpRtEN_5i_kvzx05XiC-xvUHVzAUXRoVe7v0heFBJ7JkQSRR0Ua08ISpD-ymlaFTN_KcoggNC4bXQATh5-Xn0BwTPSWbhZNRPdvLQEV5dIO_FrPZ43dOJ-cgtfWnDzFJeOZed1EVZ3r0lie06Ocgqs2q2aMPD_HvuqbfsCmpf7aYte2anrU46Cbz1qr60fdIBzH8QvW9lkl">live editor</a>]
```
pie
@@ -253,7 +247,7 @@ pie
### Git graph [experimental - <a href="https://mermaid.live/edit#pako:eNqNkMFugzAMhl8F-VyVAR1tOW_aA-zKxSSGRCMJCk6lCvHuNZPKZdM0n-zf3_8r8QIqaIIGMqnB8kfEybQ--y4VnLP8-9RF9Mpkmm40hmlnDKmvkPiH_kfS7nFo_VN0FAf6XwocQGgxa_nGsm1bYEOOWmik1dRjGrmF1q-Cpkkj07u2HCI0PY4zHQATh8-7V9BwTPSE3iwOEd1OjQE1iWkBvk_bzQY7s0Sq4Hs7bHqKo8iGeZqbPN_WR7mpSd1RHpvPVhuMbG7XOq_L-oJlRfW5wteq0qorrpe-PBW9Pr8UJcK6rg-BLYPQ">live editor</a>]
### Bar chart (using gantt chart) [<a href="https://mermaid.js.org/syntax/gantt.html">docs</a> - <a href="https://mermaid.live/edit#pako:eNptkU1vhCAQhv8KIenNugiI4rkf6bmXpvEyFVxJFDYyNt1u9r8X63Z7WQ9m5pknLzieaBeMpQ3dg0dsPUkPOhwteXZIXmJcbCT3xMAxkuh8Z8kIEclyMIB209fqKcwTICFvG4IvFy_oLrZ-g9F26ILfQgvNFN94VaRXQ1iWqpumZBcu1J8p1E1TXDx59eQNr5LyEqjJn6hv5QnGNlxevZJmdLLpy5xJSzut45biYCfb0iaVxvawjNjS1p-TCguG16PvaIPzYjO67e3BwX6GiTY9jPFKH43DMF_hGMDY1J4oHg-_f8hFTJFd8L3br3yZx4QHxENsdrt1nO8dDstH3oVpF50ZYMbhU6ud4qoGLqyqBJRCmO6j0HXPZdGbihUc6Pmc0QP49xD-b5X69ZQv2gjO81IwzWqhC1lKrjJ6pA3nVS7SMiVjrKirWlYp5fs3osgrWeo00lorLWvOzz8JVbXm">live editor</a>]
### Bar chart (using gantt chart) [<a href="https://mermaid-js.github.io/mermaid/#/gantt">docs</a> - <a href="https://mermaid.live/edit#pako:eNptkU1vhCAQhv8KIenNugiI4rkf6bmXpvEyFVxJFDYyNt1u9r8X63Z7WQ9m5pknLzieaBeMpQ3dg0dsPUkPOhwteXZIXmJcbCT3xMAxkuh8Z8kIEclyMIB209fqKcwTICFvG4IvFy_oLrZ-g9F26ILfQgvNFN94VaRXQ1iWqpumZBcu1J8p1E1TXDx59eQNr5LyEqjJn6hv5QnGNlxevZJmdLLpy5xJSzut45biYCfb0iaVxvawjNjS1p-TCguG16PvaIPzYjO67e3BwX6GiTY9jPFKH43DMF_hGMDY1J4oHg-_f8hFTJFd8L3br3yZx4QHxENsdrt1nO8dDstH3oVpF50ZYMbhU6ud4qoGLqyqBJRCmO6j0HXPZdGbihUc6Pmc0QP49xD-b5X69ZQv2gjO81IwzWqhC1lKrjJ6pA3nVS7SMiVjrKirWlYp5fs3osgrWeo00lorLWvOzz8JVbXm">live editor</a>]
```
gantt
@@ -291,7 +285,7 @@ gantt
5 : 0, 5
```
### User Journey diagram [<a href="https://mermaid.js.org/syntax/userJourney.html">docs</a> - <a href="https://mermaid.live/edit#pako:eNplkMFuwjAQRH9l5TMiTVIC-FqqnjhxzWWJN4khsSN7XRSh_HsdKBVt97R6Mzsj-yoqq0hIAXCywRkaSwNxWHNHsB_hYt1ZmwYUfiueKtbWwIcFtjf5zgH2eCZgQgkrCXt64GgMg2fUzkvIn5Xd_V5COtMFvCH_62ht_5yk7MU8sn61HDTfxD8VYiF6cj1qFd94nWkpuKWYKWRcFdUYOi5FaaZoDYNCpnel2Toha-w8LQQGtofRVEKyC_Qw7TQ2DvsfV2dRUTy6Ch6H-UMb7TlGVtbUupl5cF3ELfPgZZLM8rLR3IbjsrJ94rVq0XH7uS2SIis2mOVUrHNc5bmqjul2U2evaa3WL2mGYpqmL2BGiho">live editor</a>]
### User Journey diagram [<a href="https://mermaid-js.github.io/mermaid/#/user-journey">docs</a> - <a href="https://mermaid.live/edit#pako:eNplkMFuwjAQRH9l5TMiTVIC-FqqnjhxzWWJN4khsSN7XRSh_HsdKBVt97R6Mzsj-yoqq0hIAXCywRkaSwNxWHNHsB_hYt1ZmwYUfiueKtbWwIcFtjf5zgH2eCZgQgkrCXt64GgMg2fUzkvIn5Xd_V5COtMFvCH_62ht_5yk7MU8sn61HDTfxD8VYiF6cj1qFd94nWkpuKWYKWRcFdUYOi5FaaZoDYNCpnel2Toha-w8LQQGtofRVEKyC_Qw7TQ2DvsfV2dRUTy6Ch6H-UMb7TlGVtbUupl5cF3ELfPgZZLM8rLR3IbjsrJ94rVq0XH7uS2SIis2mOVUrHNc5bmqjul2U2evaa3WL2mGYpqmL2BGiho">live editor</a>]
```
journey
@@ -317,7 +311,7 @@ gantt
Sit down: 3: Me
```
### C4 diagram [<a href="https://mermaid.js.org/syntax/c4.html">docs</a>]
### C4 diagram [<a href="https://mermaid-js.github.io/mermaid/#/c4c">docs</a>]
```
C4Context
@@ -411,7 +405,7 @@ The above command generates files into the `dist` folder and publishes them to <
Mermaid is a growing community and is always accepting new contributors. There's a lot of different ways to help out and we're always looking for extra hands! Look at [this issue](https://github.com/mermaid-js/mermaid/issues/866) if you want to know where to start helping out.
Detailed information about how to contribute can be found in the [contribution guide](https://mermaid.js.org/community/contributing.html)
Detailed information about how to contribute can be found in the [contribution guide](CONTRIBUTING.md)
## Security and safe diagrams

View File

@@ -15,7 +15,7 @@ Mermaid
<a href="https://mermaid.live/"><b>实时编辑器!</b></a>
</p>
<p align="center">
<a href="https://mermaid.js.org">📖 文档</a> | <a href="https://mermaid.js.org/intro/">🚀 入门</a> | <a href="https://www.jsdelivr.com/package/npm/mermaid">🌐 CDN</a> | <a href="https://discord.gg/AgrbSrBer3" title="Discord invite">🙌 加入我们</a>
<a href="https://mermaid.js.org">📖 文档</a> | <a href="https://mermaid.js.org/intro/">🚀 入门</a> | <a href="https://www.jsdelivr.com/package/npm/mermaid">🌐 CDN</a> | <a href="https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE" title="Slack invite">🙌 加入我们</a>
</p>
<p align="center">
<a href="./README.md">English</a>
@@ -34,7 +34,7 @@ Mermaid
[![Coverage Status](https://codecov.io/github/mermaid-js/mermaid/branch/develop/graph/badge.svg)](https://app.codecov.io/github/mermaid-js/mermaid/tree/develop)
[![CDN Status](https://img.shields.io/jsdelivr/npm/hm/mermaid)](https://www.jsdelivr.com/package/npm/mermaid)
[![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid)
[![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/AgrbSrBer3)
[![Join our Slack!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=slack&label=slack)](https://join.slack.com/t/mermaid-talk/shared_invite/enQtNzc4NDIyNzk4OTAyLWVhYjQxOTI2OTg4YmE1ZmJkY2Y4MTU3ODliYmIwOTY3NDJlYjA0YjIyZTdkMDMyZTUwOGI0NjEzYmEwODcwOTE)
[![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_)
<img src="./img/header.png" alt="" />
@@ -43,7 +43,7 @@ Mermaid
**感谢所有参与进来提交 PR解答疑问的人们! 🙏**
<a href="https://mermaid.js.org/landing/"><img src="https://github.com/mermaid-js/mermaid/blob/master/docs/intro/img/book-banner-post-release.jpg" alt="Explore Mermaid.js in depth, with real-world examples, tips & tricks from the creator... The first official book on Mermaid is available for purchase. Check it out!"></a>
<a href="https://mermaid-js.github.io/mermaid/landing/"><img src="https://github.com/mermaid-js/mermaid/blob/master/docs/intro/img/book-banner-post-release.jpg" alt="Explore Mermaid.js in depth, with real-world examples, tips & tricks from the creator... The first official book on Mermaid is available for purchase. Check it out!"></a>
## 关于 Mermaid
@@ -57,20 +57,20 @@ Mermaid 是一个基于 Javascript 的图表绘制工具,通过解析类 Markd
Mermaid 通过允许用户创建便于修改的图表来解决这一难题,它也可以作为生产脚本(或其他代码)的一部分。<br/>
<br/>
Mermaid 甚至能让非程序员也能通过 [Mermaid Live Editor](https://mermaid.live/) 轻松创建详细的图表。<br/>
你可以访问 [教程](https://mermaid.js.org/ecosystem/tutorials.html) 来查看 Live Editor 的视频教程,也可以查看 [Mermaid 的集成和使用](https://mermaid.js.org/ecosystem/integrations-community.html) 这个清单来检查你的文档工具是否已经集成了 Mermaid 支持。
你可以访问 [教程](./docs/ecosystem/tutorials.md) 来查看 Live Editor 的视频教程,也可以查看 [Mermaid 的集成和使用](./docs/ecosystem/integrations-community.md) 这个清单来检查你的文档工具是否已经集成了 Mermaid 支持。
如果想要查看关于 Mermaid 更详细的介绍及基础使用方式,可以查看 [入门指引](https://mermaid.js.org/intro/getting-started.html), [用法](https://mermaid.js.org/config/usage.html) 和 [教程](https://mermaid.js.org/ecosystem/tutorials.html).
如果想要查看关于 Mermaid 更详细的介绍及基础使用方式,可以查看 [入门指引](./docs/intro/getting-started.md), [用法](./docs/config/usage.md) 和 [教程](./docs/ecosystem/tutorials.md).
<!-- </Main description> -->
## 示例
**下面是一些可以使用 Mermaid 创建的图表示例。点击 [语法](https://mermaid.js.org/intro/syntax-reference.html) 查看详情。**
**下面是一些可以使用 Mermaid 创建的图表示例。点击 [语法](https://mermaid-js.github.io/mermaid/#/n00b-syntaxReference) 查看详情。**
<table>
<!-- <Flowchart> -->
### 流程图 [<a href="https://mermaid.js.org/syntax/flowchart.html">文档</a> - <a href="https://mermaid.live/edit#base64:eyJjb2RlIjoiZ3JhcGggVERcbiAgICBBW0hhcmRdIC0tPnxUZXh0fCBCKFJvdW5kKVxuICAgIEIgLS0-IEN7RGVjaXNpb259XG4gICAgQyAtLT58T25lfCBEW1Jlc3VsdCAxXVxuICAgIEMgLS0-fFR3b3wgRVtSZXN1bHQgMl0iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ">live editor</a>]
### 流程图 [<a href="https://mermaid-js.github.io/mermaid/#/flowchart">文档</a> - <a href="https://mermaid.live/edit#base64:eyJjb2RlIjoiZ3JhcGggVERcbiAgICBBW0hhcmRdIC0tPnxUZXh0fCBCKFJvdW5kKVxuICAgIEIgLS0-IEN7RGVjaXNpb259XG4gICAgQyAtLT58T25lfCBEW1Jlc3VsdCAxXVxuICAgIEMgLS0-fFR3b3wgRVtSZXN1bHQgMl0iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ">live editor</a>]
```
flowchart LR
@@ -88,12 +88,12 @@ C -->|One| D[Result 1]
C -->|Two| E[Result 2]
```
### 时序图 [<a href="https://mermaid.js.org/syntax/sequenceDiagram.html">文档</a> - <a href="https://mermaid.live/edit#base64:eyJjb2RlIjoic2VxdWVuY2VEaWFncmFtXG5BbGljZS0-PkpvaG46IEhlbGxvIEpvaG4sIGhvdyBhcmUgeW91P1xubG9vcCBIZWFsdGhjaGVja1xuICAgIEpvaG4tPj5Kb2huOiBGaWdodCBhZ2FpbnN0IGh5cG9jaG9uZHJpYVxuZW5kXG5Ob3RlIHJpZ2h0IG9mIEpvaG46IFJhdGlvbmFsIHRob3VnaHRzIVxuSm9obi0tPj5BbGljZTogR3JlYXQhXG5Kb2huLT4-Qm9iOiBIb3cgYWJvdXQgeW91P1xuQm9iLS0-PkpvaG46IEpvbGx5IGdvb2QhIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
### 时序图 [<a href="https://mermaid-js.github.io/mermaid/#/sequenceDiagram">文档</a> - <a href="https://mermaid.live/edit#base64:eyJjb2RlIjoic2VxdWVuY2VEaWFncmFtXG5BbGljZS0-PkpvaG46IEhlbGxvIEpvaG4sIGhvdyBhcmUgeW91P1xubG9vcCBIZWFsdGhjaGVja1xuICAgIEpvaG4tPj5Kb2huOiBGaWdodCBhZ2FpbnN0IGh5cG9jaG9uZHJpYVxuZW5kXG5Ob3RlIHJpZ2h0IG9mIEpvaG46IFJhdGlvbmFsIHRob3VnaHRzIVxuSm9obi0tPj5BbGljZTogR3JlYXQhXG5Kb2huLT4-Qm9iOiBIb3cgYWJvdXQgeW91P1xuQm9iLS0-PkpvaG46IEpvbGx5IGdvb2QhIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
```
sequenceDiagram
Alice->>John: Hello John, how are you?
loop HealthCheck
loop Healthcheck
John->>John: Fight against hypochondria
end
Note right of John: Rational thoughts!
@@ -105,7 +105,7 @@ Bob-->>John: Jolly good!
```mermaid
sequenceDiagram
Alice->>John: Hello John, how are you?
loop HealthCheck
loop Healthcheck
John->>John: Fight against hypochondria
end
Note right of John: Rational thoughts!
@@ -114,7 +114,7 @@ John->>Bob: How about you?
Bob-->>John: Jolly good!
```
### 甘特图 [<a href="https://mermaid.js.org/syntax/gantt.html">文档</a> - <a href="https://mermaid.live/edit#base64:eyJjb2RlIjoiZ2FudHRcbnNlY3Rpb24gU2VjdGlvblxuQ29tcGxldGVkIDpkb25lLCAgICBkZXMxLCAyMDE0LTAxLTA2LDIwMTQtMDEtMDhcbkFjdGl2ZSAgICAgICAgOmFjdGl2ZSwgIGRlczIsIDIwMTQtMDEtMDcsIDNkXG5QYXJhbGxlbCAxICAgOiAgICAgICAgIGRlczMsIGFmdGVyIGRlczEsIDFkXG5QYXJhbGxlbCAyICAgOiAgICAgICAgIGRlczQsIGFmdGVyIGRlczEsIDFkXG5QYXJhbGxlbCAzICAgOiAgICAgICAgIGRlczUsIGFmdGVyIGRlczMsIDFkXG5QYXJhbGxlbCA0ICAgOiAgICAgICAgIGRlczYsIGFmdGVyIGRlczQsIDFkIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
### 甘特图 [<a href="https://mermaid-js.github.io/mermaid/#/gantt">文档</a> - <a href="https://mermaid.live/edit#base64:eyJjb2RlIjoiZ2FudHRcbnNlY3Rpb24gU2VjdGlvblxuQ29tcGxldGVkIDpkb25lLCAgICBkZXMxLCAyMDE0LTAxLTA2LDIwMTQtMDEtMDhcbkFjdGl2ZSAgICAgICAgOmFjdGl2ZSwgIGRlczIsIDIwMTQtMDEtMDcsIDNkXG5QYXJhbGxlbCAxICAgOiAgICAgICAgIGRlczMsIGFmdGVyIGRlczEsIDFkXG5QYXJhbGxlbCAyICAgOiAgICAgICAgIGRlczQsIGFmdGVyIGRlczEsIDFkXG5QYXJhbGxlbCAzICAgOiAgICAgICAgIGRlczUsIGFmdGVyIGRlczMsIDFkXG5QYXJhbGxlbCA0ICAgOiAgICAgICAgIGRlczYsIGFmdGVyIGRlczQsIDFkIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
```
gantt
@@ -138,7 +138,7 @@ gantt
Parallel 4 : des6, after des4, 1d
```
### 类图 [<a href="https://mermaid.js.org/syntax/classDiagram.html">文档</a> - <a href="https://mermaid.live/edit#base64:eyJjb2RlIjoiY2xhc3NEaWFncmFtXG5DbGFzczAxIDx8LS0gQXZlcnlMb25nQ2xhc3MgOiBDb29sXG48PGludGVyZmFjZT4-IENsYXNzMDFcbkNsYXNzMDkgLS0-IEMyIDogV2hlcmUgYW0gaT9cbkNsYXNzMDkgLS0qIEMzXG5DbGFzczA5IC0tfD4gQ2xhc3MwN1xuQ2xhc3MwNyA6IGVxdWFscygpXG5DbGFzczA3IDogT2JqZWN0W10gZWxlbWVudERhdGFcbkNsYXNzMDEgOiBzaXplKClcbkNsYXNzMDEgOiBpbnQgY2hpbXBcbkNsYXNzMDEgOiBpbnQgZ29yaWxsYVxuY2xhc3MgQ2xhc3MxMCB7XG4gID4-c2VydmljZT4-XG4gIGludCBpZFxuICBzaXplKClcbn0iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ">live editor</a>]
### 类图 [<a href="https://mermaid-js.github.io/mermaid/#/classDiagram">文档</a> - <a href="https://mermaid.live/edit#base64:eyJjb2RlIjoiY2xhc3NEaWFncmFtXG5DbGFzczAxIDx8LS0gQXZlcnlMb25nQ2xhc3MgOiBDb29sXG48PGludGVyZmFjZT4-IENsYXNzMDFcbkNsYXNzMDkgLS0-IEMyIDogV2hlcmUgYW0gaT9cbkNsYXNzMDkgLS0qIEMzXG5DbGFzczA5IC0tfD4gQ2xhc3MwN1xuQ2xhc3MwNyA6IGVxdWFscygpXG5DbGFzczA3IDogT2JqZWN0W10gZWxlbWVudERhdGFcbkNsYXNzMDEgOiBzaXplKClcbkNsYXNzMDEgOiBpbnQgY2hpbXBcbkNsYXNzMDEgOiBpbnQgZ29yaWxsYVxuY2xhc3MgQ2xhc3MxMCB7XG4gID4-c2VydmljZT4-XG4gIGludCBpZFxuICBzaXplKClcbn0iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ">live editor</a>]
```
classDiagram
@@ -178,7 +178,7 @@ class Class10 {
}
```
### 状态图 [<a href="https://mermaid.js.org/syntax/stateDiagram.html">docs</a> - <a href="https://mermaid.live/edit#pako:eNpdkLsOwjAMRX-l8ojahTEDCzB26kgYrMYtkfJAqVMJVf13QiIKqqfr44d8vUDvFYGAiZHponEMaJv5KF2V4na4V01zqjrWxhSUZYapuEetn7UbCy16P_5HzwGnR6FZfpdCDZaCRa3SWcunQQI_yJIEkaSiAaNhCdKtqRUj--7lehAcItUQn-pnBMSAZtroVWn2YYOU07b4z29Y37gJVYk">live editor</a>]
### 状态图 [[<a href="https://mermaid-js.github.io/mermaid/#/stateDiagram">docs</a> - <a href="https://mermaid.live/edit#pako:eNpdkLsOwjAMRX-l8ojahTEDCzB26kgYrMYtkfJAqVMJVf13QiIKqqfr44d8vUDvFYGAiZHponEMaJv5KF2V4na4V01zqjrWxhSUZYapuEetn7UbCy16P_5HzwGnR6FZfpdCDZaCRa3SWcunQQI_yJIEkaSiAaNhCdKtqRUj--7lehAcItUQn-pnBMSAZtroVWn2YYOU07b4z29Y37gJVYk">live editor</a>]
```
stateDiagram-v2
@@ -200,7 +200,7 @@ Moving --> Crash
Crash --> [*]
```
### 饼图 [<a href="https://mermaid.js.org/syntax/pie.html">文档</a> - <a href="https://mermaid.live/edit#base64:eyJjb2RlIjoicGllXG5cIkRvZ3NcIiA6IDQyLjk2XG5cIkNhdHNcIiA6IDUwLjA1XG5cIlJhdHNcIiA6IDEwLjAxIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
### 饼图 [<a href="https://mermaid-js.github.io/mermaid/#/pie">文档</a> - <a href="https://mermaid.live/edit#base64:eyJjb2RlIjoicGllXG5cIkRvZ3NcIiA6IDQyLjk2XG5cIkNhdHNcIiA6IDUwLjA1XG5cIlJhdHNcIiA6IDEwLjAxIiwibWVybWFpZCI6eyJ0aGVtZSI6ImRlZmF1bHQifX0">live editor</a>]
```
pie
@@ -218,7 +218,7 @@ pie
### Git 图 [实验特性 - <a href="https://mermaid.live/edit#base64:eyJjb2RlIjoiZ2l0R3JhcGg6XG5vcHRpb25zXG57XG4gICAgXCJub2RlU3BhY2luZ1wiOiAxNTAsXG4gICAgXCJub2RlUmFkaXVzXCI6IDEwXG59XG5lbmRcbmNvbW1pdFxuYnJhbmNoIG5ld2JyYW5jaFxuY2hlY2tvdXQgbmV3YnJhbmNoXG5jb21taXRcbmNvbW1pdFxuY2hlY2tvdXQgbWFzdGVyXG5jb21taXRcbmNvbW1pdFxubWVyZ2UgbmV3YnJhbmNoXG4iLCJtZXJtYWlkIjp7InRoZW1lIjoiZGVmYXVsdCJ9fQ">live editor</a>]
### 用户体验旅程图 [<a href="https://mermaid.js.org/syntax/userJourney.html">文档</a> - <a href="https://mermaid.live/edit#pako:eNpljzEPgkAMhf9K05nFGJdbJXFiYmVpuKIncDVHL4QQ_ruHaILaqXnf63vpjLVYRoMAd4nB81R5SKNOO4ZiglFC6_wVLL3JwLU68XARUHnhTQcoqGVQJgMnAwV_5GSMj0HJhcHAcU_y7d7AYVUzOJP-ddyk3ydZGf0n66uldPqCPxWYYc-hJ2fTj_OqVqg3Tplo0mq5odhphZVfkpWiSjn5Go2GyBnGhyXl3NE1UI-moW7g5QkSoF5m">live editor</a>]
### 用户体验旅程图 [<a href="https://mermaid-js.github.io/mermaid/#/user-journey">文档</a> - <a href="https://mermaid.live/edit#pako:eNpljzEPgkAMhf9K05nFGJdbJXFiYmVpuKIncDVHL4QQ_ruHaILaqXnf63vpjLVYRoMAd4nB81R5SKNOO4ZiglFC6_wVLL3JwLU68XARUHnhTQcoqGVQJgMnAwV_5GSMj0HJhcHAcU_y7d7AYVUzOJP-ddyk3ydZGf0n66uldPqCPxWYYc-hJ2fTj_OqVqg3Tplo0mq5odhphZVfkpWiSjn5Go2GyBnGhyXl3NE1UI-moW7g5QkSoF5m">live editor</a>]
```
journey
@@ -244,7 +244,7 @@ pie
Sit down: 3: Me
```
### C4 图 [<a href="https://mermaid.js.org/syntax/c4.html">文档</a>]
### C4 图 [<a href="https://mermaid-js.github.io/mermaid/#/c4c">文档</a>]
```
C4Context
@@ -338,7 +338,7 @@ npm publish
Mermaid 是一个不断发展中的社区,并且还在接收新的贡献者。有很多不同的方式可以参与进来,而且我们还在寻找额外的帮助。如果你想知道如何开始贡献,请查看 [这个 issue](https://github.com/mermaid-js/mermaid/issues/866)。
关于如何贡献的详细信息可以在 [贡献指南](https://mermaid.js.org/community/contributing.html) 中找到。
关于如何贡献的详细信息可以在 [贡献指南](CONTRIBUTING.md) 中找到。
## 安全

21
__mocks__/c4Renderer.js Normal file
View File

@@ -0,0 +1,21 @@
/**
* Mocked C4Context diagram renderer
*/
import { vi } from 'vitest';
export const drawPersonOrSystemArray = vi.fn();
export const drawBoundary = vi.fn();
export const setConf = vi.fn();
export const draw = vi.fn().mockImplementation(() => {
return '';
});
export default {
drawPersonOrSystemArray,
drawBoundary,
setConf,
draw,
};

View File

@@ -0,0 +1,16 @@
/**
* Mocked class diagram v2 renderer
*/
import { vi } from 'vitest';
export const setConf = vi.fn();
export const draw = vi.fn().mockImplementation(() => {
return '';
});
export default {
setConf,
draw,
};

View File

@@ -0,0 +1,13 @@
/**
* Mocked class diagram renderer
*/
import { vi } from 'vitest';
export const draw = vi.fn().mockImplementation(() => {
return '';
});
export default {
draw,
};

1
__mocks__/dagre-d3.ts Normal file
View File

@@ -0,0 +1 @@
// DO NOT delete this file. It is used by vitest to mock the dagre-d3 module.

View File

@@ -0,0 +1,3 @@
module.exports = function (txt: string) {
return txt;
};

16
__mocks__/erRenderer.js Normal file
View File

@@ -0,0 +1,16 @@
/**
* Mocked er diagram renderer
*/
import { vi } from 'vitest';
export const setConf = vi.fn();
export const draw = vi.fn().mockImplementation(() => {
return '';
});
export default {
setConf,
draw,
};

View File

@@ -0,0 +1,24 @@
/**
* Mocked flow (flowchart) diagram v2 renderer
*/
import { vi } from 'vitest';
export const setConf = vi.fn();
export const addVertices = vi.fn();
export const addEdges = vi.fn();
export const getClasses = vi.fn().mockImplementation(() => {
return {};
});
export const draw = vi.fn().mockImplementation(() => {
return '';
});
export default {
setConf,
addVertices,
addEdges,
getClasses,
draw,
};

View File

@@ -0,0 +1,16 @@
/**
* Mocked gantt diagram renderer
*/
import { vi } from 'vitest';
export const setConf = vi.fn();
export const draw = vi.fn().mockImplementation(() => {
return '';
});
export default {
setConf,
draw,
};

View File

@@ -0,0 +1,13 @@
/**
* Mocked git (graph) diagram renderer
*/
import { vi } from 'vitest';
export const draw = vi.fn().mockImplementation(() => {
return '';
});
export default {
draw,
};

View File

@@ -0,0 +1,15 @@
/**
* Mocked pie (picChart) diagram renderer
*/
import { vi } from 'vitest';
export const setConf = vi.fn();
export const draw = vi.fn().mockImplementation(() => {
return '';
});
export default {
setConf,
draw,
};

8
__mocks__/pieRenderer.ts Normal file
View File

@@ -0,0 +1,8 @@
/**
* Mocked pie (picChart) diagram renderer
*/
import { vi } from 'vitest';
const draw = vi.fn().mockImplementation(() => '');
export const renderer = { draw };

View File

@@ -0,0 +1,13 @@
/**
* Mocked requirement diagram renderer
*/
import { vi } from 'vitest';
export const draw = vi.fn().mockImplementation(() => {
return '';
});
export default {
draw,
};

View File

@@ -0,0 +1,13 @@
/**
* Mocked Sankey diagram renderer
*/
import { vi } from 'vitest';
export const draw = vi.fn().mockImplementation(() => {
return '';
});
export default {
draw,
};

View File

@@ -0,0 +1,23 @@
/**
* Mocked sequence diagram renderer
*/
import { vi } from 'vitest';
export const bounds = vi.fn();
export const drawActors = vi.fn();
export const drawActorsPopup = vi.fn();
export const setConf = vi.fn();
export const draw = vi.fn().mockImplementation(() => {
return '';
});
export default {
bounds,
drawActors,
drawActorsPopup,
setConf,
draw,
};

View File

@@ -0,0 +1,22 @@
/**
* Mocked state diagram v2 renderer
*/
import { vi } from 'vitest';
export const setConf = vi.fn();
export const getClasses = vi.fn().mockImplementation(() => {
return {};
});
export const stateDomId = vi.fn().mockImplementation(() => {
return 'mocked-stateDiagram-stateDomId';
});
export const draw = vi.fn().mockImplementation(() => {
return '';
});
export default {
setConf,
getClasses,
draw,
};

19
applitools.config.js Normal file
View File

@@ -0,0 +1,19 @@
// eslint-disable-next-line @typescript-eslint/no-var-requires
const { defineConfig } = require('cypress');
module.exports = defineConfig({
testConcurrency: 1,
browser: [
// Add browsers with different viewports
// { width: 800, height: 600, name: 'chrome' },
// { width: 700, height: 500, name: 'firefox' },
// { width: 1600, height: 1200, name: 'ie11' },
// { width: 1024, height: 768, name: 'edgechromium' },
// { width: 800, height: 600, name: 'safari' },
// // Add mobile emulation devices in Portrait mode
// { deviceName: 'iPhone X', screenOrientation: 'portrait' },
// { deviceName: 'Pixel 2', screenOrientation: 'portrait' },
],
// set batch name to the configuration
// batchName: `Mermaid ${process.env.APPLI_BRANCH ?? "'no APPLI_BRANCH set'"}`,
});

208
cSpell.json Normal file
View File

@@ -0,0 +1,208 @@
{
"version": "0.2",
"language": "en",
"words": [
"acyclicer",
"adamiecki",
"alois",
"aloisklink",
"antiscript",
"antlr",
"appli",
"applitools",
"asciidoctor",
"ashish",
"ashishjain",
"astah",
"bbox",
"bilkent",
"bisheng",
"blrs",
"braintree",
"brkt",
"brolin",
"brotli",
"catmull",
"città",
"classdef",
"codedoc",
"codemia",
"colour",
"commitlint",
"cpettitt",
"customizability",
"cuzon",
"cytoscape",
"dagre",
"deepdwn",
"descr",
"docsify",
"docsy",
"doku",
"dompurify",
"dont",
"doublecircle",
"edgechromium",
"elems",
"elkjs",
"elle",
"faber",
"flatmap",
"foswiki",
"frontmatter",
"ftplugin",
"gantt",
"gitea",
"gitgraph",
"globby",
"graphlib",
"graphviz",
"grav",
"greywolf",
"gzipped",
"huynh",
"huynhicode",
"inkdrop",
"jaoude",
"jgreywolf",
"jison",
"jiti",
"kaufmann",
"khroma",
"klemm",
"klink",
"knsv",
"knut",
"knutsveidqvist",
"laganeckas",
"linetype",
"lintstagedrc",
"logmsg",
"lucida",
"markdownish",
"matthieu",
"matthieumorel",
"mdast",
"mdbook",
"mermaidjs",
"mermerd",
"mindaugas",
"mindmap",
"mindmaps",
"mitigations",
"mkdocs",
"mmorel",
"mult",
"neurodiverse",
"nextra",
"nikolay",
"nirname",
"npmjs",
"orlandoni",
"pathe",
"pbrolin",
"phpbb",
"plantuml",
"playfair",
"pnpm",
"podlite",
"quence",
"radious",
"ranksep",
"rect",
"rects",
"reda",
"redmine",
"regexes",
"rehype",
"roledescription",
"rozhkov",
"sandboxed",
"sankey",
"setupgraphviewbox",
"shiki",
"sidharth",
"sidharthv",
"sphinxcontrib",
"ssim",
"startx",
"starty",
"statediagram",
"steph",
"stopx",
"stopy",
"stylis",
"subhash-halder",
"substate",
"sulais",
"sveidqvist",
"swimm",
"techn",
"teststr",
"textlength",
"treemap",
"ts-nocheck",
"tsdoc",
"tuleap",
"tylerlong",
"typora",
"ugge",
"unist",
"unocss",
"upvoting",
"valign",
"verdana",
"viewports",
"vinod",
"visio",
"vitepress",
"vueuse",
"xlink",
"xychart",
"yash",
"yokozuna",
"zenuml",
"zune"
],
"patterns": [
{ "name": "Markdown links", "pattern": "\\((.*)\\)", "description": "" },
{
"name": "Markdown code blocks",
"pattern": "/^(\\s*`{3,}).*[\\s\\S]*?^\\1/gmx",
"description": "Taken from the cSpell example at https://cspell.org/configuration/patterns/#verbose-regular-expressions"
},
{
"name": "Inline code blocks",
"pattern": "\\`([^\\`\\r\\n]+?)\\`",
"description": "https://stackoverflow.com/questions/41274241/how-to-capture-inline-markdown-code-but-not-a-markdown-code-fence-with-regex"
},
{ "name": "Link contents", "pattern": "\\<a(.*)\\>", "description": "" },
{ "name": "Snippet references", "pattern": "-- snippet:(.*)", "description": "" },
{
"name": "Snippet references 2",
"pattern": "\\<\\[sample:(.*)",
"description": "another kind of snippet reference"
},
{ "name": "Multi-line code blocks", "pattern": "/^\\s*```[\\s\\S]*?^\\s*```/gm" },
{
"name": "HTML Tags",
"pattern": "<[^>]*>",
"description": "Reference: https://stackoverflow.com/questions/11229831/regular-expression-to-remove-html-tags-from-a-string"
}
],
"ignoreRegExpList": [
"Markdown links",
"Markdown code blocks",
"Inline code blocks",
"Link contents",
"Snippet references",
"Snippet references 2",
"Multi-line code blocks",
"HTML Tags"
],
"ignorePaths": [
"packages/mermaid/src/docs/CHANGELOG.md",
"packages/mermaid/src/docs/.vitepress/redirect.ts",
"packages/mermaid/src/docs/.vitepress/contributor-names.json"
]
}

View File

@@ -1,45 +0,0 @@
# yaml-language-server: $schema=https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json
$schema: https://raw.githubusercontent.com/streetsidesoftware/cspell/main/cspell.schema.json
version: '0.2'
language: en-US,en-GB
import:
- ./.cspell/cspell.config.yaml
ignoreRegExpList:
- character-set-cyrillic
- svg-block
ignorePaths:
- '*lock.{yaml,json}'
- dist
- CHANGELOG.md
- packages/mermaid/src/docs/.vitepress/redirect.ts
- packages/mermaid/src/docs/.vitepress/contributor-names.json
- backup
- '**/*.spec.{js,ts}' # checked by eslint
- 'tests/webpack/src/index.js' # checked by eslint
- 'cypress/**/*.js' # checked by eslint
- '*.csv'
- '*.patch'
- 'docs/**/*.html'
- 'cypress/platform/**'
dictionaries:
- misc-terms
overrides:
- filename:
- '**/*.{jison,ts,mts,cjs,mjs,js,json,yaml,yml,md,html}'
- 'run'
- Dockerfile
ignoreRegExpList:
- js-unicode-escape
dictionaries:
- code-terms
- 3rd-party-terms
- fonts
- html
- lorem-ipsum
- filename: '**/package.json'
ignoreRegExpList:
- json-property
# cspell:dictionaries code-terms

32
cypress.config.cjs Normal file
View File

@@ -0,0 +1,32 @@
/* eslint-disable @typescript-eslint/no-var-requires */
const { defineConfig } = require('cypress');
const { addMatchImageSnapshotPlugin } = require('cypress-image-snapshot/plugin');
const coverage = require('@cypress/code-coverage/task');
module.exports = defineConfig({
projectId: 'n2sma2',
viewportWidth: 1440,
viewportHeight: 1024,
e2e: {
specPattern: 'cypress/integration/**/*.{js,ts}',
setupNodeEvents(on, config) {
coverage(on, config);
on('before:browser:launch', (browser = {}, launchOptions) => {
if (browser.name === 'chrome' && browser.isHeadless) {
launchOptions.args.push('--window-size=1440,1024', '--force-device-scale-factor=1');
}
return launchOptions;
});
addMatchImageSnapshotPlugin(on, config);
// copy any needed variables from process.env to config.env
config.env.useAppli = process.env.USE_APPLI ? true : false;
// do not forget to return the changed config object!
return config;
},
},
video: false,
});
require('@applitools/eyes-cypress')(module);

View File

@@ -1,41 +0,0 @@
import eyesPlugin from '@applitools/eyes-cypress';
import { registerArgosTask } from '@argos-ci/cypress/task';
import coverage from '@cypress/code-coverage/task';
import { defineConfig } from 'cypress';
import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin';
import cypressSplit from 'cypress-split';
export default eyesPlugin(
defineConfig({
projectId: 'n2sma2',
viewportWidth: 1440,
viewportHeight: 1024,
e2e: {
specPattern: 'cypress/integration/**/*.{js,ts}',
setupNodeEvents(on, config) {
coverage(on, config);
cypressSplit(on, config);
on('before:browser:launch', (browser, launchOptions) => {
if (browser.name === 'chrome' && browser.isHeadless) {
launchOptions.args.push('--window-size=1440,1024', '--force-device-scale-factor=1');
}
return launchOptions;
});
// copy any needed variables from process.env to config.env
config.env.useAppli = process.env.USE_APPLI ? true : false;
config.env.useArgos = !!process.env.CI;
if (config.env.useArgos) {
registerArgosTask(on, config, {
token: 'fc3a35cf5200db928d65b2047861582d9444032b',
});
} else {
addMatchImageSnapshotPlugin(on, config);
}
// do not forget to return the changed config object!
return config;
},
},
video: false,
})
);

View File

@@ -29,14 +29,13 @@ export const mermaidUrl = (
options: CypressMermaidConfig,
api: boolean
): string => {
options.handDrawnSeed = 1;
const codeObject: CodeObject = {
code: graphStr,
mermaid: options,
};
const objStr: string = JSON.stringify(codeObject);
let url = `http://localhost:9000/e2e.html?graph=${utf8ToB64(objStr)}`;
if (api && typeof graphStr === 'string') {
if (api) {
url = `http://localhost:9000/xss.html?graph=${graphStr}`;
}
@@ -55,15 +54,16 @@ export const imgSnapshotTest = (
): void => {
const options: CypressMermaidConfig = {
..._options,
fontFamily: _options.fontFamily ?? 'courier',
fontFamily: _options.fontFamily || 'courier',
// @ts-ignore TODO: Fix type of fontSize
fontSize: _options.fontSize ?? '16px',
fontSize: _options.fontSize || '16px',
sequence: {
...(_options.sequence ?? {}),
...(_options.sequence || {}),
actorFontFamily: 'courier',
noteFontFamily: _options.sequence?.noteFontFamily
? _options.sequence.noteFontFamily
: 'courier',
noteFontFamily:
_options.sequence && _options.sequence.noteFontFamily
? _options.sequence.noteFontFamily
: 'courier',
messageFontFamily: 'courier',
},
};
@@ -74,7 +74,7 @@ export const imgSnapshotTest = (
export const urlSnapshotTest = (
url: string,
options: CypressMermaidConfig = {},
options: CypressMermaidConfig,
_api = false,
validation?: any
): void => {
@@ -95,22 +95,8 @@ export const openURLAndVerifyRendering = (
options: CypressMermaidConfig,
validation?: any
): void => {
const name: string = (options.name ?? cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
cy.visit(url);
cy.window().should('have.property', 'rendered', true);
cy.get('svg').should('be.visible');
if (validation) {
cy.get('svg').should(validation);
}
verifyScreenshot(name);
};
export const verifyScreenshot = (name: string): void => {
const useAppli: boolean = Cypress.env('useAppli');
const useArgos: boolean = Cypress.env('useArgos');
const name: string = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
if (useAppli) {
cy.log(`Opening eyes ${Cypress.spec.name} --- ${name}`);
@@ -120,14 +106,21 @@ export const verifyScreenshot = (name: string): void => {
batchName: Cypress.spec.name,
batchId: batchId + Cypress.spec.name,
});
}
cy.visit(url);
cy.window().should('have.property', 'rendered', true);
cy.get('svg').should('be.visible');
if (validation) {
cy.get('svg').should(validation);
}
if (useAppli) {
cy.log(`Check eyes ${Cypress.spec.name}`);
cy.eyesCheckWindow('Click!');
cy.log(`Closing eyes ${Cypress.spec.name}`);
cy.eyesClose();
} else if (useArgos) {
cy.argosScreenshot(name, {
threshold: 0.01,
});
} else {
cy.matchImageSnapshot(name);
}

View File

@@ -1,4 +1,4 @@
import { renderGraph, verifyScreenshot } from '../../helpers/util.ts';
import { renderGraph } from '../../helpers/util.ts';
describe('Configuration', () => {
describe('arrowMarkerAbsolute', () => {
it('should handle default value false of arrowMarkerAbsolute', () => {
@@ -118,52 +118,11 @@ describe('Configuration', () => {
it('should not taint the initial configuration when using multiple directives', () => {
const url = 'http://localhost:9000/regression/issue-1874.html';
cy.visit(url);
cy.window().should('have.property', 'rendered', true);
verifyScreenshot(
cy.get('svg');
cy.matchImageSnapshot(
'configuration.spec-should-not-taint-initial-configuration-when-using-multiple-directives'
);
});
});
describe('suppressErrorRendering', () => {
beforeEach(() => {
cy.on('uncaught:exception', (err, runnable) => {
return !err.message.includes('Parse error on line');
});
});
it('should not render error diagram if suppressErrorRendering is set', () => {
const url = 'http://localhost:9000/suppressError.html?suppressErrorRendering=true';
cy.visit(url);
cy.window().should('have.property', 'rendered', true);
cy.get('#test')
.find('svg')
.should(($svg) => {
// all failing diagrams should not appear!
expect($svg).to.have.length(2);
// none of the diagrams should be error diagrams
expect($svg).to.not.contain('Syntax error');
});
verifyScreenshot(
'configuration.spec-should-not-render-error-diagram-if-suppressErrorRendering-is-set'
);
});
it('should render error diagram if suppressErrorRendering is not set', () => {
const url = 'http://localhost:9000/suppressError.html';
cy.visit(url);
cy.window().should('have.property', 'rendered', true);
cy.get('#test')
.find('svg')
.should(($svg) => {
// all five diagrams should be rendered
expect($svg).to.have.length(5);
// some of the diagrams should be error diagrams
expect($svg).to.contain('Syntax error');
});
verifyScreenshot(
'configuration.spec-should-render-error-diagram-if-suppressErrorRendering-is-not-set'
);
});
});
});

View File

@@ -1,11 +0,0 @@
describe('IIFE', () => {
beforeEach(() => {
cy.visit('http://localhost:9000/iife.html');
});
it('should render when using mermaid.min.js', () => {
cy.window().should('have.property', 'rendered', true);
cy.get('svg').should('be.visible');
cy.get('#d2').should('contain', 'Hello');
});
});

View File

@@ -0,0 +1,16 @@
describe('Sequencediagram', () => {
it('should render a simple sequence diagrams', () => {
const url = 'http://localhost:9000/webpackUsage.html';
cy.visit(url);
cy.get('body').find('svg').should('have.length', 1);
});
it('should handle html escapings properly', () => {
const url = 'http://localhost:9000/webpackUsage.html?test-html-escaping=true';
cy.visit(url);
cy.get('body').find('svg').should('have.length', 1);
cy.get('g.label > foreignobject > div').should('not.contain.text', '<b>');
});
});

View File

@@ -10,6 +10,7 @@ describe('XSS', () => {
cy.wait(1000).then(() => {
cy.get('.mermaid').should('exist');
});
cy.get('svg');
});
it('should not allow tags in the css', () => {
@@ -136,9 +137,4 @@ describe('XSS', () => {
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
it('should sanitize backticks block diagram labels properly', () => {
cy.visit('http://localhost:9000/xss25.html');
cy.wait(1000);
cy.get('#the-malware').should('not.exist');
});
});

View File

@@ -11,27 +11,6 @@ describe('Git Graph diagram', () => {
{}
);
});
it('Should render subgraphs with title margins and edge labels', () => {
imgSnapshotTest(
`flowchart LR
subgraph TOP
direction TB
subgraph B1
direction RL
i1 --lb1-->f1
end
subgraph B2
direction BT
i2 --lb2-->f2
end
end
A --lb3--> TOP --lb4--> B
B1 --lb5--> B2
`,
{ flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } } }
);
});
// it(`ultraFastTest`, function () {
// // Navigate to the url we want to test
// // ⭐️ Note to see visual bugs, run the test using the above URL for the 1st run.

View File

@@ -1,181 +0,0 @@
import { imgSnapshotTest, urlSnapshotTest } from '../../helpers/util.ts';
describe.skip('architecture diagram', () => {
it('should render a simple architecture diagram with groups', () => {
imgSnapshotTest(
`architecture-beta
group api(cloud)[API]
service db(database)[Database] in api
service disk1(disk)[Storage] in api
service disk2(disk)[Storage] in api
service server(server)[Server] in api
service gateway(internet)[Gateway]
db L--R server
disk1 T--B server
disk2 T--B db
server T--B gateway
`
);
});
it('should render an architecture diagram with groups within groups', () => {
imgSnapshotTest(
`architecture-beta
group api[API]
group public[Public API] in api
group private[Private API] in api
service serv1(server)[Server] in public
service serv2(server)[Server] in private
service db(database)[Database] in private
service gateway(internet)[Gateway] in api
serv1 B--T serv2
serv2 L--R db
serv1 L--R gateway
`
);
});
it('should render an architecture diagram with the fallback icon', () => {
imgSnapshotTest(
`architecture-beta
service unknown(iconnamedoesntexist)[Unknown Icon]
`
);
});
it('should render an architecture diagram with split directioning', () => {
imgSnapshotTest(
`architecture-beta
service db(database)[Database]
service s3(disk)[Storage]
service serv1(server)[Server 1]
service serv2(server)[Server 2]
service disk(disk)[Disk]
db L--R s3
serv1 L--T s3
serv2 L--B s3
serv1 T--B disk
`
);
});
it('should render an architecture diagram with directional arrows', () => {
imgSnapshotTest(
`architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC (L--R) servL
servC (R--L) servR
servC (T--B) servT
servC (B--T) servB
servL (T--L) servT
servL (B--L) servB
servR (T--R) servT
servR (B--R) servB
`
);
});
it('should render an architecture diagram with group edges', () => {
imgSnapshotTest(
`architecture-beta
group left_group(cloud)[Left]
group right_group(cloud)[Right]
group top_group(cloud)[Top]
group bottom_group(cloud)[Bottom]
group center_group(cloud)[Center]
service left_disk(disk)[Disk] in left_group
service right_disk(disk)[Disk] in right_group
service top_disk(disk)[Disk] in top_group
service bottom_disk(disk)[Disk] in bottom_group
service center_disk(disk)[Disk] in center_group
left_disk{group} (R--L) center_disk{group}
right_disk{group} (L--R) center_disk{group}
top_disk{group} (B--T) center_disk{group}
bottom_disk{group} (T--B) center_disk{group}
`
);
});
it('should render an architecture diagram with edge labels', () => {
imgSnapshotTest(
`architecture-beta
service servC(server)[Server 1]
service servL(server)[Server 2]
service servR(server)[Server 3]
service servT(server)[Server 4]
service servB(server)[Server 5]
servC L-[Label]-R servL
servC R-[Label]-L servR
servC T-[Label]-B servT
servC B-[Label]-T servB
servL T-[Label]-L servT
servL B-[Label]-L servB
servR T-[Label]-R servT
servR B-[Label]-R servB
`
);
});
it('should render an architecture diagram with simple junction edges', () => {
imgSnapshotTest(
`architecture-beta
service left_disk(disk)[Disk]
service top_disk(disk)[Disk]
service bottom_disk(disk)[Disk]
service top_gateway(internet)[Gateway]
service bottom_gateway(internet)[Gateway]
junction juncC
junction juncR
left_disk R--L juncC
top_disk B--T juncC
bottom_disk T--B juncC
juncC R--L juncR
top_gateway B--T juncR
bottom_gateway T--B juncR
`
);
});
it('should render an architecture diagram with complex junction edges', () => {
imgSnapshotTest(
`architecture-beta
group left
group right
service left_disk(disk)[Disk] in left
service top_disk(disk)[Disk] in left
service bottom_disk(disk)[Disk] in left
service top_gateway(internet)[Gateway] in right
service bottom_gateway(internet)[Gateway] in right
junction juncC in left
junction juncR in right
left_disk R--L juncC
top_disk B--T juncC
bottom_disk T--B juncC
top_gateway (B--T juncR
bottom_gateway (T--B juncR
juncC{group} R--L) juncR{group}
`
);
});
});
// Skipped as the layout is not deterministic, and causes issues in E2E tests.
describe.skip('architecture - external', () => {
it('should allow adding external icons', () => {
urlSnapshotTest('http://localhost:9000/architecture-external.html');
});
});

View File

@@ -1,387 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util';
/* eslint-disable no-useless-escape */
describe('Block diagram', () => {
it('BL1: should calculate the block widths', () => {
imgSnapshotTest(
`block-beta
columns 2
block
id2["I am a wide one"]
id1
end
id["Next row"]
`
);
});
it('BL2: should handle colums statement in sub-blocks', () => {
imgSnapshotTest(
`block-beta
id1["Hello"]
block
columns 3
id2["to"]
id3["the"]
id4["World"]
id5["World"]
end
`,
{}
);
});
it('BL3: should align block widths and handle colums statement in sub-blocks', () => {
imgSnapshotTest(
`block-beta
block
columns 1
id1
id2
id2.1
end
id3
id4
`,
{}
);
});
it('BL4: should align block widths and handle colums statements in deeper sub-blocks then 1 level', () => {
imgSnapshotTest(
`block-beta
columns 1
block
columns 1
block
columns 3
id1
id2
id2.1(("XYZ"))
end
id48
end
id3
`,
{}
);
});
it('BL5: should align block widths and handle colums statements in deeper sub-blocks then 1 level (alt)', () => {
imgSnapshotTest(
`block-beta
columns 1
block
id1
id2
block
columns 1
id3("Wider then")
id5(("id5"))
end
end
id4
`,
{}
);
});
it('BL6: should handle block arrows and spece statements', () => {
imgSnapshotTest(
`block-beta
columns 3
space:3
ida idb idc
id1 id2
blockArrowId<["Label"]>(right)
blockArrowId2<["Label"]>(left)
blockArrowId3<["Label"]>(up)
blockArrowId4<["Label"]>(down)
blockArrowId5<["Label"]>(x)
blockArrowId6<["Label"]>(y)
blockArrowId6<["Label"]>(x, down)
`,
{}
);
});
it('BL7: should handle different types of edges', () => {
imgSnapshotTest(
`block-beta
columns 3
A space:5
A --o B
A --> C
A --x D
`,
{}
);
});
it('BL8: should handle sub-blocks without columns statements', () => {
imgSnapshotTest(
`block-beta
columns 2
C A B
block
D
E
end
`,
{}
);
});
it('BL9: should handle edges from blocks in sub blocks to other blocks', () => {
imgSnapshotTest(
`block-beta
columns 3
B space
block
D
end
D --> B
`,
{}
);
});
it('BL10: should handle edges from composite blocks', () => {
imgSnapshotTest(
`block-beta
columns 3
B space
block BL
D
end
BL --> B
`,
{}
);
});
it('BL11: should handle edges to composite blocks', () => {
imgSnapshotTest(
`block-beta
columns 3
B space
block BL
D
end
B --> BL
`,
{}
);
});
it('BL12: edges should handle labels', () => {
imgSnapshotTest(
`block-beta
A
space
A -- "apa" --> E
`,
{}
);
});
it('BL13: should handle block arrows in different directions', () => {
imgSnapshotTest(
`block-beta
columns 3
space blockArrowId1<["down"]>(down) space
blockArrowId2<["right"]>(right) blockArrowId3<["Sync"]>(x, y) blockArrowId4<["left"]>(left)
space blockArrowId5<["up"]>(up) space
blockArrowId6<["x"]>(x) space blockArrowId7<["y"]>(y)
`,
{}
);
});
it('BL14: should style statements and class statements', () => {
imgSnapshotTest(
`block-beta
A
B
classDef blue fill:#66f,stroke:#333,stroke-width:2px;
class A blue
style B fill:#f9F,stroke:#333,stroke-width:4px
`,
{}
);
});
it('BL15: width alignment - D and E should share available space', () => {
imgSnapshotTest(
`block-beta
block
D
E
end
db("This is the text in the box")
`,
{}
);
});
it('BL16: width alignment - C should be as wide as the composite block', () => {
imgSnapshotTest(
`block-beta
block
A("This is the text")
B
end
C
`,
{}
);
});
it('BL17: width alignment - blocks shold be equal in width', () => {
imgSnapshotTest(
`block-beta
A("This is the text")
B
C
`,
{}
);
});
it('BL18: block types 1 - square, rounded and circle', () => {
imgSnapshotTest(
`block-beta
A["square"]
B("rounded")
C(("circle"))
`,
{}
);
});
it('BL19: block types 2 - odd, diamond and hexagon', () => {
imgSnapshotTest(
`block-beta
A>"rect_left_inv_arrow"]
B{"diamond"}
C{{"hexagon"}}
`,
{}
);
});
it('BL20: block types 3 - stadium', () => {
imgSnapshotTest(
`block-beta
A(["stadium"])
`,
{}
);
});
it('BL21: block types 4 - lean right, lean left, trapezoid and inv trapezoid', () => {
imgSnapshotTest(
`block-beta
A[/"lean right"/]
B[\"lean left"\]
C[/"trapezoid"\]
D[\"trapezoid alt"/]
`,
{}
);
});
it('BL22: block types 1 - square, rounded and circle', () => {
imgSnapshotTest(
`block-beta
A["square"]
B("rounded")
C(("circle"))
`,
{}
);
});
it('BL23: sizing - it should be possible to make a block wider', () => {
imgSnapshotTest(
`block-beta
A("rounded"):2
B:2
C
`,
{}
);
});
it('BL24: sizing - it should be possible to make a composite block wider', () => {
imgSnapshotTest(
`block-beta
block:2
A
end
B
`,
{}
);
});
it('BL25: block in the middle with space on each side', () => {
imgSnapshotTest(
`block-beta
columns 3
space
middle["In the middle"]
space
`,
{}
);
});
it('BL26: space and an edge', () => {
imgSnapshotTest(
`block-beta
columns 5
A space B
A --x B
`,
{}
);
});
it('BL27: block sizes for regular blocks', () => {
imgSnapshotTest(
`block-beta
columns 3
a["A wide one"] b:2 c:2 d
`,
{}
);
});
it('BL28: composite block with a set width - f should use the available space', () => {
imgSnapshotTest(
`block-beta
columns 3
a:3
block:e:3
f
end
g
`,
{}
);
});
it('BL29: composite block with a set width - f and g should split the available space', () => {
imgSnapshotTest(
`block-beta
columns 3
a:3
block:e:3
f
g
end
h
i
j
`,
{}
);
});
});

View File

@@ -1,7 +1,7 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
describe('C4 diagram', () => {
it('C4.1 should render a simple C4Context diagram', () => {
it('should render a simple C4Context diagram', () => {
imgSnapshotTest(
`
C4Context
@@ -30,8 +30,9 @@ describe('C4 diagram', () => {
`,
{}
);
cy.get('svg');
});
it('C4.2 should render a simple C4Container diagram', () => {
it('should render a simple C4Container diagram', () => {
imgSnapshotTest(
`
C4Container
@@ -49,8 +50,9 @@ describe('C4 diagram', () => {
`,
{}
);
cy.get('svg');
});
it('C4.3 should render a simple C4Component diagram', () => {
it('should render a simple C4Component diagram', () => {
imgSnapshotTest(
`
C4Component
@@ -67,8 +69,9 @@ describe('C4 diagram', () => {
`,
{}
);
cy.get('svg');
});
it('C4.4 should render a simple C4Dynamic diagram', () => {
it('should render a simple C4Dynamic diagram', () => {
imgSnapshotTest(
`
C4Dynamic
@@ -90,8 +93,9 @@ describe('C4 diagram', () => {
`,
{}
);
cy.get('svg');
});
it('C4.5 should render a simple C4Deployment diagram', () => {
it('should render a simple C4Deployment diagram', () => {
imgSnapshotTest(
`
C4Deployment
@@ -113,5 +117,6 @@ describe('C4 diagram', () => {
`,
{}
);
cy.get('svg');
});
});

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -76,7 +76,7 @@ describe('Class diagram V2', () => {
);
});
it('2.1 should render a simple class diagram with different visibilities', () => {
it('should render a simple class diagram with different visibilities', () => {
imgSnapshotTest(
`
classDiagram-v2
@@ -93,7 +93,7 @@ describe('Class diagram V2', () => {
);
});
it('3: should render multiple class diagrams', () => {
it('should render multiple class diagrams', () => {
imgSnapshotTest(
[
`
@@ -581,63 +581,4 @@ class C13["With Città foreign language"]
{ logLevel: 1, flowchart: { htmlLabels: false } }
);
});
it('renders a class diagram with a generic class in a namespace', () => {
const diagramDefinition = `
classDiagram-v2
namespace Company.Project.Module {
class GenericClass~T~ {
+addItem(item: T)
+getItem() T
}
}
`;
imgSnapshotTest(diagramDefinition);
});
it('renders a class diagram with nested namespaces and relationships', () => {
const diagramDefinition = `
classDiagram-v2
namespace Company.Project.Module.SubModule {
class Report {
+generatePDF(data: List)
+generateCSV(data: List)
}
}
namespace Company.Project.Module {
class Admin {
+generateReport()
}
}
Admin --> Report : generates
`;
imgSnapshotTest(diagramDefinition);
});
it('renders a class diagram with multiple classes and relationships in a namespace', () => {
const diagramDefinition = `
classDiagram-v2
namespace Company.Project.Module {
class User {
+login(username: String, password: String)
+logout()
}
class Admin {
+addUser(user: User)
+removeUser(user: User)
+generateReport()
}
class Report {
+generatePDF(reportData: List)
+generateCSV(reportData: List)
}
}
Admin --> User : manages
Admin --> Report : generates
`;
imgSnapshotTest(diagramDefinition);
});
});

Some files were not shown because too many files have changed in this diff Show More