mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-14 06:43:25 +08:00
merge(arch): : Merge branch 'develop' of https://github.com/mermaid-js/mermaid into 5367/architecture-diagram
This commit is contained in:
commit
dcb1b4871f
30
.build/common.ts
Normal file
30
.build/common.ts
Normal file
@ -0,0 +1,30 @@
|
||||
/**
|
||||
* Shared common options for both ESBuild and Vite
|
||||
*/
|
||||
export const packageOptions = {
|
||||
parser: {
|
||||
name: 'mermaid-parser',
|
||||
packageName: 'parser',
|
||||
file: 'index.ts',
|
||||
},
|
||||
mermaid: {
|
||||
name: 'mermaid',
|
||||
packageName: 'mermaid',
|
||||
file: 'mermaid.ts',
|
||||
},
|
||||
'mermaid-example-diagram': {
|
||||
name: 'mermaid-example-diagram',
|
||||
packageName: 'mermaid-example-diagram',
|
||||
file: 'detector.ts',
|
||||
},
|
||||
'mermaid-zenuml': {
|
||||
name: 'mermaid-zenuml',
|
||||
packageName: 'mermaid-zenuml',
|
||||
file: 'detector.ts',
|
||||
},
|
||||
'mermaid-flowchart-elk': {
|
||||
name: 'mermaid-flowchart-elk',
|
||||
packageName: 'mermaid-flowchart-elk',
|
||||
file: 'detector.ts',
|
||||
},
|
||||
} as const;
|
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` });
|
||||
}
|
125
.build/jsonSchema.ts
Normal file
125
.build/jsonSchema.ts
Normal file
@ -0,0 +1,125 @@
|
||||
import { load, JSON_SCHEMA } from 'js-yaml';
|
||||
import assert from 'node:assert';
|
||||
import Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js';
|
||||
import type { MermaidConfig, BaseDiagramConfig } from '../packages/mermaid/src/config.type.js';
|
||||
|
||||
/**
|
||||
* All of the keys in the mermaid config that have a mermaid diagram config.
|
||||
*/
|
||||
const MERMAID_CONFIG_DIAGRAM_KEYS = [
|
||||
'flowchart',
|
||||
'sequence',
|
||||
'gantt',
|
||||
'journey',
|
||||
'class',
|
||||
'state',
|
||||
'er',
|
||||
'pie',
|
||||
'quadrantChart',
|
||||
'xyChart',
|
||||
'requirement',
|
||||
'mindmap',
|
||||
'timeline',
|
||||
'gitGraph',
|
||||
'c4',
|
||||
'sankey',
|
||||
'block',
|
||||
'packet',
|
||||
'architecture'
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Generate default values from the JSON Schema.
|
||||
*
|
||||
* AJV does not support nested default values yet (or default values with $ref),
|
||||
* so we need to manually find them (this may be fixed in ajv v9).
|
||||
*
|
||||
* @param mermaidConfigSchema - The Mermaid JSON Schema to use.
|
||||
* @returns The default mermaid config object.
|
||||
*/
|
||||
function generateDefaults(mermaidConfigSchema: JSONSchemaType<MermaidConfig>) {
|
||||
const ajv = new Ajv2019({
|
||||
useDefaults: true,
|
||||
allowUnionTypes: true,
|
||||
strict: true,
|
||||
});
|
||||
|
||||
ajv.addKeyword({
|
||||
keyword: 'meta:enum', // used by jsonschema2md
|
||||
errors: false,
|
||||
});
|
||||
ajv.addKeyword({
|
||||
keyword: 'tsType', // used by json-schema-to-typescript
|
||||
errors: false,
|
||||
});
|
||||
|
||||
// ajv currently doesn't support nested default values, see https://github.com/ajv-validator/ajv/issues/1718
|
||||
// (may be fixed in v9) so we need to manually use sub-schemas
|
||||
const mermaidDefaultConfig = {};
|
||||
|
||||
assert.ok(mermaidConfigSchema.$defs);
|
||||
const baseDiagramConfig = mermaidConfigSchema.$defs.BaseDiagramConfig;
|
||||
|
||||
for (const key of MERMAID_CONFIG_DIAGRAM_KEYS) {
|
||||
const subSchemaRef = mermaidConfigSchema.properties[key].$ref;
|
||||
const [root, defs, defName] = subSchemaRef.split('/');
|
||||
assert.strictEqual(root, '#');
|
||||
assert.strictEqual(defs, '$defs');
|
||||
const subSchema = {
|
||||
$schema: mermaidConfigSchema.$schema,
|
||||
$defs: mermaidConfigSchema.$defs,
|
||||
...mermaidConfigSchema.$defs[defName],
|
||||
} as JSONSchemaType<BaseDiagramConfig>;
|
||||
|
||||
const validate = ajv.compile(subSchema);
|
||||
|
||||
mermaidDefaultConfig[key] = {};
|
||||
|
||||
for (const required of subSchema.required ?? []) {
|
||||
if (subSchema.properties[required] === undefined && baseDiagramConfig.properties[required]) {
|
||||
mermaidDefaultConfig[key][required] = baseDiagramConfig.properties[required].default;
|
||||
}
|
||||
}
|
||||
if (!validate(mermaidDefaultConfig[key])) {
|
||||
throw new Error(
|
||||
`schema for subconfig ${key} does not have valid defaults! Errors were ${JSON.stringify(
|
||||
validate.errors,
|
||||
undefined,
|
||||
2
|
||||
)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const validate = ajv.compile(mermaidConfigSchema);
|
||||
|
||||
if (!validate(mermaidDefaultConfig)) {
|
||||
throw new Error(
|
||||
`Mermaid config JSON Schema does not have valid defaults! Errors were ${JSON.stringify(
|
||||
validate.errors,
|
||||
undefined,
|
||||
2
|
||||
)}`
|
||||
);
|
||||
}
|
||||
|
||||
return mermaidDefaultConfig;
|
||||
}
|
||||
|
||||
export const loadSchema = (src: string, filename: string): JSONSchemaType<MermaidConfig> => {
|
||||
const jsonSchema = load(src, {
|
||||
filename,
|
||||
// only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
|
||||
// e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
|
||||
schema: JSON_SCHEMA,
|
||||
}) as JSONSchemaType<MermaidConfig>;
|
||||
return jsonSchema;
|
||||
};
|
||||
|
||||
export const getDefaults = (schema: JSONSchemaType<MermaidConfig>) => {
|
||||
return `export default ${JSON.stringify(generateDefaults(schema), undefined, 2)};`;
|
||||
};
|
||||
|
||||
export const getSchema = (schema: JSONSchemaType<MermaidConfig>) => {
|
||||
return `export default ${JSON.stringify(schema, undefined, 2)};`;
|
||||
};
|
18
.build/types.ts
Normal file
18
.build/types.ts
Normal file
@ -0,0 +1,18 @@
|
||||
import { packageOptions } from './common.js';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
const buildType = (packageName: string) => {
|
||||
console.log(`Building types for ${packageName}`);
|
||||
try {
|
||||
const out = execSync(`tsc -p ./packages/${packageName}/tsconfig.json --emitDeclarationOnly`);
|
||||
out.length > 0 && console.log(out.toString());
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
e.stdout.length > 0 && console.error(e.stdout.toString());
|
||||
e.stderr.length > 0 && console.error(e.stderr.toString());
|
||||
}
|
||||
};
|
||||
|
||||
for (const { packageName } of Object.values(packageOptions)) {
|
||||
buildType(packageName);
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"extends": ["@commitlint/config-conventional"]
|
||||
}
|
@ -53,6 +53,7 @@ GENERICTYPE
|
||||
getBoundarys
|
||||
grammr
|
||||
graphtype
|
||||
iife
|
||||
interp
|
||||
introdcued
|
||||
INVTRAPEND
|
||||
@ -74,11 +75,13 @@ loglevel
|
||||
LOGMSG
|
||||
lookaheads
|
||||
mdast
|
||||
metafile
|
||||
minlen
|
||||
Mstartx
|
||||
MULT
|
||||
NODIR
|
||||
NSTR
|
||||
outdir
|
||||
Qcontrolx
|
||||
reinit
|
||||
rels
|
||||
|
@ -36,6 +36,7 @@ jsfiddle
|
||||
jsonschema
|
||||
katex
|
||||
khroma
|
||||
langium
|
||||
mathml
|
||||
matplotlib
|
||||
mdbook
|
||||
|
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 { packageOptions } from '../.build/common.js';
|
||||
import { generateLangium } from '../.build/generateLangium.js';
|
||||
import { MermaidBuildOptions, defaultOptions, getBuildConfig } from './util.js';
|
||||
|
||||
const shouldVisualize = process.argv.includes('--visualize');
|
||||
|
||||
const buildPackage = async (entryName: keyof typeof packageOptions) => {
|
||||
const commonOptions = { ...defaultOptions, entryName } as const;
|
||||
const buildConfigs = [
|
||||
// package.mjs
|
||||
{ ...commonOptions },
|
||||
// package.min.mjs
|
||||
{
|
||||
...commonOptions,
|
||||
minify: true,
|
||||
metafile: shouldVisualize,
|
||||
},
|
||||
// package.core.mjs
|
||||
{ ...commonOptions, core: true },
|
||||
];
|
||||
|
||||
if (entryName === 'mermaid') {
|
||||
const iifeOptions: MermaidBuildOptions = { ...commonOptions, format: 'iife' };
|
||||
buildConfigs.push(
|
||||
// mermaid.js
|
||||
{ ...iifeOptions },
|
||||
// mermaid.min.js
|
||||
{ ...iifeOptions, minify: true, metafile: shouldVisualize }
|
||||
);
|
||||
}
|
||||
|
||||
const results = await Promise.all(buildConfigs.map((option) => build(getBuildConfig(option))));
|
||||
|
||||
if (shouldVisualize) {
|
||||
for (const { metafile } of results) {
|
||||
if (!metafile) {
|
||||
continue;
|
||||
}
|
||||
const fileName = Object.keys(metafile.outputs)
|
||||
.filter((file) => !file.includes('chunks') && file.endsWith('js'))[0]
|
||||
.replace('dist/', '');
|
||||
// Upload metafile into https://esbuild.github.io/analyze/
|
||||
await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handler = (e) => {
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
const main = async () => {
|
||||
await generateLangium();
|
||||
await mkdir('stats').catch(() => {});
|
||||
const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[];
|
||||
// it should build `parser` before `mermaid` because it's a dependency
|
||||
for (const pkg of packageNames) {
|
||||
await buildPackage(pkg).catch(handler);
|
||||
}
|
||||
};
|
||||
|
||||
void main();
|
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;
|
102
.esbuild/server.ts
Normal file
102
.esbuild/server.ts
Normal file
@ -0,0 +1,102 @@
|
||||
import express from 'express';
|
||||
import type { NextFunction, Request, Response } from 'express';
|
||||
import cors from 'cors';
|
||||
import { getBuildConfig, defaultOptions } from './util.js';
|
||||
import { context } from 'esbuild';
|
||||
import chokidar from 'chokidar';
|
||||
import { generateLangium } from '../.build/generateLangium.js';
|
||||
import { packageOptions } from '../.build/common.js';
|
||||
|
||||
const configs = Object.values(packageOptions).map(({ packageName }) =>
|
||||
getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: packageName })
|
||||
);
|
||||
const mermaidIIFEConfig = getBuildConfig({
|
||||
...defaultOptions,
|
||||
minify: false,
|
||||
core: false,
|
||||
entryName: 'mermaid',
|
||||
format: 'iife',
|
||||
});
|
||||
configs.push(mermaidIIFEConfig);
|
||||
|
||||
const contexts = await Promise.all(configs.map((config) => context(config)));
|
||||
|
||||
const rebuildAll = async () => {
|
||||
console.time('Rebuild time');
|
||||
await Promise.all(contexts.map((ctx) => ctx.rebuild())).catch((e) => console.error(e));
|
||||
console.timeEnd('Rebuild time');
|
||||
};
|
||||
|
||||
let clients: { id: number; response: Response }[] = [];
|
||||
function eventsHandler(request: Request, response: Response, next: NextFunction) {
|
||||
const headers = {
|
||||
'Content-Type': 'text/event-stream',
|
||||
Connection: 'keep-alive',
|
||||
'Cache-Control': 'no-cache',
|
||||
};
|
||||
response.writeHead(200, headers);
|
||||
const clientId = Date.now();
|
||||
clients.push({
|
||||
id: clientId,
|
||||
response,
|
||||
});
|
||||
request.on('close', () => {
|
||||
clients = clients.filter((client) => client.id !== clientId);
|
||||
});
|
||||
}
|
||||
|
||||
let timeoutId: NodeJS.Timeout | undefined = undefined;
|
||||
|
||||
/**
|
||||
* Debounce file change events to avoid rebuilding multiple times.
|
||||
*/
|
||||
function handleFileChange() {
|
||||
if (timeoutId !== undefined) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
timeoutId = setTimeout(async () => {
|
||||
await rebuildAll();
|
||||
sendEventsToAll();
|
||||
timeoutId = undefined;
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function sendEventsToAll() {
|
||||
clients.forEach(({ response }) => response.write(`data: ${Date.now()}\n\n`));
|
||||
}
|
||||
|
||||
async function createServer() {
|
||||
await generateLangium();
|
||||
handleFileChange();
|
||||
const app = express();
|
||||
chokidar
|
||||
.watch('**/src/**/*.{js,ts,langium,yaml,json}', {
|
||||
ignoreInitial: true,
|
||||
ignored: [/node_modules/, /dist/, /docs/, /coverage/],
|
||||
})
|
||||
.on('all', async (event, path) => {
|
||||
// Ignore other events.
|
||||
if (!['add', 'change'].includes(event)) {
|
||||
return;
|
||||
}
|
||||
if (/\.langium$/.test(path)) {
|
||||
await generateLangium();
|
||||
}
|
||||
console.log(`${path} changed. Rebuilding...`);
|
||||
handleFileChange();
|
||||
});
|
||||
|
||||
app.use(cors());
|
||||
app.get('/events', eventsHandler);
|
||||
for (const { packageName } of Object.values(packageOptions)) {
|
||||
app.use(express.static(`./packages/${packageName}/dist`));
|
||||
}
|
||||
app.use(express.static('demos'));
|
||||
app.use(express.static('cypress/platform'));
|
||||
|
||||
app.listen(9000, () => {
|
||||
console.log(`Listening on http://localhost:9000`);
|
||||
});
|
||||
}
|
||||
|
||||
createServer();
|
101
.esbuild/util.ts
Normal file
101
.esbuild/util.ts
Normal file
@ -0,0 +1,101 @@
|
||||
import { resolve } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import type { BuildOptions } from 'esbuild';
|
||||
import { readFileSync } from 'fs';
|
||||
import jsonSchemaPlugin from './jsonSchemaPlugin.js';
|
||||
import { packageOptions } from '../.build/common.js';
|
||||
import { jisonPlugin } from './jisonPlugin.js';
|
||||
|
||||
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
||||
|
||||
export interface MermaidBuildOptions {
|
||||
minify: boolean;
|
||||
core: boolean;
|
||||
metafile: boolean;
|
||||
format: 'esm' | 'iife';
|
||||
entryName: keyof typeof packageOptions;
|
||||
}
|
||||
|
||||
export const defaultOptions: Omit<MermaidBuildOptions, 'entryName'> = {
|
||||
minify: false,
|
||||
metafile: false,
|
||||
core: false,
|
||||
format: 'esm',
|
||||
} as const;
|
||||
|
||||
const buildOptions = (override: BuildOptions): BuildOptions => {
|
||||
return {
|
||||
bundle: true,
|
||||
minify: true,
|
||||
keepNames: true,
|
||||
platform: 'browser',
|
||||
tsconfig: 'tsconfig.json',
|
||||
resolveExtensions: ['.ts', '.js', '.json', '.jison', '.yaml'],
|
||||
external: ['require', 'fs', 'path'],
|
||||
outdir: 'dist',
|
||||
plugins: [jisonPlugin, jsonSchemaPlugin],
|
||||
sourcemap: 'external',
|
||||
...override,
|
||||
};
|
||||
};
|
||||
|
||||
const getFileName = (fileName: string, { core, format, minify }: MermaidBuildOptions) => {
|
||||
if (core) {
|
||||
fileName += '.core';
|
||||
} else if (format === 'esm') {
|
||||
fileName += '.esm';
|
||||
}
|
||||
if (minify) {
|
||||
fileName += '.min';
|
||||
}
|
||||
return fileName;
|
||||
};
|
||||
|
||||
export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
|
||||
const { core, entryName, metafile, format, minify } = options;
|
||||
const external: string[] = ['require', 'fs', 'path'];
|
||||
const { name, file, packageName } = packageOptions[entryName];
|
||||
const outFileName = getFileName(name, options);
|
||||
let output: BuildOptions = buildOptions({
|
||||
absWorkingDir: resolve(__dirname, `../packages/${packageName}`),
|
||||
entryPoints: {
|
||||
[outFileName]: `src/${file}`,
|
||||
},
|
||||
metafile,
|
||||
minify,
|
||||
logLevel: 'info',
|
||||
chunkNames: `chunks/${outFileName}/[name]-[hash]`,
|
||||
define: {
|
||||
'import.meta.vitest': 'undefined',
|
||||
},
|
||||
});
|
||||
|
||||
if (core) {
|
||||
const { dependencies } = JSON.parse(
|
||||
readFileSync(resolve(__dirname, `../packages/${packageName}/package.json`), 'utf-8')
|
||||
);
|
||||
// Core build is used to generate file without bundled dependencies.
|
||||
// This is used by downstream projects to bundle dependencies themselves.
|
||||
// Ignore dependencies and any dependencies of dependencies
|
||||
external.push(...Object.keys(dependencies));
|
||||
output.external = external;
|
||||
}
|
||||
|
||||
if (format === 'iife') {
|
||||
output.format = 'iife';
|
||||
output.splitting = false;
|
||||
output.globalName = '__esbuild_esm_mermaid';
|
||||
// Workaround for removing the .default access in esbuild IIFE.
|
||||
// https://github.com/mermaid-js/mermaid/pull/4109#discussion_r1292317396
|
||||
output.footer = {
|
||||
js: 'globalThis.mermaid = globalThis.__esbuild_esm_mermaid.default;',
|
||||
};
|
||||
output.outExtension = { '.js': '.js' };
|
||||
} else {
|
||||
output.format = 'esm';
|
||||
output.splitting = true;
|
||||
output.outExtension = { '.js': '.mjs' };
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
@ -6,3 +6,6 @@ cypress/plugins/index.js
|
||||
coverage
|
||||
*.json
|
||||
node_modules
|
||||
|
||||
# autogenereated by langium-cli
|
||||
generated/
|
||||
|
@ -14,7 +14,7 @@ module.exports = {
|
||||
},
|
||||
tsconfigRootDir: __dirname,
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020,
|
||||
ecmaVersion: 2022,
|
||||
allowAutomaticSingleRunInference: true,
|
||||
project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
@ -23,7 +23,7 @@ module.exports = {
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:json/recommended',
|
||||
'plugin:markdown/recommended',
|
||||
'plugin:markdown/recommended-legacy',
|
||||
'plugin:@cspell/recommended',
|
||||
'prettier',
|
||||
],
|
||||
|
1
.github/codecov.yaml
vendored
1
.github/codecov.yaml
vendored
@ -15,3 +15,4 @@ coverage:
|
||||
# Turing off for now as code coverage isn't stable and causes unnecessary build failures.
|
||||
# default:
|
||||
# threshold: 2%
|
||||
patch: off
|
||||
|
2
.github/lychee.toml
vendored
2
.github/lychee.toml
vendored
@ -40,7 +40,7 @@ exclude = [
|
||||
# BundlePhobia has frequent downtime
|
||||
"https://bundlephobia.com",
|
||||
|
||||
# Chrome webstore redirect issue
|
||||
# Chrome webstore migration issue. Temporary
|
||||
"https://chromewebstore.google.com"
|
||||
]
|
||||
|
||||
|
4
.github/workflows/build.yml
vendored
4
.github/workflows/build.yml
vendored
@ -37,13 +37,13 @@ jobs:
|
||||
run: pnpm run build
|
||||
|
||||
- name: Upload Mermaid Build as Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: mermaid-build
|
||||
path: packages/mermaid/dist
|
||||
|
||||
- name: Upload Mermaid Mindmap Build as Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: mermaid-mindmap-build
|
||||
path: packages/mermaid-mindmap/dist
|
||||
|
6
.github/workflows/codeql.yml
vendored
6
.github/workflows/codeql.yml
vendored
@ -33,7 +33,7 @@ jobs:
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@v2
|
||||
uses: github/codeql-action/init@v3
|
||||
with:
|
||||
config-file: ./.github/codeql/codeql-config.yml
|
||||
languages: ${{ matrix.language }}
|
||||
@ -45,7 +45,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
uses: github/codeql-action/autobuild@v3
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
@ -59,4 +59,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@v2
|
||||
uses: github/codeql-action/analyze@v3
|
||||
|
2
.github/workflows/dependency-review.yml
vendored
2
.github/workflows/dependency-review.yml
vendored
@ -17,4 +17,4 @@ jobs:
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@v4
|
||||
- name: 'Dependency Review'
|
||||
uses: actions/dependency-review-action@v3
|
||||
uses: actions/dependency-review-action@v4
|
||||
|
56
.github/workflows/e2e.yml
vendored
56
.github/workflows/e2e.yml
vendored
@ -17,9 +17,19 @@ permissions:
|
||||
contents: read
|
||||
|
||||
env:
|
||||
# For PRs and MergeQueues, the target commit is used, and for push events, github.event.previous is used.
|
||||
targetHash: ${{ github.event.pull_request.base.sha || github.event.merge_group.base_sha || (github.event.before == '0000000000000000000000000000000000000000' && 'develop' || github.event.before) }}
|
||||
|
||||
# For PRs and MergeQueues, the target commit is used, and for push events to non-develop branches, github.event.previous is used if available. Otherwise, 'develop' is used.
|
||||
targetHash: >-
|
||||
${{
|
||||
github.event.pull_request.base.sha ||
|
||||
github.event.merge_group.base_sha ||
|
||||
(
|
||||
(
|
||||
(github.event_name == 'push' && github.ref == 'refs/heads/develop') ||
|
||||
github.event.before == '0000000000000000000000000000000000000000'
|
||||
) && 'develop'
|
||||
) ||
|
||||
github.event.before
|
||||
}}
|
||||
jobs:
|
||||
cache:
|
||||
runs-on: ubuntu-latest
|
||||
@ -48,11 +58,26 @@ jobs:
|
||||
with:
|
||||
ref: ${{ env.targetHash }}
|
||||
|
||||
- name: Install dependencies
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
|
||||
uses: cypress-io/github-action@v6
|
||||
with:
|
||||
# just perform install
|
||||
runTests: false
|
||||
|
||||
- name: Calculate bundle size
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true'}}
|
||||
run: |
|
||||
pnpm run build:viz
|
||||
mkdir -p cypress/snapshots/stats/base
|
||||
mv stats cypress/snapshots/stats/base
|
||||
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@v4
|
||||
uses: cypress-io/github-action@v6
|
||||
id: cypress-snapshot-gen
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
|
||||
with:
|
||||
install: false
|
||||
start: pnpm run dev
|
||||
wait-on: 'http://localhost:9000'
|
||||
browser: chrome
|
||||
@ -81,20 +106,35 @@ jobs:
|
||||
# These cached snapshots are downloaded, providing the reference snapshots.
|
||||
- name: Cache snapshots
|
||||
id: cache-snapshot
|
||||
uses: actions/cache/restore@v3
|
||||
uses: actions/cache/restore@v4
|
||||
with:
|
||||
path: ./cypress/snapshots
|
||||
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
|
||||
|
||||
- name: Install dependencies
|
||||
uses: cypress-io/github-action@v6
|
||||
with:
|
||||
runTests: false
|
||||
|
||||
- name: Output size diff
|
||||
if: ${{ matrix.containers == 1 }}
|
||||
run: |
|
||||
pnpm run build:viz
|
||||
mv stats cypress/snapshots/stats/head
|
||||
echo '## Bundle size difference' >> "$GITHUB_STEP_SUMMARY"
|
||||
echo '' >> "$GITHUB_STEP_SUMMARY"
|
||||
npx tsx scripts/size.ts >> "$GITHUB_STEP_SUMMARY"
|
||||
|
||||
# Install NPM dependencies, cache them correctly
|
||||
# and run all Cypress tests
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@v4
|
||||
uses: cypress-io/github-action@v6
|
||||
id: cypress
|
||||
# If CYPRESS_RECORD_KEY is set, run in parallel on all containers
|
||||
# Otherwise (e.g. if running from fork), we run on a single container only
|
||||
if: ${{ ( env.CYPRESS_RECORD_KEY != '' ) || ( matrix.containers == 1 ) }}
|
||||
with:
|
||||
install: false
|
||||
start: pnpm run dev:coverage
|
||||
wait-on: 'http://localhost:9000'
|
||||
browser: chrome
|
||||
@ -108,7 +148,7 @@ jobs:
|
||||
CYPRESS_COMMIT: ${{ github.sha }}
|
||||
|
||||
- name: Upload Coverage to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
uses: codecov/codecov-action@v4
|
||||
# Run step only pushes to develop and pull_requests
|
||||
if: ${{ steps.cypress.conclusion == 'success' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/develop')}}
|
||||
with:
|
||||
@ -145,7 +185,7 @@ jobs:
|
||||
- name: Save snapshots cache
|
||||
id: cache-upload
|
||||
if: ${{ github.event_name == 'push' && needs.e2e.result != 'failure' }}
|
||||
uses: actions/cache/save@v3
|
||||
uses: actions/cache/save@v4
|
||||
with:
|
||||
path: ./snapshots
|
||||
key: ${{ runner.os }}-snapshots-${{ github.event.after }}
|
||||
|
2
.github/workflows/link-checker.yml
vendored
2
.github/workflows/link-checker.yml
vendored
@ -29,7 +29,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Restore lychee cache
|
||||
uses: actions/cache@v3
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: .lycheecache
|
||||
key: cache-lychee-${{ github.sha }}
|
||||
|
2
.github/workflows/pr-labeler.yml
vendored
2
.github/workflows/pr-labeler.yml
vendored
@ -22,7 +22,7 @@ jobs:
|
||||
pull-requests: write # write permission is required to label PRs
|
||||
steps:
|
||||
- name: Label PR
|
||||
uses: release-drafter/release-drafter@v5
|
||||
uses: release-drafter/release-drafter@v6
|
||||
with:
|
||||
config-name: pr-labeler.yml
|
||||
disable-autolabeler: false
|
||||
|
6
.github/workflows/publish-docs.yml
vendored
6
.github/workflows/publish-docs.yml
vendored
@ -37,13 +37,13 @@ jobs:
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@v3
|
||||
uses: actions/configure-pages@v4
|
||||
|
||||
- name: Run Build
|
||||
run: pnpm --filter mermaid run docs:build:vitepress
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@v1
|
||||
uses: actions/upload-pages-artifact@v3
|
||||
with:
|
||||
path: packages/mermaid/src/vitepress/.vitepress/dist
|
||||
|
||||
@ -56,4 +56,4 @@ jobs:
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v2
|
||||
uses: actions/deploy-pages@v4
|
||||
|
4
.github/workflows/release-draft.yml
vendored
4
.github/workflows/release-draft.yml
vendored
@ -12,11 +12,11 @@ jobs:
|
||||
draft-release:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write # write permission is required to create a github release
|
||||
contents: write # write permission is required to create a GitHub release
|
||||
pull-requests: read # required to read PR titles/labels
|
||||
steps:
|
||||
- name: Draft Release
|
||||
uses: release-drafter/release-drafter@v5
|
||||
uses: release-drafter/release-drafter@v6
|
||||
with:
|
||||
disable-autolabeler: true
|
||||
env:
|
||||
|
2
.github/workflows/test.yml
vendored
2
.github/workflows/test.yml
vendored
@ -39,7 +39,7 @@ jobs:
|
||||
pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts --coverage
|
||||
|
||||
- name: Upload Coverage to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
uses: codecov/codecov-action@v4
|
||||
# Run step only pushes to develop and pull_requests
|
||||
if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' }}
|
||||
with:
|
||||
|
2
.github/workflows/update-browserlist.yml
vendored
2
.github/workflows/update-browserlist.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
||||
message: 'chore: update browsers list'
|
||||
push: false
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
branch: update-browserslist
|
||||
title: Update Browserslist
|
||||
|
4
.gitignore
vendored
4
.gitignore
vendored
@ -46,4 +46,8 @@ stats/
|
||||
|
||||
demos/dev/**
|
||||
!/demos/dev/example.html
|
||||
!/demos/dev/reload.js
|
||||
tsx-0/**
|
||||
|
||||
# autogenereated by langium-cli
|
||||
generated/
|
@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
# . "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
# npx --no-install commitlint --edit $1
|
@ -1,4 +1,4 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
pnpm run pre-commit
|
||||
NODE_OPTIONS="--max_old_space_size=8192" pnpm run pre-commit
|
||||
|
@ -11,6 +11,8 @@ stats
|
||||
.nyc_output
|
||||
# Autogenerated by `pnpm run --filter mermaid types:build-config`
|
||||
packages/mermaid/src/config.type.ts
|
||||
# autogenereated by langium-cli
|
||||
generated/
|
||||
# Ignore the files creates in /demos/dev except for example.html
|
||||
demos/dev/**
|
||||
!/demos/dev/example.html
|
||||
|
@ -3,5 +3,6 @@
|
||||
"printWidth": 100,
|
||||
"singleQuote": true,
|
||||
"useTabs": false,
|
||||
"tabWidth": 2
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
|
@ -3,11 +3,12 @@ import { resolve } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import jisonPlugin from './jisonPlugin.js';
|
||||
import jsonSchemaPlugin from './jsonSchemaPlugin.js';
|
||||
import { readFileSync } from 'fs';
|
||||
import typescript from '@rollup/plugin-typescript';
|
||||
import { visualizer } from 'rollup-plugin-visualizer';
|
||||
import type { TemplateType } from 'rollup-plugin-visualizer/dist/plugin/template-types.js';
|
||||
import istanbul from 'vite-plugin-istanbul';
|
||||
import { packageOptions } from '../.build/common.js';
|
||||
import { generateLangium } from '../.build/generateLangium.js';
|
||||
|
||||
const visualize = process.argv.includes('--visualize');
|
||||
const watch = process.argv.includes('--watch');
|
||||
@ -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 {
|
||||
minify: boolean | 'esbuild';
|
||||
core?: boolean;
|
||||
@ -72,34 +55,8 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
|
||||
sourcemap,
|
||||
entryFileNames: `${name}.esm${minify ? '.min' : ''}.mjs`,
|
||||
},
|
||||
{
|
||||
name,
|
||||
format: 'umd',
|
||||
sourcemap,
|
||||
entryFileNames: `${name}${minify ? '.min' : ''}.js`,
|
||||
},
|
||||
];
|
||||
|
||||
if (core) {
|
||||
const { dependencies } = JSON.parse(
|
||||
readFileSync(resolve(__dirname, `../packages/${packageName}/package.json`), 'utf-8')
|
||||
);
|
||||
// Core build is used to generate file without bundled dependencies.
|
||||
// This is used by downstream projects to bundle dependencies themselves.
|
||||
// Ignore dependencies and any dependencies of dependencies
|
||||
// Adapted from the RegEx used by `rollup-plugin-node`
|
||||
external.push(new RegExp('^(?:' + Object.keys(dependencies).join('|') + ')(?:/.+)?$'));
|
||||
// This needs to be an array. Otherwise vite will build esm & umd with same name and overwrite esm with umd.
|
||||
output = [
|
||||
{
|
||||
name,
|
||||
format: 'esm',
|
||||
sourcemap,
|
||||
entryFileNames: `${name}.core.mjs`,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const config: InlineConfig = {
|
||||
configFile: false,
|
||||
build: {
|
||||
@ -129,7 +86,7 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
|
||||
// @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite
|
||||
typescript({ compilerOptions: { declaration: false } }),
|
||||
istanbul({
|
||||
exclude: ['node_modules', 'test/', '__mocks__'],
|
||||
exclude: ['node_modules', 'test/', '__mocks__', 'generated'],
|
||||
extension: ['.js', '.ts'],
|
||||
requireEnv: true,
|
||||
forceBuildInstrument: coverage,
|
||||
@ -149,24 +106,28 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
|
||||
|
||||
const buildPackage = async (entryName: keyof typeof packageOptions) => {
|
||||
await build(getBuildConfig({ minify: false, entryName }));
|
||||
await build(getBuildConfig({ minify: 'esbuild', entryName }));
|
||||
await build(getBuildConfig({ minify: false, core: true, entryName }));
|
||||
};
|
||||
|
||||
const main = async () => {
|
||||
const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[];
|
||||
for (const pkg of packageNames.filter((pkg) => !mermaidOnly || pkg === 'mermaid')) {
|
||||
for (const pkg of packageNames.filter(
|
||||
(pkg) => !mermaidOnly || pkg === 'mermaid' || pkg === 'parser'
|
||||
)) {
|
||||
await buildPackage(pkg);
|
||||
}
|
||||
};
|
||||
|
||||
await generateLangium();
|
||||
|
||||
if (watch) {
|
||||
await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' }));
|
||||
build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' }));
|
||||
if (!mermaidOnly) {
|
||||
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' }));
|
||||
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-zenuml' }));
|
||||
}
|
||||
} else if (visualize) {
|
||||
await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' }));
|
||||
await build(getBuildConfig({ minify: false, core: true, entryName: 'mermaid' }));
|
||||
await build(getBuildConfig({ minify: false, core: false, entryName: 'mermaid' }));
|
||||
} else {
|
||||
|
@ -1,10 +1,10 @@
|
||||
import { transformJison } from './jisonTransformer.js';
|
||||
import { transformJison } from '../.build/jisonTransformer.js';
|
||||
|
||||
const fileRegex = /\.(jison)$/;
|
||||
|
||||
export default function jison() {
|
||||
return {
|
||||
name: 'jison',
|
||||
|
||||
transform(src: string, id: string) {
|
||||
if (fileRegex.test(id)) {
|
||||
return {
|
||||
|
@ -1,111 +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 type { MermaidConfig, BaseDiagramConfig } from '../packages/mermaid/src/config.type.js';
|
||||
|
||||
/**
|
||||
* All of the keys in the mermaid config that have a mermaid diagram config.
|
||||
*/
|
||||
const MERMAID_CONFIG_DIAGRAM_KEYS = [
|
||||
'flowchart',
|
||||
'sequence',
|
||||
'gantt',
|
||||
'journey',
|
||||
'class',
|
||||
'state',
|
||||
'er',
|
||||
'pie',
|
||||
'quadrantChart',
|
||||
'xyChart',
|
||||
'requirement',
|
||||
'mindmap',
|
||||
'timeline',
|
||||
'gitGraph',
|
||||
'c4',
|
||||
'sankey',
|
||||
'block',
|
||||
'architecture',
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Generate default values from the JSON Schema.
|
||||
*
|
||||
* AJV does not support nested default values yet (or default values with $ref),
|
||||
* so we need to manually find them (this may be fixed in ajv v9).
|
||||
*
|
||||
* @param mermaidConfigSchema - The Mermaid JSON Schema to use.
|
||||
* @returns The default mermaid config object.
|
||||
*/
|
||||
function generateDefaults(mermaidConfigSchema: JSONSchemaType<MermaidConfig>) {
|
||||
const ajv = new Ajv2019({
|
||||
useDefaults: true,
|
||||
allowUnionTypes: true,
|
||||
strict: true,
|
||||
});
|
||||
|
||||
ajv.addKeyword({
|
||||
keyword: 'meta:enum', // used by jsonschema2md
|
||||
errors: false,
|
||||
});
|
||||
ajv.addKeyword({
|
||||
keyword: 'tsType', // used by json-schema-to-typescript
|
||||
errors: false,
|
||||
});
|
||||
|
||||
// ajv currently doesn't support nested default values, see https://github.com/ajv-validator/ajv/issues/1718
|
||||
// (may be fixed in v9) so we need to manually use sub-schemas
|
||||
const mermaidDefaultConfig = {};
|
||||
|
||||
assert.ok(mermaidConfigSchema.$defs);
|
||||
const baseDiagramConfig = mermaidConfigSchema.$defs.BaseDiagramConfig;
|
||||
|
||||
for (const key of MERMAID_CONFIG_DIAGRAM_KEYS) {
|
||||
const subSchemaRef = mermaidConfigSchema.properties[key].$ref;
|
||||
const [root, defs, defName] = subSchemaRef.split('/');
|
||||
assert.strictEqual(root, '#');
|
||||
assert.strictEqual(defs, '$defs');
|
||||
const subSchema = {
|
||||
$schema: mermaidConfigSchema.$schema,
|
||||
$defs: mermaidConfigSchema.$defs,
|
||||
...mermaidConfigSchema.$defs[defName],
|
||||
} as JSONSchemaType<BaseDiagramConfig>;
|
||||
|
||||
const validate = ajv.compile(subSchema);
|
||||
|
||||
mermaidDefaultConfig[key] = {};
|
||||
|
||||
for (const required of subSchema.required ?? []) {
|
||||
if (subSchema.properties[required] === undefined && baseDiagramConfig.properties[required]) {
|
||||
mermaidDefaultConfig[key][required] = baseDiagramConfig.properties[required].default;
|
||||
}
|
||||
}
|
||||
if (!validate(mermaidDefaultConfig[key])) {
|
||||
throw new Error(
|
||||
`schema for subconfig ${key} does not have valid defaults! Errors were ${JSON.stringify(
|
||||
validate.errors,
|
||||
undefined,
|
||||
2
|
||||
)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const validate = ajv.compile(mermaidConfigSchema);
|
||||
|
||||
if (!validate(mermaidDefaultConfig)) {
|
||||
throw new Error(
|
||||
`Mermaid config JSON Schema does not have valid defaults! Errors were ${JSON.stringify(
|
||||
validate.errors,
|
||||
undefined,
|
||||
2
|
||||
)}`
|
||||
);
|
||||
}
|
||||
|
||||
return mermaidDefaultConfig;
|
||||
}
|
||||
import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js';
|
||||
|
||||
/**
|
||||
* Vite plugin that handles JSON Schemas saved as a `.schema.yaml` file.
|
||||
@ -122,32 +16,13 @@ export default function jsonSchemaPlugin(): PluginOption {
|
||||
return;
|
||||
}
|
||||
|
||||
if (idAsUrl.searchParams.get('only-defaults')) {
|
||||
const jsonSchema = load(src, {
|
||||
filename: idAsUrl.pathname,
|
||||
// only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
|
||||
// e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
|
||||
schema: JSON_SCHEMA,
|
||||
}) as JSONSchemaType<MermaidConfig>;
|
||||
return {
|
||||
code: `export default ${JSON.stringify(generateDefaults(jsonSchema), undefined, 2)};`,
|
||||
map: null, // no source map
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
code: `export default ${JSON.stringify(
|
||||
load(src, {
|
||||
filename: idAsUrl.pathname,
|
||||
// only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
|
||||
// e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
|
||||
schema: JSON_SCHEMA,
|
||||
}),
|
||||
undefined,
|
||||
2
|
||||
)};`,
|
||||
map: null, // provide source map if available
|
||||
};
|
||||
}
|
||||
const jsonSchema = loadSchema(src, idAsUrl.pathname);
|
||||
return {
|
||||
code: idAsUrl.searchParams.get('only-defaults')
|
||||
? getDefaults(jsonSchema)
|
||||
: getSchema(jsonSchema),
|
||||
map: null, // no source map
|
||||
};
|
||||
},
|
||||
};
|
||||
}
|
||||
|
@ -1,6 +1,7 @@
|
||||
import express from 'express';
|
||||
import cors from 'cors';
|
||||
import { createServer as createViteServer } from 'vite';
|
||||
import { packageOptions } from '../.build/common.js';
|
||||
|
||||
async function createServer() {
|
||||
const app = express();
|
||||
@ -14,9 +15,9 @@ async function createServer() {
|
||||
});
|
||||
|
||||
app.use(cors());
|
||||
app.use(express.static('./packages/mermaid/dist'));
|
||||
app.use(express.static('./packages/mermaid-zenuml/dist'));
|
||||
app.use(express.static('./packages/mermaid-example-diagram/dist'));
|
||||
for (const { packageName } of Object.values(packageOptions)) {
|
||||
app.use(express.static(`./packages/${packageName}/dist`));
|
||||
}
|
||||
app.use(vite.middlewares);
|
||||
app.use(express.static('demos'));
|
||||
app.use(express.static('cypress/platform'));
|
||||
|
@ -1,21 +0,0 @@
|
||||
/**
|
||||
* Mocked C4Context diagram renderer
|
||||
*/
|
||||
|
||||
import { vi } from 'vitest';
|
||||
|
||||
export const drawPersonOrSystemArray = vi.fn();
|
||||
export const drawBoundary = vi.fn();
|
||||
|
||||
export const setConf = vi.fn();
|
||||
|
||||
export const draw = vi.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
|
||||
export default {
|
||||
drawPersonOrSystemArray,
|
||||
drawBoundary,
|
||||
setConf,
|
||||
draw,
|
||||
};
|
@ -1,16 +0,0 @@
|
||||
/**
|
||||
* Mocked class diagram v2 renderer
|
||||
*/
|
||||
|
||||
import { vi } from 'vitest';
|
||||
|
||||
export const setConf = vi.fn();
|
||||
|
||||
export const draw = vi.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
|
||||
export default {
|
||||
setConf,
|
||||
draw,
|
||||
};
|
@ -1,13 +0,0 @@
|
||||
/**
|
||||
* Mocked class diagram renderer
|
||||
*/
|
||||
|
||||
import { vi } from 'vitest';
|
||||
|
||||
export const draw = vi.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
|
||||
export default {
|
||||
draw,
|
||||
};
|
@ -1 +0,0 @@
|
||||
// DO NOT delete this file. It is used by vitest to mock the dagre-d3 module.
|
@ -1,3 +0,0 @@
|
||||
module.exports = function (txt: string) {
|
||||
return txt;
|
||||
};
|
@ -1,16 +0,0 @@
|
||||
/**
|
||||
* Mocked er diagram renderer
|
||||
*/
|
||||
|
||||
import { vi } from 'vitest';
|
||||
|
||||
export const setConf = vi.fn();
|
||||
|
||||
export const draw = vi.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
|
||||
export default {
|
||||
setConf,
|
||||
draw,
|
||||
};
|
@ -1,24 +0,0 @@
|
||||
/**
|
||||
* Mocked flow (flowchart) diagram v2 renderer
|
||||
*/
|
||||
|
||||
import { vi } from 'vitest';
|
||||
|
||||
export const setConf = vi.fn();
|
||||
export const addVertices = vi.fn();
|
||||
export const addEdges = vi.fn();
|
||||
export const getClasses = vi.fn().mockImplementation(() => {
|
||||
return {};
|
||||
});
|
||||
|
||||
export const draw = vi.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
|
||||
export default {
|
||||
setConf,
|
||||
addVertices,
|
||||
addEdges,
|
||||
getClasses,
|
||||
draw,
|
||||
};
|
@ -1,16 +0,0 @@
|
||||
/**
|
||||
* Mocked gantt diagram renderer
|
||||
*/
|
||||
|
||||
import { vi } from 'vitest';
|
||||
|
||||
export const setConf = vi.fn();
|
||||
|
||||
export const draw = vi.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
|
||||
export default {
|
||||
setConf,
|
||||
draw,
|
||||
};
|
@ -1,13 +0,0 @@
|
||||
/**
|
||||
* Mocked git (graph) diagram renderer
|
||||
*/
|
||||
|
||||
import { vi } from 'vitest';
|
||||
|
||||
export const draw = vi.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
|
||||
export default {
|
||||
draw,
|
||||
};
|
@ -1,15 +0,0 @@
|
||||
/**
|
||||
* Mocked pie (picChart) diagram renderer
|
||||
*/
|
||||
|
||||
import { vi } from 'vitest';
|
||||
export const setConf = vi.fn();
|
||||
|
||||
export const draw = vi.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
|
||||
export default {
|
||||
setConf,
|
||||
draw,
|
||||
};
|
@ -1,8 +0,0 @@
|
||||
/**
|
||||
* Mocked pie (picChart) diagram renderer
|
||||
*/
|
||||
import { vi } from 'vitest';
|
||||
|
||||
const draw = vi.fn().mockImplementation(() => '');
|
||||
|
||||
export const renderer = { draw };
|
@ -1,13 +0,0 @@
|
||||
/**
|
||||
* Mocked requirement diagram renderer
|
||||
*/
|
||||
|
||||
import { vi } from 'vitest';
|
||||
|
||||
export const draw = vi.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
|
||||
export default {
|
||||
draw,
|
||||
};
|
@ -1,13 +0,0 @@
|
||||
/**
|
||||
* Mocked Sankey diagram renderer
|
||||
*/
|
||||
|
||||
import { vi } from 'vitest';
|
||||
|
||||
export const draw = vi.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
|
||||
export default {
|
||||
draw,
|
||||
};
|
@ -1,23 +0,0 @@
|
||||
/**
|
||||
* Mocked sequence diagram renderer
|
||||
*/
|
||||
|
||||
import { vi } from 'vitest';
|
||||
|
||||
export const bounds = vi.fn();
|
||||
export const drawActors = vi.fn();
|
||||
export const drawActorsPopup = vi.fn();
|
||||
|
||||
export const setConf = vi.fn();
|
||||
|
||||
export const draw = vi.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
|
||||
export default {
|
||||
bounds,
|
||||
drawActors,
|
||||
drawActorsPopup,
|
||||
setConf,
|
||||
draw,
|
||||
};
|
@ -1,22 +0,0 @@
|
||||
/**
|
||||
* Mocked state diagram v2 renderer
|
||||
*/
|
||||
|
||||
import { vi } from 'vitest';
|
||||
|
||||
export const setConf = vi.fn();
|
||||
export const getClasses = vi.fn().mockImplementation(() => {
|
||||
return {};
|
||||
});
|
||||
export const stateDomId = vi.fn().mockImplementation(() => {
|
||||
return 'mocked-stateDiagram-stateDomId';
|
||||
});
|
||||
export const draw = vi.fn().mockImplementation(() => {
|
||||
return '';
|
||||
});
|
||||
|
||||
export default {
|
||||
setConf,
|
||||
getClasses,
|
||||
draw,
|
||||
};
|
@ -118,11 +118,53 @@ describe('Configuration', () => {
|
||||
it('should not taint the initial configuration when using multiple directives', () => {
|
||||
const url = 'http://localhost:9000/regression/issue-1874.html';
|
||||
cy.visit(url);
|
||||
|
||||
cy.get('svg');
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
cy.get('svg').should('be.visible');
|
||||
cy.matchImageSnapshot(
|
||||
'configuration.spec-should-not-taint-initial-configuration-when-using-multiple-directives'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('suppressErrorRendering', () => {
|
||||
beforeEach(() => {
|
||||
cy.on('uncaught:exception', (err, runnable) => {
|
||||
return !err.message.includes('Parse error on line');
|
||||
});
|
||||
});
|
||||
|
||||
it('should not render error diagram if suppressErrorRendering is set', () => {
|
||||
const url = 'http://localhost:9000/suppressError.html?suppressErrorRendering=true';
|
||||
cy.visit(url);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
cy.get('#test')
|
||||
.find('svg')
|
||||
.should(($svg) => {
|
||||
// all failing diagrams should not appear!
|
||||
expect($svg).to.have.length(2);
|
||||
// none of the diagrams should be error diagrams
|
||||
expect($svg).to.not.contain('Syntax error');
|
||||
});
|
||||
cy.matchImageSnapshot(
|
||||
'configuration.spec-should-not-render-error-diagram-if-suppressErrorRendering-is-set'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render error diagram if suppressErrorRendering is not set', () => {
|
||||
const url = 'http://localhost:9000/suppressError.html';
|
||||
cy.visit(url);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
cy.get('#test')
|
||||
.find('svg')
|
||||
.should(($svg) => {
|
||||
// all five diagrams should be rendered
|
||||
expect($svg).to.have.length(5);
|
||||
// some of the diagrams should be error diagrams
|
||||
expect($svg).to.contain('Syntax error');
|
||||
});
|
||||
cy.matchImageSnapshot(
|
||||
'configuration.spec-should-render-error-diagram-if-suppressErrorRendering-is-not-set'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
14
cypress/integration/other/flowchart-elk.spec.js
Normal file
14
cypress/integration/other/flowchart-elk.spec.js
Normal file
@ -0,0 +1,14 @@
|
||||
import { urlSnapshotTest, openURLAndVerifyRendering } from '../../helpers/util.ts';
|
||||
|
||||
describe('Flowchart elk', () => {
|
||||
it('should use dagre as fallback', () => {
|
||||
urlSnapshotTest('http://localhost:9000/flow-elk.html', {
|
||||
name: 'flow-elk fallback to dagre',
|
||||
});
|
||||
});
|
||||
it('should allow overriding with external package', () => {
|
||||
urlSnapshotTest('http://localhost:9000/flow-elk.html?elk=true', {
|
||||
name: 'flow-elk overriding dagre with elk',
|
||||
});
|
||||
});
|
||||
});
|
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>');
|
||||
});
|
||||
});
|
@ -844,3 +844,42 @@ end
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Title and arrow styling #4813', () => {
|
||||
it('should render a flowchart with title', () => {
|
||||
const titleString = 'Test Title';
|
||||
renderGraph(
|
||||
`---
|
||||
title: ${titleString}
|
||||
---
|
||||
flowchart LR
|
||||
A-->B
|
||||
A-->C`,
|
||||
{ flowchart: { defaultRenderer: 'elk' } }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const title = svg[0].querySelector('text');
|
||||
expect(title.textContent).to.contain(titleString);
|
||||
});
|
||||
});
|
||||
|
||||
it('Render with stylized arrows', () => {
|
||||
renderGraph(
|
||||
`
|
||||
flowchart LR
|
||||
A-->B
|
||||
B-.-oC
|
||||
C==xD
|
||||
D ~~~ A`,
|
||||
{ flowchart: { defaultRenderer: 'elk' } }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const edges = svg[0].querySelectorAll('.edges path');
|
||||
console.log(edges);
|
||||
expect(edges[0]).to.have.attr('pattern', 'solid');
|
||||
expect(edges[1]).to.have.attr('pattern', 'dotted');
|
||||
expect(edges[2]).to.have.css('stroke-width', '3.5px');
|
||||
expect(edges[3]).to.have.css('stroke-width', '1.5px');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -760,6 +760,51 @@ A ~~~ B
|
||||
);
|
||||
});
|
||||
|
||||
it('3258: Should render subgraphs with main graph nodeSpacing and rankSpacing', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
title: Subgraph nodeSpacing and rankSpacing example
|
||||
---
|
||||
flowchart LR
|
||||
X --> Y
|
||||
subgraph X
|
||||
direction LR
|
||||
A
|
||||
C
|
||||
end
|
||||
subgraph Y
|
||||
B
|
||||
D
|
||||
end
|
||||
`,
|
||||
{ flowchart: { nodeSpacing: 1, rankSpacing: 1 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('3258: Should render subgraphs with large nodeSpacing and rankSpacing', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
title: Subgraph nodeSpacing and rankSpacing example
|
||||
config:
|
||||
flowchart:
|
||||
nodeSpacing: 250
|
||||
rankSpacing: 250
|
||||
---
|
||||
flowchart LR
|
||||
X --> Y
|
||||
subgraph X
|
||||
direction LR
|
||||
A
|
||||
C
|
||||
end
|
||||
subgraph Y
|
||||
B
|
||||
D
|
||||
end
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
describe('Markdown strings flowchart (#4220)', () => {
|
||||
describe('html labels', () => {
|
||||
it('With styling and classes', () => {
|
||||
@ -904,6 +949,18 @@ end
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should not auto wrap when markdownAutoWrap is false', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TD
|
||||
angular_velocity["\`**angular_velocity**
|
||||
*angular_displacement / duration*
|
||||
[rad/s, 1/s]
|
||||
{vector}\`"]
|
||||
frequency["frequency\n(1 / period_duration)\n[Hz, 1/s]"]`,
|
||||
{ markdownAutoWrap: false }
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('Subgraph title margins', () => {
|
||||
it('Should render subgraphs with title margins set (LR)', () => {
|
||||
|
@ -101,12 +101,12 @@ describe('Gantt diagram', () => {
|
||||
title Adding GANTT diagram to mermaid
|
||||
excludes weekdays 2014-01-10
|
||||
todayMarker off
|
||||
|
||||
|
||||
section team's critical event
|
||||
deadline A :milestone, crit, deadlineA, 2024-02-01, 0
|
||||
deadline B :milestone, crit, deadlineB, 2024-02-15, 0
|
||||
boss on leave :bossaway, 2024-01-28, 2024-02-11
|
||||
|
||||
|
||||
section new intern
|
||||
onboarding :onboarding, 2024-01-02, 1w
|
||||
literature review :litreview, 2024-01-02, 10d
|
||||
@ -573,7 +573,28 @@ describe('Gantt diagram', () => {
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a gantt diagram exculding friday and saturday', () => {
|
||||
imgSnapshotTest(
|
||||
`gantt
|
||||
title A Gantt Diagram
|
||||
dateFormat YYYY-MM-DD
|
||||
excludes weekends
|
||||
weekend friday
|
||||
section Section1
|
||||
A task :a1, 2024-02-28, 10d`
|
||||
);
|
||||
});
|
||||
it('should render a gantt diagram exculding saturday and sunday', () => {
|
||||
imgSnapshotTest(
|
||||
`gantt
|
||||
title A Gantt Diagram
|
||||
dateFormat YYYY-MM-DD
|
||||
excludes weekends
|
||||
weekend saturday
|
||||
section Section1
|
||||
A task :a1, 2024-02-28, 10d`
|
||||
);
|
||||
});
|
||||
it('should render when compact is true', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
|
@ -1013,4 +1013,450 @@ gitGraph TB:
|
||||
{ gitGraph: { parallelCommits: true } }
|
||||
);
|
||||
});
|
||||
describe('Git-Graph Bottom-to-Top Orientation Tests', () => {
|
||||
it('50: should render a simple gitgraph with commit on main branch | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
commit id: "3"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('51: should render a simple gitgraph with commit on main branch with Id | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
commit id: "One"
|
||||
commit id: "Two"
|
||||
commit id: "Three"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('52: should render a simple gitgraph with different commitTypes on main branch | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
commit id: "Normal Commit"
|
||||
commit id: "Reverse Commit" type: REVERSE
|
||||
commit id: "Highlight Commit" type: HIGHLIGHT
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('53: should render a simple gitgraph with tags commitTypes on main branch | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
commit id: "Normal Commit with tag" tag: "v1.0.0"
|
||||
commit id: "Reverse Commit with tag" type: REVERSE tag: "RC_1"
|
||||
commit id: "Highlight Commit" type: HIGHLIGHT tag: "8.8.4"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('54: should render a simple gitgraph with two branches | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id: "3"
|
||||
commit id: "4"
|
||||
checkout main
|
||||
commit id: "5"
|
||||
commit id: "6"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('55: should render a simple gitgraph with two branches and merge commit | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
branch develop
|
||||
checkout develop
|
||||
commit id: "3"
|
||||
commit id: "4"
|
||||
checkout main
|
||||
merge develop
|
||||
commit id: "5"
|
||||
commit id: "6"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('56: should render a simple gitgraph with three branches and tagged merge commit | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
branch nice_feature
|
||||
checkout nice_feature
|
||||
commit id: "3"
|
||||
checkout main
|
||||
commit id: "4"
|
||||
checkout nice_feature
|
||||
branch very_nice_feature
|
||||
checkout very_nice_feature
|
||||
commit id: "5"
|
||||
checkout main
|
||||
commit id: "6"
|
||||
checkout nice_feature
|
||||
commit id: "7"
|
||||
checkout main
|
||||
merge nice_feature id: "12345" tag: "my merge commit"
|
||||
checkout very_nice_feature
|
||||
commit id: "8"
|
||||
checkout main
|
||||
commit id: "9"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('57: should render a simple gitgraph with more than 8 branches & overriding variables | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'themeVariables': {
|
||||
'gitBranchLabel0': '#ffffff',
|
||||
'gitBranchLabel1': '#ffffff',
|
||||
'gitBranchLabel2': '#ffffff',
|
||||
'gitBranchLabel3': '#ffffff',
|
||||
'gitBranchLabel4': '#ffffff',
|
||||
'gitBranchLabel5': '#ffffff',
|
||||
'gitBranchLabel6': '#ffffff',
|
||||
'gitBranchLabel7': '#ffffff',
|
||||
} } }%%
|
||||
gitGraph BT:
|
||||
checkout main
|
||||
branch branch1
|
||||
branch branch2
|
||||
branch branch3
|
||||
branch branch4
|
||||
branch branch5
|
||||
branch branch6
|
||||
branch branch7
|
||||
branch branch8
|
||||
branch branch9
|
||||
checkout branch1
|
||||
commit id: "1"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('58: should render a simple gitgraph with rotated labels | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'gitGraph': {
|
||||
'rotateCommitLabel': true
|
||||
} } }%%
|
||||
gitGraph BT:
|
||||
commit id: "75f7219e83b321cd3fdde7dcf83bc7c1000a6828"
|
||||
commit id: "0db4784daf82736dec4569e0dc92980d328c1f2e"
|
||||
commit id: "7067e9973f9eaa6cd4a4b723c506d1eab598e83e"
|
||||
commit id: "66972321ad6c199013b5b31f03b3a86fa3f9817d"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('59: should render a simple gitgraph with horizontal labels | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: { 'logLevel': 'debug', 'theme': 'default' , 'gitGraph': {
|
||||
'rotateCommitLabel': false
|
||||
} } }%%
|
||||
gitGraph BT:
|
||||
commit id: "Alpha"
|
||||
commit id: "Beta"
|
||||
commit id: "Gamma"
|
||||
commit id: "Delta"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('60: should render a simple gitgraph with cherry pick commit | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gitGraph BT:
|
||||
commit id: "ZERO"
|
||||
branch develop
|
||||
commit id:"A"
|
||||
checkout main
|
||||
commit id:"ONE"
|
||||
checkout develop
|
||||
commit id:"B"
|
||||
checkout main
|
||||
commit id:"TWO"
|
||||
cherry-pick id:"A"
|
||||
commit id:"THREE"
|
||||
checkout develop
|
||||
commit id:"C"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('61: should render a gitgraph with cherry pick commit with custom tag | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gitGraph BT:
|
||||
commit id: "ZERO"
|
||||
branch develop
|
||||
commit id:"A"
|
||||
checkout main
|
||||
commit id:"ONE"
|
||||
checkout develop
|
||||
commit id:"B"
|
||||
checkout main
|
||||
commit id:"TWO"
|
||||
cherry-pick id:"A" tag: "snapshot"
|
||||
commit id:"THREE"
|
||||
checkout develop
|
||||
commit id:"C"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('62: should render a gitgraph with cherry pick commit with no tag | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gitGraph BT:
|
||||
commit id: "ZERO"
|
||||
branch develop
|
||||
commit id:"A"
|
||||
checkout main
|
||||
commit id:"ONE"
|
||||
checkout develop
|
||||
commit id:"B"
|
||||
checkout main
|
||||
commit id:"TWO"
|
||||
cherry-pick id:"A" tag: ""
|
||||
commit id:"THREE"
|
||||
checkout develop
|
||||
commit id:"C"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('63: should render a simple gitgraph with two cherry pick commit | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gitGraph BT:
|
||||
commit id: "ZERO"
|
||||
branch develop
|
||||
commit id:"A"
|
||||
checkout main
|
||||
commit id:"ONE"
|
||||
checkout develop
|
||||
commit id:"B"
|
||||
branch featureA
|
||||
commit id:"FIX"
|
||||
commit id: "FIX-2"
|
||||
checkout main
|
||||
commit id:"TWO"
|
||||
cherry-pick id:"A"
|
||||
commit id:"THREE"
|
||||
cherry-pick id:"FIX"
|
||||
checkout develop
|
||||
commit id:"C"
|
||||
merge featureA
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('64: should render commits for more than 8 branches | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gitGraph BT:
|
||||
checkout main
|
||||
%% Make sure to manually set the ID of all commits, for consistent visual tests
|
||||
commit id: "1-abcdefg"
|
||||
checkout main
|
||||
branch branch1
|
||||
commit id: "2-abcdefg"
|
||||
checkout main
|
||||
merge branch1
|
||||
branch branch2
|
||||
commit id: "3-abcdefg"
|
||||
checkout main
|
||||
merge branch2
|
||||
branch branch3
|
||||
commit id: "4-abcdefg"
|
||||
checkout main
|
||||
merge branch3
|
||||
branch branch4
|
||||
commit id: "5-abcdefg"
|
||||
checkout main
|
||||
merge branch4
|
||||
branch branch5
|
||||
commit id: "6-abcdefg"
|
||||
checkout main
|
||||
merge branch5
|
||||
branch branch6
|
||||
commit id: "7-abcdefg"
|
||||
checkout main
|
||||
merge branch6
|
||||
branch branch7
|
||||
commit id: "8-abcdefg"
|
||||
checkout main
|
||||
merge branch7
|
||||
branch branch8
|
||||
commit id: "9-abcdefg"
|
||||
checkout main
|
||||
merge branch8
|
||||
branch branch9
|
||||
commit id: "10-abcdefg"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('65: should render a simple gitgraph with three branches,custom merge commit id,tag,type | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
branch nice_feature
|
||||
checkout nice_feature
|
||||
commit id: "3"
|
||||
checkout main
|
||||
commit id: "4"
|
||||
checkout nice_feature
|
||||
branch very_nice_feature
|
||||
checkout very_nice_feature
|
||||
commit id: "5"
|
||||
checkout main
|
||||
commit id: "6"
|
||||
checkout nice_feature
|
||||
commit id: "7"
|
||||
checkout main
|
||||
merge nice_feature id: "customID" tag: "customTag" type: REVERSE
|
||||
checkout very_nice_feature
|
||||
commit id: "8"
|
||||
checkout main
|
||||
commit id: "9"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('66: should render a simple gitgraph with a title | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
title: simple gitGraph
|
||||
---
|
||||
gitGraph BT:
|
||||
commit id: "1-abcdefg"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('67: should render a simple gitgraph overlapping commits | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
commit id:"s1"
|
||||
commit id:"s2"
|
||||
branch branch1
|
||||
commit id:"s3"
|
||||
commit id:"s4"
|
||||
checkout main
|
||||
commit id:"s5"
|
||||
checkout branch1
|
||||
commit id:"s6"
|
||||
commit id:"s7"
|
||||
merge main
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('68: should render a simple gitgraph with two branches from same commit | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
commit id:"1-abcdefg"
|
||||
commit id:"2-abcdefg"
|
||||
branch feature-001
|
||||
commit id:"3-abcdefg"
|
||||
commit id:"4-abcdefg"
|
||||
checkout main
|
||||
branch feature-002
|
||||
commit id:"5-abcdefg"
|
||||
checkout feature-001
|
||||
merge feature-002
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('69: should render GitGraph with branch that is not used immediately | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
commit id:"1-abcdefg"
|
||||
branch x
|
||||
checkout main
|
||||
commit id:"2-abcdefg"
|
||||
checkout x
|
||||
commit id:"3-abcdefg"
|
||||
checkout main
|
||||
merge x
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('70: should render GitGraph with branch and sub-branch neither of which used immediately | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
commit id:"1-abcdefg"
|
||||
branch x
|
||||
checkout main
|
||||
commit id:"2-abcdefg"
|
||||
checkout x
|
||||
commit id:"3-abcdefg"
|
||||
checkout main
|
||||
merge x
|
||||
checkout x
|
||||
branch y
|
||||
checkout x
|
||||
commit id:"4-abcdefg"
|
||||
checkout y
|
||||
commit id:"5-abcdefg"
|
||||
checkout x
|
||||
merge y
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('71: should render GitGraph with parallel commits | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
commit id:"1-abcdefg"
|
||||
commit id:"2-abcdefg"
|
||||
branch develop
|
||||
commit id:"3-abcdefg"
|
||||
commit id:"4-abcdefg"
|
||||
checkout main
|
||||
branch feature
|
||||
commit id:"5-abcdefg"
|
||||
commit id:"6-abcdefg"
|
||||
checkout main
|
||||
commit id:"7-abcdefg"
|
||||
commit id:"8-abcdefg"
|
||||
`,
|
||||
{ gitGraph: { parallelCommits: true } }
|
||||
);
|
||||
});
|
||||
it('72: should render GitGraph with unconnected branches and parallel commits | Vertical Branch - Bottom-to-top', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
branch dev
|
||||
branch v2
|
||||
branch feat
|
||||
commit id:"1-abcdefg"
|
||||
commit id:"2-abcdefg"
|
||||
checkout main
|
||||
commit id:"3-abcdefg"
|
||||
checkout dev
|
||||
commit id:"4-abcdefg"
|
||||
checkout v2
|
||||
commit id:"5-abcdefg"
|
||||
checkout main
|
||||
commit id:"6-abcdefg"
|
||||
`,
|
||||
{ gitGraph: { parallelCommits: true } }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
67
cypress/integration/rendering/packet.spec.ts
Normal file
67
cypress/integration/rendering/packet.spec.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util';
|
||||
|
||||
describe('packet structure', () => {
|
||||
it('should render a simple packet diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`packet-beta
|
||||
title Hello world
|
||||
0-10: "hello"
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a complex packet diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`packet-beta
|
||||
0-15: "Source Port"
|
||||
16-31: "Destination Port"
|
||||
32-63: "Sequence Number"
|
||||
64-95: "Acknowledgment Number"
|
||||
96-99: "Data Offset"
|
||||
100-105: "Reserved"
|
||||
106: "URG"
|
||||
107: "ACK"
|
||||
108: "PSH"
|
||||
109: "RST"
|
||||
110: "SYN"
|
||||
111: "FIN"
|
||||
112-127: "Window"
|
||||
128-143: "Checksum"
|
||||
144-159: "Urgent Pointer"
|
||||
160-191: "(Options and Padding)"
|
||||
192-223: "data"
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a complex packet diagram with showBits false', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
---
|
||||
title: "Packet Diagram"
|
||||
config:
|
||||
packet:
|
||||
showBits: false
|
||||
---
|
||||
packet-beta
|
||||
0-15: "Source Port"
|
||||
16-31: "Destination Port"
|
||||
32-63: "Sequence Number"
|
||||
64-95: "Acknowledgment Number"
|
||||
96-99: "Data Offset"
|
||||
100-105: "Reserved"
|
||||
106: "URG"
|
||||
107: "ACK"
|
||||
108: "PSH"
|
||||
109: "RST"
|
||||
110: "SYN"
|
||||
111: "FIN"
|
||||
112-127: "Window"
|
||||
128-143: "Checksum"
|
||||
144-159: "Urgent Pointer"
|
||||
160-191: "(Options and Padding)"
|
||||
192-223: "data"
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
@ -375,7 +375,7 @@ context('Sequence diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should have actor-top and actor-bottom classes on top and bottom actor box and symbol', () => {
|
||||
it('should have actor-top and actor-bottom classes on top and bottom actor box and symbol and actor-box and actor-man classes for text tags', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
@ -394,6 +394,9 @@ context('Sequence diagram', () => {
|
||||
cy.get('.actor-man').should('have.class', 'actor-bottom');
|
||||
cy.get('.actor.actor-bottom').should('not.have.class', 'actor-top');
|
||||
cy.get('.actor-man.actor-bottom').should('not.have.class', 'actor-top');
|
||||
|
||||
cy.get('text.actor-box').should('include.text', 'Alice');
|
||||
cy.get('text.actor-man').should('include.text', 'Bob');
|
||||
});
|
||||
it('should render long notes left of actor', () => {
|
||||
imgSnapshotTest(
|
||||
@ -807,7 +810,10 @@ context('Sequence diagram', () => {
|
||||
note left of Alice: config: mirrorActors=true<br/>directive: mirrorActors=false
|
||||
Bob->>Alice: Short as well
|
||||
`,
|
||||
{ logLevel: 0, sequence: { mirrorActors: true, noteFontSize: 18, noteFontFamily: 'Arial' } }
|
||||
{
|
||||
logLevel: 0,
|
||||
sequence: { mirrorActors: true, noteFontSize: 18, noteFontFamily: 'Arial' },
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
@ -858,7 +864,10 @@ context('Sequence diagram', () => {
|
||||
a->>j: Hello John, how are you?
|
||||
j-->>a: Great!
|
||||
`,
|
||||
{ logLevel: 0, sequence: { mirrorActors: true, noteFontSize: 18, noteFontFamily: 'Arial' } }
|
||||
{
|
||||
logLevel: 0,
|
||||
sequence: { mirrorActors: true, noteFontSize: 18, noteFontFamily: 'Arial' },
|
||||
}
|
||||
);
|
||||
});
|
||||
it('should support actor links and properties when not mirrored EXPERIMENTAL: USE WITH CAUTION', () => {
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
|
||||
@ -33,7 +33,9 @@
|
||||
background-image: radial-gradient(#fff 1%, transparent 11%),
|
||||
radial-gradient(#fff 1%, transparent 11%);
|
||||
background-size: 20px 20px;
|
||||
background-position: 0 0, 10px 10px;
|
||||
background-position:
|
||||
0 0,
|
||||
10px 10px;
|
||||
background-repeat: repeat;
|
||||
}
|
||||
.malware {
|
||||
|
@ -3,7 +3,7 @@
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
@ -1,7 +1,7 @@
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<script src="./viewer.js" type="module"></script>
|
||||
<script type="module" src="./viewer.js"></script>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
rel="stylesheet"
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8" />
|
||||
|
@ -11,8 +11,7 @@ example-diagram
|
||||
<!-- <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">
|
||||
import exampleDiagram from '../../packages/mermaid-example-diagram/dist/mermaid-example-diagram.core.mjs';
|
||||
// import example from '../../packages/mermaid-example-diagram/src/detector';
|
||||
import exampleDiagram from './mermaid-example-diagram.esm.mjs';
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
|
||||
await mermaid.registerExternalDiagrams([exampleDiagram]);
|
||||
|
28
cypress/platform/flow-elk.html
Normal file
28
cypress/platform/flow-elk.html
Normal file
@ -0,0 +1,28 @@
|
||||
<html>
|
||||
<body>
|
||||
<pre class="mermaid">
|
||||
flowchart-elk
|
||||
a[hello] --> b[world]
|
||||
b --> c{test}
|
||||
c --> one
|
||||
c --> two
|
||||
c --> three
|
||||
</pre>
|
||||
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
import elk from './mermaid-flowchart-elk.esm.min.mjs';
|
||||
if (window.location.search.includes('elk')) {
|
||||
await mermaid.registerExternalDiagrams([elk]);
|
||||
}
|
||||
mermaid.initialize({
|
||||
logLevel: 3,
|
||||
startOnLoad: false,
|
||||
});
|
||||
await mermaid.run();
|
||||
if (window.Cypress) {
|
||||
window.rendered = true;
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -4,7 +4,7 @@
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
@ -3,7 +3,7 @@
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
@ -3,7 +3,7 @@
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
@ -3,7 +3,7 @@
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
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>
|
@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
@ -17,20 +17,20 @@
|
||||
graph TB
|
||||
Function-->URL
|
||||
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 id="FirstLine" class="mermaid2">
|
||||
graph TB
|
||||
1Function-->2URL
|
||||
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 id="FirstLine" class="mermaid2">
|
||||
classDiagram
|
||||
class Test
|
||||
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
|
||||
callback ShapeCallback "clickByClass" "This is a tooltip for a callback"
|
||||
</pre>
|
||||
@ -42,7 +42,7 @@
|
||||
<pre id="FirstLine" class="mermaid">
|
||||
classDiagram-v2
|
||||
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>
|
||||
</div>
|
||||
|
||||
@ -77,7 +77,7 @@
|
||||
Calling a Callback (look at the console log) :cl2, 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 cl3 call clickByGantt("test1", test2, test3)
|
||||
|
||||
@ -102,9 +102,15 @@
|
||||
div.className = 'created-by-gant-click';
|
||||
div.style = 'padding: 20px; background: green; color: white;';
|
||||
div.innerText = 'Clicked By Gant';
|
||||
if (arg1) div.innerText += ' ' + arg1;
|
||||
if (arg2) div.innerText += ' ' + arg2;
|
||||
if (arg3) div.innerText += ' ' + arg3;
|
||||
if (arg1) {
|
||||
div.innerText += ' ' + arg1;
|
||||
}
|
||||
if (arg2) {
|
||||
div.innerText += ' ' + arg2;
|
||||
}
|
||||
if (arg3) {
|
||||
div.innerText += ' ' + arg3;
|
||||
}
|
||||
|
||||
document.getElementsByTagName('body')[0].appendChild(div);
|
||||
}
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
@ -21,7 +21,11 @@ sequenceDiagram
|
||||
mermaid.initialize({
|
||||
theme: 'base',
|
||||
themeVariables: {},
|
||||
startOnLoad: true,
|
||||
startOnLoad: false,
|
||||
});
|
||||
await mermaid.run();
|
||||
if (window.Cypress) {
|
||||
window.rendered = true;
|
||||
}
|
||||
</script>
|
||||
</html>
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
59
cypress/platform/suppressError.html
Normal file
59
cypress/platform/suppressError.html
Normal file
@ -0,0 +1,59 @@
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Mermaid Quick Test Page</title>
|
||||
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
|
||||
</head>
|
||||
<body>
|
||||
<div id="test">
|
||||
<pre class="mermaid">
|
||||
flowchart
|
||||
a[This should be visible]
|
||||
</pre
|
||||
>
|
||||
<pre class="mermaid">
|
||||
flowchart
|
||||
a --< b
|
||||
</pre
|
||||
>
|
||||
<pre class="mermaid">
|
||||
flowchart
|
||||
a[This should be visible]
|
||||
</pre
|
||||
>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
suppressErrorRendering: true # This should not affect anything, as suppressErrorRendering is a secure config
|
||||
---
|
||||
flowchart
|
||||
a --< b
|
||||
</pre
|
||||
>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
suppressErrorRendering: false # This should not affect anything, as suppressErrorRendering is a secure config
|
||||
---
|
||||
flowchart
|
||||
a --< b
|
||||
</pre
|
||||
>
|
||||
</div>
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
const shouldSuppress =
|
||||
new URLSearchParams(window.location.search).get('suppressErrorRendering') === 'true';
|
||||
mermaid.initialize({ startOnLoad: false, suppressErrorRendering: shouldSuppress });
|
||||
try {
|
||||
await mermaid.run();
|
||||
} catch {
|
||||
if (window.Cypress) {
|
||||
window.rendered = true;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
@ -1,4 +1,4 @@
|
||||
<!DOCTYPE html>
|
||||
<!doctype html>
|
||||
<html>
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
|
@ -1,6 +1,7 @@
|
||||
import mermaid2 from './mermaid.esm.mjs';
|
||||
import externalExample from '../../packages/mermaid-example-diagram/dist/mermaid-example-diagram.core.mjs';
|
||||
import zenUml from '../../packages/mermaid-zenuml/dist/mermaid-zenuml.core.mjs';
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
import flowchartELK from './mermaid-flowchart-elk.esm.mjs';
|
||||
import externalExample from './mermaid-example-diagram.esm.mjs';
|
||||
import zenUml from './mermaid-zenuml.esm.mjs';
|
||||
|
||||
function b64ToUtf8(str) {
|
||||
return decodeURIComponent(escape(window.atob(str)));
|
||||
@ -45,9 +46,9 @@ const contentLoaded = async function () {
|
||||
document.getElementsByTagName('body')[0].appendChild(div);
|
||||
}
|
||||
|
||||
await mermaid2.registerExternalDiagrams([externalExample, zenUml]);
|
||||
mermaid2.initialize(graphObj.mermaid);
|
||||
await mermaid2.run();
|
||||
await mermaid.registerExternalDiagrams([externalExample, zenUml, flowchartELK]);
|
||||
mermaid.initialize(graphObj.mermaid);
|
||||
await mermaid.run();
|
||||
}
|
||||
};
|
||||
|
||||
@ -95,18 +96,14 @@ const contentLoadedApi = async function () {
|
||||
divs[i] = div;
|
||||
}
|
||||
|
||||
const defaultE2eCnf = { theme: 'forest' };
|
||||
const defaultE2eCnf = { theme: 'forest', startOnLoad: false };
|
||||
|
||||
const cnf = merge(defaultE2eCnf, graphObj.mermaid);
|
||||
|
||||
mermaid2.initialize(cnf);
|
||||
mermaid.initialize(cnf);
|
||||
|
||||
for (let i = 0; i < numCodes; i++) {
|
||||
const { svg, bindFunctions } = await mermaid2.render(
|
||||
'newid' + i,
|
||||
graphObj.code[i],
|
||||
divs[i]
|
||||
);
|
||||
const { svg, bindFunctions } = await mermaid.render('newid' + i, graphObj.code[i], divs[i]);
|
||||
div.innerHTML = svg;
|
||||
bindFunctions(div);
|
||||
}
|
||||
@ -114,18 +111,21 @@ const contentLoadedApi = async function () {
|
||||
const div = document.createElement('div');
|
||||
div.id = 'block';
|
||||
div.className = 'mermaid';
|
||||
console.warn('graphObj.mermaid', graphObj.mermaid);
|
||||
console.warn('graphObj', graphObj);
|
||||
document.getElementsByTagName('body')[0].appendChild(div);
|
||||
mermaid2.initialize(graphObj.mermaid);
|
||||
|
||||
const { svg, bindFunctions } = await mermaid2.render('newid', graphObj.code, div);
|
||||
mermaid.initialize(graphObj.mermaid);
|
||||
const { svg, bindFunctions } = await mermaid.render('newid', graphObj.code, div);
|
||||
div.innerHTML = svg;
|
||||
console.log(div.innerHTML);
|
||||
bindFunctions(div);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof document !== 'undefined') {
|
||||
mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
});
|
||||
/*!
|
||||
* 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>
|
||||
<head>
|
||||
<script src="./viewer.js" type="module"></script>
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
|
||||
<style>
|
||||
.malware {
|
||||
@ -33,12 +32,6 @@
|
||||
</script>
|
||||
</head>
|
||||
<body>
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
useMaxWidth: true,
|
||||
});
|
||||
</script>
|
||||
<script type="module" src="./viewer.js"></script>
|
||||
</body>
|
||||
</html>
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
@ -4,7 +4,7 @@
|
||||
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
|
||||
<link
|
||||
rel="stylesheet"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
|
||||
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user