mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-10-24 16:34:09 +02:00
Compare commits
185 Commits
v10.6.1
...
sidv/remov
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
927217d77c | ||
|
|
b5f3cdc0b0 | ||
|
|
510549f365 | ||
|
|
e8ee5f548f | ||
|
|
862d20ce9d | ||
|
|
c56025ec3b | ||
|
|
6ce543e118 | ||
|
|
0c0f7a739e | ||
|
|
33e94d3f35 | ||
|
|
5fdbf5d891 | ||
|
|
6d0d8ac8e6 | ||
|
|
adff22c1e2 | ||
|
|
aa5d586bd6 | ||
|
|
b12b8a9278 | ||
|
|
3c13386e5d | ||
|
|
a177141962 | ||
|
|
92f1644550 | ||
|
|
07dcb64b22 | ||
|
|
0f2b941e2d | ||
|
|
c89557d85c | ||
|
|
e8ad72a980 | ||
|
|
a8fe640546 | ||
|
|
01bbcc597a | ||
|
|
6fb5641afc | ||
|
|
fe32bcbf7c | ||
|
|
f47e920a97 | ||
|
|
1571b25d29 | ||
|
|
4a92fc5c92 | ||
|
|
8d6317b49a | ||
|
|
ee49c4b660 | ||
|
|
72038a68a9 | ||
|
|
051260e9a8 | ||
|
|
3cf0a2b290 | ||
|
|
adfb60e045 | ||
|
|
ac595eb96c | ||
|
|
79bae62ce0 | ||
|
|
3038ce5864 | ||
|
|
c8a826dfce | ||
|
|
fadae38bec | ||
|
|
d1fba9c567 | ||
|
|
c2e26baf4d | ||
|
|
f6b1e049f1 | ||
|
|
71478f5a64 | ||
|
|
c9ace33cf1 | ||
|
|
30646d80f1 | ||
|
|
6e74e91b5d | ||
|
|
eb4bd314b6 | ||
|
|
7a3ce3e337 | ||
|
|
d1045ed644 | ||
|
|
396ea3cec2 | ||
|
|
51d076a83b | ||
|
|
dff8b783b8 | ||
|
|
78c1a3d980 | ||
|
|
23cbf50413 | ||
|
|
dff13439f6 | ||
|
|
b61ea4b8aa | ||
|
|
b5fd8fb7c1 | ||
|
|
4ba3e2cff3 | ||
|
|
a818f3e3ae | ||
|
|
58bad981be | ||
|
|
6a5b7c40bd | ||
|
|
6e6e92a1d1 | ||
|
|
0c5cf72235 | ||
|
|
fff25e7e2c | ||
|
|
2a8323f951 | ||
|
|
390e22cc0b | ||
|
|
a3ee21d7fc | ||
|
|
8f2a5064cb | ||
|
|
3394541b41 | ||
|
|
54ab3fc3b2 | ||
|
|
36a727d44e | ||
|
|
06d2ba8398 | ||
|
|
9637b0c187 | ||
|
|
7960f94eba | ||
|
|
3f486ac0e1 | ||
|
|
b36cdaceca | ||
|
|
3b8c48dd26 | ||
|
|
af73818c90 | ||
|
|
77e700832f | ||
|
|
111e067df5 | ||
|
|
f31cddee0c | ||
|
|
b232975064 | ||
|
|
3389ecdfea | ||
|
|
99a79e15f3 | ||
|
|
31ec3d1496 | ||
|
|
d97e31a38c | ||
|
|
f12b19216b | ||
|
|
345e82abee | ||
|
|
995449cbf6 | ||
|
|
ce3d9fcdde | ||
|
|
c279a9f9ed | ||
|
|
cdb4639aa4 | ||
|
|
2a9eb7f123 | ||
|
|
1fec55d5f7 | ||
|
|
4559ba625c | ||
|
|
49a197eaa8 | ||
|
|
3abe7cfc45 | ||
|
|
0239e49d92 | ||
|
|
99beeba261 | ||
|
|
a1673d3aca | ||
|
|
672a289909 | ||
|
|
dc22189eef | ||
|
|
5f740312fe | ||
|
|
123d53c265 | ||
|
|
b928e60d8b | ||
|
|
9688269027 | ||
|
|
91eb824c21 | ||
|
|
3c90894e38 | ||
|
|
271b779995 | ||
|
|
52b33f6f47 | ||
|
|
5aee43d05b | ||
|
|
7b29a380fc | ||
|
|
997c23befa | ||
|
|
4ce26296d6 | ||
|
|
4342759da7 | ||
|
|
25f2d224f1 | ||
|
|
0abb4f8c6f | ||
|
|
697ac18872 | ||
|
|
fc229cf274 | ||
|
|
b48136d994 | ||
|
|
77ba7c987a | ||
|
|
84f3baf013 | ||
|
|
44b93c039a | ||
|
|
4d5313699e | ||
|
|
cd198290d7 | ||
|
|
60ed7d3273 | ||
|
|
9bcfba6620 | ||
|
|
7ea3c64268 | ||
|
|
2b6a34e9e0 | ||
|
|
458b90c78d | ||
|
|
dd284c0986 | ||
|
|
21539dfb6a | ||
|
|
91785b8284 | ||
|
|
f202770b70 | ||
|
|
8186a54962 | ||
|
|
866909b803 | ||
|
|
408910e6e8 | ||
|
|
24c8e575f4 | ||
|
|
8d0ca2c876 | ||
|
|
fc96ebefd4 | ||
|
|
394330175f | ||
|
|
f946c3da06 | ||
|
|
156fbd1958 | ||
|
|
7dd0d126e2 | ||
|
|
205360c109 | ||
|
|
984a0e6d06 | ||
|
|
eb63568ceb | ||
|
|
cc6f896b69 | ||
|
|
83e47a7216 | ||
|
|
1d64549cce | ||
|
|
4ae361bd1f | ||
|
|
6502496a2c | ||
|
|
8678ceeb3c | ||
|
|
9cb62f4d2e | ||
|
|
6c0ef54e18 | ||
|
|
fd731c5ccd | ||
|
|
cbe9490dc0 | ||
|
|
82054bfabc | ||
|
|
963dd75c39 | ||
|
|
1c24617f98 | ||
|
|
1559c2ca21 | ||
|
|
6141722b1f | ||
|
|
222d8eed4e | ||
|
|
718d52a72c | ||
|
|
fe1a06271a | ||
|
|
bd2370555b | ||
|
|
86c9ee4e90 | ||
|
|
b26bcf1343 | ||
|
|
5d5c6275f9 | ||
|
|
9c1a47d1fc | ||
|
|
13852b7f4e | ||
|
|
4fd7a88a15 | ||
|
|
5c2a6b5eb1 | ||
|
|
9cbebbb8a0 | ||
|
|
e26d987c4e | ||
|
|
53669efaf8 | ||
|
|
b68f45ef59 | ||
|
|
8f44de651b | ||
|
|
2ede244da0 | ||
|
|
77a181978e | ||
|
|
170bbce0d3 | ||
|
|
fc99d9be41 | ||
|
|
9fb9bed806 | ||
|
|
01b2f80a95 | ||
|
|
da7ff777d1 |
25
.build/common.ts
Normal file
25
.build/common.ts
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
/**
|
||||||
|
* 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',
|
||||||
|
},
|
||||||
|
} as const;
|
||||||
5
.build/generateLangium.ts
Normal file
5
.build/generateLangium.ts
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
import { generate } from 'langium-cli';
|
||||||
|
|
||||||
|
export async function generateLangium() {
|
||||||
|
await generate({ file: `./packages/parser/langium-config.json` });
|
||||||
|
}
|
||||||
123
.build/jsonSchema.ts
Normal file
123
.build/jsonSchema.ts
Normal file
@@ -0,0 +1,123 @@
|
|||||||
|
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',
|
||||||
|
] 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)};`;
|
||||||
|
};
|
||||||
9
.build/langium-cli.d.ts
vendored
Normal file
9
.build/langium-cli.d.ts
vendored
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
declare module 'langium-cli' {
|
||||||
|
export interface GenerateOptions {
|
||||||
|
file?: string;
|
||||||
|
mode?: 'development' | 'production';
|
||||||
|
watch?: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function generate(options: GenerateOptions): Promise<boolean>;
|
||||||
|
}
|
||||||
65
.esbuild/build.ts
Normal file
65
.esbuild/build.ts
Normal file
@@ -0,0 +1,65 @@
|
|||||||
|
import { build } from 'esbuild';
|
||||||
|
import { mkdir, writeFile } from 'node:fs/promises';
|
||||||
|
import { MermaidBuildOptions, defaultOptions, getBuildConfig } from './util.js';
|
||||||
|
import { packageOptions } from '../.build/common.js';
|
||||||
|
import { generateLangium } from '../.build/generateLangium.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 dependecy
|
||||||
|
for (const pkg of packageNames) {
|
||||||
|
await buildPackage(pkg).catch(handler);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
void main();
|
||||||
15
.esbuild/jisonPlugin.ts
Normal file
15
.esbuild/jisonPlugin.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
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: [] };
|
||||||
|
});
|
||||||
|
},
|
||||||
|
};
|
||||||
35
.esbuild/jsonSchemaPlugin.ts
Normal file
35
.esbuild/jsonSchemaPlugin.ts
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
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;
|
||||||
116
.esbuild/server.ts
Normal file
116
.esbuild/server.ts
Normal file
@@ -0,0 +1,116 @@
|
|||||||
|
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';
|
||||||
|
|
||||||
|
const parserCtx = await context(
|
||||||
|
getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: 'parser' })
|
||||||
|
);
|
||||||
|
const mermaidCtx = await context(
|
||||||
|
getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: 'mermaid' })
|
||||||
|
);
|
||||||
|
const mermaidIIFECtx = await context(
|
||||||
|
getBuildConfig({
|
||||||
|
...defaultOptions,
|
||||||
|
minify: false,
|
||||||
|
core: false,
|
||||||
|
entryName: 'mermaid',
|
||||||
|
format: 'iife',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const externalCtx = await context(
|
||||||
|
getBuildConfig({
|
||||||
|
...defaultOptions,
|
||||||
|
minify: false,
|
||||||
|
core: false,
|
||||||
|
entryName: 'mermaid-example-diagram',
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const zenumlCtx = await context(
|
||||||
|
getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: 'mermaid-zenuml' })
|
||||||
|
);
|
||||||
|
const contexts = [parserCtx, mermaidCtx, mermaidIIFECtx, externalCtx, zenumlCtx];
|
||||||
|
|
||||||
|
const rebuildAll = async () => {
|
||||||
|
console.time('Rebuild time');
|
||||||
|
await Promise.all(contexts.map((ctx) => ctx.rebuild()));
|
||||||
|
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);
|
||||||
|
app.use(express.static('./packages/parser/dist'));
|
||||||
|
app.use(express.static('./packages/mermaid/dist'));
|
||||||
|
app.use(express.static('./packages/mermaid-zenuml/dist'));
|
||||||
|
app.use(express.static('./packages/mermaid-example-diagram/dist'));
|
||||||
|
app.use(express.static('demos'));
|
||||||
|
app.use(express.static('cypress/platform'));
|
||||||
|
|
||||||
|
app.listen(9000, () => {
|
||||||
|
console.log(`Listening on http://localhost:9000`);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
createServer();
|
||||||
98
.esbuild/util.ts
Normal file
98
.esbuild/util.ts
Normal file
@@ -0,0 +1,98 @@
|
|||||||
|
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]`,
|
||||||
|
});
|
||||||
|
|
||||||
|
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;
|
||||||
|
};
|
||||||
@@ -6,3 +6,6 @@ cypress/plugins/index.js
|
|||||||
coverage
|
coverage
|
||||||
*.json
|
*.json
|
||||||
node_modules
|
node_modules
|
||||||
|
|
||||||
|
# autogenereated by langium-cli
|
||||||
|
generated/
|
||||||
|
|||||||
26
.github/pr-labeler.yml
vendored
26
.github/pr-labeler.yml
vendored
@@ -1,4 +1,22 @@
|
|||||||
'Type: Bug / Error': ['bug/*', fix/*]
|
# yaml-language-server: $schema=https://raw.githubusercontent.com/release-drafter/release-drafter/master/schema.json
|
||||||
'Type: Enhancement': ['feature/*', 'feat/*']
|
autolabeler:
|
||||||
'Type: Other': ['other/*', 'chore/*', 'test/*', 'refactor/*']
|
- label: 'Type: Bug / Error'
|
||||||
'Area: Documentation': ['docs/*']
|
branch:
|
||||||
|
- '/bug\/.+/'
|
||||||
|
- '/fix\/.+/'
|
||||||
|
- label: 'Type: Enhancement'
|
||||||
|
branch:
|
||||||
|
- '/feature\/.+/'
|
||||||
|
- '/feat\/.+/'
|
||||||
|
- label: 'Type: Other'
|
||||||
|
branch:
|
||||||
|
- '/other\/.+/'
|
||||||
|
- '/chore\/.+/'
|
||||||
|
- '/test\/.+/'
|
||||||
|
- '/refactor\/.+/'
|
||||||
|
- label: 'Area: Documentation'
|
||||||
|
branch:
|
||||||
|
- '/docs\/.+/'
|
||||||
|
|
||||||
|
template: |
|
||||||
|
This field is unused, as we only use this config file for labeling PRs.
|
||||||
|
|||||||
2
.github/release-drafter.yml
vendored
2
.github/release-drafter.yml
vendored
@@ -25,8 +25,6 @@ categories:
|
|||||||
change-template: '- $TITLE (#$NUMBER) @$AUTHOR'
|
change-template: '- $TITLE (#$NUMBER) @$AUTHOR'
|
||||||
sort-by: title
|
sort-by: title
|
||||||
sort-direction: ascending
|
sort-direction: ascending
|
||||||
branches:
|
|
||||||
- develop
|
|
||||||
exclude-labels:
|
exclude-labels:
|
||||||
- 'Skip changelog'
|
- 'Skip changelog'
|
||||||
no-changes-template: 'This release contains minor changes and bugfixes.'
|
no-changes-template: 'This release contains minor changes and bugfixes.'
|
||||||
|
|||||||
4
.github/workflows/build-docs.yml
vendored
4
.github/workflows/build-docs.yml
vendored
@@ -16,12 +16,12 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
cache: pnpm
|
cache: pnpm
|
||||||
node-version: 18
|
node-version: 18
|
||||||
|
|||||||
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@@ -19,13 +19,13 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
node-version: [18.x]
|
node-version: [18.x]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
# uses version from "packageManager" field in package.json
|
# uses version from "packageManager" field in package.json
|
||||||
|
|
||||||
- name: Setup Node.js ${{ matrix.node-version }}
|
- name: Setup Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
cache: pnpm
|
cache: pnpm
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|||||||
2
.github/workflows/check-readme-in-sync.yml
vendored
2
.github/workflows/check-readme-in-sync.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Check for difference in README.md and docs/README.md
|
- name: Check for difference in README.md and docs/README.md
|
||||||
run: |
|
run: |
|
||||||
|
|||||||
2
.github/workflows/checks.yml
vendored
2
.github/workflows/checks.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
|||||||
name: check tests
|
name: check tests
|
||||||
if: github.repository_owner == 'mermaid-js'
|
if: github.repository_owner == 'mermaid-js'
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- uses: testomatio/check-tests@stable
|
- uses: testomatio/check-tests@stable
|
||||||
|
|||||||
2
.github/workflows/codeql.yml
vendored
2
.github/workflows/codeql.yml
vendored
@@ -29,7 +29,7 @@ jobs:
|
|||||||
|
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
|
|||||||
4
.github/workflows/dependency-review.yml
vendored
4
.github/workflows/dependency-review.yml
vendored
@@ -1,6 +1,6 @@
|
|||||||
# Dependency Review Action
|
# Dependency Review Action
|
||||||
#
|
#
|
||||||
# This Action will scan dependency manifest files that change as part of a Pull Reqest, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.
|
# This Action will scan dependency manifest files that change as part of a Pull Request, surfacing known-vulnerable versions of the packages declared or updated in the PR. Once installed, if the workflow run is marked as required, PRs introducing known-vulnerable packages will be blocked from merging.
|
||||||
#
|
#
|
||||||
# Source repository: https://github.com/actions/dependency-review-action
|
# Source repository: https://github.com/actions/dependency-review-action
|
||||||
# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
|
# Public documentation: https://docs.github.com/en/code-security/supply-chain-security/understanding-your-software-supply-chain/about-dependency-review#dependency-review-enforcement
|
||||||
@@ -15,6 +15,6 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: 'Checkout Repository'
|
- name: 'Checkout Repository'
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
- name: 'Dependency Review'
|
- name: 'Dependency Review'
|
||||||
uses: actions/dependency-review-action@v3
|
uses: actions/dependency-review-action@v3
|
||||||
|
|||||||
4
.github/workflows/e2e-applitools.yml
vendored
4
.github/workflows/e2e-applitools.yml
vendored
@@ -30,13 +30,13 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
echo "::error,title=Not using Applitols::APPLITOOLS_API_KEY is empty, disabling Applitools for this run."
|
echo "::error,title=Not using Applitols::APPLITOOLS_API_KEY is empty, disabling Applitools for this run."
|
||||||
|
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
# uses version from "packageManager" field in package.json
|
# uses version from "packageManager" field in package.json
|
||||||
|
|
||||||
- name: Setup Node.js ${{ matrix.node-version }}
|
- name: Setup Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
|
|||||||
4
.github/workflows/e2e.yml
vendored
4
.github/workflows/e2e.yml
vendored
@@ -17,13 +17,13 @@ jobs:
|
|||||||
node-version: [18.x]
|
node-version: [18.x]
|
||||||
containers: [1, 2, 3, 4]
|
containers: [1, 2, 3, 4]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
# uses version from "packageManager" field in package.json
|
# uses version from "packageManager" field in package.json
|
||||||
|
|
||||||
- name: Setup Node.js ${{ matrix.node-version }}
|
- name: Setup Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|
||||||
|
|||||||
2
.github/workflows/link-checker.yml
vendored
2
.github/workflows/link-checker.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
|||||||
# lychee only uses the GITHUB_TOKEN to avoid rate-limiting
|
# lychee only uses the GITHUB_TOKEN to avoid rate-limiting
|
||||||
contents: read
|
contents: read
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- name: Restore lychee cache
|
- name: Restore lychee cache
|
||||||
uses: actions/cache@v3
|
uses: actions/cache@v3
|
||||||
|
|||||||
4
.github/workflows/lint.yml
vendored
4
.github/workflows/lint.yml
vendored
@@ -20,13 +20,13 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
node-version: [18.x]
|
node-version: [18.x]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
# uses version from "packageManager" field in package.json
|
# uses version from "packageManager" field in package.json
|
||||||
|
|
||||||
- name: Setup Node.js ${{ matrix.node-version }}
|
- name: Setup Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
cache: pnpm
|
cache: pnpm
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|||||||
@@ -1,23 +0,0 @@
|
|||||||
name: Validate PR Labeler Configuration
|
|
||||||
on:
|
|
||||||
push:
|
|
||||||
paths:
|
|
||||||
- .github/workflows/pr-labeler-config-validator.yml
|
|
||||||
- .github/workflows/pr-labeler.yml
|
|
||||||
- .github/pr-labeler.yml
|
|
||||||
pull_request:
|
|
||||||
paths:
|
|
||||||
- .github/workflows/pr-labeler-config-validator.yml
|
|
||||||
- .github/workflows/pr-labeler.yml
|
|
||||||
- .github/pr-labeler.yml
|
|
||||||
|
|
||||||
jobs:
|
|
||||||
pr-labeler:
|
|
||||||
runs-on: ubuntu-latest
|
|
||||||
steps:
|
|
||||||
- name: Checkout Repository
|
|
||||||
uses: actions/checkout@v3
|
|
||||||
- name: Validate Configuration
|
|
||||||
uses: Yash-Singh1/pr-labeler-config-validator@releases/v0.0.3
|
|
||||||
with:
|
|
||||||
configuration-path: .github/pr-labeler.yml
|
|
||||||
22
.github/workflows/pr-labeler.yml
vendored
22
.github/workflows/pr-labeler.yml
vendored
@@ -1,13 +1,31 @@
|
|||||||
name: Apply labels to PR
|
name: Apply labels to PR
|
||||||
on:
|
on:
|
||||||
pull_request_target:
|
pull_request_target:
|
||||||
types: [opened]
|
# required for pr-labeler to support PRs from forks
|
||||||
|
# ===================== ⛔ ☢️ 🚫 ⚠️ Warning ⚠️ 🚫 ☢️ ⛔ =======================
|
||||||
|
# Be very careful what you put in this GitHub Action workflow file to avoid
|
||||||
|
# malicious PRs from getting access to the Mermaid-js repo.
|
||||||
|
#
|
||||||
|
# Please read the following first before reviewing/merging:
|
||||||
|
# - https://docs.github.com/en/actions/using-workflows/events-that-trigger-workflows#pull_request_target
|
||||||
|
# - https://securitylab.github.com/research/github-actions-preventing-pwn-requests/
|
||||||
|
types: [opened, reopened, synchronize]
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
pr-labeler:
|
pr-labeler:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: read # read permission is required to read config file
|
||||||
|
pull-requests: write # write permission is required to label PRs
|
||||||
steps:
|
steps:
|
||||||
- name: Label PR
|
- name: Label PR
|
||||||
uses: TimonVS/pr-labeler-action@v4
|
uses: release-drafter/release-drafter@v5
|
||||||
|
with:
|
||||||
|
config-name: pr-labeler.yml
|
||||||
|
disable-autolabeler: false
|
||||||
|
disable-releaser: true
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
4
.github/workflows/publish-docs.yml
vendored
4
.github/workflows/publish-docs.yml
vendored
@@ -23,12 +23,12 @@ jobs:
|
|||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v3
|
uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
cache: pnpm
|
cache: pnpm
|
||||||
node-version: 18
|
node-version: 18
|
||||||
|
|||||||
10
.github/workflows/release-draft.yml
vendored
10
.github/workflows/release-draft.yml
vendored
@@ -5,11 +5,19 @@ on:
|
|||||||
branches:
|
branches:
|
||||||
- develop
|
- develop
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: read
|
||||||
|
|
||||||
jobs:
|
jobs:
|
||||||
draft-release:
|
draft-release:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
|
permissions:
|
||||||
|
contents: write # write permission is required to create a github release
|
||||||
|
pull-requests: read # required to read PR titles/labels
|
||||||
steps:
|
steps:
|
||||||
- name: Draft Release
|
- name: Draft Release
|
||||||
uses: toolmantim/release-drafter@v5
|
uses: release-drafter/release-drafter@v5
|
||||||
|
with:
|
||||||
|
disable-autolabeler: true
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
|||||||
@@ -9,14 +9,14 @@ jobs:
|
|||||||
publish-preview:
|
publish-preview:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
|
|
||||||
- name: Setup Node.js
|
- name: Setup Node.js
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
cache: pnpm
|
cache: pnpm
|
||||||
node-version: 18.x
|
node-version: 18.x
|
||||||
|
|||||||
4
.github/workflows/release-publish.yml
vendored
4
.github/workflows/release-publish.yml
vendored
@@ -8,14 +8,14 @@ jobs:
|
|||||||
publish:
|
publish:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- 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@v2
|
||||||
# uses version from "packageManager" field in package.json
|
# uses version from "packageManager" field in package.json
|
||||||
|
|
||||||
- name: Setup Node.js v18
|
- name: Setup Node.js v18
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
cache: pnpm
|
cache: pnpm
|
||||||
node-version: 18.x
|
node-version: 18.x
|
||||||
|
|||||||
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@@ -12,13 +12,13 @@ jobs:
|
|||||||
matrix:
|
matrix:
|
||||||
node-version: [18.x]
|
node-version: [18.x]
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
- uses: pnpm/action-setup@v2
|
- uses: pnpm/action-setup@v2
|
||||||
# uses version from "packageManager" field in package.json
|
# uses version from "packageManager" field in package.json
|
||||||
|
|
||||||
- name: Setup Node.js ${{ matrix.node-version }}
|
- name: Setup Node.js ${{ matrix.node-version }}
|
||||||
uses: actions/setup-node@v3
|
uses: actions/setup-node@v4
|
||||||
with:
|
with:
|
||||||
cache: pnpm
|
cache: pnpm
|
||||||
node-version: ${{ matrix.node-version }}
|
node-version: ${{ matrix.node-version }}
|
||||||
|
|||||||
2
.github/workflows/update-browserlist.yml
vendored
2
.github/workflows/update-browserlist.yml
vendored
@@ -8,7 +8,7 @@ jobs:
|
|||||||
update-browser-list:
|
update-browser-list:
|
||||||
runs-on: ubuntu-latest
|
runs-on: ubuntu-latest
|
||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v3
|
- uses: actions/checkout@v4
|
||||||
- run: npx browserslist@latest --update-db
|
- run: npx browserslist@latest --update-db
|
||||||
- name: Commit changes
|
- name: Commit changes
|
||||||
uses: EndBug/add-and-commit@v9
|
uses: EndBug/add-and-commit@v9
|
||||||
|
|||||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -46,3 +46,7 @@ stats/
|
|||||||
|
|
||||||
demos/dev/**
|
demos/dev/**
|
||||||
!/demos/dev/example.html
|
!/demos/dev/example.html
|
||||||
|
!/demos/dev/reload.js
|
||||||
|
|
||||||
|
# autogenereated by langium-cli
|
||||||
|
generated/
|
||||||
|
|||||||
@@ -10,3 +10,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/
|
||||||
|
|||||||
@@ -3,11 +3,12 @@ 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');
|
||||||
@@ -36,24 +37,6 @@ 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;
|
||||||
@@ -72,34 +55,8 @@ 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: {
|
||||||
@@ -126,7 +83,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__'],
|
exclude: ['node_modules', 'test/', '__mocks__', 'generated'],
|
||||||
extension: ['.js', '.ts'],
|
extension: ['.js', '.ts'],
|
||||||
requireEnv: true,
|
requireEnv: true,
|
||||||
forceBuildInstrument: coverage,
|
forceBuildInstrument: coverage,
|
||||||
@@ -146,24 +103,28 @@ 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((pkg) => !mermaidOnly || pkg === 'mermaid')) {
|
for (const pkg of packageNames.filter(
|
||||||
|
(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 {
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
import { transformJison } from './jisonTransformer.js';
|
import { transformJison } from '../.build/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 {
|
||||||
|
|||||||
@@ -1,109 +1,5 @@
|
|||||||
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',
|
|
||||||
] 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.
|
||||||
@@ -120,32 +16,13 @@ export default function jsonSchemaPlugin(): PluginOption {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (idAsUrl.searchParams.get('only-defaults')) {
|
const jsonSchema = loadSchema(src, idAsUrl.pathname);
|
||||||
const jsonSchema = load(src, {
|
return {
|
||||||
filename: idAsUrl.pathname,
|
code: idAsUrl.searchParams.get('only-defaults')
|
||||||
// only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
|
? getDefaults(jsonSchema)
|
||||||
// e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
|
: getSchema(jsonSchema),
|
||||||
schema: JSON_SCHEMA,
|
map: null, // no source map
|
||||||
}) 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
|
|
||||||
};
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@ async function createServer() {
|
|||||||
});
|
});
|
||||||
|
|
||||||
app.use(cors());
|
app.use(cors());
|
||||||
|
app.use(express.static('./packages/parser/dist'));
|
||||||
app.use(express.static('./packages/mermaid/dist'));
|
app.use(express.static('./packages/mermaid/dist'));
|
||||||
app.use(express.static('./packages/mermaid-zenuml/dist'));
|
app.use(express.static('./packages/mermaid-zenuml/dist'));
|
||||||
app.use(express.static('./packages/mermaid-example-diagram/dist'));
|
app.use(express.static('./packages/mermaid-example-diagram/dist'));
|
||||||
|
|||||||
16
README.md
16
README.md
@@ -44,6 +44,22 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai
|
|||||||
|
|
||||||
<a href="https://mermaid-js.github.io/mermaid/landing/"><img src="https://github.com/mermaid-js/mermaid/blob/master/docs/intro/img/book-banner-post-release.jpg" alt="Explore Mermaid.js in depth, with real-world examples, tips & tricks from the creator... The first official book on Mermaid is available for purchase. Check it out!"></a>
|
<a href="https://mermaid-js.github.io/mermaid/landing/"><img src="https://github.com/mermaid-js/mermaid/blob/master/docs/intro/img/book-banner-post-release.jpg" alt="Explore Mermaid.js in depth, with real-world examples, tips & tricks from the creator... The first official book on Mermaid is available for purchase. Check it out!"></a>
|
||||||
|
|
||||||
|
## Table of content
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Expand contents</summary>
|
||||||
|
|
||||||
|
- [About](#about)
|
||||||
|
- [Examples](#examples)
|
||||||
|
- [Release](#release)
|
||||||
|
- [Related projects](#related-projects)
|
||||||
|
- [Contributors](#contributors)
|
||||||
|
- [Security and safe diagrams](#security-and-safe-diagrams)
|
||||||
|
- [Reporting vulnerabilities](#reporting-vulnerabilities)
|
||||||
|
- [Appreciation](#appreciation)
|
||||||
|
|
||||||
|
</details>
|
||||||
|
|
||||||
## About
|
## About
|
||||||
|
|
||||||
<!-- <Main description> -->
|
<!-- <Main description> -->
|
||||||
|
|||||||
@@ -61,6 +61,7 @@
|
|||||||
"gzipped",
|
"gzipped",
|
||||||
"huynh",
|
"huynh",
|
||||||
"huynhicode",
|
"huynhicode",
|
||||||
|
"iife",
|
||||||
"inkdrop",
|
"inkdrop",
|
||||||
"jaoude",
|
"jaoude",
|
||||||
"jgreywolf",
|
"jgreywolf",
|
||||||
@@ -74,6 +75,7 @@
|
|||||||
"knut",
|
"knut",
|
||||||
"knutsveidqvist",
|
"knutsveidqvist",
|
||||||
"laganeckas",
|
"laganeckas",
|
||||||
|
"langium",
|
||||||
"linetype",
|
"linetype",
|
||||||
"lintstagedrc",
|
"lintstagedrc",
|
||||||
"logmsg",
|
"logmsg",
|
||||||
@@ -85,6 +87,7 @@
|
|||||||
"mdbook",
|
"mdbook",
|
||||||
"mermaidjs",
|
"mermaidjs",
|
||||||
"mermerd",
|
"mermerd",
|
||||||
|
"metafile",
|
||||||
"mindaugas",
|
"mindaugas",
|
||||||
"mindmap",
|
"mindmap",
|
||||||
"mindmaps",
|
"mindmaps",
|
||||||
@@ -98,6 +101,7 @@
|
|||||||
"nirname",
|
"nirname",
|
||||||
"npmjs",
|
"npmjs",
|
||||||
"orlandoni",
|
"orlandoni",
|
||||||
|
"outdir",
|
||||||
"pathe",
|
"pathe",
|
||||||
"pbrolin",
|
"pbrolin",
|
||||||
"phpbb",
|
"phpbb",
|
||||||
|
|||||||
11
cypress/integration/other/iife.spec.js
Normal file
11
cypress/integration/other/iife.spec.js
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
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');
|
||||||
|
});
|
||||||
|
});
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
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>');
|
|
||||||
});
|
|
||||||
});
|
|
||||||
@@ -501,4 +501,16 @@ describe('Class diagram', () => {
|
|||||||
B : -methods()
|
B : -methods()
|
||||||
`);
|
`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle notes with anchor tag having target attribute', () => {
|
||||||
|
renderGraph(
|
||||||
|
`classDiagram
|
||||||
|
class test { }
|
||||||
|
note for test "<a href='https://mermaid.js.org/' target="_blank"><code>note about mermaid</code></a>"`
|
||||||
|
);
|
||||||
|
|
||||||
|
cy.get('svg').then((svg) => {
|
||||||
|
cy.get('a').should('have.attr', 'target', '_blank').should('have.attr', 'rel', 'noopener');
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
<script src="./viewer.js" type="module"></script>
|
<script type="module" src="./viewer.js"></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"
|
||||||
|
|||||||
@@ -11,8 +11,7 @@ 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 '../../packages/mermaid-example-diagram/dist/mermaid-example-diagram.core.mjs';
|
import exampleDiagram from './mermaid-example-diagram.esm.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]);
|
||||||
|
|||||||
29
cypress/platform/iife.html
Normal file
29
cypress/platform/iife.html
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
<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>
|
||||||
@@ -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/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
|
click URL "http://localhost:9000/info.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/webpackUsage.html" "Visit <strong>mermaid docs</strong>"
|
click 2URL "http://localhost:9000/info.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/webpackUsage.html" "This is a tooltip for a link"
|
link ShapeLink "http://localhost:9000/info.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/webpackUsage.html" "This is a tooltip for a link"
|
link ShapeLink "http://localhost:9000/info.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/webpackUsage.html"
|
click cl1 href "http://localhost:9000/info.html"
|
||||||
click cl2 call clickByGantt()
|
click cl2 call clickByGantt()
|
||||||
click cl3 call clickByGantt("test1", test2, test3)
|
click cl3 call clickByGantt("test1", test2, test3)
|
||||||
|
|
||||||
@@ -102,9 +102,15 @@
|
|||||||
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) div.innerText += ' ' + arg1;
|
if (arg1) {
|
||||||
if (arg2) div.innerText += ' ' + arg2;
|
div.innerText += ' ' + arg1;
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
import mermaid2 from './mermaid.esm.mjs';
|
import mermaid from './mermaid.esm.mjs';
|
||||||
import externalExample from '../../packages/mermaid-example-diagram/dist/mermaid-example-diagram.core.mjs';
|
import externalExample from './mermaid-example-diagram.esm.mjs';
|
||||||
import zenUml from '../../packages/mermaid-zenuml/dist/mermaid-zenuml.core.mjs';
|
import zenUml from './mermaid-zenuml.esm.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 mermaid2.registerExternalDiagrams([externalExample, zenUml]);
|
await mermaid.registerExternalDiagrams([externalExample, zenUml]);
|
||||||
mermaid2.initialize(graphObj.mermaid);
|
mermaid.initialize(graphObj.mermaid);
|
||||||
await mermaid2.run();
|
await mermaid.run();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -95,18 +95,14 @@ const contentLoadedApi = async function () {
|
|||||||
divs[i] = div;
|
divs[i] = div;
|
||||||
}
|
}
|
||||||
|
|
||||||
const defaultE2eCnf = { theme: 'forest' };
|
const defaultE2eCnf = { theme: 'forest', startOnLoad: false };
|
||||||
|
|
||||||
const cnf = merge(defaultE2eCnf, graphObj.mermaid);
|
const cnf = merge(defaultE2eCnf, graphObj.mermaid);
|
||||||
|
|
||||||
mermaid2.initialize(cnf);
|
mermaid.initialize(cnf);
|
||||||
|
|
||||||
for (let i = 0; i < numCodes; i++) {
|
for (let i = 0; i < numCodes; i++) {
|
||||||
const { svg, bindFunctions } = await mermaid2.render(
|
const { svg, bindFunctions } = await mermaid.render('newid' + i, graphObj.code[i], divs[i]);
|
||||||
'newid' + i,
|
|
||||||
graphObj.code[i],
|
|
||||||
divs[i]
|
|
||||||
);
|
|
||||||
div.innerHTML = svg;
|
div.innerHTML = svg;
|
||||||
bindFunctions(div);
|
bindFunctions(div);
|
||||||
}
|
}
|
||||||
@@ -114,18 +110,21 @@ 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.mermaid', graphObj.mermaid);
|
console.warn('graphObj', graphObj);
|
||||||
document.getElementsByTagName('body')[0].appendChild(div);
|
document.getElementsByTagName('body')[0].appendChild(div);
|
||||||
mermaid2.initialize(graphObj.mermaid);
|
mermaid.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
|
||||||
*/
|
*/
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
<!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>
|
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<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 {
|
||||||
@@ -33,12 +32,6 @@
|
|||||||
</script>
|
</script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<script type="module">
|
<script type="module" src="./viewer.js"></script>
|
||||||
import mermaid from './mermaid.esm.mjs';
|
|
||||||
mermaid.initialize({
|
|
||||||
startOnLoad: false,
|
|
||||||
useMaxWidth: true,
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -5,6 +5,8 @@
|
|||||||
<title>Mermaid development page</title>
|
<title>Mermaid development page</title>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
|
<pre class="mermaid">info</pre>
|
||||||
|
|
||||||
<pre id="diagram" class="mermaid">
|
<pre id="diagram" class="mermaid">
|
||||||
graph TB
|
graph TB
|
||||||
a --> b
|
a --> b
|
||||||
@@ -30,5 +32,7 @@ graph TB
|
|||||||
console.log(svg);
|
console.log(svg);
|
||||||
el.innerHTML = svg;
|
el.innerHTML = svg;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
<script src="/dev/reload.js"></script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
22
demos/dev/reload.js
Normal file
22
demos/dev/reload.js
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
// 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);
|
||||||
@@ -37,7 +37,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,
|
||||||
|
|||||||
@@ -164,6 +164,13 @@
|
|||||||
end
|
end
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
|
<pre class="mermaid">
|
||||||
|
sequenceDiagram
|
||||||
|
actor Alice
|
||||||
|
actor John
|
||||||
|
Alice-xJohn: Hello John, how are you?
|
||||||
|
John--xAlice: Great!
|
||||||
|
</pre>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import mermaid from './mermaid.esm.mjs';
|
import mermaid from './mermaid.esm.mjs';
|
||||||
mermaid.initialize({
|
mermaid.initialize({
|
||||||
|
|||||||
@@ -10,9 +10,8 @@
|
|||||||
|
|
||||||
## First search to see if someone has already asked (and hopefully been answered) or suggested the same thing.
|
## First search to see if someone has already asked (and hopefully been answered) or suggested the same thing.
|
||||||
|
|
||||||
- Search in Discussions
|
- [Search in Discussions](https://github.com/orgs/mermaid-js/discussions)
|
||||||
- Search in open Issues
|
- [Search in Issues (Open & Closed)](https://github.com/mermaid-js/mermaid/issues?q=is%3Aissue)
|
||||||
- Search in closed Issues
|
|
||||||
|
|
||||||
If you find an open issue or discussion thread that is similar to your question but isn't answered, you can let us know that you are also interested in it.
|
If you find an open issue or discussion thread that is similar to your question but isn't answered, you can let us know that you are also interested in it.
|
||||||
Use the GitHub reactions to add a thumbs-up to the issue or discussion thread.
|
Use the GitHub reactions to add a thumbs-up to the issue or discussion thread.
|
||||||
|
|||||||
@@ -10,8 +10,8 @@ When mermaid starts, configuration is extracted to determine a configuration to
|
|||||||
|
|
||||||
- The default configuration
|
- The default configuration
|
||||||
- Overrides at the site level are set by the initialize call, and will be applied to all diagrams in the site/app. The term for this is the **siteConfig**.
|
- Overrides at the site level are set by the initialize call, and will be applied to all diagrams in the site/app. The term for this is the **siteConfig**.
|
||||||
- Frontmatter (v10.5.0+) - diagram authors can update select configuration parameters in the frontmatter of the diagram. These are applied to the render config.
|
- Frontmatter (v10.5.0+) - diagram authors can update selected configuration parameters in the frontmatter of the diagram. These are applied to the render config.
|
||||||
- Directives (Deprecated by Frontmatter) - diagram authors can update select configuration parameters directly in the diagram code via directives. These are applied to the render config.
|
- Directives (Deprecated by Frontmatter) - diagram authors can update selected configuration parameters directly in the diagram code via directives. These are applied to the render config.
|
||||||
|
|
||||||
**The render config** is configuration that is used when rendering by applying these configurations.
|
**The render config** is configuration that is used when rendering by applying these configurations.
|
||||||
|
|
||||||
|
|||||||
@@ -16,4 +16,4 @@
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:59](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L59)
|
[mermaidAPI.ts:60](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L60)
|
||||||
|
|||||||
@@ -39,7 +39,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:79](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L79)
|
[mermaidAPI.ts:80](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L80)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -51,4 +51,4 @@ The svg code for the rendered graph.
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:69](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L69)
|
[mermaidAPI.ts:70](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L70)
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ Renames and re-exports [mermaidAPI](mermaidAPI.md#mermaidapi)
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:63](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L63)
|
[mermaidAPI.ts:64](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L64)
|
||||||
|
|
||||||
## Variables
|
## Variables
|
||||||
|
|
||||||
@@ -96,7 +96,7 @@ mermaid.initialize(config);
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:641](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L641)
|
[mermaidAPI.ts:603](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L603)
|
||||||
|
|
||||||
## Functions
|
## Functions
|
||||||
|
|
||||||
@@ -127,7 +127,7 @@ Return the last node appended
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:299](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L299)
|
[mermaidAPI.ts:263](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L263)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -153,7 +153,7 @@ the cleaned up svgCode
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:245](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L245)
|
[mermaidAPI.ts:209](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L209)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -178,7 +178,7 @@ the string with all the user styles
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:175](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L175)
|
[mermaidAPI.ts:139](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L139)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -201,7 +201,7 @@ the string with all the user styles
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:222](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L222)
|
[mermaidAPI.ts:186](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L186)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -228,47 +228,7 @@ with an enclosing block that has each of the cssClasses followed by !important;
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:160](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L160)
|
[mermaidAPI.ts:124](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L124)
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### decodeEntities
|
|
||||||
|
|
||||||
▸ **decodeEntities**(`text`): `string`
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| :----- | :------- | :----------------- |
|
|
||||||
| `text` | `string` | text to be decoded |
|
|
||||||
|
|
||||||
#### Returns
|
|
||||||
|
|
||||||
`string`
|
|
||||||
|
|
||||||
#### Defined in
|
|
||||||
|
|
||||||
[mermaidAPI.ts:146](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L146)
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
### encodeEntities
|
|
||||||
|
|
||||||
▸ **encodeEntities**(`text`): `string`
|
|
||||||
|
|
||||||
#### Parameters
|
|
||||||
|
|
||||||
| Name | Type | Description |
|
|
||||||
| :----- | :------- | :----------------- |
|
|
||||||
| `text` | `string` | text to be encoded |
|
|
||||||
|
|
||||||
#### Returns
|
|
||||||
|
|
||||||
`string`
|
|
||||||
|
|
||||||
#### Defined in
|
|
||||||
|
|
||||||
[mermaidAPI.ts:117](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L117)
|
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -294,7 +254,7 @@ Put the svgCode into an iFrame. Return the iFrame code
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:276](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L276)
|
[mermaidAPI.ts:240](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L240)
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -319,4 +279,4 @@ Remove any existing elements from the given document
|
|||||||
|
|
||||||
#### Defined in
|
#### Defined in
|
||||||
|
|
||||||
[mermaidAPI.ts:349](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L349)
|
[mermaidAPI.ts:313](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L313)
|
||||||
|
|||||||
@@ -64,7 +64,7 @@ Example:
|
|||||||
|
|
||||||
```html
|
```html
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/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@10/dist/mermaid.esm.min.mjs';
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -42,6 +42,12 @@ Below are a list of community plugins and integrations created with Mermaid.
|
|||||||
- [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf)
|
- [Mermaid plugin for GitBook](https://github.com/wwformat/gitbook-plugin-mermaid-pdf)
|
||||||
- [LiveBook](https://livebook.dev) ✅
|
- [LiveBook](https://livebook.dev) ✅
|
||||||
- [Atlassian Products](https://www.atlassian.com)
|
- [Atlassian Products](https://www.atlassian.com)
|
||||||
|
- [Mermaid for Confluence](https://marketplace.atlassian.com/apps/1224722/mermaid-for-confluence?hosting=cloud&tab=overview)
|
||||||
|
- [Mermaid Integration for Confluence](https://marketplace.atlassian.com/apps/1222792/mermaid-integration-for-confluence?hosting=cloud&tab=overview)
|
||||||
|
- [Mermaid Diagrams for Confluence](https://marketplace.atlassian.com/apps/1226945/mermaid-diagrams-for-confluence?hosting=cloud&tab=overview)
|
||||||
|
- [Mermaid Macro for Confluence](https://marketplace.atlassian.com/apps/1231150/mermaid-macro-for-confluence?hosting=cloud&tab=overview)
|
||||||
|
- [EliteSoft Mermaid Charts and Diagrams](https://marketplace.atlassian.com/apps/1227286/elitesoft-mermaid-charts-and-diagrams?hosting=cloud&tab=overview)
|
||||||
|
- [Mermaid for Jira Cloud - Draw UML diagrams easily](https://marketplace.atlassian.com/apps/1223053/mermaid-for-jira-cloud-draw-uml-diagrams-easily?hosting=cloud&tab=overview)
|
||||||
- [Mermaid Charts & Diagrams for Confluence](https://marketplace.atlassian.com/apps/1222572/)
|
- [Mermaid Charts & Diagrams for Confluence](https://marketplace.atlassian.com/apps/1222572/)
|
||||||
- [Mermaid Charts & Diagrams for Jira](https://marketplace.atlassian.com/apps/1224537/)
|
- [Mermaid Charts & Diagrams for Jira](https://marketplace.atlassian.com/apps/1224537/)
|
||||||
- [Mermaid Live Editor for Confluence Cloud](https://marketplace.atlassian.com/apps/1231571/mermaid-live-editor-for-confluence?hosting=cloud&tab=overview)
|
- [Mermaid Live Editor for Confluence Cloud](https://marketplace.atlassian.com/apps/1231571/mermaid-live-editor-for-confluence?hosting=cloud&tab=overview)
|
||||||
@@ -100,6 +106,8 @@ Communication tools and platforms
|
|||||||
- [phpbb-ext-mermaid](https://github.com/AlfredoRamos/phpbb-ext-mermaid)
|
- [phpbb-ext-mermaid](https://github.com/AlfredoRamos/phpbb-ext-mermaid)
|
||||||
- [NodeBB](https://nodebb.org)
|
- [NodeBB](https://nodebb.org)
|
||||||
- [Mermaid Plugin](https://www.npmjs.com/package/nodebb-plugin-mermaid)
|
- [Mermaid Plugin](https://www.npmjs.com/package/nodebb-plugin-mermaid)
|
||||||
|
- [Slack](https://slack.com)
|
||||||
|
- [Mermaid for Slack](https://github.com/JackuB/mermaid-for-slack)
|
||||||
|
|
||||||
### Wikis
|
### Wikis
|
||||||
|
|
||||||
|
|||||||
@@ -128,7 +128,7 @@ b. The importing of mermaid library through the `mermaid.esm.mjs` or `mermaid.es
|
|||||||
```html
|
```html
|
||||||
<body>
|
<body>
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
||||||
mermaid.initialize({ startOnLoad: true });
|
mermaid.initialize({ startOnLoad: true });
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
@@ -168,7 +168,7 @@ Rendering in Mermaid is initialized by `mermaid.initialize()` call. However, doi
|
|||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
||||||
mermaid.initialize({ startOnLoad: true });
|
mermaid.initialize({ startOnLoad: true });
|
||||||
</script>
|
</script>
|
||||||
</body>
|
</body>
|
||||||
|
|||||||
@@ -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@10>
|
Latest Version: <https://cdn.jsdelivr.net/npm/mermaid@11>
|
||||||
|
|
||||||
## Deploying Mermaid
|
## Deploying Mermaid
|
||||||
|
|
||||||
@@ -335,12 +335,12 @@ To Deploy Mermaid:
|
|||||||
|
|
||||||
```html
|
```html
|
||||||
<script type="module">
|
<script type="module">
|
||||||
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10/dist/mermaid.esm.min.mjs';
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
||||||
mermaid.initialize({ startOnLoad: true });
|
mermaid.initialize({ startOnLoad: true });
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Doing so commands the mermaid parser to look for the `<div>` or `<pre>` tags with `class="mermaid"`. From these tags, mermaid tries read the diagram/chart definitions and render them into SVG charts.**
|
**Doing so commands the mermaid parser to look for the `<div>` or `<pre>` tags with `class="mermaid"`. From these tags, mermaid tries to read the diagram/chart definitions and render them into SVG charts.**
|
||||||
|
|
||||||
**Examples can be found in** [Other examples](../syntax/examples.md)
|
**Examples can be found in** [Other examples](../syntax/examples.md)
|
||||||
|
|
||||||
|
|||||||
@@ -399,7 +399,7 @@ UpdateRelStyle(customerA, bankA, $offsetY="60")
|
|||||||
title Component diagram for Internet Banking System - API Application
|
title Component diagram for Internet Banking System - API Application
|
||||||
|
|
||||||
Container(spa, "Single Page Application", "javascript and angular", "Provides all the internet banking functionality to customers via their web browser.")
|
Container(spa, "Single Page Application", "javascript and angular", "Provides all the internet banking functionality to customers via their web browser.")
|
||||||
Container(ma, "Mobile App", "Xamarin", "Provides a limited subset ot the internet banking functionality to customers via their mobile mobile device.")
|
Container(ma, "Mobile App", "Xamarin", "Provides a limited subset to the internet banking functionality to customers via their mobile mobile device.")
|
||||||
ContainerDb(db, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
|
ContainerDb(db, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
|
||||||
System_Ext(mbs, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
|
System_Ext(mbs, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
|
||||||
|
|
||||||
@@ -439,7 +439,7 @@ UpdateRelStyle(customerA, bankA, $offsetY="60")
|
|||||||
title Component diagram for Internet Banking System - API Application
|
title Component diagram for Internet Banking System - API Application
|
||||||
|
|
||||||
Container(spa, "Single Page Application", "javascript and angular", "Provides all the internet banking functionality to customers via their web browser.")
|
Container(spa, "Single Page Application", "javascript and angular", "Provides all the internet banking functionality to customers via their web browser.")
|
||||||
Container(ma, "Mobile App", "Xamarin", "Provides a limited subset ot the internet banking functionality to customers via their mobile mobile device.")
|
Container(ma, "Mobile App", "Xamarin", "Provides a limited subset to the internet banking functionality to customers via their mobile mobile device.")
|
||||||
ContainerDb(db, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
|
ContainerDb(db, "Database", "Relational Database Schema", "Stores user registration information, hashed authentication credentials, access logs, etc.")
|
||||||
System_Ext(mbs, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
|
System_Ext(mbs, "Mainframe Banking System", "Stores all of the core banking information about customers, accounts, transactions, etc.")
|
||||||
|
|
||||||
|
|||||||
@@ -425,8 +425,6 @@ And `Link` can be one of:
|
|||||||
|
|
||||||
A namespace groups classes.
|
A namespace groups classes.
|
||||||
|
|
||||||
Code:
|
|
||||||
|
|
||||||
```mermaid-example
|
```mermaid-example
|
||||||
classDiagram
|
classDiagram
|
||||||
namespace BaseShapes {
|
namespace BaseShapes {
|
||||||
|
|||||||
@@ -467,7 +467,7 @@ flowchart TB
|
|||||||
A & B--> C & D
|
A & B--> C & D
|
||||||
```
|
```
|
||||||
|
|
||||||
If you describe the same diagram using the the basic syntax, it will take four lines. A
|
If you describe the same diagram using the basic syntax, it will take four lines. A
|
||||||
word of warning, one could go overboard with this making the flowchart harder to read in
|
word of warning, one could go overboard with this making the flowchart harder to read in
|
||||||
markdown form. The Swedish word `lagom` comes to mind. It means, not too much and not too little.
|
markdown form. The Swedish word `lagom` comes to mind. It means, not too much and not too little.
|
||||||
This goes for expressive syntaxes as well.
|
This goes for expressive syntaxes as well.
|
||||||
|
|||||||
@@ -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@10/dist/mermaid.esm.min.mjs';
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -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@10/dist/mermaid.esm.min.mjs';
|
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@11/dist/mermaid.esm.min.mjs';
|
||||||
</script>
|
</script>
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
22
package.json
22
package.json
@@ -4,7 +4,7 @@
|
|||||||
"version": "10.2.4",
|
"version": "10.2.4",
|
||||||
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
"description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"packageManager": "pnpm@8.10.2",
|
"packageManager": "pnpm@8.10.4",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"diagram",
|
"diagram",
|
||||||
"markdown",
|
"markdown",
|
||||||
@@ -15,15 +15,15 @@
|
|||||||
"git graph"
|
"git graph"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"build:vite": "ts-node-esm --transpileOnly .vite/build.ts",
|
"build": "pnpm build:esbuild && pnpm build:types",
|
||||||
"build:mermaid": "pnpm build:vite --mermaid",
|
"build:esbuild": "pnpm run -r clean && ts-node-esm --transpileOnly .esbuild/build.ts",
|
||||||
"build:viz": "pnpm build:mermaid --visualize",
|
"build:mermaid": "pnpm build:esbuild --mermaid",
|
||||||
"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:viz": "pnpm build:esbuild --visualize",
|
||||||
|
"build:types": "tsc -p ./packages/parser/tsconfig.json --emitDeclarationOnly && 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:watch": "tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly --watch",
|
"build:types:watch": "tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly --watch",
|
||||||
"build:watch": "pnpm build:vite --watch",
|
"dev": "ts-node-esm --transpileOnly .esbuild/server.ts",
|
||||||
"build": "pnpm run -r clean && pnpm build:types && pnpm build:vite",
|
"dev:vite": "ts-node-esm --transpileOnly .vite/server.ts",
|
||||||
"dev": "concurrently \"pnpm build:vite --watch\" \"ts-node-esm .vite/server.ts\"",
|
"dev:coverage": "pnpm coverage:cypress:clean && VITE_COVERAGE=true pnpm dev:vite",
|
||||||
"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 . && ts-node-esm scripts/fixCSpell.ts",
|
"lint:fix": "eslint --cache --cache-strategy content --fix --ignore-path .gitignore . && prettier --write . && ts-node-esm 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": "ts-node-esm scripts/coverage.ts",
|
"coverage:merge": "ts-node-esm 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",
|
||||||
@@ -83,6 +83,7 @@
|
|||||||
"@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",
|
||||||
"cypress": "^12.10.0",
|
"cypress": "^12.10.0",
|
||||||
@@ -107,6 +108,7 @@
|
|||||||
"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": "2.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",
|
||||||
|
|||||||
@@ -43,8 +43,7 @@
|
|||||||
"cytoscape-cose-bilkent": "^4.1.0",
|
"cytoscape-cose-bilkent": "^4.1.0",
|
||||||
"cytoscape-fcose": "^2.1.0",
|
"cytoscape-fcose": "^2.1.0",
|
||||||
"d3": "^7.0.0",
|
"d3": "^7.0.0",
|
||||||
"khroma": "^2.0.0",
|
"khroma": "^2.0.0"
|
||||||
"non-layered-tidy-tree-layout": "^2.0.2"
|
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/cytoscape": "^3.19.9",
|
"@types/cytoscape": "^3.19.9",
|
||||||
|
|||||||
12
packages/mermaid-flowchart-elk/package.json
Normal file
12
packages/mermaid-flowchart-elk/package.json
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
{
|
||||||
|
"name": "@mermaid-js/flowchart-elk",
|
||||||
|
"version": "1.0.0",
|
||||||
|
"description": "",
|
||||||
|
"main": "index.js",
|
||||||
|
"scripts": {
|
||||||
|
"test": "echo \"Error: no test specified\" && exit 1"
|
||||||
|
},
|
||||||
|
"keywords": [],
|
||||||
|
"author": "",
|
||||||
|
"license": "MIT"
|
||||||
|
}
|
||||||
@@ -19,6 +19,7 @@
|
|||||||
"mermaid"
|
"mermaid"
|
||||||
],
|
],
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
"clean": "rimraf dist",
|
||||||
"prepublishOnly": "pnpm -w run build"
|
"prepublishOnly": "pnpm -w run build"
|
||||||
},
|
},
|
||||||
"repository": {
|
"repository": {
|
||||||
|
|||||||
@@ -5,7 +5,6 @@
|
|||||||
* 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
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "mermaid",
|
"name": "mermaid",
|
||||||
"version": "10.6.1",
|
"version": "11.0.0-alpha.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,8 +60,6 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@braintree/sanitize-url": "^6.0.1",
|
"@braintree/sanitize-url": "^6.0.1",
|
||||||
"@types/d3-scale": "^4.0.3",
|
|
||||||
"@types/d3-scale-chromatic": "^3.0.0",
|
|
||||||
"cytoscape": "^3.23.0",
|
"cytoscape": "^3.23.0",
|
||||||
"cytoscape-cose-bilkent": "^4.1.0",
|
"cytoscape-cose-bilkent": "^4.1.0",
|
||||||
"cytoscape-fcose": "^2.1.0",
|
"cytoscape-fcose": "^2.1.0",
|
||||||
@@ -74,11 +72,10 @@
|
|||||||
"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",
|
"mermaid-parser": "workspace:^",
|
||||||
"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",
|
||||||
@@ -86,6 +83,7 @@
|
|||||||
"@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",
|
||||||
|
|||||||
@@ -1,8 +1,10 @@
|
|||||||
import * as configApi from './config.js';
|
import * as configApi from './config.js';
|
||||||
import { log } from './logger.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, getDiagramLoaderAndPriority } from './diagram-api/detectType.js';
|
||||||
import { UnknownDiagramError } from './errors.js';
|
import { UnknownDiagramError } from './errors.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';
|
||||||
|
|
||||||
@@ -21,6 +23,7 @@ export class Diagram {
|
|||||||
|
|
||||||
private detectError?: UnknownDiagramError;
|
private detectError?: UnknownDiagramError;
|
||||||
constructor(public text: string, public metadata: Pick<DiagramMetadata, 'title'> = {}) {
|
constructor(public text: string, public metadata: Pick<DiagramMetadata, 'title'> = {}) {
|
||||||
|
this.text = encodeEntities(text);
|
||||||
this.text += '\n';
|
this.text += '\n';
|
||||||
const cnf = configApi.getConfig();
|
const cnf = configApi.getConfig();
|
||||||
try {
|
try {
|
||||||
@@ -35,7 +38,10 @@ export class Diagram {
|
|||||||
this.db = diagram.db;
|
this.db = diagram.db;
|
||||||
this.renderer = diagram.renderer;
|
this.renderer = diagram.renderer;
|
||||||
this.parser = diagram.parser;
|
this.parser = diagram.parser;
|
||||||
this.parser.parser.yy = this.db;
|
if (this.parser.parser) {
|
||||||
|
// The parser.parser.yy is only present in JISON parsers. So, we'll only set if required.
|
||||||
|
this.parser.parser.yy = this.db;
|
||||||
|
}
|
||||||
this.init = diagram.init;
|
this.init = diagram.init;
|
||||||
this.parse();
|
this.parse();
|
||||||
}
|
}
|
||||||
@@ -86,14 +92,14 @@ export const getDiagramFromText = async (
|
|||||||
// Trying to find the diagram
|
// Trying to find the diagram
|
||||||
getDiagram(type);
|
getDiagram(type);
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
const loader = getDiagramLoader(type);
|
const { loader, priority } = getDiagramLoaderAndPriority(type);
|
||||||
if (!loader) {
|
if (!loader) {
|
||||||
throw new UnknownDiagramError(`Diagram ${type} not found.`);
|
throw new UnknownDiagramError(`Diagram ${type} not found.`);
|
||||||
}
|
}
|
||||||
// Diagram not available, loading it.
|
// Diagram not available, loading it.
|
||||||
// new diagram will try getDiagram again and if fails then it is a valid throw
|
// new diagram will try getDiagram again and if fails then it is a valid throw
|
||||||
const { id, diagram } = await loader();
|
const { id, diagram } = await loader();
|
||||||
registerDiagram(id, diagram);
|
registerDiagram(id, diagram, priority);
|
||||||
}
|
}
|
||||||
return new Diagram(text, metadata);
|
return new Diagram(text, metadata);
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -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?: string | 'default' | 'forest' | 'dark' | 'neutral' | 'null';
|
theme?: 'default' | 'forest' | 'dark' | 'neutral' | 'null';
|
||||||
themeVariables?: any;
|
themeVariables?: any;
|
||||||
themeCSS?: string;
|
themeCSS?: string;
|
||||||
/**
|
/**
|
||||||
@@ -82,26 +82,11 @@ 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?:
|
logLevel?: 'trace' | 0 | 'debug' | 1 | 'info' | 2 | 'warn' | 3 | 'error' | 4 | 'fatal' | 5;
|
||||||
| 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?: string | 'strict' | 'loose' | 'antiscript' | 'sandbox' | undefined;
|
securityLevel?: 'strict' | 'loose' | 'antiscript' | 'sandbox';
|
||||||
/**
|
/**
|
||||||
* Dictates whether mermaid starts on Page load
|
* Dictates whether mermaid starts on Page load
|
||||||
*/
|
*/
|
||||||
@@ -912,7 +897,7 @@ export interface ErDiagramConfig extends BaseDiagramConfig {
|
|||||||
/**
|
/**
|
||||||
* Directional bias for layout of entities
|
* Directional bias for layout of entities
|
||||||
*/
|
*/
|
||||||
layoutDirection?: string | 'TB' | 'BT' | 'LR' | 'RL';
|
layoutDirection?: 'TB' | 'BT' | 'LR' | 'RL';
|
||||||
/**
|
/**
|
||||||
* The minimum width of an entity box. Expressed in pixels.
|
* The minimum width of an entity box. Expressed in pixels.
|
||||||
*/
|
*/
|
||||||
@@ -977,7 +962,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?: string | 'dagre-d3' | 'dagre-wrapper' | 'elk';
|
defaultRenderer?: 'dagre-d3' | 'dagre-wrapper' | 'elk';
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* This interface was referenced by `MermaidConfig`'s JSON-Schema
|
* This interface was referenced by `MermaidConfig`'s JSON-Schema
|
||||||
@@ -1001,7 +986,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?: string | 'dagre-d3' | 'dagre-wrapper' | 'elk';
|
defaultRenderer?: 'dagre-d3' | 'dagre-wrapper' | 'elk';
|
||||||
nodeSpacing?: number;
|
nodeSpacing?: number;
|
||||||
rankSpacing?: number;
|
rankSpacing?: number;
|
||||||
/**
|
/**
|
||||||
@@ -1061,7 +1046,7 @@ export interface JourneyDiagramConfig extends BaseDiagramConfig {
|
|||||||
/**
|
/**
|
||||||
* Multiline message alignment
|
* Multiline message alignment
|
||||||
*/
|
*/
|
||||||
messageAlign?: string | 'left' | 'center' | 'right';
|
messageAlign?: 'left' | 'center' | 'right';
|
||||||
/**
|
/**
|
||||||
* Prolongs the edge of the diagram downwards.
|
* Prolongs the edge of the diagram downwards.
|
||||||
*
|
*
|
||||||
@@ -1140,7 +1125,7 @@ export interface TimelineDiagramConfig extends BaseDiagramConfig {
|
|||||||
/**
|
/**
|
||||||
* Multiline message alignment
|
* Multiline message alignment
|
||||||
*/
|
*/
|
||||||
messageAlign?: string | 'left' | 'center' | 'right';
|
messageAlign?: 'left' | 'center' | 'right';
|
||||||
/**
|
/**
|
||||||
* Prolongs the edge of the diagram downwards.
|
* Prolongs the edge of the diagram downwards.
|
||||||
*
|
*
|
||||||
@@ -1251,7 +1236,7 @@ export interface GanttDiagramConfig extends BaseDiagramConfig {
|
|||||||
* Controls the display mode.
|
* Controls the display mode.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
displayMode?: string | 'compact';
|
displayMode?: '' | 'compact';
|
||||||
/**
|
/**
|
||||||
* On which day a week-based interval should start
|
* On which day a week-based interval should start
|
||||||
*
|
*
|
||||||
@@ -1310,7 +1295,7 @@ export interface SequenceDiagramConfig extends BaseDiagramConfig {
|
|||||||
/**
|
/**
|
||||||
* Multiline message alignment
|
* Multiline message alignment
|
||||||
*/
|
*/
|
||||||
messageAlign?: string | 'left' | 'center' | 'right';
|
messageAlign?: 'left' | 'center' | 'right';
|
||||||
/**
|
/**
|
||||||
* Mirror actors under diagram
|
* Mirror actors under diagram
|
||||||
*
|
*
|
||||||
@@ -1367,7 +1352,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?: string | 'left' | 'center' | 'right';
|
noteAlign?: 'left' | 'center' | 'right';
|
||||||
/**
|
/**
|
||||||
* This sets the font size of actor messages
|
* This sets the font size of actor messages
|
||||||
*/
|
*/
|
||||||
@@ -1443,7 +1428,7 @@ export interface FlowchartDiagramConfig extends BaseDiagramConfig {
|
|||||||
* Defines how mermaid renders curves for flowcharts.
|
* Defines how mermaid renders curves for flowcharts.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
curve?: string | 'basis' | 'linear' | 'cardinal';
|
curve?: 'basis' | 'linear' | 'cardinal';
|
||||||
/**
|
/**
|
||||||
* Represents the padding between the labels and the shape
|
* Represents the padding between the labels and the shape
|
||||||
*
|
*
|
||||||
@@ -1455,7 +1440,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?: string | 'dagre-d3' | 'dagre-wrapper' | 'elk';
|
defaultRenderer?: 'dagre-d3' | 'dagre-wrapper' | 'elk';
|
||||||
/**
|
/**
|
||||||
* Width of nodes where text is wrapped.
|
* Width of nodes where text is wrapped.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ import { select } from 'd3';
|
|||||||
import { log } from '../logger.js';
|
import { log } from '../logger.js';
|
||||||
import { getConfig } from '../diagram-api/diagramAPI.js';
|
import { getConfig } from '../diagram-api/diagramAPI.js';
|
||||||
import { evaluate } from '../diagrams/common/common.js';
|
import { evaluate } from '../diagrams/common/common.js';
|
||||||
import { decodeEntities } from '../mermaidAPI.js';
|
import { decodeEntities } from '../utils.js';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param dom
|
* @param dom
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
import createLabel from '../createLabel.js';
|
import createLabel from '../createLabel.js';
|
||||||
import { createText } from '../../rendering-util/createText.js';
|
import { createText } from '../../rendering-util/createText.js';
|
||||||
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
import { getConfig } from '../../diagram-api/diagramAPI.js';
|
||||||
import { decodeEntities } from '../../mermaidAPI.js';
|
|
||||||
import { select } from 'd3';
|
import { select } from 'd3';
|
||||||
import { evaluate, sanitizeText } from '../../diagrams/common/common.js';
|
import { evaluate, sanitizeText } from '../../diagrams/common/common.js';
|
||||||
|
import { decodeEntities } from '../../utils.js';
|
||||||
|
|
||||||
export const labelHelper = async (parent, node, _classes, isNode) => {
|
export const labelHelper = async (parent, node, _classes, isNode) => {
|
||||||
let classes;
|
let classes;
|
||||||
|
|||||||
@@ -61,23 +61,37 @@ export const detectType = function (text: string, config?: MermaidConfig): strin
|
|||||||
* The first detector to return `true` is the diagram that will be loaded
|
* The first detector to return `true` is the diagram that will be loaded
|
||||||
* and used, so put more specific detectors at the beginning!
|
* and used, so put more specific detectors at the beginning!
|
||||||
*
|
*
|
||||||
|
* If two diagrams are registered with the same id,
|
||||||
|
* the one with higher `priority` property will be used.
|
||||||
|
*
|
||||||
* @param diagrams - Diagrams to lazy load, and their detectors, in order of importance.
|
* @param diagrams - Diagrams to lazy load, and their detectors, in order of importance.
|
||||||
*/
|
*/
|
||||||
export const registerLazyLoadedDiagrams = (...diagrams: ExternalDiagramDefinition[]) => {
|
export const registerLazyLoadedDiagrams = (...diagrams: ExternalDiagramDefinition[]) => {
|
||||||
for (const { id, detector, loader } of diagrams) {
|
for (const { id, detector, priority, loader } of diagrams) {
|
||||||
addDetector(id, detector, loader);
|
addDetector(id, detector, priority ?? 0, loader);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
export const addDetector = (key: string, detector: DiagramDetector, loader?: DiagramLoader) => {
|
export const addDetector = (
|
||||||
if (detectors[key]) {
|
key: string,
|
||||||
log.error(`Detector with key ${key} already exists`);
|
detector: DiagramDetector,
|
||||||
} else {
|
priority: number,
|
||||||
detectors[key] = { detector, loader };
|
loader?: DiagramLoader
|
||||||
|
) => {
|
||||||
|
if (detectors[key] && priority <= detectors[key].priority) {
|
||||||
|
log.error(
|
||||||
|
`Detector with key ${key} already exists with priority ${detectors[key].priority}. Cannot add new detector with priority ${priority}`
|
||||||
|
);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
log.debug(`Detector with key ${key} added${loader ? ' with loader' : ''}`);
|
|
||||||
|
detectors[key] = { detector, loader, priority };
|
||||||
|
log.debug(
|
||||||
|
`Detector with key ${key} added with priority ${priority} ${loader ? 'and loader' : ''}`
|
||||||
|
);
|
||||||
};
|
};
|
||||||
|
|
||||||
export const getDiagramLoader = (key: string) => {
|
export const getDiagramLoaderAndPriority = (key: string) => {
|
||||||
return detectors[key].loader;
|
const { loader, priority } = detectors[key];
|
||||||
|
return { loader, priority };
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -31,7 +31,7 @@ export const addDiagrams = () => {
|
|||||||
// This is added here to avoid race-conditions.
|
// This is added here to avoid race-conditions.
|
||||||
// We could optimize the loading logic somehow.
|
// We could optimize the loading logic somehow.
|
||||||
hasLoadedDiagrams = true;
|
hasLoadedDiagrams = true;
|
||||||
registerDiagram('error', errorDiagram, (text) => {
|
registerDiagram('error', errorDiagram, 0, (text) => {
|
||||||
return text.toLowerCase().trim() === 'error';
|
return text.toLowerCase().trim() === 'error';
|
||||||
});
|
});
|
||||||
registerDiagram(
|
registerDiagram(
|
||||||
@@ -50,7 +50,6 @@ export const addDiagrams = () => {
|
|||||||
},
|
},
|
||||||
},
|
},
|
||||||
parser: {
|
parser: {
|
||||||
parser: { yy: {} },
|
|
||||||
parse: () => {
|
parse: () => {
|
||||||
throw new Error(
|
throw new Error(
|
||||||
'Diagrams beginning with --- are not valid. ' +
|
'Diagrams beginning with --- are not valid. ' +
|
||||||
@@ -61,6 +60,7 @@ export const addDiagrams = () => {
|
|||||||
},
|
},
|
||||||
init: () => null, // no op
|
init: () => null, // no op
|
||||||
},
|
},
|
||||||
|
0,
|
||||||
(text) => {
|
(text) => {
|
||||||
return text.toLowerCase().trimStart().startsWith('---');
|
return text.toLowerCase().trimStart().startsWith('---');
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -39,7 +39,6 @@ describe('DiagramAPI', () => {
|
|||||||
parse: (_text) => {
|
parse: (_text) => {
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
parser: { yy: {} },
|
|
||||||
},
|
},
|
||||||
renderer: {
|
renderer: {
|
||||||
draw: () => {
|
draw: () => {
|
||||||
@@ -48,6 +47,7 @@ describe('DiagramAPI', () => {
|
|||||||
},
|
},
|
||||||
styles: {},
|
styles: {},
|
||||||
},
|
},
|
||||||
|
0,
|
||||||
detector
|
detector
|
||||||
);
|
);
|
||||||
expect(getDiagram('loki')).not.toBeNull();
|
expect(getDiagram('loki')).not.toBeNull();
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ export const getCommonDb = () => {
|
|||||||
return _commonDb;
|
return _commonDb;
|
||||||
};
|
};
|
||||||
|
|
||||||
const diagrams: Record<string, DiagramDefinition> = {};
|
const diagrams: Record<string, DiagramDefinition & { priority: number }> = {};
|
||||||
export interface Detectors {
|
export interface Detectors {
|
||||||
[key: string]: DiagramDetector;
|
[key: string]: DiagramDetector;
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,8 @@ export interface Detectors {
|
|||||||
/**
|
/**
|
||||||
* Registers the given diagram with Mermaid.
|
* Registers the given diagram with Mermaid.
|
||||||
*
|
*
|
||||||
* Can be used for third-party custom diagrams.
|
* To be used internally by Mermaid.
|
||||||
|
* Use `mermaid.registerExternalDiagrams` to register external diagrams.
|
||||||
*
|
*
|
||||||
* @param id - A unique ID for the given diagram.
|
* @param id - A unique ID for the given diagram.
|
||||||
* @param diagram - The diagram definition.
|
* @param diagram - The diagram definition.
|
||||||
@@ -46,14 +47,17 @@ export interface Detectors {
|
|||||||
export const registerDiagram = (
|
export const registerDiagram = (
|
||||||
id: string,
|
id: string,
|
||||||
diagram: DiagramDefinition,
|
diagram: DiagramDefinition,
|
||||||
|
priority: number,
|
||||||
detector?: DiagramDetector
|
detector?: DiagramDetector
|
||||||
) => {
|
) => {
|
||||||
if (diagrams[id]) {
|
if (diagrams[id] && priority <= diagrams[id].priority) {
|
||||||
throw new Error(`Diagram ${id} already registered.`);
|
throw new Error(
|
||||||
|
`Diagram ${id} already registered with priority ${diagrams[id].priority}. Cannot add new diagram with priority ${priority}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
diagrams[id] = diagram;
|
diagrams[id] = { ...diagram, priority };
|
||||||
if (detector) {
|
if (detector) {
|
||||||
addDetector(id, detector);
|
addDetector(id, detector, priority);
|
||||||
}
|
}
|
||||||
addStylesForDiagram(id, diagram.styles);
|
addStylesForDiagram(id, diagram.styles);
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import type { MermaidConfig } from '../config.type.js';
|
import type { GanttDiagramConfig, MermaidConfig } from '../config.type.js';
|
||||||
import { frontMatterRegex } from './regexes.js';
|
import { frontMatterRegex } from './regexes.js';
|
||||||
// The "* as yaml" part is necessary for tree-shaking
|
// The "* as yaml" part is necessary for tree-shaking
|
||||||
import * as yaml from 'js-yaml';
|
import * as yaml from 'js-yaml';
|
||||||
@@ -6,7 +6,7 @@ import * as yaml from 'js-yaml';
|
|||||||
interface FrontMatterMetadata {
|
interface FrontMatterMetadata {
|
||||||
title?: string;
|
title?: string;
|
||||||
// Allows custom display modes. Currently used for compact mode in gantt charts.
|
// Allows custom display modes. Currently used for compact mode in gantt charts.
|
||||||
displayMode?: string;
|
displayMode?: GanttDiagramConfig['displayMode'];
|
||||||
config?: MermaidConfig;
|
config?: MermaidConfig;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -44,7 +44,7 @@ export function extractFrontMatter(text: string): FrontMatterResult {
|
|||||||
|
|
||||||
// Only add properties that are explicitly supported, if they exist
|
// Only add properties that are explicitly supported, if they exist
|
||||||
if (parsed.displayMode) {
|
if (parsed.displayMode) {
|
||||||
metadata.displayMode = parsed.displayMode.toString();
|
metadata.displayMode = parsed.displayMode.toString() as GanttDiagramConfig['displayMode'];
|
||||||
}
|
}
|
||||||
if (parsed.title) {
|
if (parsed.title) {
|
||||||
metadata.title = parsed.title.toString();
|
metadata.title = parsed.title.toString();
|
||||||
|
|||||||
@@ -6,7 +6,7 @@ export const loadRegisteredDiagrams = async () => {
|
|||||||
log.debug(`Loading registered diagrams`);
|
log.debug(`Loading registered diagrams`);
|
||||||
// Load all lazy loaded diagrams in parallel
|
// Load all lazy loaded diagrams in parallel
|
||||||
const results = await Promise.allSettled(
|
const results = await Promise.allSettled(
|
||||||
Object.entries(detectors).map(async ([key, { detector, loader }]) => {
|
Object.entries(detectors).map(async ([key, { detector, loader, priority }]) => {
|
||||||
if (loader) {
|
if (loader) {
|
||||||
try {
|
try {
|
||||||
getDiagram(key);
|
getDiagram(key);
|
||||||
@@ -14,7 +14,7 @@ export const loadRegisteredDiagrams = async () => {
|
|||||||
try {
|
try {
|
||||||
// Register diagram if it is not already registered
|
// Register diagram if it is not already registered
|
||||||
const { diagram, id } = await loader();
|
const { diagram, id } = await loader();
|
||||||
registerDiagram(id, diagram, detector);
|
registerDiagram(id, diagram, priority, detector);
|
||||||
} catch (err) {
|
} catch (err) {
|
||||||
// Remove failed diagram from detectors
|
// Remove failed diagram from detectors
|
||||||
log.error(`Failed to load external diagram with key ${key}. Removing from detectors.`);
|
log.error(`Failed to load external diagram with key ${key}. Removing from detectors.`);
|
||||||
|
|||||||
@@ -76,13 +76,23 @@ export interface DiagramDefinition {
|
|||||||
|
|
||||||
export interface DetectorRecord {
|
export interface DetectorRecord {
|
||||||
detector: DiagramDetector;
|
detector: DiagramDetector;
|
||||||
|
priority: number;
|
||||||
loader?: DiagramLoader;
|
loader?: DiagramLoader;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* External diagrams, which are not bundled with mermaid should expose the following to be registered using the `mermaid.registerExternalDiagrams` function.
|
||||||
|
*
|
||||||
|
* @param id - An ID for the given diagram. If two diagrams are registered with the same ID, the one with the higher priority will be used.
|
||||||
|
* @param detector - Function that returns `true` if a given mermaid text satisfies with this diagram definition.
|
||||||
|
* @param loader - Function that returns a promise of the diagram definition.
|
||||||
|
* @param priority - The priority of the diagram. Optional, defaults to 0.
|
||||||
|
*/
|
||||||
export interface ExternalDiagramDefinition {
|
export interface ExternalDiagramDefinition {
|
||||||
id: string;
|
id: string;
|
||||||
detector: DiagramDetector;
|
detector: DiagramDetector;
|
||||||
loader: DiagramLoader;
|
loader: DiagramLoader;
|
||||||
|
priority?: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type DiagramDetector = (text: string, config?: MermaidConfig) => boolean;
|
export type DiagramDetector = (text: string, config?: MermaidConfig) => boolean;
|
||||||
@@ -105,7 +115,7 @@ export type DrawDefinition = (
|
|||||||
|
|
||||||
export interface ParserDefinition {
|
export interface ParserDefinition {
|
||||||
parse: (text: string) => void;
|
parse: (text: string) => void;
|
||||||
parser: { yy: DiagramDB };
|
parser?: { yy: DiagramDB };
|
||||||
}
|
}
|
||||||
|
|
||||||
export type HTML = d3.Selection<HTMLIFrameElement, unknown, Element | null, unknown>;
|
export type HTML = d3.Selection<HTMLIFrameElement, unknown, Element | null, unknown>;
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ describe('diagram detection', () => {
|
|||||||
addDetector(
|
addDetector(
|
||||||
'loki',
|
'loki',
|
||||||
(str) => str.startsWith('loki'),
|
(str) => str.startsWith('loki'),
|
||||||
|
0,
|
||||||
() =>
|
() =>
|
||||||
Promise.resolve({
|
Promise.resolve({
|
||||||
id: 'loki',
|
id: 'loki',
|
||||||
@@ -30,9 +31,6 @@ describe('diagram detection', () => {
|
|||||||
parse: () => {
|
parse: () => {
|
||||||
// no-op
|
// no-op
|
||||||
},
|
},
|
||||||
parser: {
|
|
||||||
yy: {},
|
|
||||||
},
|
|
||||||
},
|
},
|
||||||
renderer: {
|
renderer: {
|
||||||
draw: () => {
|
draw: () => {
|
||||||
@@ -48,6 +46,37 @@ describe('diagram detection', () => {
|
|||||||
expect(diagram.type).toBe('loki');
|
expect(diagram.type).toBe('loki');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should allow external diagrams to override internal ones with same ID', async () => {
|
||||||
|
addDetector(
|
||||||
|
'flowchart-elk',
|
||||||
|
(str) => str.startsWith('flowchart-elk'),
|
||||||
|
1,
|
||||||
|
() =>
|
||||||
|
Promise.resolve({
|
||||||
|
id: 'flowchart-elk',
|
||||||
|
diagram: {
|
||||||
|
db: {
|
||||||
|
getDiagramTitle: () => 'overridden',
|
||||||
|
},
|
||||||
|
parser: {
|
||||||
|
parse: () => {
|
||||||
|
// no-op
|
||||||
|
},
|
||||||
|
},
|
||||||
|
renderer: {
|
||||||
|
draw: () => {
|
||||||
|
// no-op
|
||||||
|
},
|
||||||
|
},
|
||||||
|
styles: {},
|
||||||
|
},
|
||||||
|
})
|
||||||
|
);
|
||||||
|
const diagram = (await getDiagramFromText('flowchart-elk TD; A-->B')) as Diagram;
|
||||||
|
expect(diagram).toBeInstanceOf(Diagram);
|
||||||
|
expect(diagram.db.getDiagramTitle?.()).toBe('overridden');
|
||||||
|
});
|
||||||
|
|
||||||
test('should throw the right error for incorrect diagram', async () => {
|
test('should throw the right error for incorrect diagram', async () => {
|
||||||
await expect(getDiagramFromText('graph TD; A-->')).rejects.toThrowErrorMatchingInlineSnapshot(`
|
await expect(getDiagramFromText('graph TD; A-->')).rejects.toThrowErrorMatchingInlineSnapshot(`
|
||||||
"Parse error on line 2:
|
"Parse error on line 2:
|
||||||
@@ -69,4 +98,18 @@ Expecting 'TXT', got 'NEWLINE'"
|
|||||||
'"No diagram type detected matching given configuration for text: thor TD; A-->B"'
|
'"No diagram type detected matching given configuration for text: thor TD; A-->B"'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
test('should consider entity codes when present in diagram defination', async () => {
|
||||||
|
const diagram = await getDiagramFromText(`sequenceDiagram
|
||||||
|
A->>B: I #9829; you!
|
||||||
|
B->>A: I #9829; you #infin; times more!`);
|
||||||
|
// @ts-ignore: we need to add types for sequenceDb which will be done in separate PR
|
||||||
|
const messages = diagram.db?.getMessages?.();
|
||||||
|
if (!messages) {
|
||||||
|
throw new Error('Messages not found!');
|
||||||
|
}
|
||||||
|
|
||||||
|
expect(messages[0].message).toBe('I fl°°9829¶ß you!');
|
||||||
|
expect(messages[1].message).toBe('I fl°°9829¶ß you fl°infin¶ß times more!');
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -231,7 +231,7 @@ export const addRelations = function (relations: ClassRelation[], g: graphlib.Gr
|
|||||||
//Set relationship style and line type
|
//Set relationship style and line type
|
||||||
classes: 'relation',
|
classes: 'relation',
|
||||||
pattern: edge.relation.lineType == 1 ? 'dashed' : 'solid',
|
pattern: edge.relation.lineType == 1 ? 'dashed' : 'solid',
|
||||||
id: 'id' + cnt,
|
id: `id_${edge.id1}_${edge.id2}_${cnt}`,
|
||||||
// Set link type for rendering
|
// Set link type for rendering
|
||||||
arrowhead: edge.type === 'arrow_open' ? 'none' : 'normal',
|
arrowhead: edge.type === 'arrow_open' ? 'none' : 'normal',
|
||||||
//Set edge extra labels
|
//Set edge extra labels
|
||||||
|
|||||||
@@ -681,3 +681,82 @@ describe('given text representing a method, ', function () {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
describe('given text representing an attribute', () => {
|
||||||
|
describe('when the attribute has no modifiers', () => {
|
||||||
|
it('should parse the display text correctly', () => {
|
||||||
|
const str = 'name String';
|
||||||
|
|
||||||
|
const displayDetails = new ClassMember(str, 'attribute').getDisplayDetails();
|
||||||
|
|
||||||
|
expect(displayDetails.displayText).toBe('name String');
|
||||||
|
expect(displayDetails.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the attribute has public "+" modifier', () => {
|
||||||
|
it('should parse the display text correctly', () => {
|
||||||
|
const str = '+name String';
|
||||||
|
|
||||||
|
const displayDetails = new ClassMember(str, 'attribute').getDisplayDetails();
|
||||||
|
|
||||||
|
expect(displayDetails.displayText).toBe('+name String');
|
||||||
|
expect(displayDetails.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the attribute has protected "#" modifier', () => {
|
||||||
|
it('should parse the display text correctly', () => {
|
||||||
|
const str = '#name String';
|
||||||
|
|
||||||
|
const displayDetails = new ClassMember(str, 'attribute').getDisplayDetails();
|
||||||
|
|
||||||
|
expect(displayDetails.displayText).toBe('#name String');
|
||||||
|
expect(displayDetails.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the attribute has private "-" modifier', () => {
|
||||||
|
it('should parse the display text correctly', () => {
|
||||||
|
const str = '-name String';
|
||||||
|
|
||||||
|
const displayDetails = new ClassMember(str, 'attribute').getDisplayDetails();
|
||||||
|
|
||||||
|
expect(displayDetails.displayText).toBe('-name String');
|
||||||
|
expect(displayDetails.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the attribute has internal "~" modifier', () => {
|
||||||
|
it('should parse the display text correctly', () => {
|
||||||
|
const str = '~name String';
|
||||||
|
|
||||||
|
const displayDetails = new ClassMember(str, 'attribute').getDisplayDetails();
|
||||||
|
|
||||||
|
expect(displayDetails.displayText).toBe('~name String');
|
||||||
|
expect(displayDetails.cssStyle).toBe('');
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the attribute has static "$" modifier', () => {
|
||||||
|
it('should parse the display text correctly and apply static css style', () => {
|
||||||
|
const str = 'name String$';
|
||||||
|
|
||||||
|
const displayDetails = new ClassMember(str, 'attribute').getDisplayDetails();
|
||||||
|
|
||||||
|
expect(displayDetails.displayText).toBe('name String');
|
||||||
|
expect(displayDetails.cssStyle).toBe(staticCssStyle);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
describe('when the attribute has abstract "*" modifier', () => {
|
||||||
|
it('should parse the display text correctly and apply abstract css style', () => {
|
||||||
|
const str = 'name String*';
|
||||||
|
|
||||||
|
const displayDetails = new ClassMember(str, 'attribute').getDisplayDetails();
|
||||||
|
|
||||||
|
expect(displayDetails.displayText).toBe('name String');
|
||||||
|
expect(displayDetails.cssStyle).toBe(abstractCssStyle);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|||||||
@@ -106,7 +106,7 @@ export class ClassMember {
|
|||||||
this.visibility = firstChar as Visibility;
|
this.visibility = firstChar as Visibility;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (lastChar.match(/[*?]/)) {
|
if (lastChar.match(/[$*]/)) {
|
||||||
potentialClassifier = lastChar;
|
potentialClassifier = lastChar;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -38,6 +38,20 @@ describe('when securityLevel is antiscript, all script must be removed', () => {
|
|||||||
compareRemoveScript(`<img onerror="alert('hello');">`, `<img>`);
|
compareRemoveScript(`<img onerror="alert('hello');">`, `<img>`);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should detect unsecured target attribute, if value is _blank then generate a secured link', () => {
|
||||||
|
compareRemoveScript(
|
||||||
|
`<a href="https://mermaid.js.org/" target="_blank">note about mermaid</a>`,
|
||||||
|
`<a href="https://mermaid.js.org/" target="_blank" rel="noopener">note about mermaid</a>`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should detect unsecured target attribute from links', () => {
|
||||||
|
compareRemoveScript(
|
||||||
|
`<a href="https://mermaid.js.org/" target="_self">note about mermaid</a>`,
|
||||||
|
`<a href="https://mermaid.js.org/" target="_self">note about mermaid</a>`
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
it('should detect iframes', () => {
|
it('should detect iframes', () => {
|
||||||
compareRemoveScript(
|
compareRemoveScript(
|
||||||
`<iframe src="http://abc.com/script1.js"></iframe>
|
`<iframe src="http://abc.com/script1.js"></iframe>
|
||||||
|
|||||||
@@ -25,7 +25,27 @@ export const getRows = (s?: string): string[] => {
|
|||||||
* @returns The safer text
|
* @returns The safer text
|
||||||
*/
|
*/
|
||||||
export const removeScript = (txt: string): string => {
|
export const removeScript = (txt: string): string => {
|
||||||
return DOMPurify.sanitize(txt);
|
const TEMPORARY_ATTRIBUTE = 'data-temp-href-target';
|
||||||
|
|
||||||
|
DOMPurify.addHook('beforeSanitizeAttributes', (node: Element) => {
|
||||||
|
if (node.tagName === 'A' && node.hasAttribute('target')) {
|
||||||
|
node.setAttribute(TEMPORARY_ATTRIBUTE, node.getAttribute('target') || '');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
const sanitizedText = DOMPurify.sanitize(txt);
|
||||||
|
|
||||||
|
DOMPurify.addHook('afterSanitizeAttributes', (node: Element) => {
|
||||||
|
if (node.tagName === 'A' && node.hasAttribute(TEMPORARY_ATTRIBUTE)) {
|
||||||
|
node.setAttribute('target', node.getAttribute(TEMPORARY_ATTRIBUTE) || '');
|
||||||
|
node.removeAttribute(TEMPORARY_ATTRIBUTE);
|
||||||
|
if (node.getAttribute('target') === '_blank') {
|
||||||
|
node.setAttribute('rel', 'noopener');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
return sanitizedText;
|
||||||
};
|
};
|
||||||
|
|
||||||
const sanitizeMore = (text: string, config: MermaidConfig) => {
|
const sanitizeMore = (text: string, config: MermaidConfig) => {
|
||||||
|
|||||||
15
packages/mermaid/src/diagrams/common/populateCommonDb.ts
Normal file
15
packages/mermaid/src/diagrams/common/populateCommonDb.ts
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
import type { DiagramAST } from 'mermaid-parser';
|
||||||
|
|
||||||
|
import type { DiagramDB } from '../../diagram-api/types.js';
|
||||||
|
|
||||||
|
export function populateCommonDb(ast: DiagramAST, db: DiagramDB) {
|
||||||
|
if (ast.accDescr) {
|
||||||
|
db.setAccDescription?.(ast.accDescr);
|
||||||
|
}
|
||||||
|
if (ast.accTitle) {
|
||||||
|
db.setAccTitle?.(ast.accTitle);
|
||||||
|
}
|
||||||
|
if (ast.title) {
|
||||||
|
db.setDiagramTitle?.(ast.title);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -5,7 +5,6 @@ const diagram: DiagramDefinition = {
|
|||||||
db: {},
|
db: {},
|
||||||
renderer,
|
renderer,
|
||||||
parser: {
|
parser: {
|
||||||
parser: { yy: {} },
|
|
||||||
parse: (): void => {
|
parse: (): void => {
|
||||||
return;
|
return;
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -201,6 +201,13 @@ export const updateLinkInterpolate = function (positions, interp) {
|
|||||||
*/
|
*/
|
||||||
export const updateLink = function (positions, style) {
|
export const updateLink = function (positions, style) {
|
||||||
positions.forEach(function (pos) {
|
positions.forEach(function (pos) {
|
||||||
|
if (pos >= edges.length) {
|
||||||
|
throw new Error(
|
||||||
|
`The index ${pos} for linkStyle is out of bounds. Valid indices for linkStyle are between 0 and ${
|
||||||
|
edges.length - 1
|
||||||
|
}. (Help: Ensure that the index is within the range of existing edges.)`
|
||||||
|
);
|
||||||
|
}
|
||||||
if (pos === 'default') {
|
if (pos === 'default') {
|
||||||
edges.defaultStyle = style;
|
edges.defaultStyle = style;
|
||||||
} else {
|
} else {
|
||||||
@@ -425,7 +432,7 @@ const setupToolTips = function (element) {
|
|||||||
tooltipElem
|
tooltipElem
|
||||||
.text(el.attr('title'))
|
.text(el.attr('title'))
|
||||||
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
|
.style('left', window.scrollX + rect.left + (rect.right - rect.left) / 2 + 'px')
|
||||||
.style('top', window.scrollY + rect.top - 14 + document.body.scrollTop + 'px');
|
.style('top', window.scrollY + rect.bottom + 'px');
|
||||||
tooltipElem.html(tooltipElem.html().replace(/<br\/>/g, '<br/>'));
|
tooltipElem.html(tooltipElem.html().replace(/<br\/>/g, '<br/>'));
|
||||||
el.classed('hover', true);
|
el.classed('hover', true);
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -286,6 +286,30 @@ describe('[Style] when parsing', () => {
|
|||||||
expect(edges[0].type).toBe('arrow_point');
|
expect(edges[0].type).toBe('arrow_point');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('should handle style definitions within number of edges', function () {
|
||||||
|
expect(() =>
|
||||||
|
flow.parser
|
||||||
|
.parse(
|
||||||
|
`graph TD
|
||||||
|
A-->B
|
||||||
|
linkStyle 1 stroke-width:1px;`
|
||||||
|
)
|
||||||
|
.toThrow(
|
||||||
|
'The index 1 for linkStyle is out of bounds. Valid indices for linkStyle are between 0 and 0. (Help: Ensure that the index is within the range of existing edges.)'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should handle style definitions within number of edges', function () {
|
||||||
|
const res = flow.parser.parse(`graph TD
|
||||||
|
A-->B
|
||||||
|
linkStyle 0 stroke-width:1px;`);
|
||||||
|
|
||||||
|
const edges = flow.parser.yy.getEdges();
|
||||||
|
|
||||||
|
expect(edges[0].style[0]).toBe('stroke-width:1px');
|
||||||
|
});
|
||||||
|
|
||||||
it('should handle multi-numbered style definitions with more then 1 digit in a row', function () {
|
it('should handle multi-numbered style definitions with more then 1 digit in a row', function () {
|
||||||
const res = flow.parser.parse(
|
const res = flow.parser.parse(
|
||||||
'graph TD\n' +
|
'graph TD\n' +
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
const getStyles = (options) =>
|
const getStyles = (options) =>
|
||||||
`
|
`
|
||||||
.mermaid-main-font {
|
.mermaid-main-font {
|
||||||
font-family: "trebuchet ms", verdana, arial, sans-serif;
|
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
|
||||||
font-family: var(--mermaid-font-family);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.exclude-range {
|
.exclude-range {
|
||||||
fill: ${options.excludeBkgColor};
|
fill: ${options.excludeBkgColor};
|
||||||
}
|
}
|
||||||
@@ -45,11 +45,7 @@ const getStyles = (options) =>
|
|||||||
|
|
||||||
.sectionTitle {
|
.sectionTitle {
|
||||||
text-anchor: start;
|
text-anchor: start;
|
||||||
// font-size: ${options.ganttFontSize};
|
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
|
||||||
// text-height: 14px;
|
|
||||||
font-family: 'trebuchet ms', verdana, arial, sans-serif;
|
|
||||||
font-family: var(--mermaid-font-family);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -59,10 +55,11 @@ const getStyles = (options) =>
|
|||||||
stroke: ${options.gridColor};
|
stroke: ${options.gridColor};
|
||||||
opacity: 0.8;
|
opacity: 0.8;
|
||||||
shape-rendering: crispEdges;
|
shape-rendering: crispEdges;
|
||||||
text {
|
}
|
||||||
font-family: ${options.fontFamily};
|
|
||||||
fill: ${options.textColor};
|
.grid .tick text {
|
||||||
}
|
font-family: ${options.fontFamily};
|
||||||
|
fill: ${options.textColor};
|
||||||
}
|
}
|
||||||
|
|
||||||
.grid path {
|
.grid path {
|
||||||
@@ -89,33 +86,27 @@ const getStyles = (options) =>
|
|||||||
|
|
||||||
.taskText {
|
.taskText {
|
||||||
text-anchor: middle;
|
text-anchor: middle;
|
||||||
font-family: 'trebuchet ms', verdana, arial, sans-serif;
|
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
|
||||||
font-family: var(--mermaid-font-family);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// .taskText:not([font-size]) {
|
|
||||||
// font-size: ${options.ganttFontSize};
|
|
||||||
// }
|
|
||||||
|
|
||||||
.taskTextOutsideRight {
|
.taskTextOutsideRight {
|
||||||
fill: ${options.taskTextDarkColor};
|
fill: ${options.taskTextDarkColor};
|
||||||
text-anchor: start;
|
text-anchor: start;
|
||||||
// font-size: ${options.ganttFontSize};
|
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
|
||||||
font-family: 'trebuchet ms', verdana, arial, sans-serif;
|
|
||||||
font-family: var(--mermaid-font-family);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.taskTextOutsideLeft {
|
.taskTextOutsideLeft {
|
||||||
fill: ${options.taskTextDarkColor};
|
fill: ${options.taskTextDarkColor};
|
||||||
text-anchor: end;
|
text-anchor: end;
|
||||||
// font-size: ${options.ganttFontSize};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Special case clickable */
|
/* Special case clickable */
|
||||||
|
|
||||||
.task.clickable {
|
.task.clickable {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
}
|
}
|
||||||
|
|
||||||
.taskText.clickable {
|
.taskText.clickable {
|
||||||
cursor: pointer;
|
cursor: pointer;
|
||||||
fill: ${options.taskTextClickableColor} !important;
|
fill: ${options.taskTextClickableColor} !important;
|
||||||
@@ -134,6 +125,7 @@ const getStyles = (options) =>
|
|||||||
font-weight: bold;
|
font-weight: bold;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Specific task settings for the sections*/
|
/* Specific task settings for the sections*/
|
||||||
|
|
||||||
.taskText0,
|
.taskText0,
|
||||||
@@ -255,9 +247,8 @@ const getStyles = (options) =>
|
|||||||
.titleText {
|
.titleText {
|
||||||
text-anchor: middle;
|
text-anchor: middle;
|
||||||
font-size: 18px;
|
font-size: 18px;
|
||||||
fill: ${options.textColor} ;
|
fill: ${options.titleColor || options.textColor};
|
||||||
font-family: 'trebuchet ms', verdana, arial, sans-serif;
|
font-family: var(--mermaid-font-family, "trebuchet ms", verdana, arial, sans-serif);
|
||||||
font-family: var(--mermaid-font-family);
|
|
||||||
}
|
}
|
||||||
`;
|
`;
|
||||||
|
|
||||||
|
|||||||
@@ -1,24 +1,31 @@
|
|||||||
// @ts-ignore - jison doesn't export types
|
import { parser } from './infoParser.js';
|
||||||
import { parser } from './parser/info.jison';
|
|
||||||
import { db } from './infoDb.js';
|
|
||||||
|
|
||||||
describe('info diagram', () => {
|
|
||||||
beforeEach(() => {
|
|
||||||
parser.yy = db;
|
|
||||||
parser.yy.clear();
|
|
||||||
});
|
|
||||||
|
|
||||||
|
describe('info', () => {
|
||||||
it('should handle an info definition', () => {
|
it('should handle an info definition', () => {
|
||||||
const str = `info`;
|
const str = `info`;
|
||||||
parser.parse(str);
|
expect(() => {
|
||||||
|
parser.parse(str);
|
||||||
expect(db.getInfo()).toBeFalsy();
|
}).not.toThrow();
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should handle an info definition with showInfo', () => {
|
it('should handle an info definition with showInfo', () => {
|
||||||
const str = `info showInfo`;
|
const str = `info showInfo`;
|
||||||
parser.parse(str);
|
expect(() => {
|
||||||
|
parser.parse(str);
|
||||||
|
}).not.toThrow();
|
||||||
|
});
|
||||||
|
|
||||||
expect(db.getInfo()).toBeTruthy();
|
it('should throw because of unsupported info grammar', () => {
|
||||||
|
const str = `info unsupported`;
|
||||||
|
expect(() => {
|
||||||
|
parser.parse(str);
|
||||||
|
}).toThrow('Parsing failed: unexpected character: ->u<- at offset: 5, skipped 11 characters.');
|
||||||
|
});
|
||||||
|
|
||||||
|
it('should throw because of unsupported info grammar', () => {
|
||||||
|
const str = `info unsupported`;
|
||||||
|
expect(() => {
|
||||||
|
parser.parse(str);
|
||||||
|
}).toThrow('Parsing failed: unexpected character: ->u<- at offset: 5, skipped 11 characters.');
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -1,23 +1,10 @@
|
|||||||
import type { InfoFields, InfoDB } from './infoTypes.js';
|
import type { InfoFields, InfoDB } from './infoTypes.js';
|
||||||
|
import { version } from '../../../package.json';
|
||||||
|
|
||||||
export const DEFAULT_INFO_DB: InfoFields = {
|
export const DEFAULT_INFO_DB: InfoFields = { version } as const;
|
||||||
info: false,
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
let info: boolean = DEFAULT_INFO_DB.info;
|
export const getVersion = (): string => DEFAULT_INFO_DB.version;
|
||||||
|
|
||||||
export const setInfo = (toggle: boolean): void => {
|
|
||||||
info = toggle;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const getInfo = (): boolean => info;
|
|
||||||
|
|
||||||
const clear = (): void => {
|
|
||||||
info = DEFAULT_INFO_DB.info;
|
|
||||||
};
|
|
||||||
|
|
||||||
export const db: InfoDB = {
|
export const db: InfoDB = {
|
||||||
clear,
|
getVersion,
|
||||||
setInfo,
|
|
||||||
getInfo,
|
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
import type { DiagramDefinition } from '../../diagram-api/types.js';
|
import type { DiagramDefinition } from '../../diagram-api/types.js';
|
||||||
// @ts-ignore - jison doesn't export types
|
import { parser } from './infoParser.js';
|
||||||
import parser from './parser/info.jison';
|
|
||||||
import { db } from './infoDb.js';
|
import { db } from './infoDb.js';
|
||||||
import { renderer } from './infoRenderer.js';
|
import { renderer } from './infoRenderer.js';
|
||||||
|
|
||||||
|
|||||||
12
packages/mermaid/src/diagrams/info/infoParser.ts
Normal file
12
packages/mermaid/src/diagrams/info/infoParser.ts
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
import type { Info } from 'mermaid-parser';
|
||||||
|
import { parse } from 'mermaid-parser';
|
||||||
|
|
||||||
|
import { log } from '../../logger.js';
|
||||||
|
import type { ParserDefinition } from '../../diagram-api/types.js';
|
||||||
|
|
||||||
|
export const parser: ParserDefinition = {
|
||||||
|
parse: (input: string): void => {
|
||||||
|
const ast: Info = parse('info', input);
|
||||||
|
log.debug(ast);
|
||||||
|
},
|
||||||
|
};
|
||||||
@@ -1,11 +1,9 @@
|
|||||||
import type { DiagramDB } from '../../diagram-api/types.js';
|
import type { DiagramDB } from '../../diagram-api/types.js';
|
||||||
|
|
||||||
export interface InfoFields {
|
export interface InfoFields {
|
||||||
info: boolean;
|
version: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface InfoDB extends DiagramDB {
|
export interface InfoDB extends DiagramDB {
|
||||||
clear: () => void;
|
getVersion: () => string;
|
||||||
setInfo: (info: boolean) => void;
|
|
||||||
getInfo: () => boolean;
|
|
||||||
}
|
}
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user