Compare commits

..

49 Commits

Author SHA1 Message Date
Sidharth Vinod
4dd4997c4d chore: Bump version 2024-10-02 15:01:48 +05:30
Jiahao Guo
fc61512a0a [10] ci: upgrade to pnpm/action-setup@v4 to avoid CI failures
see: https://github.com/pnpm/action-setup/issues/135

(cherry picked from commit fde668a3a6)
2024-10-02 14:52:25 +09:00
Alois Klink
402abdf883 [10] fix: ban version v3.1.7 of DOMPurify
[DOMPurify v3.1.7][1] forbids the use of `<foreignElement>` for HTML
inside of an `<svg>` element, which breaks many mermaid diagrams.

It is likely that v3.1.8 will add a new option that will allow us to
re-enable this behaviour, but v3.1.7 definitely does not work.

(cherry picked from commit de2c05cd54)

[1]: https://github.com/cure53/DOMPurify/releases/tag/3.1.7

See: https://github.com/cure53/DOMPurify/issues/1002
Fix: https://github.com/mermaid-js/mermaid/issues/5904
2024-10-02 14:30:19 +09:00
Knut Sveidqvist
8d815f878c Lint fix 2024-05-14 13:00:45 +02:00
Knut Sveidqvist
dab26df9c4 Fix for proper handling of block-diagram labels 2024-05-14 12:55:39 +02:00
Knut Sveidqvist
c7fe9a6465 Fix for proper handling of block-diagram labels 2024-05-14 12:53:41 +02:00
Steph
4f26f3ae2e docs: Add blog post - Documentation Software (#5519)
Add blog post documentation software
2024-05-14 16:39:16 +09:00
Justin Greywolf
a536484408 Merge pull request #5495 from mermaid-js/update-mermaid-chart-page
DOCS: update Mermaid Chart page
2024-05-01 08:09:07 -07:00
Steph
76801ff564 update content 2024-04-29 14:12:55 -07:00
Sidharth Vinod
f2d3ac1e7b Merge pull request #5492 from mermaid-js/add-blog-post
DOCS: Add AI in Software Diagramming blog post
2024-04-27 11:12:15 +05:30
Steph
edad740e15 add ai blog post 2024-04-26 13:17:36 -07:00
Sidharth Vinod
a2e3b4ca06 Merge pull request #5456 from dudeofawesome/patch-1
📝🐛 fix schema link
2024-04-12 23:57:44 +05:30
Louis Orleans
909ad02a18 📝🐛 fix schema link
The original domain (`mermaid-js.github.io`) only redirects to the new domain (`mermaid.js.org`) from the root `/`. I've updated the link to point to the new domain directly.
2024-04-12 23:56:14 +05:30
Sidharth Vinod
4a930d2b5b Merge pull request #5455 from mermaid-js/update-latest-news
DOCS: update latest news
2024-04-12 09:25:08 +05:30
steph
4a19103891 update latest news section 2024-04-11 10:53:34 -07:00
Alois Klink
2d91aa0b06 Merge pull request #5425 from mermaid-js/add-blog-post
DOCS: add Turing machine blog post
2024-03-29 17:47:30 +00:00
Steph
aca0bebaf4 add Turing machine blog post 2024-03-28 12:50:10 -07:00
Alois Klink
46d20c9968 Merge pull request #5400 from mermaid-js/add-press-release
DOCS: Add Press Release
2024-03-22 00:12:59 +00:00
steph
de1b2c31a1 update link 2024-03-21 12:45:13 -07:00
steph
1f9cbe218f update announcement and blog pages 2024-03-21 12:37:05 -07:00
Sidharth Vinod
6502036be9 Merge pull request #5394 from mermaid-js/update-announcement-bar-link
DOCS: update Announcement bar link
2024-03-19 08:49:25 +05:30
Sidharth Vinod
f86da19362 Remove --force flag 2024-03-19 08:45:19 +05:30
Sidharth Vinod
b04e150dc1 Tweak editor.bash 2024-03-19 08:38:45 +05:30
Steph
1c0c374c29 update link 2024-03-18 14:32:26 -07:00
Sidharth Vinod
33287a63ad Support Firefox 2024-03-11 19:11:15 +05:30
Sidharth Vinod
3134a87e72 Merge pull request #5368 from mermaid-js/add-blog-posts
DOCS: add latest blog posts
2024-03-11 18:57:11 +05:30
Sidharth Vinod
447263ecc2 Merge pull request #5376 from mermaid-js/sidv/editableExamples
feat: Make the examples interactive in the documentation site
2024-03-11 17:59:58 +05:30
Sidharth Vinod
08a7f662ea Address review comments
Support ctrl+enter
Support mermaid-nocode
Use `contenteditable="plaintext-only"`

Co-authored-by: Alois Klink <alois@aloisklink.com>
2024-03-11 17:03:26 +05:30
Sidharth Vinod
6422175ef2 Change run symbol 2024-03-11 14:56:37 +05:30
Sidharth Vinod
32ca0b97fc feat: Make the examples interactive in the documentation site.
Ctrl/Cmd + Enter and a run button is added.

The feature was first implemented in https://github.com/mermaid-js/mermaid/pull/5330.

This is a simplified version without introducing additional dependencies.

Co-authored-by: Anton <m@antonz.org>
2024-03-11 14:56:37 +05:30
Sidharth Vinod
244b161032 Add langium 2024-03-11 14:56:18 +05:30
Sidharth Vinod
cd3d560e8d Merge pull request #5372 from mermaid-js/sidv/updateNewDiagramDoc
Update new diagram doc to reflect focus on Langium
2024-03-08 23:12:51 +05:30
Sidharth Vinod
c0497d3413 Update new diagram doc to reflect focus on Langium
Mark JISON as deprecated.
2024-03-08 23:11:28 +05:30
Sidharth Vinod
e6d80c60fb Merge pull request #5370 from JackuB/docs/update-slack-integration
docs(integrations): update link to Mermaid app for Slack
2024-03-08 15:06:08 +05:30
Jakub Mikulas
8f457815e9 docs(integrations): update link to Mermaid app for Slack
Signed-off-by: Jakub Mikulas <jakub@mikul.as>
2024-03-08 10:13:52 +01:00
Steph
3926594c6a add latest blog posts 2024-03-07 13:02:16 -08:00
Sidharth Vinod
dbeb0a4720 @mermaid-js/mermaid-zenuml v0.2.0 2024-03-05 22:56:09 +05:30
Sidharth Vinod
da33867ad7 Draft release 2024-03-05 22:52:07 +05:30
Sidharth Vinod
539010c65c Merge pull request #5337 from mermaid-js/release/10.9.0
Release/10.9.0
2024-03-05 22:48:12 +05:30
Sidharth Vinod
cbe44a6cff v10.9.0 2024-03-05 22:47:16 +05:30
Sidharth Vinod
b077fedd4c Merge branch 'develop' into release/10.9.0
* develop:
  Update docs
  Lychee ignore chrome webstore
  Update link
  chore(deps): update all patch dependencies
  build(docs): vendor CSS dependencies
  chore(deps): update all minor dependencies
  Ran lint:fix
  Fix chrome webstore url causing 404
  Resolves E2E testing issues and issue #5343
2024-03-05 22:25:06 +05:30
Sidharth Vinod
38fcc2847b Add release version in docs 2024-02-29 08:41:15 +05:30
Sidharth Vinod
2caeb9db47 zenUML 0.2.0-rc.2 2024-02-29 08:38:47 +05:30
Sidharth Vinod
f9c359e70c v10.9.0-rc.2 2024-02-29 08:38:03 +05:30
Sidharth Vinod
24528c1426 Merge branch 'develop' into release/10.9.0
* develop:
  Fix spelling
  Update all minor dependencies
  Fix color and arrow for merge commit
  minor stylistic changes
  revert changes on existing e2e tests; add new e2e test for nez until keyword
  modify invalid e2e test for gantt chart
  fix minor mistake in parsing test
  adapt e2e tests to include new 'until' keyword in gantt chart
  add parsing unit test for after/until keywords
  address review comment on implementation; apply similar changes on existing impl of keyword 'after'
  fix bad expected values in gantt units tests
  implement until keyword in gantt charts
2024-02-29 08:37:42 +05:30
Sidharth Vinod
df026c795d Bump @mermaid-js/mermaid-zenuml version to 0.2.0 2024-02-28 23:04:19 +05:30
Sidharth Vinod
077b1a5d8a Merge branch 'develop' into release/10.9.0
* develop:
  Fix community integrations
  Fix docs
  docs: Fix config
  Amend docs to document gitgraph parallel commits
  Added link to Blazorade Mermaid to the community integrations page.
2024-02-27 15:46:22 +05:30
Sidharth Vinod
31686802b3 Bump version 2024-02-27 13:21:49 +05:30
Sidharth Vinod
b96eaed6f4 Fix store link 2024-02-27 12:54:56 +05:30
202 changed files with 2869 additions and 4595 deletions

View File

@@ -1,30 +0,0 @@
/**
* 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-flowchart-elk': {
name: 'mermaid-flowchart-elk',
packageName: 'mermaid-flowchart-elk',
file: 'detector.ts',
},
} as const;

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,124 +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',
'timeline',
'gitGraph',
'c4',
'sankey',
'block',
'packet',
] 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,18 +0,0 @@
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`);
out.length > 0 && console.log(out.toString());
} catch (e) {
console.error(e);
e.stdout.length > 0 && console.error(e.stdout.toString());
e.stderr.length > 0 && console.error(e.stderr.toString());
}
};
for (const { packageName } of Object.values(packageOptions)) {
buildType(packageName);
}

View File

@@ -53,7 +53,6 @@ GENERICTYPE
getBoundarys getBoundarys
grammr grammr
graphtype graphtype
iife
interp interp
introdcued introdcued
INVTRAPEND INVTRAPEND
@@ -75,13 +74,11 @@ loglevel
LOGMSG LOGMSG
lookaheads lookaheads
mdast mdast
metafile
minlen minlen
Mstartx Mstartx
MULT MULT
NODIR NODIR
NSTR NSTR
outdir
Qcontrolx Qcontrolx
reinit reinit
rels rels

View File

@@ -1,65 +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 { MermaidBuildOptions, defaultOptions, getBuildConfig } from './util.js';
const shouldVisualize = process.argv.includes('--visualize');
const buildPackage = async (entryName: keyof typeof packageOptions) => {
const commonOptions = { ...defaultOptions, entryName } as const;
const buildConfigs = [
// 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) {
continue;
}
const fileName = Object.keys(metafile.outputs)
.filter((file) => !file.includes('chunks') && file.endsWith('js'))[0]
.replace('dist/', '');
// Upload metafile into https://esbuild.github.io/analyze/
await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile));
}
}
};
const handler = (e) => {
console.error(e);
process.exit(1);
};
const main = async () => {
await generateLangium();
await mkdir('stats').catch(() => {});
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 { 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,102 +0,0 @@
import express from 'express';
import type { NextFunction, Request, Response } from 'express';
import cors from 'cors';
import { getBuildConfig, defaultOptions } from './util.js';
import { context } from 'esbuild';
import chokidar from 'chokidar';
import { generateLangium } from '../.build/generateLangium.js';
import { packageOptions } from '../.build/common.js';
const configs = Object.values(packageOptions).map(({ packageName }) =>
getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: packageName })
);
const mermaidIIFEConfig = getBuildConfig({
...defaultOptions,
minify: false,
core: false,
entryName: 'mermaid',
format: 'iife',
});
configs.push(mermaidIIFEConfig);
const contexts = await Promise.all(configs.map((config) => context(config)));
const rebuildAll = async () => {
console.time('Rebuild time');
await Promise.all(contexts.map((ctx) => ctx.rebuild())).catch((e) => console.error(e));
console.timeEnd('Rebuild time');
};
let clients: { id: number; response: Response }[] = [];
function eventsHandler(request: Request, response: Response, next: NextFunction) {
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);
}
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/],
})
.on('all', async (event, path) => {
// Ignore other events.
if (!['add', 'change'].includes(event)) {
return;
}
if (/\.langium$/.test(path)) {
await generateLangium();
}
console.log(`${path} changed. Rebuilding...`);
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`);
});
}
createServer();

View File

@@ -1,101 +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 { packageOptions } from '../.build/common.js';
import { jisonPlugin } from './jisonPlugin.js';
const __dirname = fileURLToPath(new URL('.', import.meta.url));
export interface MermaidBuildOptions {
minify: boolean;
core: boolean;
metafile: boolean;
format: 'esm' | 'iife';
entryName: keyof typeof packageOptions;
}
export const defaultOptions: Omit<MermaidBuildOptions, 'entryName'> = {
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, entryName, metafile, format, minify } = options;
const external: string[] = ['require', 'fs', 'path'];
const { name, file, packageName } = packageOptions[entryName];
const outFileName = getFileName(name, options);
let 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;
};

View File

@@ -6,6 +6,3 @@ cypress/plugins/index.js
coverage coverage
*.json *.json
node_modules node_modules
# autogenereated by langium-cli
generated/

View File

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

2
.github/lychee.toml vendored
View File

@@ -40,7 +40,7 @@ exclude = [
# BundlePhobia has frequent downtime # BundlePhobia has frequent downtime
"https://bundlephobia.com", "https://bundlephobia.com",
# Chrome webstore redirect issue # Chrome webstore migration issue. Temporary
"https://chromewebstore.google.com" "https://chromewebstore.google.com"
] ]

View File

@@ -18,7 +18,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v4

View File

@@ -18,7 +18,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v4
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js - name: Setup Node.js

View File

@@ -32,7 +32,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v4
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js - name: Setup Node.js

View File

@@ -28,7 +28,7 @@ jobs:
options: --user 1001 options: --user 1001
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v4
with: with:
@@ -70,7 +70,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v4
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js - name: Setup Node.js

View File

@@ -19,7 +19,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v4
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js - name: Setup Node.js

View File

@@ -25,7 +25,7 @@ jobs:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v4

View File

@@ -12,7 +12,7 @@ jobs:
draft-release: draft-release:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions: permissions:
contents: write # write permission is required to create a github release contents: write # write permission is required to create a GitHub release
pull-requests: read # required to read PR titles/labels pull-requests: read # required to read PR titles/labels
steps: steps:
- name: Draft Release - name: Draft Release

View File

@@ -13,7 +13,7 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v4
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@v4 uses: actions/setup-node@v4

View File

@@ -11,7 +11,7 @@ jobs:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: fregante/setup-git-user@v2 - uses: fregante/setup-git-user@v2
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v4
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js - name: Setup Node.js

View File

@@ -11,7 +11,7 @@ jobs:
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v4
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js - name: Setup Node.js

View File

@@ -9,7 +9,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@v4 - uses: actions/checkout@v4
- uses: pnpm/action-setup@v2 - uses: pnpm/action-setup@v4
- run: npx update-browserslist-db@latest - run: npx update-browserslist-db@latest
- name: Commit changes - name: Commit changes
uses: EndBug/add-and-commit@v9 uses: EndBug/add-and-commit@v9

4
.gitignore vendored
View File

@@ -46,8 +46,4 @@ stats/
demos/dev/** demos/dev/**
!/demos/dev/example.html !/demos/dev/example.html
!/demos/dev/reload.js
tsx-0/** tsx-0/**
# autogenereated by langium-cli
generated/

View File

@@ -11,8 +11,6 @@ stats
.nyc_output .nyc_output
# Autogenerated by `pnpm run --filter mermaid types:build-config` # Autogenerated by `pnpm run --filter mermaid types:build-config`
packages/mermaid/src/config.type.ts packages/mermaid/src/config.type.ts
# autogenereated by langium-cli
generated/
# Ignore the files creates in /demos/dev except for example.html # Ignore the files creates in /demos/dev except for example.html
demos/dev/** demos/dev/**
!/demos/dev/example.html !/demos/dev/example.html

View File

@@ -3,12 +3,11 @@ import { resolve } from 'path';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import jisonPlugin from './jisonPlugin.js'; import jisonPlugin from './jisonPlugin.js';
import jsonSchemaPlugin from './jsonSchemaPlugin.js'; import jsonSchemaPlugin from './jsonSchemaPlugin.js';
import { readFileSync } from 'fs';
import typescript from '@rollup/plugin-typescript'; import typescript from '@rollup/plugin-typescript';
import { visualizer } from 'rollup-plugin-visualizer'; import { visualizer } from 'rollup-plugin-visualizer';
import type { TemplateType } from 'rollup-plugin-visualizer/dist/plugin/template-types.js'; import type { TemplateType } from 'rollup-plugin-visualizer/dist/plugin/template-types.js';
import istanbul from 'vite-plugin-istanbul'; 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 visualize = process.argv.includes('--visualize');
const watch = process.argv.includes('--watch'); const watch = process.argv.includes('--watch');
@@ -37,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 { interface BuildOptions {
minify: boolean | 'esbuild'; minify: boolean | 'esbuild';
core?: boolean; core?: boolean;
@@ -55,8 +72,34 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
sourcemap, sourcemap,
entryFileNames: `${name}.esm${minify ? '.min' : ''}.mjs`, 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 = { const config: InlineConfig = {
configFile: false, configFile: false,
build: { build: {
@@ -86,7 +129,7 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
// @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite // @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite
typescript({ compilerOptions: { declaration: false } }), typescript({ compilerOptions: { declaration: false } }),
istanbul({ istanbul({
exclude: ['node_modules', 'test/', '__mocks__', 'generated'], exclude: ['node_modules', 'test/', '__mocks__'],
extension: ['.js', '.ts'], extension: ['.js', '.ts'],
requireEnv: true, requireEnv: true,
forceBuildInstrument: coverage, forceBuildInstrument: coverage,
@@ -106,28 +149,24 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
const buildPackage = async (entryName: keyof typeof packageOptions) => { const buildPackage = async (entryName: keyof typeof packageOptions) => {
await build(getBuildConfig({ minify: false, entryName })); await build(getBuildConfig({ minify: false, entryName }));
await build(getBuildConfig({ minify: 'esbuild', entryName }));
await build(getBuildConfig({ minify: false, core: true, entryName }));
}; };
const main = async () => { const main = async () => {
const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[]; const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[];
for (const pkg of packageNames.filter( for (const pkg of packageNames.filter((pkg) => !mermaidOnly || pkg === 'mermaid')) {
(pkg) => !mermaidOnly || pkg === 'mermaid' || pkg === 'parser'
)) {
await buildPackage(pkg); await buildPackage(pkg);
} }
}; };
await generateLangium();
if (watch) { if (watch) {
await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' }));
build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' })); build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' }));
if (!mermaidOnly) { if (!mermaidOnly) {
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' })); build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' }));
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-zenuml' })); build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-zenuml' }));
} }
} else if (visualize) { } 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: true, entryName: 'mermaid' }));
await build(getBuildConfig({ minify: false, core: false, entryName: 'mermaid' })); await build(getBuildConfig({ minify: false, core: false, entryName: 'mermaid' }));
} else { } else {

View File

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

View File

@@ -1,5 +1,110 @@
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 { PluginOption } from 'vite';
import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.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',
'timeline',
'gitGraph',
'c4',
'sankey',
'block',
] 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. * Vite plugin that handles JSON Schemas saved as a `.schema.yaml` file.
@@ -16,13 +121,32 @@ export default function jsonSchemaPlugin(): PluginOption {
return; return;
} }
const jsonSchema = loadSchema(src, idAsUrl.pathname); if (idAsUrl.searchParams.get('only-defaults')) {
return { const jsonSchema = load(src, {
code: idAsUrl.searchParams.get('only-defaults') filename: idAsUrl.pathname,
? getDefaults(jsonSchema) // only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
: getSchema(jsonSchema), // e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
map: null, // no source map 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 express from 'express';
import cors from 'cors'; import cors from 'cors';
import { createServer as createViteServer } from 'vite'; import { createServer as createViteServer } from 'vite';
import { packageOptions } from '../.build/common.js';
async function createServer() { async function createServer() {
const app = express(); const app = express();
@@ -15,9 +14,9 @@ async function createServer() {
}); });
app.use(cors()); app.use(cors());
for (const { packageName } of Object.values(packageOptions)) { app.use(express.static('./packages/mermaid/dist'));
app.use(express.static(`./packages/${packageName}/dist`)); app.use(express.static('./packages/mermaid-zenuml/dist'));
} app.use(express.static('./packages/mermaid-example-diagram/dist'));
app.use(vite.middlewares); app.use(vite.middlewares);
app.use(express.static('demos')); app.use(express.static('demos'));
app.use(express.static('cypress/platform')); app.use(express.static('cypress/platform'));

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,
};

View File

@@ -1,14 +0,0 @@
import { urlSnapshotTest, openURLAndVerifyRendering } from '../../helpers/util.ts';
describe('Flowchart elk', () => {
it('should use dagre as fallback', () => {
urlSnapshotTest('http://localhost:9000/flow-elk.html', {
name: 'flow-elk fallback to dagre',
});
});
it('should allow overriding with external package', () => {
urlSnapshotTest('http://localhost:9000/flow-elk.html?elk=true', {
name: 'flow-elk overriding dagre with elk',
});
});
});

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

@@ -137,4 +137,9 @@ describe('XSS', () => {
cy.wait(1000); cy.wait(1000);
cy.get('#the-malware').should('not.exist'); 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

@@ -1,67 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util';
describe('packet structure', () => {
it('should render a simple packet diagram', () => {
imgSnapshotTest(
`packet-beta
title Hello world
0-10: "hello"
`
);
});
it('should render a complex packet diagram', () => {
imgSnapshotTest(
`packet-beta
0-15: "Source Port"
16-31: "Destination Port"
32-63: "Sequence Number"
64-95: "Acknowledgment Number"
96-99: "Data Offset"
100-105: "Reserved"
106: "URG"
107: "ACK"
108: "PSH"
109: "RST"
110: "SYN"
111: "FIN"
112-127: "Window"
128-143: "Checksum"
144-159: "Urgent Pointer"
160-191: "(Options and Padding)"
192-223: "data"
`
);
});
it('should render a complex packet diagram with showBits false', () => {
imgSnapshotTest(
`
---
title: "Packet Diagram"
config:
packet:
showBits: false
---
packet-beta
0-15: "Source Port"
16-31: "Destination Port"
32-63: "Sequence Number"
64-95: "Acknowledgment Number"
96-99: "Data Offset"
100-105: "Reserved"
106: "URG"
107: "ACK"
108: "PSH"
109: "RST"
110: "SYN"
111: "FIN"
112-127: "Window"
128-143: "Checksum"
144-159: "Urgent Pointer"
160-191: "(Options and Padding)"
192-223: "data"
`
);
});
});

View File

@@ -1,7 +1,7 @@
<html> <html>
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />
<script type="module" src="./viewer.js"></script> <script src="./viewer.js" type="module"></script>
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
rel="stylesheet" rel="stylesheet"

View File

@@ -11,7 +11,8 @@ example-diagram
<!-- <script src="//cdn.jsdelivr.net/npm/mermaid@9.1.7/dist/mermaid.min.js"></script> --> <!-- <script src="//cdn.jsdelivr.net/npm/mermaid@9.1.7/dist/mermaid.min.js"></script> -->
<!-- <script type="module" src="./external-diagrams-mindmap.mjs" /> --> <!-- <script type="module" src="./external-diagrams-mindmap.mjs" /> -->
<script type="module"> <script type="module">
import exampleDiagram from './mermaid-example-diagram.esm.mjs'; import exampleDiagram from '../../packages/mermaid-example-diagram/dist/mermaid-example-diagram.core.mjs';
// import example from '../../packages/mermaid-example-diagram/src/detector';
import mermaid from './mermaid.esm.mjs'; import mermaid from './mermaid.esm.mjs';
await mermaid.registerExternalDiagrams([exampleDiagram]); await mermaid.registerExternalDiagrams([exampleDiagram]);

View File

@@ -1,28 +0,0 @@
<html>
<body>
<pre class="mermaid">
flowchart-elk
a[hello] --> b[world]
b --> c{test}
c --> one
c --> two
c --> three
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import elk from './mermaid-flowchart-elk.esm.min.mjs';
if (window.location.search.includes('elk')) {
await mermaid.registerExternalDiagrams([elk]);
}
mermaid.initialize({
logLevel: 3,
startOnLoad: false,
});
await mermaid.run();
if (window.Cypress) {
window.rendered = true;
}
</script>
</body>
</html>

View File

@@ -1,29 +0,0 @@
<html>
<body>
<pre id="diagram" class="mermaid">
graph TB
a --> b
a --> c
b --> d
c --> d
</pre>
<div id="d2"></div>
<script src="/mermaid.min.js"></script>
<script>
mermaid.initialize({
startOnLoad: true,
});
const value = `graph TD\nHello --> World`;
const el = document.getElementById('d2');
mermaid.render('did', value).then(({ svg }) => {
console.log(svg);
el.innerHTML = svg;
if (window.Cypress) {
window.rendered = true;
}
});
</script>
</body>
</html>

View File

@@ -17,20 +17,20 @@
graph TB graph TB
Function-->URL Function-->URL
click Function clickByFlow "Add a div" click Function clickByFlow "Add a div"
click URL "http://localhost:9000/info.html" "Visit <strong>mermaid docs</strong>" click URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
</pre> </pre>
<pre id="FirstLine" class="mermaid2"> <pre id="FirstLine" class="mermaid2">
graph TB graph TB
1Function-->2URL 1Function-->2URL
click 1Function clickByFlow "Add a div" click 1Function clickByFlow "Add a div"
click 2URL "http://localhost:9000/info.html" "Visit <strong>mermaid docs</strong>" click 2URL "http://localhost:9000/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
</pre> </pre>
<pre id="FirstLine" class="mermaid2"> <pre id="FirstLine" class="mermaid2">
classDiagram classDiagram
class Test class Test
class ShapeLink class ShapeLink
link ShapeLink "http://localhost:9000/info.html" "This is a tooltip for a link" link ShapeLink "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
class ShapeCallback class ShapeCallback
callback ShapeCallback "clickByClass" "This is a tooltip for a callback" callback ShapeCallback "clickByClass" "This is a tooltip for a callback"
</pre> </pre>
@@ -42,7 +42,7 @@
<pre id="FirstLine" class="mermaid"> <pre id="FirstLine" class="mermaid">
classDiagram-v2 classDiagram-v2
class ShapeLink class ShapeLink
link ShapeLink "http://localhost:9000/info.html" "This is a tooltip for a link" link ShapeLink "http://localhost:9000/webpackUsage.html" "This is a tooltip for a link"
</pre> </pre>
</div> </div>
@@ -77,7 +77,7 @@
Calling a Callback (look at the console log) :cl2, after cl1, 3d Calling a Callback (look at the console log) :cl2, after cl1, 3d
Calling a Callback with args :cl3, after cl1, 3d Calling a Callback with args :cl3, after cl1, 3d
click cl1 href "http://localhost:9000/info.html" click cl1 href "http://localhost:9000/webpackUsage.html"
click cl2 call clickByGantt() click cl2 call clickByGantt()
click cl3 call clickByGantt("test1", test2, test3) click cl3 call clickByGantt("test1", test2, test3)
@@ -102,15 +102,9 @@
div.className = 'created-by-gant-click'; div.className = 'created-by-gant-click';
div.style = 'padding: 20px; background: green; color: white;'; div.style = 'padding: 20px; background: green; color: white;';
div.innerText = 'Clicked By Gant'; div.innerText = 'Clicked By Gant';
if (arg1) { if (arg1) div.innerText += ' ' + arg1;
div.innerText += ' ' + arg1; if (arg2) div.innerText += ' ' + arg2;
} if (arg3) div.innerText += ' ' + arg3;
if (arg2) {
div.innerText += ' ' + arg2;
}
if (arg3) {
div.innerText += ' ' + arg3;
}
document.getElementsByTagName('body')[0].appendChild(div); document.getElementsByTagName('body')[0].appendChild(div);
} }

View File

@@ -1,6 +1,6 @@
import mermaid from './mermaid.esm.mjs'; import mermaid2 from './mermaid.esm.mjs';
import externalExample from './mermaid-example-diagram.esm.mjs'; import externalExample from '../../packages/mermaid-example-diagram/dist/mermaid-example-diagram.core.mjs';
import zenUml from './mermaid-zenuml.esm.mjs'; import zenUml from '../../packages/mermaid-zenuml/dist/mermaid-zenuml.core.mjs';
function b64ToUtf8(str) { function b64ToUtf8(str) {
return decodeURIComponent(escape(window.atob(str))); return decodeURIComponent(escape(window.atob(str)));
@@ -45,9 +45,9 @@ const contentLoaded = async function () {
document.getElementsByTagName('body')[0].appendChild(div); document.getElementsByTagName('body')[0].appendChild(div);
} }
await mermaid.registerExternalDiagrams([externalExample, zenUml]); await mermaid2.registerExternalDiagrams([externalExample, zenUml]);
mermaid.initialize(graphObj.mermaid); mermaid2.initialize(graphObj.mermaid);
await mermaid.run(); await mermaid2.run();
} }
}; };
@@ -95,14 +95,18 @@ const contentLoadedApi = async function () {
divs[i] = div; divs[i] = div;
} }
const defaultE2eCnf = { theme: 'forest', startOnLoad: false }; const defaultE2eCnf = { theme: 'forest' };
const cnf = merge(defaultE2eCnf, graphObj.mermaid); const cnf = merge(defaultE2eCnf, graphObj.mermaid);
mermaid.initialize(cnf); mermaid2.initialize(cnf);
for (let i = 0; i < numCodes; i++) { for (let i = 0; i < numCodes; i++) {
const { svg, bindFunctions } = await mermaid.render('newid' + i, graphObj.code[i], divs[i]); const { svg, bindFunctions } = await mermaid2.render(
'newid' + i,
graphObj.code[i],
divs[i]
);
div.innerHTML = svg; div.innerHTML = svg;
bindFunctions(div); bindFunctions(div);
} }
@@ -110,21 +114,18 @@ const contentLoadedApi = async function () {
const div = document.createElement('div'); const div = document.createElement('div');
div.id = 'block'; div.id = 'block';
div.className = 'mermaid'; div.className = 'mermaid';
console.warn('graphObj', graphObj); console.warn('graphObj.mermaid', graphObj.mermaid);
document.getElementsByTagName('body')[0].appendChild(div); document.getElementsByTagName('body')[0].appendChild(div);
mermaid.initialize(graphObj.mermaid); mermaid2.initialize(graphObj.mermaid);
const { svg, bindFunctions } = await mermaid.render('newid', graphObj.code, div);
const { svg, bindFunctions } = await mermaid2.render('newid', graphObj.code, div);
div.innerHTML = svg; div.innerHTML = svg;
console.log(div.innerHTML);
bindFunctions(div); bindFunctions(div);
} }
} }
}; };
if (typeof document !== 'undefined') { if (typeof document !== 'undefined') {
mermaid.initialize({
startOnLoad: false,
});
/*! /*!
* Wait for document loaded before starting the execution * Wait for document loaded before starting the execution
*/ */

View File

@@ -0,0 +1,19 @@
<!DOCTYPE html>
<html>
<head>
<style>
/* .mermaid {
font-family: "trebuchet ms", verdana, arial;;
} */
/* .mermaid {
font-family: 'arial';
} */
</style>
</head>
<body>
<div id="graph-to-be"></div>
<script type="module" charset="utf-8">
import './bundle-test.js';
</script>
</body>
</html>

View File

@@ -1,5 +1,6 @@
<html> <html>
<head> <head>
<script src="./viewer.js" type="module"></script>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" /> <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<style> <style>
.malware { .malware {
@@ -32,6 +33,12 @@
</script> </script>
</head> </head>
<body> <body>
<script type="module" src="./viewer.js"></script> <script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({
startOnLoad: false,
useMaxWidth: true,
});
</script>
</body> </body>
</html> </html>

108
cypress/platform/xss25.html Normal file
View File

@@ -0,0 +1,108 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
rel="stylesheet"
/>
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 {
color: grey;
}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
}
.malware {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
</style>
<script>
function xssAttack() {
const div = document.createElement('div');
div.id = 'the-malware';
div.className = 'malware';
div.innerHTML = 'XSS Succeeded';
document.getElementsByTagName('body')[0].appendChild(div);
throw new Error('XSS Succeeded');
}
</script>
</head>
<body>
<div>Security check</div>
<div class="flex">
<div id="diagram" class="mermaid"></div>
<div id="res" class=""></div>
</div>
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.parseError = function (err, hash) {
// console.error('Mermaid error: ', err);
};
mermaid.initialize({
theme: 'forest',
arrowMarkerAbsolute: true,
// themeCSS: '.edgePath .path {stroke: red;} .arrowheadPath {fill: red;}',
logLevel: 0,
state: {
defaultRenderer: 'dagre-wrapper',
},
flowchart: {
// defaultRenderer: 'dagre-wrapper',
nodeSpacing: 10,
curve: 'cardinal',
htmlLabels: true,
},
htmlLabels: false,
// gantt: { axisFormat: '%m/%d/%Y' },
sequence: { actorFontFamily: 'courier', actorMargin: 50, showSequenceNumbers: false },
// sequenceDiagram: { actorMargin: 300 } // deprecated
// fontFamily: '"times", sans-serif',
// fontFamily: 'courier',
fontSize: 18,
curve: 'basis',
securityLevel: 'strict',
startOnLoad: false,
secure: ['secure', 'securityLevel', 'startOnLoad', 'maxTextSize'],
// themeVariables: {relationLabelColor: 'red'}
});
function callback() {
alert('It worked');
}
let diagram = 'block-beta\n';
diagram += '`A-- "X<img src=x on';
diagram += 'error=xssAttack()>" -->B';
console.log(diagram);
// document.querySelector('#diagram').innerHTML = diagram;
const { svg } = await mermaid.render('diagram', diagram);
document.querySelector('#res').innerHTML = svg;
</script>
</body>
</html>

View File

@@ -3,22 +3,6 @@
<html> <html>
<head> <head>
<title>Mermaid development page</title> <title>Mermaid development page</title>
<style>
.container {
display: flex;
flex-direction: row;
}
#code {
max-width: 30vw;
width: 30vw;
}
#dynamicDiagram {
padding-left: 2em;
flex: 1;
}
</style>
</head> </head>
<body> <body>
<pre id="diagram" class="mermaid"> <pre id="diagram" class="mermaid">
@@ -29,37 +13,22 @@ graph TB
c --> d c --> d
</pre> </pre>
<hr /> <div id="dynamicDiagram"></div>
Type code to view diagram:
<div class="container">
<textarea name="code" id="code" cols="30" rows="10"></textarea>
<div id="dynamicDiagram"></div>
</div>
<pre class="mermaid">info</pre>
<script type="module"> <script type="module">
import mermaid from '/mermaid.esm.mjs'; import mermaid from '/mermaid.esm.mjs';
async function render(str) { mermaid.parseError = function (err, hash) {
const { svg } = await mermaid.render('dynamic', str); console.error('Mermaid error: ', err);
document.getElementById('dynamicDiagram').innerHTML = svg; };
}
const storeKey = window.location.pathname;
const code = localStorage.getItem(storeKey);
if (code) {
document.getElementById('code').value = code;
await render(code);
}
mermaid.initialize({ mermaid.initialize({
startOnLoad: true, startOnLoad: true,
logLevel: 0, logLevel: 0,
}); });
document.getElementById('code').addEventListener('input', async (e) => { const value = `graph TD\nHello --> World`;
const value = e.target.value; const el = document.getElementById('dynamicDiagram');
localStorage.setItem(storeKey, value); const { svg } = await mermaid.render('dd', value);
await render(value); console.log(svg);
}); el.innerHTML = svg;
</script> </script>
<script src="/dev/reload.js"></script>
</body> </body>
</html> </html>

View File

@@ -1,22 +0,0 @@
// Connect to the server and reload the page if the server sends a reload message
const connectToEvents = () => {
const events = new EventSource('/events');
const loadTime = Date.now();
events.onmessage = (event) => {
const time = JSON.parse(event.data);
if (time && time > loadTime) {
location.reload();
}
};
events.onerror = (error) => {
console.error(error);
events.close();
// Try to reconnect after 1 second in case of errors
setTimeout(connectToEvents, 1000);
};
events.onopen = () => {
console.log('Connected to live reload server');
};
};
setTimeout(connectToEvents, 500);

View File

@@ -1,35 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Mermaid Flowchart ELK Test Page</title>
</head>
<body>
<h1>Flowchart ELK</h1>
<pre class="mermaid">
flowchart-elk TD
A([Start]) ==> B[Step 1]
B ==> C{Flow 1}
C -- Choice 1.1 --> D[Step 2.1]
C -- Choice 1.3 --> I[Step 2.3]
C == Choice 1.2 ==> E[Step 2.2]
D --> F{Flow 2}
E ==> F{Flow 2}
F{Flow 2} == Choice 2.1 ==> H[Feedback node]
H[Feedback node] ==> B[Step 1]
F{Flow 2} == Choice 2.2 ==> G((Finish))
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import flowchartELK from './mermaid-flowchart-elk.esm.mjs';
await mermaid.registerExternalDiagrams([flowchartELK]);
mermaid.initialize({
logLevel: 3,
});
</script>
</body>
</html>

View File

@@ -81,9 +81,6 @@
<li> <li>
<h2><a href="./sankey.html">Sankey</a></h2> <h2><a href="./sankey.html">Sankey</a></h2>
</li> </li>
<li>
<h2><a href="./packet.html">Packet</a></h2>
</li>
<li> <li>
<h2><a href="./block.html">Layered Blocks</a></h2> <h2><a href="./block.html">Layered Blocks</a></h2>
</li> </li>

View File

@@ -1,141 +0,0 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Mermaid Quick Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
<style>
div.mermaid {
font-family: 'Courier New', Courier, monospace !important;
}
</style>
</head>
<body>
<h1>Packet diagram demo</h1>
<div class="diagrams">
<pre class="mermaid">
packet-beta
0-15: "Source Port"
16-31: "Destination Port"
32-63: "Sequence Number"
64-95: "Acknowledgment Number"
96-99: "Data Offset"
100-105: "Reserved"
106: "URG"
107: "ACK"
108: "PSH"
109: "RST"
110: "SYN"
111: "FIN"
112-127: "Window"
128-143: "Checksum"
144-159: "Urgent Pointer"
160-191: "(Options and Padding)"
192-223: "data"
</pre
>
<pre class="mermaid">
---
config:
packet:
showBits: false
---
packet-beta
0-15: "Source Port"
16-31: "Destination Port"
32-63: "Sequence Number"
64-95: "Acknowledgment Number"
96-99: "Data Offset"
100-105: "Reserved"
106: "URG"
107: "ACK"
108: "PSH"
109: "RST"
110: "SYN"
111: "FIN"
112-127: "Window"
128-143: "Checksum"
144-159: "Urgent Pointer"
160-191: "(Options and Padding)"
192-223: "data"
</pre
>
<pre class="mermaid">
---
config:
theme: forest
---
packet-beta
title Forest theme
0-15: "Source Port"
16-31: "Destination Port"
32-63: "Sequence Number"
64-95: "Acknowledgment Number"
96-99: "Data Offset"
100-105: "Reserved"
106: "URG"
107: "ACK"
108: "PSH"
109: "RST"
110: "SYN"
111: "FIN"
112-127: "Window"
128-143: "Checksum"
144-159: "Urgent Pointer"
160-191: "(Options and Padding)"
192-223: "data"
</pre
>
<pre class="mermaid" style="background-color: black">
---
config:
theme: dark
---
packet-beta
title Dark theme
0-15: "Source Port"
16-31: "Destination Port"
32-63: "Sequence Number"
64-95: "Acknowledgment Number"
96-99: "Data Offset"
100-105: "Reserved"
106: "URG"
107: "ACK"
108: "PSH"
109: "RST"
110: "SYN"
111: "FIN"
112-127: "Window"
128-143: "Checksum"
144-159: "Urgent Pointer"
160-191: "(Options and Padding)"
192-223: "data"
</pre
>
</div>
<script type="module">
import mermaid from '/mermaid.esm.mjs';
mermaid.initialize({
logLevel: 3,
securityLevel: 'loose',
});
</script>
<style>
.diagrams {
display: flex;
flex-wrap: wrap;
}
pre {
width: 45vw;
padding: 2em;
}
</style>
</body>
</html>

View File

@@ -50,7 +50,7 @@
</pre> </pre>
<script type="module"> <script type="module">
import mermaid from '/mermaid.esm.mjs'; import mermaid from './mermaid.esm.mjs';
mermaid.initialize({ mermaid.initialize({
theme: 'forest', theme: 'forest',
logLevel: 3, logLevel: 3,

View File

@@ -0,0 +1,222 @@
> **Warning**
>
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
>
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/community/new-diagram-jison.md](../../packages/mermaid/src/docs/community/new-diagram-jison.md).
# Adding a New Diagram/Chart (Deprecated) 📊
> **Warning**
> JISON grammars are deprecated in mermaid. Please use Langium instead. See [New Diagram](./new-diagram.md) for more information.
>
> **New diagrams with JISON grammars will not be accepted.**
### Step 1: Grammar & Parsing
#### Grammar
This would be to define a JISON grammar for the new diagram type. That should start with a way to identify that the text in the mermaid tag is a diagram of that type. Create a new folder under diagrams for your new diagram type and a parser folder in it. This leads us to step 2.
For instance:
- the flowchart starts with the keyword _graph_
- the sequence diagram starts with the keyword _sequenceDiagram_
#### Store data found during parsing
There are some jison specific sub steps here where the parser stores the data encountered when parsing the diagram, this data is later used by the renderer. You can during the parsing call an object provided to the parser by the user of the parser. This object can be called during parsing for storing data.
```jison
statement
: 'participant' actor { $$='actor'; }
| signal { $$='signal'; }
| note_statement { $$='note'; }
| 'title' message { yy.setTitle($2); }
;
```
In the extract of the grammar above, it is defined that a call to the setTitle method in the data object will be done when parsing and the title keyword is encountered.
> **Note**
> Make sure that the `parseError` function for the parser is defined and calling `mermaid.parseError`. This way a common way of detecting parse errors is provided for the end-user.
For more info look at the example diagram type:
The `yy` object has the following function:
```javascript
exports.parseError = function (err, hash) {
mermaid.parseError(err, hash);
};
```
when parsing the `yy` object is initialized as per below:
```javascript
const parser = exampleParser.parser;
parser.yy = db;
```
### Step 2: Rendering
Write a renderer that given the data found during parsing renders the diagram. To look at an example look at sequenceRenderer.js rather than the flowchart renderer as this is a more generic example.
Place the renderer in the diagram folder.
### Step 3: Detection of the new diagram type
The second thing to do is to add the capability to detect the new diagram to type to the detectType in `diagram-api/detectType.ts`. The detection should return a key for the new diagram type.
[This key will be used to as the aria roledescription](#aria-roledescription), so it should be a word that clearly describes the diagram type.
For example, if your new diagram uses a UML deployment diagram, a good key would be "UMLDeploymentDiagram" because assistive technologies such as a screen reader
would voice that as "U-M-L Deployment diagram." Another good key would be "deploymentDiagram" because that would be voiced as "Deployment Diagram." A bad key would be "deployment" because that would not sufficiently describe the diagram.
Note that the diagram type key does not have to be the same as the diagram keyword chosen for the [grammar](#grammar), but it is helpful if they are the same.
### Step 4: The final piece - triggering the rendering
At this point when mermaid is trying to render the diagram, it will detect it as being of the new type but there will be no match when trying to render the diagram. To fix this add a new case in the switch statement in main.js:init this should match the diagram type returned from step #2. The code in this new case statement should call the renderer for the diagram type with the data found by the parser as an argument.
## Usage of the parser as a separate module
### Setup
```javascript
const graph = require('./graphDb');
const flow = require('./parser/flow');
flow.parser.yy = graph;
```
### Parsing
```javascript
flow.parser.parse(text);
```
### Data extraction
```javascript
graph.getDirection();
graph.getVertices();
graph.getEdges();
```
The parser is also exposed in the mermaid api by calling:
```javascript
const parser = mermaid.getParser();
```
Note that the parse needs a graph object to store the data as per:
```javascript
flow.parser.yy = graph;
```
Look at `graphDb.js` for more details on that object.
## Layout
If you are using a dagre based layout, please use flowchart-v2 as a template and by doing that you will be using dagre-wrapper instead of dagreD3 which we are migrating away from.
### Common parts of a diagram
There are a few features that are common between the different types of diagrams. We try to standardize the diagrams that work as similar as possible for the end user. The commonalities are:
- Directives, a way of modifying the diagram configuration from within the diagram code.
- Accessibility, a way for an author to provide additional information like titles and descriptions to people accessing a text with diagrams using a screen reader.
- Themes, there is a common way to modify the styling of diagrams in Mermaid.
- Comments should follow mermaid standards
Here are some pointers on how to handle these different areas.
## Accessibility
Mermaid automatically adds the following accessibility information for the diagram SVG HTML element:
- aria-roledescription
- accessible title
- accessible description
### aria-roledescription
The aria-roledescription is automatically set to [the diagram type](#step-3--detection-of-the-new-diagram-type) and inserted into the SVG element.
See [the definition of aria-roledescription](https://www.w3.org/TR/wai-aria-1.1/#aria-roledescription) in [the Accessible Rich Internet Applications W3 standard.](https://www.w3.org/WAI/standards-guidelines/aria/)
### accessible title and description
The syntax for accessible titles and descriptions is described in [the Accessibility documentation section.](../config/accessibility.md)
As a design goal, the jison syntax should be similar between the diagrams.
```jison
* lexical grammar */
%lex
%x acc_title
%x acc_descr
%x acc_descr_multiline
%%
accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; }
<acc_title>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; }
accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; }
<acc_descr>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; }
accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
<acc_descr_multiline>[\}] { this.popState(); }
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
statement
: acc_title acc_title_value { $$=$2.trim();yy.setTitle($$); }
| acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); }
| acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); }
```
The functions for setting title and description are provided by a common module. This is the import from flowDb.js:
import {
setAccTitle,
getAccTitle,
getAccDescription,
setAccDescription,
clear as commonClear,
} from '../../commonDb';
The accessibility title and description are inserted into the SVG element in the `render` function in mermaidAPI.
## Theming
Mermaid supports themes and has an integrated theming engine. You can read more about how the themes can be used [in the docs](../config/theming.md).
When adding themes to a diagram it comes down to a few important locations in the code.
The entry point for the styling engine is in **src/styles.js**. The getStyles function will be called by Mermaid when the styles are being applied to the diagram.
This function will in turn call a function _your diagram should provide_ returning the css for the new diagram. The diagram specific, also which is commonly also called getStyles and located in the folder for your diagram under src/diagrams and should be named styles.js. The getStyles function will be called with the theme options as an argument like in the following example:
```js
const getStyles = (options) =>
`
.line {
stroke-width: 1;
stroke: ${options.lineColor};
stroke-dasharray: 2;
}
// ...
`;
```
Note that you need to provide your function to the main getStyles by adding it into the themes object in **src/styles.js** like in the xyzDiagram in the provided example:
```js
const themes = {
flowchart,
'flowchart-v2': flowchart,
sequence,
xyzDiagram,
//...
};
```
The actual options and values for the colors are defined in **src/theme/theme-\[xyz].js**. If you provide the options your diagram needs in the existing theme files then the theming will work smoothly without hiccups.

View File

@@ -6,52 +6,18 @@
# Adding a New Diagram/Chart 📊 # Adding a New Diagram/Chart 📊
### Examples
Please refer to the following PRs on how to use Langium to add a new diagram grammar.
- <https://github.com/mermaid-js/mermaid/pull/4839>
- <https://github.com/mermaid-js/mermaid/pull/4751>
> **Warning**
> The below steps are a work in progress and will be updated soon.
### Step 1: Grammar & Parsing ### Step 1: Grammar & Parsing
#### Grammar
This would be to define a JISON grammar for the new diagram type. That should start with a way to identify that the text in the mermaid tag is a diagram of that type. Create a new folder under diagrams for your new diagram type and a parser folder in it. This leads us to step 2.
For instance:
- the flowchart starts with the keyword _graph_
- the sequence diagram starts with the keyword _sequenceDiagram_
#### Store data found during parsing
There are some jison specific sub steps here where the parser stores the data encountered when parsing the diagram, this data is later used by the renderer. You can during the parsing call an object provided to the parser by the user of the parser. This object can be called during parsing for storing data.
```jison
statement
: 'participant' actor { $$='actor'; }
| signal { $$='signal'; }
| note_statement { $$='note'; }
| 'title' message { yy.setTitle($2); }
;
```
In the extract of the grammar above, it is defined that a call to the setTitle method in the data object will be done when parsing and the title keyword is encountered.
> **Note**
> Make sure that the `parseError` function for the parser is defined and calling `mermaid.parseError`. This way a common way of detecting parse errors is provided for the end-user.
For more info look at the example diagram type:
The `yy` object has the following function:
```javascript
exports.parseError = function (err, hash) {
mermaid.parseError(err, hash);
};
```
when parsing the `yy` object is initialized as per below:
```javascript
const parser = exampleParser.parser;
parser.yy = db;
```
### Step 2: Rendering ### Step 2: Rendering
Write a renderer that given the data found during parsing renders the diagram. To look at an example look at sequenceRenderer.js rather than the flowchart renderer as this is a more generic example. Write a renderer that given the data found during parsing renders the diagram. To look at an example look at sequenceRenderer.js rather than the flowchart renderer as this is a more generic example.
@@ -67,52 +33,6 @@ would voice that as "U-M-L Deployment diagram." Another good key would be "deplo
Note that the diagram type key does not have to be the same as the diagram keyword chosen for the [grammar](#grammar), but it is helpful if they are the same. Note that the diagram type key does not have to be the same as the diagram keyword chosen for the [grammar](#grammar), but it is helpful if they are the same.
### Step 4: The final piece - triggering the rendering
At this point when mermaid is trying to render the diagram, it will detect it as being of the new type but there will be no match when trying to render the diagram. To fix this add a new case in the switch statement in main.js:init this should match the diagram type returned from step #2. The code in this new case statement should call the renderer for the diagram type with the data found by the parser as an argument.
## Usage of the parser as a separate module
### Setup
```javascript
const graph = require('./graphDb');
const flow = require('./parser/flow');
flow.parser.yy = graph;
```
### Parsing
```javascript
flow.parser.parse(text);
```
### Data extraction
```javascript
graph.getDirection();
graph.getVertices();
graph.getEdges();
```
The parser is also exposed in the mermaid api by calling:
```javascript
const parser = mermaid.getParser();
```
Note that the parse needs a graph object to store the data as per:
```javascript
flow.parser.yy = graph;
```
Look at `graphDb.js` for more details on that object.
## Layout
If you are using a dagre based layout, please use flowchart-v2 as a template and by doing that you will be using dagre-wrapper instead of dagreD3 which we are migrating away from.
### Common parts of a diagram ### Common parts of a diagram
There are a few features that are common between the different types of diagrams. We try to standardize the diagrams that work as similar as possible for the end user. The commonalities are: There are a few features that are common between the different types of diagrams. We try to standardize the diagrams that work as similar as possible for the end user. The commonalities are:
@@ -142,33 +62,7 @@ See [the definition of aria-roledescription](https://www.w3.org/TR/wai-aria-1.1/
The syntax for accessible titles and descriptions is described in [the Accessibility documentation section.](../config/accessibility.md) The syntax for accessible titles and descriptions is described in [the Accessibility documentation section.](../config/accessibility.md)
As a design goal, the jison syntax should be similar between the diagrams. The functions for setting title and description are provided by a common module. This is the import in flowDb.js:
```jison
* lexical grammar */
%lex
%x acc_title
%x acc_descr
%x acc_descr_multiline
%%
accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; }
<acc_title>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; }
accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; }
<acc_descr>(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; }
accDescr\s*"{"\s* { this.begin("acc_descr_multiline");}
<acc_descr_multiline>[\}] { this.popState(); }
<acc_descr_multiline>[^\}]* return "acc_descr_multiline_value";
statement
: acc_title acc_title_value { $$=$2.trim();yy.setTitle($$); }
| acc_descr acc_descr_value { $$=$2.trim();yy.setAccDescription($$); }
| acc_descr_multiline_value { $$=$1.trim();yy.setAccDescription($$); }
```
The functions for setting title and description are provided by a common module. This is the import from flowDb.js:
import { import {
setAccTitle, setAccTitle,

View File

@@ -4,7 +4,7 @@
> >
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/math.md](../../packages/mermaid/src/docs/config/math.md). > ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/math.md](../../packages/mermaid/src/docs/config/math.md).
# Math Configuration (v\<MERMAID_RELEASE_VERSION>+) # Math Configuration (v10.9.0+)
Mermaid supports rendering mathematical expressions through the [KaTeX](https://katex.org/) typesetter. Mermaid supports rendering mathematical expressions through the [KaTeX](https://katex.org/) typesetter.

View File

@@ -14,9 +14,6 @@
`Optional` **suppressErrors**: `boolean` `Optional` **suppressErrors**: `boolean`
If `true`, parse will return `false` instead of throwing error when the diagram is invalid.
The `parseError` function will not be called.
#### Defined in #### Defined in
[mermaidAPI.ts:64](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L64) [mermaidAPI.ts:60](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L60)

View File

@@ -1,21 +0,0 @@
> **Warning**
>
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
>
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/interfaces/mermaidAPI.ParseResult.md](../../../../packages/mermaid/src/docs/config/setup/interfaces/mermaidAPI.ParseResult.md).
# Interface: ParseResult
[mermaidAPI](../modules/mermaidAPI.md).ParseResult
## Properties
### diagramType
**diagramType**: `string`
The diagram type, e.g. 'flowchart', 'sequence', etc.
#### Defined in
[mermaidAPI.ts:71](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L71)

View File

@@ -39,19 +39,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
#### Defined in #### Defined in
[mermaidAPI.ts:94](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L94) [mermaidAPI.ts:80](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L80)
---
### diagramType
**diagramType**: `string`
The diagram type, e.g. 'flowchart', 'sequence', etc.
#### Defined in
[mermaidAPI.ts:84](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L84)
--- ---
@@ -63,4 +51,4 @@ The svg code for the rendered graph.
#### Defined in #### Defined in
[mermaidAPI.ts:80](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L80) [mermaidAPI.ts:70](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L70)

View File

@@ -14,7 +14,7 @@
#### Defined in #### Defined in
[defaultConfig.ts:275](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L275) [defaultConfig.ts:272](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L272)
--- ---

View File

@@ -9,7 +9,6 @@
## Interfaces ## Interfaces
- [ParseOptions](../interfaces/mermaidAPI.ParseOptions.md) - [ParseOptions](../interfaces/mermaidAPI.ParseOptions.md)
- [ParseResult](../interfaces/mermaidAPI.ParseResult.md)
- [RenderResult](../interfaces/mermaidAPI.RenderResult.md) - [RenderResult](../interfaces/mermaidAPI.RenderResult.md)
## References ## References
@@ -26,13 +25,13 @@ Renames and re-exports [mermaidAPI](mermaidAPI.md#mermaidapi)
#### Defined in #### Defined in
[mermaidAPI.ts:74](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L74) [mermaidAPI.ts:64](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L64)
## Variables ## Variables
### mermaidAPI ### mermaidAPI
`Const` **mermaidAPI**: `Readonly`<{ `defaultConfig`: `MermaidConfig` = configApi.defaultConfig; `getConfig`: () => `MermaidConfig` = configApi.getConfig; `getDiagramFromText`: (`text`: `string`, `metadata`: `Pick`<`DiagramMetadata`, `"title"`>) => `Promise`<`Diagram`> ; `getSiteConfig`: () => `MermaidConfig` = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`options`: `MermaidConfig`) => `void` ; `parse`: (`text`: `string`, `parseOptions`: [`ParseOptions`](../interfaces/mermaidAPI.ParseOptions.md) & { `suppressErrors`: `true` }) => `Promise`<[`ParseResult`](../interfaces/mermaidAPI.ParseResult.md) | `false`>(`text`: `string`, `parseOptions?`: [`ParseOptions`](../interfaces/mermaidAPI.ParseOptions.md)) => `Promise`<[`ParseResult`](../interfaces/mermaidAPI.ParseResult.md)> ; `render`: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`) => `Promise`<[`RenderResult`](../interfaces/mermaidAPI.RenderResult.md)> ; `reset`: () => `void` ; `setConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.setConfig; `updateSiteConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.updateSiteConfig }> `Const` **mermaidAPI**: `Readonly`<{ `defaultConfig`: `MermaidConfig` = configApi.defaultConfig; `getConfig`: () => `MermaidConfig` = configApi.getConfig; `getDiagramFromText`: (`text`: `string`, `metadata`: `Pick`<`DiagramMetadata`, `"title"`>) => `Promise`<`Diagram`> ; `getSiteConfig`: () => `MermaidConfig` = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`options`: `MermaidConfig`) => `void` ; `parse`: (`text`: `string`, `parseOptions?`: [`ParseOptions`](../interfaces/mermaidAPI.ParseOptions.md)) => `Promise`<`boolean`> ; `render`: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`) => `Promise`<[`RenderResult`](../interfaces/mermaidAPI.RenderResult.md)> ; `reset`: () => `void` ; `setConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.setConfig; `updateSiteConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.updateSiteConfig }>
## mermaidAPI configuration defaults ## mermaidAPI configuration defaults
@@ -97,7 +96,7 @@ mermaid.initialize(config);
#### Defined in #### Defined in
[mermaidAPI.ts:622](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L622) [mermaidAPI.ts:607](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L607)
## Functions ## Functions
@@ -128,7 +127,7 @@ Return the last node appended
#### Defined in #### Defined in
[mermaidAPI.ts:277](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L277) [mermaidAPI.ts:263](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L263)
--- ---
@@ -154,7 +153,7 @@ the cleaned up svgCode
#### Defined in #### Defined in
[mermaidAPI.ts:223](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L223) [mermaidAPI.ts:209](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L209)
--- ---
@@ -179,7 +178,7 @@ the string with all the user styles
#### Defined in #### Defined in
[mermaidAPI.ts:153](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L153) [mermaidAPI.ts:139](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L139)
--- ---
@@ -202,7 +201,7 @@ the string with all the user styles
#### Defined in #### Defined in
[mermaidAPI.ts:200](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L200) [mermaidAPI.ts:186](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L186)
--- ---
@@ -229,7 +228,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
#### Defined in #### Defined in
[mermaidAPI.ts:138](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L138) [mermaidAPI.ts:124](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L124)
--- ---
@@ -255,7 +254,7 @@ Put the svgCode into an iFrame. Return the iFrame code
#### Defined in #### Defined in
[mermaidAPI.ts:254](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L254) [mermaidAPI.ts:240](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L240)
--- ---
@@ -280,4 +279,4 @@ Remove any existing elements from the given document
#### Defined in #### Defined in
[mermaidAPI.ts:327](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L327) [mermaidAPI.ts:313](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L313)

View File

@@ -64,7 +64,7 @@ Example:
```html ```html
<script type="module"> <script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs'; import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
</script> </script>
``` ```
@@ -83,7 +83,7 @@ Example:
B-->D(fa:fa-spinner); B-->D(fa:fa-spinner);
</pre> </pre>
<script type="module"> <script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs'; import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
</script> </script>
</body> </body>
</html> </html>
@@ -331,17 +331,15 @@ module.exports = (options) ->
## Advanced usage ## Advanced usage
### Syntax validation without rendering **Syntax validation without rendering (Work in Progress)**
The `mermaid.parse(text, parseOptions)` function validates graph definitions without rendering a graph. The **mermaid.parse(txt)** function validates graph definitions without rendering a graph. **[This function is still a work in progress](https://github.com/mermaid-js/mermaid/issues/1066), find alternatives below.**
The function `mermaid.parse(text, parseOptions)`, takes a text string as an argument and returns `{ diagramType: string }` if the definition follows mermaid's syntax. The function **mermaid.parse(txt)**, takes a text string as an argument and returns true if the definition follows mermaid's syntax and
false if it does not. The parseError function will be called when the parse function returns false.
If the definition is invalid, the function returns `false` if `parseOptions.suppressErrors` is set to `true`. Otherwise, it throws an error. When the parser encounters invalid syntax the **mermaid.parseError** function is called. It is possible to override this
function in order to handle the error in an application-specific way.
The parseError function will be called when the parse function throws an error. It will not be called if `parseOptions.suppressErrors` is set to `true`.
It is possible to override this function in order to handle the error in an application-specific way.
The code-example below in meta code illustrates how this could work: The code-example below in meta code illustrates how this could work:
@@ -361,10 +359,26 @@ const textFieldUpdated = async function () {
bindEventHandler('change', 'code', textFieldUpdated); bindEventHandler('change', 'code', textFieldUpdated);
``` ```
**Alternative to mermaid.parse():**
One effective and more future-proof method of validating your graph definitions, is to paste and render them via the [Mermaid Live Editor](https://mermaid.live/). This will ensure that your code is compliant with the syntax of Mermaid's most recent version.
## Configuration ## Configuration
You can pass the required configuration to the `mermaid.initialize` call. This is the preferred way of configuring mermaid. Mermaid takes a number of options which lets you tweak the rendering of the diagrams. Currently there are three ways of
The list of configuration objects are described [in the mermaidAPI documentation](./setup/README.md). setting the options in mermaid.
1. Instantiation of the configuration using the initialize call
2. _Using the global mermaid object_ - **Deprecated**
3. _using the global mermaid_config object_ - **Deprecated**
4. Instantiation of the configuration using the **mermaid.init** call- **Deprecated**
The list above has two ways too many of doing this. Three are deprecated and will eventually be removed. The list of
configuration objects are described [in the mermaidAPI documentation](./setup/README.md).
## Using the `mermaidAPI.initialize`/`mermaid.initialize` call
The future proof way of setting the configuration is by using the initialization call to mermaid or mermaidAPI depending
on what kind of integration you use.
```html ```html
<script type="module"> <script type="module">
@@ -394,6 +408,35 @@ mermaid.startOnLoad = true;
> **Warning** > **Warning**
> This way of setting the configuration is deprecated. Instead the preferred way is to use the initialize method. This functionality is only kept for backwards compatibility. > This way of setting the configuration is deprecated. Instead the preferred way is to use the initialize method. This functionality is only kept for backwards compatibility.
## Using the mermaid_config
It is possible to set some configuration via the mermaid object. The two parameters that are supported using this
approach are:
- mermaid_config.startOnLoad
- mermaid_config.htmlLabels
```javascript
mermaid_config.startOnLoad = true;
```
> **Warning**
> This way of setting the configuration is deprecated. Instead the preferred way is to use the initialize method. This functionality is only kept for backwards compatibility.
## Using the mermaid.init call
To set some configuration via the mermaid object. The two parameters that are supported using this approach are:
- mermaid_config.startOnLoad
- mermaid_config.htmlLabels
```javascript
mermaid_config.startOnLoad = true;
```
> **Warning**
> This way of setting the configuration is deprecated. Instead the preferred way is to use the initialize method. This functionality is only kept for backwards compatibility.
<!--- <!---
cspell:locale en,en-gb cspell:locale en,en-gb
cspell:ignore pumbaa cspell:ignore pumbaa

View File

@@ -118,7 +118,7 @@ Communication tools and platforms
- [phpBB](https://phpbb.com) - [phpBB](https://phpbb.com)
- [phpbb-ext-mermaid](https://github.com/AlfredoRamos/phpbb-ext-mermaid) - [phpbb-ext-mermaid](https://github.com/AlfredoRamos/phpbb-ext-mermaid)
- [Slack](https://slack.com) - [Slack](https://slack.com)
- [Mermaid Preview](https://github.com/JackuB/mermaid-for-slack) - [Mermaid Preview](https://mermaid-preview.com)
### Wikis ### Wikis

View File

@@ -6,6 +6,10 @@
# Mermaid Chart # Mermaid Chart
The Future of Diagramming & Visual Collaboration
Try the Ultimate AI, Mermaid, and Visual Diagramming Suite by creating an account at [Mermaid Chart](https://www.mermaidchart.com/app/sign-up).
<br /> <br />
<a href="https://www.producthunt.com/posts/mermaid-chart?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-mermaid&#0045;chart" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=416671&theme=light" alt="Mermaid&#0032;Chart - A&#0032;smarter&#0032;way&#0032;to&#0032;create&#0032;diagrams | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a> <a href="https://www.producthunt.com/posts/mermaid-chart?utm_source=badge-featured&utm_medium=badge&utm_souce=badge-mermaid&#0045;chart" target="_blank"><img src="https://api.producthunt.com/widgets/embed-image/v1/featured.svg?post_id=416671&theme=light" alt="Mermaid&#0032;Chart - A&#0032;smarter&#0032;way&#0032;to&#0032;create&#0032;diagrams | Product Hunt" style="width: 250px; height: 54px;" width="250" height="54" /></a>
@@ -18,22 +22,26 @@
- **Editor** - A web based editor for creating and editing Mermaid diagrams. - **Editor** - A web based editor for creating and editing Mermaid diagrams.
- **Presentation** - A presentation mode for viewing Mermaid diagrams in a slideshow format. - **Visual Editor** - The Visual Editor enables users of all skill levels to create diagrams easily and efficiently, with both GUI and code-based editing options.
- **Collaboration** - A web based collaboration feature for multi-user editing on Mermaid diagrams in real-time (Pro plan). - **AI Chat** - Use our embedded AI Chat to generate diagrams from natural language descriptions.
- **Plugins** - A plugin system for extending the functionality of Mermaid. - **Plugins** - A plugin system for extending the functionality of Mermaid.
Plugins are available for: Official Mermaid Chart plugins:
- [ChatGPT](https://docs.mermaidchart.com/plugins/chatgpt) - [Mermaid Chart GPT](https://chat.openai.com/g/g-1IRFKwq4G-mermaid-chart)
- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=MermaidChart.vscode-mermaid-chart)
- [JetBrains IDE](https://plugins.jetbrains.com/plugin/23043-mermaid-chart) - [JetBrains IDE](https://plugins.jetbrains.com/plugin/23043-mermaid-chart)
- [Microsoft PowerPoint and Word](https://appsource.microsoft.com/en-us/product/office/WA200006214?tab=Overview) - [Microsoft PowerPoint and Word](https://appsource.microsoft.com/en-us/product/office/WA200006214?tab=Overview)
- [Visual Studio Code](https://marketplace.visualstudio.com/items?itemName=MermaidChart.vscode-mermaid-chart)
- **AI diagramming** - A feature for generating Mermaid diagrams from text using AI (Pro plan). Visit our [Plugins](https://www.mermaidchart.com/plugins) page for more information.
- **More** - To learn more, visit our [Product](https://www.mermaidchart.com/product) page. - **Collaboration** - A web based collaboration feature for multi-user editing on Mermaid diagrams in real-time (Pro and Enterprise plans).
- **Comments** - Enhance collaboration by adding comments to diagrams.
- **Presentations** - A presentation mode for viewing Mermaid diagrams in a slideshow format.
## Plans ## Plans
@@ -43,11 +51,9 @@
- **Enterprise** - A paid plan for enterprise use that includes all Pro features, and more. - **Enterprise** - A paid plan for enterprise use that includes all Pro features, and more.
## Access To learn more, visit our [Pricing](https://mermaidchart.com/pricing) page.
Sign up for a free account at [Mermaid Chart](https://www.mermaidchart.com/app/sign-up). Mermaid Chart is currently offering a 14-day free trial on our Pro and Enterprise tiers. Sign up for a free account at [Mermaid Chart](https://www.mermaidchart.com/app/sign-up).
Mermaid Chart is currently offering a 14-day free trial of our newly-launched Pro tier. To learn more, visit our [Pricing](https://mermaidchart.com/pricing) page.
## Mermaid JS contributions ## Mermaid JS contributions

View File

@@ -224,7 +224,7 @@ b. The importing of the Mermaid library through the `mermaid.esm.mjs` or `mermai
```html ```html
<body> <body>
<script type="module"> <script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs'; import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true }); mermaid.initialize({ startOnLoad: true });
</script> </script>
</body> </body>
@@ -246,23 +246,23 @@ In this example, the `mermaidAPI` is being called through the `CDN`:
<body> <body>
Here is one mermaid diagram: Here is one mermaid diagram:
<pre class="mermaid"> <pre class="mermaid">
graph TD graph TD
A[Client] --> B[Load Balancer] A[Client] --> B[Load Balancer]
B --> C[Server1] B --> C[Server1]
B --> D[Server2] B --> D[Server2]
</pre> </pre>
And here is another: And here is another:
<pre class="mermaid"> <pre class="mermaid">
graph TD graph TD
A[Client] -->|tcp_123| B A[Client] -->|tcp_123| B
B(Load Balancer) B(Load Balancer)
B -->|tcp_456| C[Server1] B -->|tcp_456| C[Server1]
B -->|tcp_456| D[Server2] B -->|tcp_456| D[Server2]
</pre> </pre>
<script type="module"> <script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs'; import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true }); mermaid.initialize({ startOnLoad: true });
</script> </script>
</body> </body>
@@ -278,15 +278,15 @@ In this example, `mermaid.js` is referenced in `src` as a separate JavaScript fi
</head> </head>
<body> <body>
<pre class="mermaid"> <pre class="mermaid">
graph LR graph LR
A --- B A --- B
B-->C[fa:fa-ban forbidden] B-->C[fa:fa-ban forbidden]
B-->D(fa:fa-spinner); B-->D(fa:fa-spinner);
</pre> </pre>
<pre class="mermaid"> <pre class="mermaid">
graph TD graph TD
A[Client] --> B[Load Balancer] A[Client] --> B[Load Balancer]
B --> C[Server1] B --> C[Server1]
B --> D[Server2] B --> D[Server2]
</pre> </pre>
<script type="module"> <script type="module">

View File

@@ -317,7 +317,7 @@ To select a version:
Replace `<version>` with the desired version number. Replace `<version>` with the desired version number.
Latest Version: <https://cdn.jsdelivr.net/npm/mermaid@11> Latest Version: <https://cdn.jsdelivr.net/npm/mermaid@10>
## Deploying Mermaid ## Deploying Mermaid
@@ -335,7 +335,7 @@ To Deploy Mermaid:
```html ```html
<script type="module"> <script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs'; import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
mermaid.initialize({ startOnLoad: true }); mermaid.initialize({ startOnLoad: true });
</script> </script>
``` ```

View File

@@ -6,13 +6,45 @@
# Announcements # Announcements
## 🚀 Mermaid Chart's Visual Editor for Flowcharts ## 🚀 Exciting News from Mermaid Chart! 🚀
The Mermaid Chart team is excited to introduce a new Visual Editor for flowcharts, enabling users of all skill levels to create diagrams easily and efficiently, with both GUI and code-based editing options. We're thrilled to announce that Mermaid Chart has successfully raised $7.5 million in Seed funding! 🌟 This achievement marks the beginning of a new era for Mermaid and Mermaid Chart.
Create flowchart nodes, connect them with edges, update shapes, change colors, and edit labels with just a few clicks that automatically reflect in your diagrams code for easy customizability. **Why It Matters for Mermaid Chart:**
Read more about it in our latest [BLOG POST](https://www.mermaidchart.com/blog/posts/mermaid-chart-releases-new-visual-editor-for-flowcharts) and watch a [DEMO VIDEO](https://www.youtube.com/watch?v=5aja0gijoO0) on our YouTube page. - **Empowering Collaboration**: Our tools are designed to enable faster, more efficient team collaboration across any distance, leveraging the best of text, voice, and automation.
- **Opening New Doors**: Mermaid AI and our Visual Editor are breaking down barriers, making sophisticated diagramming accessible to everyone, not just software engineers.
- **Looking Forward**: We're not stopping here! Expect groundbreaking features like automated documentation tools, advanced AI diagramming, and high-security on-premise solutions.
**Why It Matters for Mermaid JS:**
- **Continued support from Mermaid Chart**: At Mermaid Chart, we value our still-growing Mermaid JS roots. As such, we have funneled back development and support to the project. Thanks to the successful seed round, we can continue to ramp up these efforts.
We are incredibly excited about the future and are grateful to the community, our team, and our investors for being part of this journey. Together, we're not just creating diagrams; we're designing the future of collaboration.
🌐 Learn more about our groundbreaking tools and what's next for Mermaid Chart by visiting [our website](https://www.mermaidchart.com/blog/posts/mermaid-chart-raises-7.5m-to-reinvent-visual-collaoration-for-enterprises).
Thank you for being part of our story. Here's to creating, innovating, and collaborating on a global scale!
Knut Sveidqvist 🧜‍♂️✨
## Mermaid Chart's Visual Editor for Flowcharts and Sequence diagrams
The Mermaid Chart team is excited to introduce a new Visual Editor for Flowcharts and Sequence diagrams, enabling users of all skill levels to create diagrams easily and efficiently, with both GUI and code-based editing options.
Learn more:
- Visual Editor For Flowcharts
- [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-releases-new-visual-editor-for-flowcharts)
- [Demo video](https://www.youtube.com/watch?v=5aja0gijoO0)
- Visual Editor For Sequence diagrams
- [Blog post](https://www.mermaidchart.com/blog/posts/mermaid-chart-unveils-visual-editor-for-sequence-diagrams)
- [Demo video](https://youtu.be/imc2u5_N6Dc)
## 📖 Blog posts ## 📖 Blog posts

View File

@@ -6,6 +6,48 @@
# Blog # Blog
## [How to Choose the Right Documentation Software](https://www.mermaidchart.com/blog/posts/how-to-choose-the-right-documentation-software/)
7 May 2024 · 5 mins
How to Choose the Right Documentation Software. Reliable and efficient documentation software is crucial in the fast-paced world of software development.
## [AI in software diagramming: What trends will define the future?](https://www.mermaidchart.com/blog/posts/ai-in-software-diagramming/)
24 April 2024 · 5 mins
Artificial intelligence (AI) tools are changing the way developers work.
## [Mermaid Chart Unveils Visual Editor for Sequence Diagrams](https://www.mermaidchart.com/blog/posts/mermaid-chart-unveils-visual-editor-for-sequence-diagrams/)
8 April 2024 · 5 mins
Sequence diagrams are excellent tools for communication and documentation.
## [Modeling system states: It starts with a Turing machine](https://www.mermaidchart.com/blog/posts/modeling-system-states/)
27 March 2024 · 12 mins
In computer science, there are a few fundamental papers that, without exaggeration, changed everything.
## [Mermaid Chart Raises $7.5M to Reinvent Visual Collaboration for Enterprises](https://www.mermaidchart.com/blog/posts/mermaid-chart-raises-7.5m-to-reinvent-visual-collaoration-for-enterprises/)
20 March 2024 · 4 mins
Mermaid Chart, the company offering text-based diagramming and workflow management tools, today announced it has raised $7.5 million in Seed funding.
## [Mermaid Chart GPT Is Now Available In the GPT Store!](https://www.mermaidchart.com/blog/posts/mermaid-chart-gpt-is-now-available-in-the-gpt-store/)
7 March 2024 · 3 mins
Mermaid Chart GPT is Now Available In the GPT Store!
## [How to Make a Flowchart with Mermaid Chart](https://www.mermaidchart.com/blog/posts/how-to-make-flowcharts-with-mermaid-chart/)
30 January 2024 · 6 mins
Learn how to make a flowchart with Mermaid Chart, the leading text-to-diagram platform for both developers and non-developers.
## [How one data scientist uses Mermaid Chart to quickly and easily build flowcharts](https://www.mermaidchart.com/blog/posts/customer-spotlight-ari-tal/) ## [How one data scientist uses Mermaid Chart to quickly and easily build flowcharts](https://www.mermaidchart.com/blog/posts/customer-spotlight-ari-tal/)
23 January 2024 · 4 mins 23 January 2024 · 4 mins

View File

@@ -143,7 +143,7 @@ After processing the tags, the remaining metadata items are interpreted as follo
| `until <otherTaskId>` | End date of preceding task | Start date of previously specified task `otherTaskID` | n/a | | `until <otherTaskId>` | End date of preceding task | Start date of previously specified task `otherTaskID` | n/a |
> **Note** > **Note**
> Support for keyword `until` was added in (v\<MERMAID_RELEASE_VERSION>+). This can be used to define a task which is running until some other specific task or milestone starts. > Support for keyword `until` was added in (v10.9.0+). This can be used to define a task which is running until some other specific task or milestone starts.
For simplicity, the table does not show the use of multiple tasks listed with the `after` keyword. Here is an example of how to use it and how it's interpreted: For simplicity, the table does not show the use of multiple tasks listed with the `after` keyword. Here is an example of how to use it and how it's interpreted:

View File

@@ -300,7 +300,7 @@ From version 9.4.0 you can simplify this code to:
```html ```html
<script type="module"> <script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs'; import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
</script> </script>
``` ```

View File

@@ -1,141 +0,0 @@
> **Warning**
>
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
>
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/syntax/packet.md](../../packages/mermaid/src/docs/syntax/packet.md).
# Packet Diagram (v\<MERMAID_RELEASE_VERSION>+)
## Introduction
A packet diagram is a visual representation used to illustrate the structure and contents of a network packet. Network packets are the fundamental units of data transferred over a network.
## Usage
This diagram type is particularly useful for network engineers, educators, and students who require a clear and concise way to represent the structure of network packets.
## Syntax
```md
packet-beta
start: "Block name" %% Single-bit block
start-end: "Block name" %% Multi-bit blocks
... More Fields ...
```
## Examples
```mermaid-example
---
title: "TCP Packet"
---
packet-beta
0-15: "Source Port"
16-31: "Destination Port"
32-63: "Sequence Number"
64-95: "Acknowledgment Number"
96-99: "Data Offset"
100-105: "Reserved"
106: "URG"
107: "ACK"
108: "PSH"
109: "RST"
110: "SYN"
111: "FIN"
112-127: "Window"
128-143: "Checksum"
144-159: "Urgent Pointer"
160-191: "(Options and Padding)"
192-255: "Data (variable length)"
```
```mermaid
---
title: "TCP Packet"
---
packet-beta
0-15: "Source Port"
16-31: "Destination Port"
32-63: "Sequence Number"
64-95: "Acknowledgment Number"
96-99: "Data Offset"
100-105: "Reserved"
106: "URG"
107: "ACK"
108: "PSH"
109: "RST"
110: "SYN"
111: "FIN"
112-127: "Window"
128-143: "Checksum"
144-159: "Urgent Pointer"
160-191: "(Options and Padding)"
192-255: "Data (variable length)"
```
```mermaid-example
packet-beta
title UDP Packet
0-15: "Source Port"
16-31: "Destination Port"
32-47: "Length"
48-63: "Checksum"
64-95: "Data (variable length)"
```
```mermaid
packet-beta
title UDP Packet
0-15: "Source Port"
16-31: "Destination Port"
32-47: "Length"
48-63: "Checksum"
64-95: "Data (variable length)"
```
## Details of Syntax
- **Ranges**: Each line after the title represents a different field in the packet. The range (e.g., `0-15`) indicates the bit positions in the packet.
- **Field Description**: A brief description of what the field represents, enclosed in quotes.
## Configuration
Please refer to the [configuration](/config/schema-docs/config-defs-packet-diagram-config.html) guide for details.
<!--
Theme variables are not currently working due to a mermaid bug. The passed values are not being propagated into styles function.
## Theme Variables
| Property | Description | Default Value |
| ---------------- | -------------------------- | ------------- |
| byteFontSize | Font size of the bytes | '10px' |
| startByteColor | Color of the starting byte | 'black' |
| endByteColor | Color of the ending byte | 'black' |
| labelColor | Color of the labels | 'black' |
| labelFontSize | Font size of the labels | '12px' |
| titleColor | Color of the title | 'black' |
| titleFontSize | Font size of the title | '14px' |
| blockStrokeColor | Color of the block stroke | 'black' |
| blockStrokeWidth | Width of the block stroke | '1' |
| blockFillColor | Fill color of the block | '#efefef' |
## Example on config and theme
```mermaid-example
---
config:
packet:
showBits: true
themeVariables:
packet:
startByteColor: red
---
packet-beta
0-15: "Source Port"
16-31: "Destination Port"
32-63: "Sequence Number"
```
-->

View File

@@ -469,7 +469,7 @@ You can use this method to add mermaid including the timeline diagram to a web p
```html ```html
<script type="module"> <script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs'; import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
</script> </script>
``` ```

View File

@@ -7,9 +7,9 @@
base = "" base = ""
# Directory that contains the deploy-ready HTML files and # Directory that contains the deploy-ready HTML files and
# assets generated by the build. This is an absolute path relative # assets generated by the build. This is an absolute path relative
# to the base directory, which is the root by default (/). # to the base directory, which is the root by default (/).
# This sample publishes the directory located at the absolute # This sample publishes the directory located at the absolute
# path "root/project/build-output" # path "root/project/build-output"
publish = "mermaid-live-editor/docs" publish = "mermaid-live-editor/docs"

View File

@@ -15,15 +15,15 @@
"git graph" "git graph"
], ],
"scripts": { "scripts": {
"build": "pnpm build:esbuild && pnpm build:types", "build:vite": "tsx .vite/build.ts",
"build:esbuild": "pnpm run -r clean && tsx .esbuild/build.ts", "build:mermaid": "pnpm build:vite --mermaid",
"build:mermaid": "pnpm build:esbuild --mermaid", "build:viz": "pnpm build:mermaid --visualize",
"build:viz": "pnpm build:esbuild --visualize", "build:types": "tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly && tsc -p ./packages/mermaid-zenuml/tsconfig.json --emitDeclarationOnly && tsc -p ./packages/mermaid-example-diagram/tsconfig.json --emitDeclarationOnly",
"build:types": "tsx .build/types.ts",
"build:types:watch": "tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly --watch", "build:types:watch": "tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly --watch",
"dev": "tsx .esbuild/server.ts", "build:watch": "pnpm build:vite --watch",
"dev:vite": "tsx .vite/server.ts", "build": "pnpm run -r clean && pnpm build:types && pnpm build:vite",
"dev:coverage": "pnpm coverage:cypress:clean && VITE_COVERAGE=true pnpm dev:vite", "dev": "concurrently \"pnpm build:vite --watch\" \"tsx .vite/server.ts\"",
"dev:coverage": "pnpm coverage:cypress:clean && VITE_COVERAGE=true pnpm dev",
"release": "pnpm build", "release": "pnpm build",
"lint": "eslint --cache --cache-strategy content --ignore-path .gitignore . && pnpm lint:jison && prettier --cache --check .", "lint": "eslint --cache --cache-strategy content --ignore-path .gitignore . && pnpm lint:jison && prettier --cache --check .",
"lint:fix": "eslint --cache --cache-strategy content --fix --ignore-path .gitignore . && prettier --write . && tsx scripts/fixCSpell.ts", "lint:fix": "eslint --cache --cache-strategy content --fix --ignore-path .gitignore . && prettier --write . && tsx scripts/fixCSpell.ts",
@@ -32,8 +32,8 @@
"cypress": "cypress run", "cypress": "cypress run",
"cypress:open": "cypress open", "cypress:open": "cypress open",
"e2e": "start-server-and-test dev http://localhost:9000/ cypress", "e2e": "start-server-and-test dev http://localhost:9000/ cypress",
"e2e:coverage": "start-server-and-test dev:coverage http://localhost:9000/ cypress",
"coverage:cypress:clean": "rimraf .nyc_output coverage/cypress", "coverage:cypress:clean": "rimraf .nyc_output coverage/cypress",
"e2e:coverage": "pnpm coverage:cypress:clean && VITE_COVERAGE=true pnpm e2e",
"coverage:merge": "tsx scripts/coverage.ts", "coverage:merge": "tsx scripts/coverage.ts",
"coverage": "pnpm test:coverage --run && pnpm e2e:coverage && pnpm coverage:merge", "coverage": "pnpm test:coverage --run && pnpm e2e:coverage && pnpm coverage:merge",
"ci": "vitest run", "ci": "vitest run",
@@ -74,7 +74,7 @@
"@types/jsdom": "^21.1.1", "@types/jsdom": "^21.1.1",
"@types/lodash": "^4.14.194", "@types/lodash": "^4.14.194",
"@types/mdast": "^3.0.11", "@types/mdast": "^3.0.11",
"@types/node": "^20.11.17", "@types/node": "^20.11.10",
"@types/prettier": "^2.7.2", "@types/prettier": "^2.7.2",
"@types/rollup-plugin-visualizer": "^4.2.1", "@types/rollup-plugin-visualizer": "^4.2.1",
"@typescript-eslint/eslint-plugin": "^6.7.2", "@typescript-eslint/eslint-plugin": "^6.7.2",
@@ -83,7 +83,6 @@
"@vitest/spy": "^0.34.0", "@vitest/spy": "^0.34.0",
"@vitest/ui": "^0.34.0", "@vitest/ui": "^0.34.0",
"ajv": "^8.12.0", "ajv": "^8.12.0",
"chokidar": "^3.5.3",
"concurrently": "^8.0.1", "concurrently": "^8.0.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"cspell": "^8.3.2", "cspell": "^8.3.2",
@@ -109,7 +108,6 @@
"jison": "^0.4.18", "jison": "^0.4.18",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"jsdom": "^22.0.0", "jsdom": "^22.0.0",
"langium-cli": "3.0.1",
"lint-staged": "^13.2.1", "lint-staged": "^13.2.1",
"nyc": "^15.1.0", "nyc": "^15.1.0",
"path-browserify": "^1.0.1", "path-browserify": "^1.0.1",

View File

@@ -1,45 +0,0 @@
{
"name": "@mermaid-js/flowchart-elk",
"version": "1.0.0-rc.1",
"description": "Flowchart plugin for mermaid with ELK layout",
"module": "dist/mermaid-flowchart-elk.core.mjs",
"types": "dist/packages/mermaid-flowchart-elk/src/detector.d.ts",
"type": "module",
"exports": {
".": {
"import": "./dist/mermaid-flowchart-elk.core.mjs",
"types": "./dist/packages/mermaid-flowchart-elk/src/detector.d.ts"
},
"./*": "./*"
},
"keywords": [
"diagram",
"markdown",
"flowchart",
"elk",
"mermaid"
],
"scripts": {
"prepublishOnly": "pnpm -w run build"
},
"repository": {
"type": "git",
"url": "https://github.com/mermaid-js/mermaid"
},
"author": "Knut Sveidqvist",
"license": "MIT",
"dependencies": {
"d3": "^7.4.0",
"dagre-d3-es": "7.0.10",
"khroma": "^2.0.0",
"elkjs": "^0.8.2"
},
"devDependencies": {
"concurrently": "^8.0.0",
"rimraf": "^5.0.0",
"mermaid": "workspace:^"
},
"files": [
"dist"
]
}

View File

@@ -1,32 +0,0 @@
import type {
ExternalDiagramDefinition,
DiagramDetector,
DiagramLoader,
} from '../../mermaid/src/diagram-api/types.js';
const id = 'flowchart-elk';
const detector: DiagramDetector = (txt, config): boolean => {
if (
// If diagram explicitly states flowchart-elk
/^\s*flowchart-elk/.test(txt) ||
// If a flowchart/graph diagram has their default renderer set to elk
(/^\s*flowchart|graph/.test(txt) && config?.flowchart?.defaultRenderer === 'elk')
) {
return true;
}
return false;
};
const loader: DiagramLoader = async () => {
const { diagram } = await import('./diagram-definition.js');
return { id, diagram };
};
const plugin: ExternalDiagramDefinition = {
id,
detector,
loader,
};
export default plugin;

View File

@@ -1,12 +0,0 @@
// @ts-ignore: JISON typing missing
import parser from '../../mermaid/src/diagrams/flowchart/parser/flow.jison';
import * as db from '../../mermaid/src/diagrams/flowchart/flowDb.js';
import styles from '../../mermaid/src/diagrams/flowchart/styles.js';
import renderer from './flowRenderer-elk.js';
export const diagram = {
db,
renderer,
parser,
styles,
};

View File

@@ -1,10 +0,0 @@
{
"extends": "../../tsconfig.json",
"compilerOptions": {
"rootDir": "../..",
"outDir": "./dist",
"types": ["vitest/importMeta", "vitest/globals"]
},
"include": ["./src/**/*.ts"],
"typeRoots": ["./src/types"]
}

View File

@@ -1,6 +1,6 @@
{ {
"name": "@mermaid-js/mermaid-zenuml", "name": "@mermaid-js/mermaid-zenuml",
"version": "0.1.2", "version": "0.2.0",
"description": "MermaidJS plugin for ZenUML integration", "description": "MermaidJS plugin for ZenUML integration",
"module": "dist/mermaid-zenuml.core.mjs", "module": "dist/mermaid-zenuml.core.mjs",
"types": "dist/detector.d.ts", "types": "dist/detector.d.ts",
@@ -19,7 +19,6 @@
"mermaid" "mermaid"
], ],
"scripts": { "scripts": {
"clean": "rimraf dist",
"prepublishOnly": "pnpm -w run build" "prepublishOnly": "pnpm -w run build"
}, },
"repository": { "repository": {

View File

@@ -5,6 +5,7 @@
* This is a dummy parser that satisfies the mermaid API logic. * This is a dummy parser that satisfies the mermaid API logic.
*/ */
export default { export default {
parser: { yy: {} },
parse: () => { parse: () => {
// no op // no op
}, },

View File

@@ -1,6 +1,6 @@
{ {
"name": "mermaid", "name": "mermaid",
"version": "11.0.0-alpha.6", "version": "10.9.2",
"description": "Markdown-ish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.", "description": "Markdown-ish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
"type": "module", "type": "module",
"module": "./dist/mermaid.core.mjs", "module": "./dist/mermaid.core.mjs",
@@ -60,22 +60,25 @@
}, },
"dependencies": { "dependencies": {
"@braintree/sanitize-url": "^6.0.1", "@braintree/sanitize-url": "^6.0.1",
"@mermaid-js/parser": "workspace:^", "@types/d3-scale": "^4.0.3",
"@types/d3-scale-chromatic": "^3.0.0",
"cytoscape": "^3.28.1", "cytoscape": "^3.28.1",
"cytoscape-cose-bilkent": "^4.1.0", "cytoscape-cose-bilkent": "^4.1.0",
"d3": "^7.4.0", "d3": "^7.4.0",
"d3-sankey": "^0.12.3", "d3-sankey": "^0.12.3",
"dagre-d3-es": "7.0.10", "dagre-d3-es": "7.0.10",
"dayjs": "^1.11.7", "dayjs": "^1.11.7",
"dompurify": "^3.0.5", "dompurify": "^3.0.5 <3.1.7",
"elkjs": "^0.9.0", "elkjs": "^0.9.0",
"katex": "^0.16.9", "katex": "^0.16.9",
"khroma": "^2.0.0", "khroma": "^2.0.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"mdast-util-from-markdown": "^1.3.0", "mdast-util-from-markdown": "^1.3.0",
"non-layered-tidy-tree-layout": "^2.0.2",
"stylis": "^4.1.3", "stylis": "^4.1.3",
"ts-dedent": "^2.2.0", "ts-dedent": "^2.2.0",
"uuid": "^9.0.0" "uuid": "^9.0.0",
"web-worker": "^1.2.0"
}, },
"devDependencies": { "devDependencies": {
"@adobe/jsonschema2md": "^7.1.4", "@adobe/jsonschema2md": "^7.1.4",
@@ -83,7 +86,6 @@
"@types/d3": "^7.4.0", "@types/d3": "^7.4.0",
"@types/d3-sankey": "^0.12.1", "@types/d3-sankey": "^0.12.1",
"@types/d3-scale": "^4.0.3", "@types/d3-scale": "^4.0.3",
"@types/d3-scale-chromatic": "^3.0.0",
"@types/d3-selection": "^3.0.5", "@types/d3-selection": "^3.0.5",
"@types/d3-shape": "^3.1.1", "@types/d3-shape": "^3.1.1",
"@types/dompurify": "^3.0.2", "@types/dompurify": "^3.0.2",

View File

@@ -233,23 +233,6 @@ async function generateTypescript(mermaidConfigSchema: JSONSchemaType<MermaidCon
} }
} }
/**
* Workaround for type duplication when a $ref property has siblings.
*
* @param json - The input JSON object.
*
* @see https://github.com/bcherny/json-schema-to-typescript/issues/193
*/
function removeProp(json: any, name: string) {
for (const prop in json) {
if (prop === name) {
delete json[prop];
} else if (typeof json[prop] === 'object') {
removeProp(json[prop], name);
}
}
}
/** Main function */ /** Main function */
async function main() { async function main() {
if (verifyOnly) { if (verifyOnly) {
@@ -260,8 +243,6 @@ async function main() {
const configJsonSchema = await loadJsonSchemaFromYaml(); const configJsonSchema = await loadJsonSchemaFromYaml();
removeProp(configJsonSchema, 'default');
validateSchema(configJsonSchema); validateSchema(configJsonSchema);
// Generate types from JSON Schema // Generate types from JSON Schema

View File

@@ -252,11 +252,12 @@ export function transformMarkdownAst({
node.lang = MERMAID_KEYWORD; node.lang = MERMAID_KEYWORD;
return [node]; return [node];
} else if (MERMAID_EXAMPLE_KEYWORDS.includes(node.lang)) { } else if (MERMAID_EXAMPLE_KEYWORDS.includes(node.lang)) {
// Return 2 nodes: // If Vitepress, return only the original node with the language now set to 'mermaid-example' (will be rendered using custom renderer)
// Else Return 2 nodes:
// 1. the original node with the language now set to 'mermaid-example' (will be rendered as code), and // 1. the original node with the language now set to 'mermaid-example' (will be rendered as code), and
// 2. a copy of the original node with the language set to 'mermaid' (will be rendered as a diagram) // 2. a copy of the original node with the language set to 'mermaid' (will be rendered as a diagram)
node.lang = MERMAID_CODE_ONLY_KEYWORD; node.lang = MERMAID_CODE_ONLY_KEYWORD;
return [node, Object.assign({}, node, { lang: MERMAID_KEYWORD })]; return vitepress ? [node] : [node, Object.assign({}, node, { lang: MERMAID_KEYWORD })];
} }
// Transform these blocks into block quotes. // Transform these blocks into block quotes.

View File

@@ -1,8 +1,10 @@
import * as configApi from './config.js'; import * as configApi from './config.js';
import { log } from './logger.js';
import { getDiagram, registerDiagram } from './diagram-api/diagramAPI.js'; import { getDiagram, registerDiagram } from './diagram-api/diagramAPI.js';
import { detectType, getDiagramLoader } from './diagram-api/detectType.js'; import { detectType, getDiagramLoader } from './diagram-api/detectType.js';
import { UnknownDiagramError } from './errors.js'; import { UnknownDiagramError } from './errors.js';
import { encodeEntities } from './utils.js'; import { encodeEntities } from './utils.js';
import type { DetailedError } from './utils.js'; import type { DetailedError } from './utils.js';
import type { DiagramDefinition, DiagramMetadata } from './diagram-api/types.js'; import type { DiagramDefinition, DiagramMetadata } from './diagram-api/types.js';
@@ -13,44 +15,47 @@ export type ParseErrorFunction = (err: string | DetailedError | unknown, hash?:
* @privateRemarks This is exported as part of the public mermaidAPI. * @privateRemarks This is exported as part of the public mermaidAPI.
*/ */
export class Diagram { export class Diagram {
public static async fromText(text: string, metadata: Pick<DiagramMetadata, 'title'> = {}) { type = 'graph';
const config = configApi.getConfig(); parser: DiagramDefinition['parser'];
const type = detectType(text, config); renderer: DiagramDefinition['renderer'];
text = encodeEntities(text) + '\n'; db: DiagramDefinition['db'];
private init?: DiagramDefinition['init'];
private detectError?: UnknownDiagramError;
constructor(public text: string, public metadata: Pick<DiagramMetadata, 'title'> = {}) {
this.text = encodeEntities(text);
this.text += '\n';
const cnf = configApi.getConfig();
try { try {
getDiagram(type); this.type = detectType(text, cnf);
} catch (e) { } catch (e) {
const loader = getDiagramLoader(type); this.type = 'error';
if (!loader) { this.detectError = e as UnknownDiagramError;
throw new UnknownDiagramError(`Diagram ${type} not found.`);
}
// Diagram not available, loading it.
// new diagram will try getDiagram again and if fails then it is a valid throw
const { id, diagram } = await loader();
registerDiagram(id, diagram);
} }
const { db, parser, renderer, init } = getDiagram(type); const diagram = getDiagram(this.type);
if (parser.parser) { log.debug('Type ' + this.type);
// The parser.parser.yy is only present in JISON parsers. So, we'll only set if required. // Setup diagram
parser.parser.yy = db; this.db = diagram.db;
} this.renderer = diagram.renderer;
db.clear?.(); this.parser = diagram.parser;
init?.(config); this.parser.parser.yy = this.db;
// This block was added for legacy compatibility. Use frontmatter instead of adding more special cases. this.init = diagram.init;
if (metadata.title) { this.parse();
db.setDiagramTitle?.(metadata.title);
}
await parser.parse(text);
return new Diagram(type, text, db, parser, renderer);
} }
private constructor( parse() {
public type: string, if (this.detectError) {
public text: string, throw this.detectError;
public db: DiagramDefinition['db'], }
public parser: DiagramDefinition['parser'], this.db.clear?.();
public renderer: DiagramDefinition['renderer'] const config = configApi.getConfig();
) {} this.init?.(config);
// This block was added for legacy compatibility. Use frontmatter instead of adding more special cases.
if (this.metadata.title) {
this.db.setDiagramTitle?.(this.metadata.title);
}
this.parser.parse(this.text);
}
async render(id: string, version: string) { async render(id: string, version: string) {
await this.renderer.draw(this.text, id, version, this); await this.renderer.draw(this.text, id, version, this);
@@ -64,3 +69,34 @@ export class Diagram {
return this.type; return this.type;
} }
} }
/**
* Parse the text asynchronously and generate a Diagram object asynchronously.
* **Warning:** This function may be changed in the future.
* @alpha
* @param text - The mermaid diagram definition.
* @param metadata - Diagram metadata, defined in YAML.
* @returns A the Promise of a Diagram object.
* @throws {@link UnknownDiagramError} if the diagram type can not be found.
* @privateRemarks This is exported as part of the public mermaidAPI.
*/
export const getDiagramFromText = async (
text: string,
metadata: Pick<DiagramMetadata, 'title'> = {}
): Promise<Diagram> => {
const type = detectType(text, configApi.getConfig());
try {
// Trying to find the diagram
getDiagram(type);
} catch (error) {
const loader = getDiagramLoader(type);
if (!loader) {
throw new UnknownDiagramError(`Diagram ${type} not found.`);
}
// Diagram not available, loading it.
// new diagram will try getDiagram again and if fails then it is a valid throw
const { id, diagram } = await loader();
registerDiagram(id, diagram);
}
return new Diagram(text, metadata);
};

View File

@@ -61,7 +61,7 @@ export interface MermaidConfig {
* You may also use `themeCSS` to override this value. * You may also use `themeCSS` to override this value.
* *
*/ */
theme?: 'default' | 'forest' | 'dark' | 'neutral' | 'null'; theme?: string | 'default' | 'forest' | 'dark' | 'neutral' | 'null';
themeVariables?: any; themeVariables?: any;
themeCSS?: string; themeCSS?: string;
/** /**
@@ -87,11 +87,26 @@ export interface MermaidConfig {
* This option decides the amount of logging to be used by mermaid. * This option decides the amount of logging to be used by mermaid.
* *
*/ */
logLevel?: 'trace' | 0 | 'debug' | 1 | 'info' | 2 | 'warn' | 3 | 'error' | 4 | 'fatal' | 5; logLevel?:
| number
| string
| 0
| 2
| 1
| 'trace'
| 'debug'
| 'info'
| 'warn'
| 'error'
| 'fatal'
| 3
| 4
| 5
| undefined;
/** /**
* Level of trust for parsed diagram * Level of trust for parsed diagram
*/ */
securityLevel?: 'strict' | 'loose' | 'antiscript' | 'sandbox'; securityLevel?: string | 'strict' | 'loose' | 'antiscript' | 'sandbox' | undefined;
/** /**
* Dictates whether mermaid starts on Page load * Dictates whether mermaid starts on Page load
*/ */
@@ -154,43 +169,19 @@ export interface MermaidConfig {
gitGraph?: GitGraphDiagramConfig; gitGraph?: GitGraphDiagramConfig;
c4?: C4DiagramConfig; c4?: C4DiagramConfig;
sankey?: SankeyDiagramConfig; sankey?: SankeyDiagramConfig;
packet?: PacketDiagramConfig;
block?: BlockDiagramConfig; block?: BlockDiagramConfig;
dompurifyConfig?: DOMPurifyConfiguration; dompurifyConfig?: DOMPurifyConfiguration;
wrap?: boolean; wrap?: boolean;
fontSize?: number; fontSize?: number;
} }
/** /**
* The object containing configurations specific for packet diagrams. * The object containing configurations specific for block diagrams.
* *
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfig`'s JSON-Schema
* via the `definition` "PacketDiagramConfig". * via the `definition` "BlockDiagramConfig".
*/ */
export interface PacketDiagramConfig extends BaseDiagramConfig { export interface BlockDiagramConfig extends BaseDiagramConfig {
/** padding?: number;
* The height of each row in the packet diagram.
*/
rowHeight?: number;
/**
* The width of each bit in the packet diagram.
*/
bitWidth?: number;
/**
* The number of bits to display per row.
*/
bitsPerRow?: number;
/**
* Toggle to display or hide bit numbers.
*/
showBits?: boolean;
/**
* The horizontal padding between the blocks in a row.
*/
paddingX?: number;
/**
* The vertical padding between the rows.
*/
paddingY?: number;
} }
/** /**
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfig`'s JSON-Schema
@@ -206,15 +197,6 @@ export interface BaseDiagramConfig {
*/ */
useMaxWidth?: boolean; useMaxWidth?: boolean;
} }
/**
* The object containing configurations specific for block diagrams.
*
* This interface was referenced by `MermaidConfig`'s JSON-Schema
* via the `definition` "BlockDiagramConfig".
*/
export interface BlockDiagramConfig extends BaseDiagramConfig {
padding?: number;
}
/** /**
* The object containing configurations specific for c4 diagrams * The object containing configurations specific for c4 diagrams
* *
@@ -825,8 +807,8 @@ export interface XYChartConfig extends BaseDiagramConfig {
* Should show the chart title * Should show the chart title
*/ */
showTitle?: boolean; showTitle?: boolean;
xAxis?: XYChartAxisConfig; xAxis?: XYChartAxisConfig1;
yAxis?: XYChartAxisConfig; yAxis?: XYChartAxisConfig2;
/** /**
* How to plot will be drawn horizontal or vertical * How to plot will be drawn horizontal or vertical
*/ */
@@ -836,6 +818,104 @@ export interface XYChartConfig extends BaseDiagramConfig {
*/ */
plotReservedSpacePercent?: number; plotReservedSpacePercent?: number;
} }
/**
* This object contains configuration for XYChart axis config
*/
export interface XYChartAxisConfig1 {
/**
* Should show the axis labels (tick text)
*/
showLabel?: boolean;
/**
* font size of the axis labels (tick text)
*/
labelFontSize?: number;
/**
* top and bottom space from axis label (tick text)
*/
labelPadding?: number;
/**
* Should show the axis title
*/
showTitle?: boolean;
/**
* font size of the axis title
*/
titleFontSize?: number;
/**
* top and bottom space from axis title
*/
titlePadding?: number;
/**
* Should show the axis tick lines
*/
showTick?: boolean;
/**
* length of the axis tick lines
*/
tickLength?: number;
/**
* width of the axis tick lines
*/
tickWidth?: number;
/**
* Show line across the axis
*/
showAxisLine?: boolean;
/**
* Width of the axis line
*/
axisLineWidth?: number;
}
/**
* This object contains configuration for XYChart axis config
*/
export interface XYChartAxisConfig2 {
/**
* Should show the axis labels (tick text)
*/
showLabel?: boolean;
/**
* font size of the axis labels (tick text)
*/
labelFontSize?: number;
/**
* top and bottom space from axis label (tick text)
*/
labelPadding?: number;
/**
* Should show the axis title
*/
showTitle?: boolean;
/**
* font size of the axis title
*/
titleFontSize?: number;
/**
* top and bottom space from axis title
*/
titlePadding?: number;
/**
* Should show the axis tick lines
*/
showTick?: boolean;
/**
* length of the axis tick lines
*/
tickLength?: number;
/**
* width of the axis tick lines
*/
tickWidth?: number;
/**
* Show line across the axis
*/
showAxisLine?: boolean;
/**
* Width of the axis line
*/
axisLineWidth?: number;
}
/** /**
* The object containing configurations specific for entity relationship diagrams * The object containing configurations specific for entity relationship diagrams
* *
@@ -856,7 +936,7 @@ export interface ErDiagramConfig extends BaseDiagramConfig {
/** /**
* Directional bias for layout of entities * Directional bias for layout of entities
*/ */
layoutDirection?: 'TB' | 'BT' | 'LR' | 'RL'; layoutDirection?: string | 'TB' | 'BT' | 'LR' | 'RL';
/** /**
* The minimum width of an entity box. Expressed in pixels. * The minimum width of an entity box. Expressed in pixels.
*/ */
@@ -921,7 +1001,7 @@ export interface StateDiagramConfig extends BaseDiagramConfig {
* Decides which rendering engine that is to be used for the rendering. * Decides which rendering engine that is to be used for the rendering.
* *
*/ */
defaultRenderer?: 'dagre-d3' | 'dagre-wrapper' | 'elk'; defaultRenderer?: string | 'dagre-d3' | 'dagre-wrapper' | 'elk';
} }
/** /**
* This interface was referenced by `MermaidConfig`'s JSON-Schema * This interface was referenced by `MermaidConfig`'s JSON-Schema
@@ -945,7 +1025,7 @@ export interface ClassDiagramConfig extends BaseDiagramConfig {
* Decides which rendering engine that is to be used for the rendering. * Decides which rendering engine that is to be used for the rendering.
* *
*/ */
defaultRenderer?: 'dagre-d3' | 'dagre-wrapper' | 'elk'; defaultRenderer?: string | 'dagre-d3' | 'dagre-wrapper' | 'elk';
nodeSpacing?: number; nodeSpacing?: number;
rankSpacing?: number; rankSpacing?: number;
/** /**
@@ -1005,7 +1085,7 @@ export interface JourneyDiagramConfig extends BaseDiagramConfig {
/** /**
* Multiline message alignment * Multiline message alignment
*/ */
messageAlign?: 'left' | 'center' | 'right'; messageAlign?: string | 'left' | 'center' | 'right';
/** /**
* Prolongs the edge of the diagram downwards. * Prolongs the edge of the diagram downwards.
* *
@@ -1084,7 +1164,7 @@ export interface TimelineDiagramConfig extends BaseDiagramConfig {
/** /**
* Multiline message alignment * Multiline message alignment
*/ */
messageAlign?: 'left' | 'center' | 'right'; messageAlign?: string | 'left' | 'center' | 'right';
/** /**
* Prolongs the edge of the diagram downwards. * Prolongs the edge of the diagram downwards.
* *
@@ -1195,7 +1275,7 @@ export interface GanttDiagramConfig extends BaseDiagramConfig {
* Controls the display mode. * Controls the display mode.
* *
*/ */
displayMode?: '' | 'compact'; displayMode?: string | 'compact';
/** /**
* On which day a week-based interval should start * On which day a week-based interval should start
* *
@@ -1254,7 +1334,7 @@ export interface SequenceDiagramConfig extends BaseDiagramConfig {
/** /**
* Multiline message alignment * Multiline message alignment
*/ */
messageAlign?: 'left' | 'center' | 'right'; messageAlign?: string | 'left' | 'center' | 'right';
/** /**
* Mirror actors under diagram * Mirror actors under diagram
* *
@@ -1311,7 +1391,7 @@ export interface SequenceDiagramConfig extends BaseDiagramConfig {
/** /**
* This sets the text alignment of actor-attached notes * This sets the text alignment of actor-attached notes
*/ */
noteAlign?: 'left' | 'center' | 'right'; noteAlign?: string | 'left' | 'center' | 'right';
/** /**
* This sets the font size of actor messages * This sets the font size of actor messages
*/ */
@@ -1395,7 +1475,7 @@ export interface FlowchartDiagramConfig extends BaseDiagramConfig {
* Defines how mermaid renders curves for flowcharts. * Defines how mermaid renders curves for flowcharts.
* *
*/ */
curve?: 'basis' | 'linear' | 'cardinal'; curve?: string | 'basis' | 'linear' | 'cardinal';
/** /**
* Represents the padding between the labels and the shape * Represents the padding between the labels and the shape
* *
@@ -1407,7 +1487,7 @@ export interface FlowchartDiagramConfig extends BaseDiagramConfig {
* Decides which rendering engine that is to be used for the rendering. * Decides which rendering engine that is to be used for the rendering.
* *
*/ */
defaultRenderer?: 'dagre-d3' | 'dagre-wrapper' | 'elk'; defaultRenderer?: string | 'dagre-d3' | 'dagre-wrapper' | 'elk';
/** /**
* Width of nodes where text is wrapped. * Width of nodes where text is wrapped.
* *
@@ -1431,7 +1511,13 @@ export interface SankeyDiagramConfig extends BaseDiagramConfig {
* *
*/ */
linkColor?: SankeyLinkColor | string; linkColor?: SankeyLinkColor | string;
nodeAlignment?: SankeyNodeAlignment; /**
* Controls the alignment of the Sankey diagrams.
*
* See <https://github.com/d3/d3-sankey#alignments>.
*
*/
nodeAlignment?: 'left' | 'right' | 'center' | 'justify';
useMaxWidth?: boolean; useMaxWidth?: boolean;
/** /**
* Toggle to display or hide values along with title. * Toggle to display or hide values along with title.

View File

@@ -257,9 +257,6 @@ const config: RequiredDeep<MermaidConfig> = {
// TODO: can we make this default to `true` instead? // TODO: can we make this default to `true` instead?
useMaxWidth: false, useMaxWidth: false,
}, },
packet: {
...defaultConfigJson.packet,
},
}; };
const keyify = (obj: any, prefix = ''): string[] => const keyify = (obj: any, prefix = ''): string[] =>

View File

@@ -71,9 +71,10 @@ export const registerLazyLoadedDiagrams = (...diagrams: ExternalDiagramDefinitio
export const addDetector = (key: string, detector: DiagramDetector, loader?: DiagramLoader) => { export const addDetector = (key: string, detector: DiagramDetector, loader?: DiagramLoader) => {
if (detectors[key]) { if (detectors[key]) {
log.warn(`Detector with key ${key} already exists. Overwriting.`); log.error(`Detector with key ${key} already exists`);
} else {
detectors[key] = { detector, loader };
} }
detectors[key] = { detector, loader };
log.debug(`Detector with key ${key} added${loader ? ' with loader' : ''}`); log.debug(`Detector with key ${key} added${loader ? ' with loader' : ''}`);
}; };

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