mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-01-14 06:43:25 +08:00
Merge branch 'release/11.0.0'
This commit is contained in:
commit
b9f4faa916
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-layout-elk': {
|
||||
name: 'mermaid-layout-elk',
|
||||
packageName: 'mermaid-layout-elk',
|
||||
file: 'layouts.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` });
|
||||
}
|
@ -1,6 +1,7 @@
|
||||
import jison from 'jison';
|
||||
|
||||
export const transformJison = (src: string): string => {
|
||||
// @ts-ignore - Jison is not typed properly
|
||||
const parser = new jison.Generator(src, {
|
||||
moduleType: 'js',
|
||||
'token-stack': true,
|
124
.build/jsonSchema.ts
Normal file
124
.build/jsonSchema.ts
Normal file
@ -0,0 +1,124 @@
|
||||
import { load, JSON_SCHEMA } from 'js-yaml';
|
||||
import assert from 'node:assert';
|
||||
import Ajv2019, { type JSONSchemaType } from 'ajv/dist/2019.js';
|
||||
import type { MermaidConfig, BaseDiagramConfig } from '../packages/mermaid/src/config.type.js';
|
||||
|
||||
/**
|
||||
* All of the keys in the mermaid config that have a mermaid diagram config.
|
||||
*/
|
||||
const MERMAID_CONFIG_DIAGRAM_KEYS = [
|
||||
'flowchart',
|
||||
'sequence',
|
||||
'gantt',
|
||||
'journey',
|
||||
'class',
|
||||
'state',
|
||||
'er',
|
||||
'pie',
|
||||
'quadrantChart',
|
||||
'xyChart',
|
||||
'requirement',
|
||||
'mindmap',
|
||||
'timeline',
|
||||
'gitGraph',
|
||||
'c4',
|
||||
'sankey',
|
||||
'block',
|
||||
'packet',
|
||||
] as const;
|
||||
|
||||
/**
|
||||
* Generate default values from the JSON Schema.
|
||||
*
|
||||
* AJV does not support nested default values yet (or default values with $ref),
|
||||
* so we need to manually find them (this may be fixed in ajv v9).
|
||||
*
|
||||
* @param mermaidConfigSchema - The Mermaid JSON Schema to use.
|
||||
* @returns The default mermaid config object.
|
||||
*/
|
||||
function generateDefaults(mermaidConfigSchema: JSONSchemaType<MermaidConfig>) {
|
||||
const ajv = new Ajv2019({
|
||||
useDefaults: true,
|
||||
allowUnionTypes: true,
|
||||
strict: true,
|
||||
});
|
||||
|
||||
ajv.addKeyword({
|
||||
keyword: 'meta:enum', // used by jsonschema2md
|
||||
errors: false,
|
||||
});
|
||||
ajv.addKeyword({
|
||||
keyword: 'tsType', // used by json-schema-to-typescript
|
||||
errors: false,
|
||||
});
|
||||
|
||||
// ajv currently doesn't support nested default values, see https://github.com/ajv-validator/ajv/issues/1718
|
||||
// (may be fixed in v9) so we need to manually use sub-schemas
|
||||
const mermaidDefaultConfig = {};
|
||||
|
||||
assert.ok(mermaidConfigSchema.$defs);
|
||||
const baseDiagramConfig = mermaidConfigSchema.$defs.BaseDiagramConfig;
|
||||
|
||||
for (const key of MERMAID_CONFIG_DIAGRAM_KEYS) {
|
||||
const subSchemaRef = mermaidConfigSchema.properties[key].$ref;
|
||||
const [root, defs, defName] = subSchemaRef.split('/');
|
||||
assert.strictEqual(root, '#');
|
||||
assert.strictEqual(defs, '$defs');
|
||||
const subSchema = {
|
||||
$schema: mermaidConfigSchema.$schema,
|
||||
$defs: mermaidConfigSchema.$defs,
|
||||
...mermaidConfigSchema.$defs[defName],
|
||||
} as JSONSchemaType<BaseDiagramConfig>;
|
||||
|
||||
const validate = ajv.compile(subSchema);
|
||||
|
||||
mermaidDefaultConfig[key] = {};
|
||||
|
||||
for (const required of subSchema.required ?? []) {
|
||||
if (subSchema.properties[required] === undefined && baseDiagramConfig.properties[required]) {
|
||||
mermaidDefaultConfig[key][required] = baseDiagramConfig.properties[required].default;
|
||||
}
|
||||
}
|
||||
if (!validate(mermaidDefaultConfig[key])) {
|
||||
throw new Error(
|
||||
`schema for subconfig ${key} does not have valid defaults! Errors were ${JSON.stringify(
|
||||
validate.errors,
|
||||
undefined,
|
||||
2
|
||||
)}`
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
const validate = ajv.compile(mermaidConfigSchema);
|
||||
|
||||
if (!validate(mermaidDefaultConfig)) {
|
||||
throw new Error(
|
||||
`Mermaid config JSON Schema does not have valid defaults! Errors were ${JSON.stringify(
|
||||
validate.errors,
|
||||
undefined,
|
||||
2
|
||||
)}`
|
||||
);
|
||||
}
|
||||
|
||||
return mermaidDefaultConfig;
|
||||
}
|
||||
|
||||
export const loadSchema = (src: string, filename: string): JSONSchemaType<MermaidConfig> => {
|
||||
const jsonSchema = load(src, {
|
||||
filename,
|
||||
// only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
|
||||
// e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
|
||||
schema: JSON_SCHEMA,
|
||||
}) as JSONSchemaType<MermaidConfig>;
|
||||
return jsonSchema;
|
||||
};
|
||||
|
||||
export const getDefaults = (schema: JSONSchemaType<MermaidConfig>) => {
|
||||
return `export default ${JSON.stringify(generateDefaults(schema), undefined, 2)};`;
|
||||
};
|
||||
|
||||
export const getSchema = (schema: JSONSchemaType<MermaidConfig>) => {
|
||||
return `export default ${JSON.stringify(schema, undefined, 2)};`;
|
||||
};
|
25
.build/types.ts
Normal file
25
.build/types.ts
Normal file
@ -0,0 +1,25 @@
|
||||
/* eslint-disable no-console */
|
||||
import { packageOptions } from './common.js';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
const buildType = (packageName: string) => {
|
||||
console.log(`Building types for ${packageName}`);
|
||||
try {
|
||||
const out = execSync(`tsc -p ./packages/${packageName}/tsconfig.json --emitDeclarationOnly`);
|
||||
if (out.length > 0) {
|
||||
console.log(out.toString());
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
if (e.stdout.length > 0) {
|
||||
console.error(e.stdout.toString());
|
||||
}
|
||||
if (e.stderr.length > 0) {
|
||||
console.error(e.stderr.toString());
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
for (const { packageName } of Object.values(packageOptions)) {
|
||||
buildType(packageName);
|
||||
}
|
@ -1,3 +0,0 @@
|
||||
{
|
||||
"extends": ["@commitlint/config-conventional"]
|
||||
}
|
@ -13,6 +13,7 @@ bqstring
|
||||
BQUOTE
|
||||
bramp
|
||||
BRKT
|
||||
brotli
|
||||
callbackargs
|
||||
callbackname
|
||||
classdef
|
||||
@ -27,6 +28,7 @@ controly
|
||||
CSSCLASS
|
||||
CYLINDEREND
|
||||
CYLINDERSTART
|
||||
DAGA
|
||||
datakey
|
||||
DEND
|
||||
descr
|
||||
@ -53,6 +55,7 @@ GENERICTYPE
|
||||
getBoundarys
|
||||
grammr
|
||||
graphtype
|
||||
iife
|
||||
interp
|
||||
introdcued
|
||||
INVTRAPEND
|
||||
@ -74,11 +77,13 @@ loglevel
|
||||
LOGMSG
|
||||
lookaheads
|
||||
mdast
|
||||
metafile
|
||||
minlen
|
||||
Mstartx
|
||||
MULT
|
||||
NODIR
|
||||
NSTR
|
||||
outdir
|
||||
Qcontrolx
|
||||
reinit
|
||||
rels
|
||||
@ -86,6 +91,7 @@ reqs
|
||||
rewritelinks
|
||||
rgba
|
||||
RIGHTOF
|
||||
roughjs
|
||||
sankey
|
||||
sequencenumber
|
||||
shrc
|
||||
@ -105,13 +111,17 @@ strikethrough
|
||||
stringifying
|
||||
struct
|
||||
STYLECLASS
|
||||
STYLEDEF
|
||||
STYLEOPTS
|
||||
subcomponent
|
||||
subcomponents
|
||||
subconfig
|
||||
SUBROUTINEEND
|
||||
SUBROUTINESTART
|
||||
Subschemas
|
||||
substr
|
||||
SVGG
|
||||
SVGSVG
|
||||
TAGEND
|
||||
TAGSTART
|
||||
techn
|
||||
@ -122,6 +132,7 @@ titlevalue
|
||||
topbar
|
||||
TRAPEND
|
||||
TRAPSTART
|
||||
treemap
|
||||
ts-nocheck
|
||||
tsdoc
|
||||
typeof
|
||||
|
@ -4,5 +4,6 @@ cpettitt
|
||||
Dong Cai
|
||||
Nikolay Rozhkov
|
||||
Peng Xiao
|
||||
Per Brolin
|
||||
subhash-halder
|
||||
Vinod Sidharth
|
||||
|
@ -20,6 +20,7 @@ dagre-d3
|
||||
Deepdwn
|
||||
Docsify
|
||||
Docsy
|
||||
Doctave
|
||||
DokuWiki
|
||||
dompurify
|
||||
elkjs
|
||||
@ -54,7 +55,9 @@ presetAttributify
|
||||
pyplot
|
||||
redmine
|
||||
rehype
|
||||
roughjs
|
||||
rscratch
|
||||
shiki
|
||||
Slidev
|
||||
sparkline
|
||||
sphinxcontrib
|
||||
@ -62,6 +65,7 @@ ssim
|
||||
stylis
|
||||
Swimm
|
||||
tsbuildinfo
|
||||
tseslint
|
||||
Tuleap
|
||||
Typora
|
||||
unocss
|
||||
|
@ -9,6 +9,7 @@ elems
|
||||
gantt
|
||||
gitgraph
|
||||
gzipped
|
||||
handDrawn
|
||||
knsv
|
||||
Knut
|
||||
marginx
|
||||
@ -17,6 +18,7 @@ Markdownish
|
||||
mermaidjs
|
||||
mindmap
|
||||
mindmaps
|
||||
mrtree
|
||||
multigraph
|
||||
nodesep
|
||||
NOTEGROUP
|
||||
|
@ -1 +1,6 @@
|
||||
BRANDES
|
||||
circo
|
||||
handDrawn
|
||||
KOEPF
|
||||
neato
|
||||
newbranch
|
||||
|
67
.esbuild/build.ts
Normal file
67
.esbuild/build.ts
Normal file
@ -0,0 +1,67 @@
|
||||
import { build } from 'esbuild';
|
||||
import { mkdir, writeFile } from 'node:fs/promises';
|
||||
import { packageOptions } from '../.build/common.js';
|
||||
import { generateLangium } from '../.build/generateLangium.js';
|
||||
import type { MermaidBuildOptions } from './util.js';
|
||||
import { defaultOptions, getBuildConfig } from './util.js';
|
||||
|
||||
const shouldVisualize = process.argv.includes('--visualize');
|
||||
|
||||
const buildPackage = async (entryName: keyof typeof packageOptions) => {
|
||||
const commonOptions: MermaidBuildOptions = { ...defaultOptions, entryName } as const;
|
||||
const buildConfigs: MermaidBuildOptions[] = [
|
||||
// package.mjs
|
||||
{ ...commonOptions },
|
||||
// package.min.mjs
|
||||
{
|
||||
...commonOptions,
|
||||
minify: true,
|
||||
metafile: shouldVisualize,
|
||||
},
|
||||
// package.core.mjs
|
||||
{ ...commonOptions, core: true },
|
||||
];
|
||||
|
||||
if (entryName === 'mermaid') {
|
||||
const iifeOptions: MermaidBuildOptions = { ...commonOptions, format: 'iife' };
|
||||
buildConfigs.push(
|
||||
// mermaid.js
|
||||
{ ...iifeOptions },
|
||||
// mermaid.min.js
|
||||
{ ...iifeOptions, minify: true, metafile: shouldVisualize }
|
||||
);
|
||||
}
|
||||
|
||||
const results = await Promise.all(buildConfigs.map((option) => build(getBuildConfig(option))));
|
||||
|
||||
if (shouldVisualize) {
|
||||
for (const { metafile } of results) {
|
||||
if (!metafile?.outputs) {
|
||||
continue;
|
||||
}
|
||||
const fileName = Object.keys(metafile.outputs)
|
||||
.find((file) => !file.includes('chunks') && file.endsWith('js'))
|
||||
.replace('dist/', '');
|
||||
// Upload metafile into https://esbuild.github.io/analyze/
|
||||
await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile));
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const handler = (e) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
const main = async () => {
|
||||
await generateLangium();
|
||||
await mkdir('stats', { recursive: true });
|
||||
const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[];
|
||||
// it should build `parser` before `mermaid` because it's a dependency
|
||||
for (const pkg of packageNames) {
|
||||
await buildPackage(pkg).catch(handler);
|
||||
}
|
||||
};
|
||||
|
||||
void main();
|
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 type { Plugin } from 'esbuild';
|
||||
|
||||
export const jisonPlugin: Plugin = {
|
||||
name: 'jison',
|
||||
setup(build) {
|
||||
build.onLoad({ filter: /\.jison$/ }, async (args) => {
|
||||
// Load the file from the file system
|
||||
const source = await readFile(args.path, 'utf8');
|
||||
const contents = transformJison(source);
|
||||
return { contents, warnings: [] };
|
||||
});
|
||||
},
|
||||
};
|
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;
|
117
.esbuild/server.ts
Normal file
117
.esbuild/server.ts
Normal file
@ -0,0 +1,117 @@
|
||||
/* eslint-disable no-console */
|
||||
import chokidar from 'chokidar';
|
||||
import cors from 'cors';
|
||||
import { context } from 'esbuild';
|
||||
import type { Request, Response } from 'express';
|
||||
import express from 'express';
|
||||
import { packageOptions } from '../.build/common.js';
|
||||
import { generateLangium } from '../.build/generateLangium.js';
|
||||
import { defaultOptions, getBuildConfig } from './util.js';
|
||||
|
||||
const configs = Object.values(packageOptions).map(({ packageName }) =>
|
||||
getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: packageName })
|
||||
);
|
||||
const mermaidIIFEConfig = getBuildConfig({
|
||||
...defaultOptions,
|
||||
minify: false,
|
||||
core: false,
|
||||
entryName: 'mermaid',
|
||||
format: 'iife',
|
||||
});
|
||||
configs.push(mermaidIIFEConfig);
|
||||
|
||||
const contexts = await Promise.all(
|
||||
configs.map(async (config) => ({ config, context: await context(config) }))
|
||||
);
|
||||
|
||||
let rebuildCounter = 1;
|
||||
const rebuildAll = async () => {
|
||||
const buildNumber = rebuildCounter++;
|
||||
const timeLabel = `Rebuild ${buildNumber} Time (total)`;
|
||||
console.time(timeLabel);
|
||||
await Promise.all(
|
||||
contexts.map(async ({ config, context }) => {
|
||||
const buildVariant = `Rebuild ${buildNumber} Time (${Object.keys(config.entryPoints!)[0]} ${config.format})`;
|
||||
console.time(buildVariant);
|
||||
await context.rebuild();
|
||||
console.timeEnd(buildVariant);
|
||||
})
|
||||
).catch((e) => console.error(e));
|
||||
console.timeEnd(timeLabel);
|
||||
};
|
||||
|
||||
let clients: { id: number; response: Response }[] = [];
|
||||
function eventsHandler(request: Request, response: Response) {
|
||||
const headers = {
|
||||
'Content-Type': 'text/event-stream',
|
||||
Connection: 'keep-alive',
|
||||
'Cache-Control': 'no-cache',
|
||||
};
|
||||
response.writeHead(200, headers);
|
||||
const clientId = Date.now();
|
||||
clients.push({
|
||||
id: clientId,
|
||||
response,
|
||||
});
|
||||
request.on('close', () => {
|
||||
clients = clients.filter((client) => client.id !== clientId);
|
||||
});
|
||||
}
|
||||
|
||||
let timeoutID: NodeJS.Timeout | undefined = undefined;
|
||||
|
||||
/**
|
||||
* Debounce file change events to avoid rebuilding multiple times.
|
||||
*/
|
||||
function handleFileChange() {
|
||||
if (timeoutID !== undefined) {
|
||||
clearTimeout(timeoutID);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
timeoutID = setTimeout(async () => {
|
||||
await rebuildAll();
|
||||
sendEventsToAll();
|
||||
timeoutID = undefined;
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function sendEventsToAll() {
|
||||
clients.forEach(({ response }) => response.write(`data: ${Date.now()}\n\n`));
|
||||
}
|
||||
|
||||
async function createServer() {
|
||||
await generateLangium();
|
||||
handleFileChange();
|
||||
const app = express();
|
||||
chokidar
|
||||
.watch('**/src/**/*.{js,ts,langium,yaml,json}', {
|
||||
ignoreInitial: true,
|
||||
ignored: [/node_modules/, /dist/, /docs/, /coverage/],
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
.on('all', async (event, path) => {
|
||||
// Ignore other events.
|
||||
if (!['add', 'change'].includes(event)) {
|
||||
return;
|
||||
}
|
||||
console.log(`${path} changed. Rebuilding...`);
|
||||
if (path.endsWith('.langium')) {
|
||||
await generateLangium();
|
||||
}
|
||||
handleFileChange();
|
||||
});
|
||||
|
||||
app.use(cors());
|
||||
app.get('/events', eventsHandler);
|
||||
for (const { packageName } of Object.values(packageOptions)) {
|
||||
app.use(express.static(`./packages/${packageName}/dist`));
|
||||
}
|
||||
app.use(express.static('demos'));
|
||||
app.use(express.static('cypress/platform'));
|
||||
|
||||
app.listen(9000, () => {
|
||||
console.log(`Listening on http://localhost:9000`);
|
||||
});
|
||||
}
|
||||
|
||||
void createServer();
|
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 extends BuildOptions {
|
||||
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);
|
||||
const output: BuildOptions = buildOptions({
|
||||
absWorkingDir: resolve(__dirname, `../packages/${packageName}`),
|
||||
entryPoints: {
|
||||
[outFileName]: `src/${file}`,
|
||||
},
|
||||
metafile,
|
||||
minify,
|
||||
logLevel: 'info',
|
||||
chunkNames: `chunks/${outFileName}/[name]-[hash]`,
|
||||
define: {
|
||||
'import.meta.vitest': 'undefined',
|
||||
},
|
||||
});
|
||||
|
||||
if (core) {
|
||||
const { dependencies } = JSON.parse(
|
||||
readFileSync(resolve(__dirname, `../packages/${packageName}/package.json`), 'utf-8')
|
||||
);
|
||||
// Core build is used to generate file without bundled dependencies.
|
||||
// This is used by downstream projects to bundle dependencies themselves.
|
||||
// Ignore dependencies and any dependencies of dependencies
|
||||
external.push(...Object.keys(dependencies));
|
||||
output.external = external;
|
||||
}
|
||||
|
||||
if (format === 'iife') {
|
||||
output.format = 'iife';
|
||||
output.splitting = false;
|
||||
output.globalName = '__esbuild_esm_mermaid';
|
||||
// Workaround for removing the .default access in esbuild IIFE.
|
||||
// https://github.com/mermaid-js/mermaid/pull/4109#discussion_r1292317396
|
||||
output.footer = {
|
||||
js: 'globalThis.mermaid = globalThis.__esbuild_esm_mermaid.default;',
|
||||
};
|
||||
output.outExtension = { '.js': '.js' };
|
||||
} else {
|
||||
output.format = 'esm';
|
||||
output.splitting = true;
|
||||
output.outExtension = { '.js': '.mjs' };
|
||||
}
|
||||
|
||||
return output;
|
||||
};
|
@ -1,8 +0,0 @@
|
||||
dist/**
|
||||
.github/**
|
||||
docs/Setup.md
|
||||
cypress.config.js
|
||||
cypress/plugins/index.js
|
||||
coverage
|
||||
*.json
|
||||
node_modules
|
189
.eslintrc.cjs
189
.eslintrc.cjs
@ -1,189 +0,0 @@
|
||||
module.exports = {
|
||||
env: {
|
||||
browser: true,
|
||||
es6: true,
|
||||
'jest/globals': true,
|
||||
node: true,
|
||||
},
|
||||
root: true,
|
||||
parser: '@typescript-eslint/parser',
|
||||
parserOptions: {
|
||||
ecmaFeatures: {
|
||||
experimentalObjectRestSpread: true,
|
||||
jsx: true,
|
||||
},
|
||||
tsconfigRootDir: __dirname,
|
||||
sourceType: 'module',
|
||||
ecmaVersion: 2020,
|
||||
allowAutomaticSingleRunInference: true,
|
||||
project: ['./tsconfig.eslint.json', './packages/*/tsconfig.json'],
|
||||
parser: '@typescript-eslint/parser',
|
||||
},
|
||||
extends: [
|
||||
'eslint:recommended',
|
||||
'plugin:@typescript-eslint/recommended',
|
||||
'plugin:json/recommended',
|
||||
'plugin:markdown/recommended',
|
||||
'plugin:@cspell/recommended',
|
||||
'prettier',
|
||||
],
|
||||
plugins: [
|
||||
'@typescript-eslint',
|
||||
'no-only-tests',
|
||||
'html',
|
||||
'jest',
|
||||
'jsdoc',
|
||||
'json',
|
||||
'@cspell',
|
||||
'lodash',
|
||||
'unicorn',
|
||||
],
|
||||
ignorePatterns: [
|
||||
// this file is automatically generated by `pnpm run --filter mermaid types:build-config`
|
||||
'packages/mermaid/src/config.type.ts',
|
||||
],
|
||||
rules: {
|
||||
curly: 'error',
|
||||
'no-console': 'error',
|
||||
'no-prototype-builtins': 'off',
|
||||
'no-unused-vars': 'off',
|
||||
'cypress/no-async-tests': 'off',
|
||||
'@typescript-eslint/consistent-type-imports': 'error',
|
||||
'@typescript-eslint/no-explicit-any': 'warn',
|
||||
'@typescript-eslint/no-floating-promises': 'error',
|
||||
'@typescript-eslint/no-misused-promises': 'error',
|
||||
'@typescript-eslint/no-unused-vars': 'warn',
|
||||
'@typescript-eslint/ban-ts-comment': [
|
||||
'error',
|
||||
{
|
||||
'ts-expect-error': 'allow-with-description',
|
||||
'ts-ignore': 'allow-with-description',
|
||||
'ts-nocheck': 'allow-with-description',
|
||||
'ts-check': 'allow-with-description',
|
||||
minimumDescriptionLength: 10,
|
||||
},
|
||||
],
|
||||
'@typescript-eslint/naming-convention': [
|
||||
'error',
|
||||
{
|
||||
selector: 'typeLike',
|
||||
format: ['PascalCase'],
|
||||
custom: {
|
||||
regex: '^I[A-Z]',
|
||||
match: false,
|
||||
},
|
||||
},
|
||||
],
|
||||
'json/*': ['error', 'allowComments'],
|
||||
'@cspell/spellchecker': [
|
||||
'error',
|
||||
{
|
||||
checkIdentifiers: true,
|
||||
checkStrings: true,
|
||||
checkStringTemplates: true,
|
||||
},
|
||||
],
|
||||
'no-empty': [
|
||||
'error',
|
||||
{
|
||||
allowEmptyCatch: true,
|
||||
},
|
||||
],
|
||||
'no-only-tests/no-only-tests': 'error',
|
||||
'lodash/import-scope': ['error', 'method'],
|
||||
'unicorn/better-regex': 'error',
|
||||
'unicorn/no-abusive-eslint-disable': 'error',
|
||||
'unicorn/no-array-push-push': 'error',
|
||||
'unicorn/no-for-loop': 'error',
|
||||
'unicorn/no-instanceof-array': 'error',
|
||||
'unicorn/no-typeof-undefined': 'error',
|
||||
'unicorn/no-unnecessary-await': 'error',
|
||||
'unicorn/no-unsafe-regex': 'warn',
|
||||
'unicorn/no-useless-promise-resolve-reject': 'error',
|
||||
'unicorn/prefer-array-find': 'error',
|
||||
'unicorn/prefer-array-flat-map': 'error',
|
||||
'unicorn/prefer-array-index-of': 'error',
|
||||
'unicorn/prefer-array-some': 'error',
|
||||
'unicorn/prefer-default-parameters': 'error',
|
||||
'unicorn/prefer-includes': 'error',
|
||||
'unicorn/prefer-negative-index': 'error',
|
||||
'unicorn/prefer-object-from-entries': 'error',
|
||||
'unicorn/prefer-string-starts-ends-with': 'error',
|
||||
'unicorn/prefer-string-trim-start-end': 'error',
|
||||
'unicorn/string-content': 'error',
|
||||
'unicorn/prefer-spread': 'error',
|
||||
'unicorn/no-lonely-if': 'error',
|
||||
},
|
||||
overrides: [
|
||||
{
|
||||
files: ['cypress/**', 'demos/**'],
|
||||
rules: {
|
||||
'no-console': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.{js,jsx,mjs,cjs}'],
|
||||
extends: ['plugin:jsdoc/recommended'],
|
||||
rules: {
|
||||
'jsdoc/check-indentation': 'off',
|
||||
'jsdoc/check-alignment': 'off',
|
||||
'jsdoc/check-line-alignment': 'off',
|
||||
'jsdoc/multiline-blocks': 'off',
|
||||
'jsdoc/newline-after-description': 'off',
|
||||
'jsdoc/tag-lines': 'off',
|
||||
'jsdoc/require-param-description': 'off',
|
||||
'jsdoc/require-param-type': 'off',
|
||||
'jsdoc/require-returns': 'off',
|
||||
'jsdoc/require-returns-description': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.{ts,tsx}'],
|
||||
plugins: ['tsdoc'],
|
||||
rules: {
|
||||
'no-restricted-syntax': [
|
||||
'error',
|
||||
{
|
||||
selector: 'TSEnumDeclaration',
|
||||
message:
|
||||
'Prefer using TypeScript union types over TypeScript enum, since TypeScript enums have a bunch of issues, see https://dev.to/dvddpl/whats-the-problem-with-typescript-enums-2okj',
|
||||
},
|
||||
],
|
||||
'tsdoc/syntax': 'error',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.spec.{ts,js}', 'cypress/**', 'demos/**', '**/docs/**'],
|
||||
rules: {
|
||||
'jsdoc/require-jsdoc': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.spec.{ts,js}', 'tests/**', 'cypress/**/*.js'],
|
||||
rules: {
|
||||
'@cspell/spellchecker': [
|
||||
'error',
|
||||
{
|
||||
checkIdentifiers: false,
|
||||
checkStrings: false,
|
||||
checkStringTemplates: false,
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
files: ['*.html', '*.md', '**/*.md/*'],
|
||||
rules: {
|
||||
'no-var': 'error',
|
||||
'no-undef': 'off',
|
||||
'@typescript-eslint/no-unused-vars': 'off',
|
||||
'@typescript-eslint/no-floating-promises': 'off',
|
||||
'@typescript-eslint/no-misused-promises': 'off',
|
||||
},
|
||||
parserOptions: {
|
||||
project: null,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
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
|
||||
|
5
.github/lychee.toml
vendored
5
.github/lychee.toml
vendored
@ -41,7 +41,10 @@ exclude = [
|
||||
"https://bundlephobia.com",
|
||||
|
||||
# Chrome webstore migration issue. Temporary
|
||||
"https://chromewebstore.google.com"
|
||||
"https://chromewebstore.google.com",
|
||||
|
||||
# Drupal 403
|
||||
"https://(www.)?drupal.org"
|
||||
]
|
||||
|
||||
# Exclude all private IPs from checking.
|
||||
|
43
.github/workflows/autofix.yml
vendored
Normal file
43
.github/workflows/autofix.yml
vendored
Normal file
@ -0,0 +1,43 @@
|
||||
name: autofix.ci # needed to securely identify the workflow
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches-ignore:
|
||||
- 'renovate/**'
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
autofix:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v4
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
|
||||
- name: Install Packages
|
||||
run: |
|
||||
pnpm install --frozen-lockfile
|
||||
env:
|
||||
CYPRESS_CACHE_FOLDER: .cache/Cypress
|
||||
|
||||
- name: Fix Linting
|
||||
shell: bash
|
||||
run: pnpm -w run lint:fix
|
||||
|
||||
- name: Sync `./src/config.type.ts` with `./src/schemas/config.schema.yaml`
|
||||
shell: bash
|
||||
run: pnpm run --filter mermaid types:build-config
|
||||
|
||||
- name: Build Docs
|
||||
working-directory: ./packages/mermaid
|
||||
run: pnpm run docs:build
|
||||
|
||||
- uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c
|
2
.github/workflows/build-docs.yml
vendored
2
.github/workflows/build-docs.yml
vendored
@ -18,7 +18,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
|
6
.github/workflows/build.yml
vendored
6
.github/workflows/build.yml
vendored
@ -18,7 +18,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
@ -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
|
||||
|
2
.github/workflows/e2e-applitools.yml
vendored
2
.github/workflows/e2e-applitools.yml
vendored
@ -32,7 +32,7 @@ jobs:
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
|
127
.github/workflows/e2e.yml
vendored
127
.github/workflows/e2e.yml
vendored
@ -1,9 +1,3 @@
|
||||
# We use github cache to save snapshots between runs.
|
||||
# For PRs and MergeQueues, the target commit is used, and for push events, github.event.previous is used.
|
||||
# If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots.
|
||||
# These are then downloaded before running the E2E, providing the reference snapshots.
|
||||
# If there are any errors, the diff image is uploaded to artifacts, and the user is notified.
|
||||
|
||||
name: E2E
|
||||
|
||||
on:
|
||||
@ -17,9 +11,20 @@ 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
|
||||
}}
|
||||
shouldRunParallel: ${{ secrets.CYPRESS_RECORD_KEY != '' && !(github.event_name == 'push' && github.ref == 'refs/heads/develop') }}
|
||||
jobs:
|
||||
cache:
|
||||
runs-on: ubuntu-latest
|
||||
@ -28,7 +33,7 @@ jobs:
|
||||
options: --user 1001
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
@ -48,14 +53,19 @@ jobs:
|
||||
with:
|
||||
ref: ${{ env.targetHash }}
|
||||
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@v4
|
||||
id: cypress-snapshot-gen
|
||||
- name: Install dependencies
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
|
||||
uses: cypress-io/github-action@v6
|
||||
with:
|
||||
start: pnpm run dev
|
||||
wait-on: 'http://localhost:9000'
|
||||
browser: chrome
|
||||
# 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
|
||||
|
||||
e2e:
|
||||
runs-on: ubuntu-latest
|
||||
@ -70,7 +80,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
@ -81,34 +91,53 @@ 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 ) }}
|
||||
if: ${{ env.shouldRunParallel == 'true' || ( matrix.containers == 1 ) }}
|
||||
with:
|
||||
install: false
|
||||
start: pnpm run dev:coverage
|
||||
wait-on: 'http://localhost:9000'
|
||||
browser: chrome
|
||||
# Disable recording if we don't have an API key
|
||||
# e.g. if this action was run from a fork
|
||||
record: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
|
||||
parallel: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
|
||||
record: ${{ env.shouldRunParallel == 'true' }}
|
||||
parallel: ${{ env.shouldRunParallel == 'true' }}
|
||||
env:
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
VITEST_COVERAGE: true
|
||||
CYPRESS_COMMIT: ${{ github.sha }}
|
||||
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
|
||||
ARGOS_PARALLEL: ${{ env.shouldRunParallel == 'true' }}
|
||||
ARGOS_PARALLEL_TOTAL: 4
|
||||
ARGOS_PARALLEL_INDEX: ${{ matrix.containers }}
|
||||
|
||||
- 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:
|
||||
@ -118,55 +147,3 @@ jobs:
|
||||
fail_ci_if_error: false
|
||||
verbose: true
|
||||
token: 6845cc80-77ee-4e17-85a1-026cd95e0766
|
||||
|
||||
# We upload the artifacts into numbered archives to prevent overwriting
|
||||
- name: Upload Artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
if: ${{ always() }}
|
||||
with:
|
||||
name: snapshots-${{ matrix.containers }}
|
||||
retention-days: 1
|
||||
path: ./cypress/snapshots
|
||||
|
||||
combineArtifacts:
|
||||
needs: e2e
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ always() }}
|
||||
steps:
|
||||
# Download all snapshot artifacts and merge them into a single folder
|
||||
- name: Download All Artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
path: snapshots
|
||||
pattern: snapshots-*
|
||||
merge-multiple: true
|
||||
|
||||
# For successful push events, we save the snapshots cache
|
||||
- name: Save snapshots cache
|
||||
id: cache-upload
|
||||
if: ${{ github.event_name == 'push' && needs.e2e.result != 'failure' }}
|
||||
uses: actions/cache/save@v3
|
||||
with:
|
||||
path: ./snapshots
|
||||
key: ${{ runner.os }}-snapshots-${{ github.event.after }}
|
||||
|
||||
- name: Flatten images to a folder
|
||||
if: ${{ needs.e2e.result == 'failure' }}
|
||||
run: |
|
||||
mkdir errors
|
||||
cd snapshots
|
||||
find . -mindepth 2 -type d -name "*__diff_output__*" -exec sh -c 'mv "$0"/*.png ../errors/' {} \;
|
||||
|
||||
- name: Upload Error snapshots
|
||||
if: ${{ needs.e2e.result == 'failure' }}
|
||||
uses: actions/upload-artifact@v4
|
||||
id: upload-artifacts
|
||||
with:
|
||||
name: error-snapshots
|
||||
retention-days: 10
|
||||
path: errors/
|
||||
|
||||
- name: Notify Users
|
||||
if: ${{ needs.e2e.result == 'failure' }}
|
||||
run: |
|
||||
echo "::error title=Visual tests failed::You can view images that failed by downloading the error-snapshots artifact: ${{ steps.upload-artifacts.outputs.artifact-url }}"
|
||||
|
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 }}
|
||||
|
14
.github/workflows/lint.yml
vendored
14
.github/workflows/lint.yml
vendored
@ -19,7 +19,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
@ -82,15 +82,3 @@ jobs:
|
||||
working-directory: ./packages/mermaid
|
||||
continue-on-error: ${{ github.event_name == 'push' }}
|
||||
run: pnpm run docs:verify
|
||||
|
||||
- name: Rebuild Docs
|
||||
if: ${{ steps.verifyDocs.outcome == 'failure' && github.event_name == 'push' }}
|
||||
working-directory: ./packages/mermaid
|
||||
run: pnpm run docs:build
|
||||
|
||||
- name: Commit changes
|
||||
uses: EndBug/add-and-commit@v9
|
||||
if: ${{ steps.verifyDocs.outcome == 'failure' && github.event_name == 'push' }}
|
||||
with:
|
||||
message: 'Update docs'
|
||||
add: 'docs/*'
|
||||
|
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
|
||||
|
8
.github/workflows/publish-docs.yml
vendored
8
.github/workflows/publish-docs.yml
vendored
@ -25,7 +25,7 @@ jobs:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
@ -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
|
||||
|
3
.github/workflows/release-draft.yml
vendored
3
.github/workflows/release-draft.yml
vendored
@ -4,6 +4,7 @@ on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- release/**
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
@ -16,7 +17,7 @@ jobs:
|
||||
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:
|
||||
|
@ -13,7 +13,7 @@ jobs:
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
|
2
.github/workflows/release-publish.yml
vendored
2
.github/workflows/release-publish.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: fregante/setup-git-user@v2
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
|
4
.github/workflows/test.yml
vendored
4
.github/workflows/test.yml
vendored
@ -11,7 +11,7 @@ jobs:
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
@ -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:
|
||||
|
4
.github/workflows/update-browserlist.yml
vendored
4
.github/workflows/update-browserlist.yml
vendored
@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
- uses: pnpm/action-setup@v4
|
||||
- run: npx update-browserslist-db@latest
|
||||
- name: Commit changes
|
||||
uses: EndBug/add-and-commit@v9
|
||||
@ -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
|
||||
|
7
.gitignore
vendored
7
.gitignore
vendored
@ -35,7 +35,7 @@ cypress/snapshots/
|
||||
.tsbuildinfo
|
||||
tsconfig.tsbuildinfo
|
||||
|
||||
knsv*.html
|
||||
#knsv*.html
|
||||
local*.html
|
||||
stats/
|
||||
|
||||
@ -46,4 +46,9 @@ stats/
|
||||
|
||||
demos/dev/**
|
||||
!/demos/dev/example.html
|
||||
!/demos/dev/reload.js
|
||||
tsx-0/**
|
||||
vite.config.ts.timestamp-*
|
||||
|
||||
# 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
|
||||
|
@ -1 +1 @@
|
||||
v20.11.1
|
||||
20.12.2
|
||||
|
@ -11,6 +11,10 @@ stats
|
||||
.nyc_output
|
||||
# Autogenerated by `pnpm run --filter mermaid types:build-config`
|
||||
packages/mermaid/src/config.type.ts
|
||||
# autogenereated by langium-cli
|
||||
generated/
|
||||
# Ignore the files creates in /demos/dev except for example.html
|
||||
demos/dev/**
|
||||
!/demos/dev/example.html
|
||||
# TODO: Lots of errors to fix
|
||||
cypress/platform/state-refactor.html
|
||||
|
@ -3,5 +3,6 @@
|
||||
"printWidth": 100,
|
||||
"singleQuote": true,
|
||||
"useTabs": false,
|
||||
"tabWidth": 2
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
}
|
||||
|
@ -1,13 +1,15 @@
|
||||
import { build, InlineConfig, type PluginOption } from 'vite';
|
||||
import type { InlineConfig } from 'vite';
|
||||
import { build, type PluginOption } from 'vite';
|
||||
import { resolve } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import jisonPlugin from './jisonPlugin.js';
|
||||
import jsonSchemaPlugin from './jsonSchemaPlugin.js';
|
||||
import { readFileSync } from 'fs';
|
||||
import typescript from '@rollup/plugin-typescript';
|
||||
import { visualizer } from 'rollup-plugin-visualizer';
|
||||
import type { TemplateType } from 'rollup-plugin-visualizer/dist/plugin/template-types.js';
|
||||
import istanbul from 'vite-plugin-istanbul';
|
||||
import { packageOptions } from '../.build/common.js';
|
||||
import { generateLangium } from '../.build/generateLangium.js';
|
||||
|
||||
const visualize = process.argv.includes('--visualize');
|
||||
const watch = process.argv.includes('--watch');
|
||||
@ -36,24 +38,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;
|
||||
@ -63,43 +47,18 @@ interface BuildOptions {
|
||||
|
||||
export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions): InlineConfig => {
|
||||
const external: (string | RegExp)[] = ['require', 'fs', 'path'];
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(entryName, packageOptions[entryName]);
|
||||
const { name, file, packageName } = packageOptions[entryName];
|
||||
let output: OutputOptions = [
|
||||
const output: OutputOptions = [
|
||||
{
|
||||
name,
|
||||
format: 'esm',
|
||||
sourcemap,
|
||||
entryFileNames: `${name}.esm${minify ? '.min' : ''}.mjs`,
|
||||
},
|
||||
{
|
||||
name,
|
||||
format: 'umd',
|
||||
sourcemap,
|
||||
entryFileNames: `${name}${minify ? '.min' : ''}.js`,
|
||||
},
|
||||
];
|
||||
|
||||
if (core) {
|
||||
const { dependencies } = JSON.parse(
|
||||
readFileSync(resolve(__dirname, `../packages/${packageName}/package.json`), 'utf-8')
|
||||
);
|
||||
// Core build is used to generate file without bundled dependencies.
|
||||
// This is used by downstream projects to bundle dependencies themselves.
|
||||
// Ignore dependencies and any dependencies of dependencies
|
||||
// Adapted from the RegEx used by `rollup-plugin-node`
|
||||
external.push(new RegExp('^(?:' + Object.keys(dependencies).join('|') + ')(?:/.+)?$'));
|
||||
// This needs to be an array. Otherwise vite will build esm & umd with same name and overwrite esm with umd.
|
||||
output = [
|
||||
{
|
||||
name,
|
||||
format: 'esm',
|
||||
sourcemap,
|
||||
entryFileNames: `${name}.core.mjs`,
|
||||
},
|
||||
];
|
||||
}
|
||||
|
||||
const config: InlineConfig = {
|
||||
configFile: false,
|
||||
build: {
|
||||
@ -126,10 +85,9 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
|
||||
plugins: [
|
||||
jisonPlugin(),
|
||||
jsonSchemaPlugin(), // handles `.schema.yaml` files
|
||||
// @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite
|
||||
typescript({ compilerOptions: { declaration: false } }),
|
||||
istanbul({
|
||||
exclude: ['node_modules', 'test/', '__mocks__'],
|
||||
exclude: ['node_modules', 'test/', '__mocks__', 'generated'],
|
||||
extension: ['.js', '.ts'],
|
||||
requireEnv: true,
|
||||
forceBuildInstrument: coverage,
|
||||
@ -149,24 +107,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) {
|
||||
build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' }));
|
||||
await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' }));
|
||||
void 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' }));
|
||||
void build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' }));
|
||||
void 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,110 +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',
|
||||
] 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 type { PluginOption } from 'vite';
|
||||
import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js';
|
||||
|
||||
/**
|
||||
* Vite plugin that handles JSON Schemas saved as a `.schema.yaml` file.
|
||||
@ -121,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,16 +15,17 @@ 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'));
|
||||
|
||||
app.listen(9000, () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Listening on http://localhost:9000`);
|
||||
});
|
||||
}
|
||||
|
||||
createServer();
|
||||
void createServer();
|
||||
|
@ -1,2 +1,2 @@
|
||||
FROM node:20.11.1-alpine3.19 AS base
|
||||
FROM node:20.12.2-alpine3.19 AS base
|
||||
RUN wget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.shrc" SHELL="$(which sh)" sh -
|
||||
|
7
FUNDING.json
Normal file
7
FUNDING.json
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"drips": {
|
||||
"ethereum": {
|
||||
"ownedBy": "0x0831DDFe60d009d9448CC976157b539089aB821E"
|
||||
}
|
||||
}
|
||||
}
|
@ -35,6 +35,7 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai
|
||||
[![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid)
|
||||
[![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/AgrbSrBer3)
|
||||
[![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_)
|
||||
[![Covered by Argos Visual Testing](https://argos-ci.com/badge.svg)](https://argos-ci.com)
|
||||
|
||||
<img src="./img/header.png" alt="" />
|
||||
|
||||
|
@ -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,
|
||||
};
|
@ -2,6 +2,8 @@ import { defineConfig } from 'cypress';
|
||||
import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin';
|
||||
import coverage from '@cypress/code-coverage/task';
|
||||
import eyesPlugin from '@applitools/eyes-cypress';
|
||||
import { registerArgosTask } from '@argos-ci/cypress/task';
|
||||
|
||||
export default eyesPlugin(
|
||||
defineConfig({
|
||||
projectId: 'n2sma2',
|
||||
@ -17,10 +19,17 @@ export default eyesPlugin(
|
||||
}
|
||||
return launchOptions;
|
||||
});
|
||||
addMatchImageSnapshotPlugin(on, config);
|
||||
// copy any needed variables from process.env to config.env
|
||||
config.env.useAppli = process.env.USE_APPLI ? true : false;
|
||||
config.env.useArgos = !!process.env.CI;
|
||||
|
||||
if (config.env.useArgos) {
|
||||
registerArgosTask(on, config, {
|
||||
token: 'fc3a35cf5200db928d65b2047861582d9444032b',
|
||||
});
|
||||
} else {
|
||||
addMatchImageSnapshotPlugin(on, config);
|
||||
}
|
||||
// do not forget to return the changed config object!
|
||||
return config;
|
||||
},
|
||||
|
@ -35,7 +35,7 @@ export const mermaidUrl = (
|
||||
};
|
||||
const objStr: string = JSON.stringify(codeObject);
|
||||
let url = `http://localhost:9000/e2e.html?graph=${utf8ToB64(objStr)}`;
|
||||
if (api) {
|
||||
if (api && typeof graphStr === 'string') {
|
||||
url = `http://localhost:9000/xss.html?graph=${graphStr}`;
|
||||
}
|
||||
|
||||
@ -54,16 +54,15 @@ export const imgSnapshotTest = (
|
||||
): void => {
|
||||
const options: CypressMermaidConfig = {
|
||||
..._options,
|
||||
fontFamily: _options.fontFamily || 'courier',
|
||||
fontFamily: _options.fontFamily ?? 'courier',
|
||||
// @ts-ignore TODO: Fix type of fontSize
|
||||
fontSize: _options.fontSize || '16px',
|
||||
fontSize: _options.fontSize ?? '16px',
|
||||
sequence: {
|
||||
...(_options.sequence || {}),
|
||||
...(_options.sequence ?? {}),
|
||||
actorFontFamily: 'courier',
|
||||
noteFontFamily:
|
||||
_options.sequence && _options.sequence.noteFontFamily
|
||||
? _options.sequence.noteFontFamily
|
||||
: 'courier',
|
||||
noteFontFamily: _options.sequence?.noteFontFamily
|
||||
? _options.sequence.noteFontFamily
|
||||
: 'courier',
|
||||
messageFontFamily: 'courier',
|
||||
},
|
||||
};
|
||||
@ -95,18 +94,7 @@ export const openURLAndVerifyRendering = (
|
||||
options: CypressMermaidConfig,
|
||||
validation?: any
|
||||
): void => {
|
||||
const useAppli: boolean = Cypress.env('useAppli');
|
||||
const name: string = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
|
||||
|
||||
if (useAppli) {
|
||||
cy.log(`Opening eyes ${Cypress.spec.name} --- ${name}`);
|
||||
cy.eyesOpen({
|
||||
appName: 'Mermaid',
|
||||
testName: name,
|
||||
batchName: Cypress.spec.name,
|
||||
batchId: batchId + Cypress.spec.name,
|
||||
});
|
||||
}
|
||||
const name: string = (options.name ?? cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
|
||||
|
||||
cy.visit(url);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
@ -116,11 +104,29 @@ export const openURLAndVerifyRendering = (
|
||||
cy.get('svg').should(validation);
|
||||
}
|
||||
|
||||
verifyScreenshot(name);
|
||||
};
|
||||
|
||||
export const verifyScreenshot = (name: string): void => {
|
||||
const useAppli: boolean = Cypress.env('useAppli');
|
||||
const useArgos: boolean = Cypress.env('useArgos');
|
||||
|
||||
if (useAppli) {
|
||||
cy.log(`Opening eyes ${Cypress.spec.name} --- ${name}`);
|
||||
cy.eyesOpen({
|
||||
appName: 'Mermaid',
|
||||
testName: name,
|
||||
batchName: Cypress.spec.name,
|
||||
batchId: batchId + Cypress.spec.name,
|
||||
});
|
||||
cy.log(`Check eyes ${Cypress.spec.name}`);
|
||||
cy.eyesCheckWindow('Click!');
|
||||
cy.log(`Closing eyes ${Cypress.spec.name}`);
|
||||
cy.eyesClose();
|
||||
} else if (useArgos) {
|
||||
cy.argosScreenshot(name, {
|
||||
threshold: 0.01,
|
||||
});
|
||||
} else {
|
||||
cy.matchImageSnapshot(name);
|
||||
}
|
||||
|
@ -1,4 +1,4 @@
|
||||
import { renderGraph } from '../../helpers/util.ts';
|
||||
import { renderGraph, verifyScreenshot } from '../../helpers/util.ts';
|
||||
describe('Configuration', () => {
|
||||
describe('arrowMarkerAbsolute', () => {
|
||||
it('should handle default value false of arrowMarkerAbsolute', () => {
|
||||
@ -118,11 +118,52 @@ 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.matchImageSnapshot(
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
verifyScreenshot(
|
||||
'configuration.spec-should-not-taint-initial-configuration-when-using-multiple-directives'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('suppressErrorRendering', () => {
|
||||
beforeEach(() => {
|
||||
cy.on('uncaught:exception', (err, runnable) => {
|
||||
return !err.message.includes('Parse error on line');
|
||||
});
|
||||
});
|
||||
|
||||
it('should not render error diagram if suppressErrorRendering is set', () => {
|
||||
const url = 'http://localhost:9000/suppressError.html?suppressErrorRendering=true';
|
||||
cy.visit(url);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
cy.get('#test')
|
||||
.find('svg')
|
||||
.should(($svg) => {
|
||||
// all failing diagrams should not appear!
|
||||
expect($svg).to.have.length(2);
|
||||
// none of the diagrams should be error diagrams
|
||||
expect($svg).to.not.contain('Syntax error');
|
||||
});
|
||||
verifyScreenshot(
|
||||
'configuration.spec-should-not-render-error-diagram-if-suppressErrorRendering-is-set'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render error diagram if suppressErrorRendering is not set', () => {
|
||||
const url = 'http://localhost:9000/suppressError.html';
|
||||
cy.visit(url);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
cy.get('#test')
|
||||
.find('svg')
|
||||
.should(($svg) => {
|
||||
// all five diagrams should be rendered
|
||||
expect($svg).to.have.length(5);
|
||||
// some of the diagrams should be error diagrams
|
||||
expect($svg).to.contain('Syntax error');
|
||||
});
|
||||
verifyScreenshot(
|
||||
'configuration.spec-should-render-error-diagram-if-suppressErrorRendering-is-not-set'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
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>');
|
||||
});
|
||||
});
|
@ -10,7 +10,6 @@ describe('XSS', () => {
|
||||
cy.wait(1000).then(() => {
|
||||
cy.get('.mermaid').should('exist');
|
||||
});
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('should not allow tags in the css', () => {
|
||||
|
@ -11,6 +11,27 @@ describe('Git Graph diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('Should render subgraphs with title margins and edge labels', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart LR
|
||||
|
||||
subgraph TOP
|
||||
direction TB
|
||||
subgraph B1
|
||||
direction RL
|
||||
i1 --lb1-->f1
|
||||
end
|
||||
subgraph B2
|
||||
direction BT
|
||||
i2 --lb2-->f2
|
||||
end
|
||||
end
|
||||
A --lb3--> TOP --lb4--> B
|
||||
B1 --lb5--> B2
|
||||
`,
|
||||
{ flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } } }
|
||||
);
|
||||
});
|
||||
// it(`ultraFastTest`, function () {
|
||||
// // Navigate to the url we want to test
|
||||
// // ⭐️ Note to see visual bugs, run the test using the above URL for the 1st run.
|
||||
|
@ -236,7 +236,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL16: width alignment - blocks shold be equal in width', () => {
|
||||
it('BL17: width alignment - blocks shold be equal in width', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A("This is the text")
|
||||
@ -247,7 +247,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL17: block types 1 - square, rounded and circle', () => {
|
||||
it('BL18: block types 1 - square, rounded and circle', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A["square"]
|
||||
@ -258,7 +258,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL18: block types 2 - odd, diamond and hexagon', () => {
|
||||
it('BL19: block types 2 - odd, diamond and hexagon', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A>"rect_left_inv_arrow"]
|
||||
@ -269,7 +269,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL19: block types 3 - stadium', () => {
|
||||
it('BL20: block types 3 - stadium', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A(["stadium"])
|
||||
@ -278,7 +278,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL20: block types 4 - lean right, lean left, trapezoid and inv trapezoid', () => {
|
||||
it('BL21: block types 4 - lean right, lean left, trapezoid and inv trapezoid', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A[/"lean right"/]
|
||||
@ -290,7 +290,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL21: block types 1 - square, rounded and circle', () => {
|
||||
it('BL22: block types 1 - square, rounded and circle', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A["square"]
|
||||
@ -301,7 +301,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL22: sizing - it should be possible to make a block wider', () => {
|
||||
it('BL23: sizing - it should be possible to make a block wider', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A("rounded"):2
|
||||
@ -312,7 +312,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL23: sizing - it should be possible to make a composite block wider', () => {
|
||||
it('BL24: sizing - it should be possible to make a composite block wider', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
block:2
|
||||
@ -324,7 +324,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL24: block in the middle with space on each side', () => {
|
||||
it('BL25: block in the middle with space on each side', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 3
|
||||
@ -335,7 +335,7 @@ describe('Block diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('BL25: space and an edge', () => {
|
||||
it('BL26: space and an edge', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 5
|
||||
@ -345,7 +345,7 @@ describe('Block diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('BL26: block sizes for regular blocks', () => {
|
||||
it('BL27: block sizes for regular blocks', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 3
|
||||
@ -354,7 +354,7 @@ describe('Block diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('BL27: composite block with a set width - f should use the available space', () => {
|
||||
it('BL28: composite block with a set width - f should use the available space', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 3
|
||||
@ -363,11 +363,12 @@ describe('Block diagram', () => {
|
||||
f
|
||||
end
|
||||
g
|
||||
`,
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('BL23: composite block with a set width - f and g should split the available space', () => {
|
||||
|
||||
it('BL29: composite block with a set width - f and g should split the available space', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 3
|
||||
@ -379,7 +380,7 @@ describe('Block diagram', () => {
|
||||
h
|
||||
i
|
||||
j
|
||||
`,
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
@ -1,7 +1,7 @@
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('C4 diagram', () => {
|
||||
it('should render a simple C4Context diagram', () => {
|
||||
it('C4.1 should render a simple C4Context diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
C4Context
|
||||
@ -30,9 +30,8 @@ describe('C4 diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a simple C4Container diagram', () => {
|
||||
it('C4.2 should render a simple C4Container diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
C4Container
|
||||
@ -50,9 +49,8 @@ describe('C4 diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a simple C4Component diagram', () => {
|
||||
it('C4.3 should render a simple C4Component diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
C4Component
|
||||
@ -69,9 +67,8 @@ describe('C4 diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a simple C4Dynamic diagram', () => {
|
||||
it('C4.4 should render a simple C4Dynamic diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
C4Dynamic
|
||||
@ -93,9 +90,8 @@ describe('C4 diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a simple C4Deployment diagram', () => {
|
||||
it('C4.5 should render a simple C4Deployment diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
C4Deployment
|
||||
@ -117,6 +113,5 @@ describe('C4 diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
});
|
||||
|
@ -76,7 +76,7 @@ describe('Class diagram V2', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a simple class diagram with different visibilities', () => {
|
||||
it('2.1 should render a simple class diagram with different visibilities', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
classDiagram-v2
|
||||
@ -93,7 +93,7 @@ describe('Class diagram V2', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should render multiple class diagrams', () => {
|
||||
it('3: should render multiple class diagrams', () => {
|
||||
imgSnapshotTest(
|
||||
[
|
||||
`
|
||||
|
@ -32,7 +32,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{ logLevel: 1 }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('2: should render a simple class diagrams with cardinality', () => {
|
||||
@ -61,7 +60,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('3: should render a simple class diagram with different visibilities', () => {
|
||||
@ -79,7 +77,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('4: should render a simple class diagram with comments', () => {
|
||||
@ -109,7 +106,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('5: should render a simple class diagram with abstract method', () => {
|
||||
@ -121,7 +117,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('6: should render a simple class diagram with static method', () => {
|
||||
@ -133,7 +128,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('7: should render a simple class diagram with Generic class', () => {
|
||||
@ -153,7 +147,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('8: should render a simple class diagram with Generic class and relations', () => {
|
||||
@ -174,7 +167,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('9: should render a simple class diagram with clickable link', () => {
|
||||
@ -196,7 +188,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('10: should render a simple class diagram with clickable callback', () => {
|
||||
@ -218,7 +209,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('11: should render a simple class diagram with return type on method', () => {
|
||||
@ -233,7 +223,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('12: should render a simple class diagram with generic types', () => {
|
||||
@ -249,7 +238,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('13: should render a simple class diagram with css classes applied', () => {
|
||||
@ -267,7 +255,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('14: should render a simple class diagram with css classes applied directly', () => {
|
||||
@ -283,7 +270,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('15: should render a simple class diagram with css classes applied to multiple classes', () => {
|
||||
@ -298,7 +284,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('16: should render multiple class diagrams', () => {
|
||||
@ -351,7 +336,6 @@ describe('Class diagram', () => {
|
||||
],
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
// it('17: should render a class diagram when useMaxWidth is true (default)', () => {
|
||||
@ -421,7 +405,6 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{ logLevel: 1 }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('should render class diagram with newlines in title', () => {
|
||||
@ -439,7 +422,6 @@ describe('Class diagram', () => {
|
||||
+quack()
|
||||
}
|
||||
`);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('should render class diagram with many newlines in title', () => {
|
||||
|
@ -218,7 +218,6 @@ describe('Entity Relationship Diagram', () => {
|
||||
`,
|
||||
{ loglevel: 1 }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('should render entities with keys', () => {
|
||||
|
@ -3,7 +3,7 @@ import { imgSnapshotTest } from '../../helpers/util';
|
||||
describe('Error Diagrams', () => {
|
||||
beforeEach(() => {
|
||||
cy.on('uncaught:exception', (err) => {
|
||||
expect(err.message).to.include('Parse error');
|
||||
expect(err.message).to.include('error');
|
||||
// return false to prevent the error from
|
||||
// failing this test
|
||||
return false;
|
||||
|
@ -837,6 +837,26 @@ subgraph "\`**Two**\`"
|
||||
in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog")
|
||||
end
|
||||
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('Sub graphs and markdown strings', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
|
||||
flowchart LR
|
||||
subgraph subgraph_ko6czgs5u["Untitled subgraph"]
|
||||
D["Option 1"]
|
||||
end
|
||||
C{"Evaluate"} -- One --> D
|
||||
C -- Two --> E(("Option 2"))
|
||||
D --> E
|
||||
A["A"]
|
||||
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
@ -844,3 +864,41 @@ 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`,
|
||||
{ layout: '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`,
|
||||
{ layout: 'elk' }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const edges = svg[0].querySelectorAll('.edges path');
|
||||
expect(edges[0].getAttribute('class')).to.contain('edge-pattern-solid');
|
||||
expect(edges[1].getAttribute('class')).to.contain('edge-pattern-dotted');
|
||||
expect(edges[2].getAttribute('class')).to.contain('edge-thickness-thick');
|
||||
expect(edges[3].getAttribute('class')).to.contain('edge-thickness-invisible');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
1060
cypress/integration/rendering/flowchart-handDrawn.spec.js
Normal file
1060
cypress/integration/rendering/flowchart-handDrawn.spec.js
Normal file
File diff suppressed because it is too large
Load Diff
@ -99,7 +99,7 @@ describe('Flowchart v2', () => {
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
expect(maxWidthValue).to.be.within(290 * 0.95 - 1, 290 * 1.05);
|
||||
expect(maxWidthValue).to.be.within(446 * 0.95 - 1, 446 * 1.05);
|
||||
});
|
||||
});
|
||||
it('8: should render a flowchart when useMaxWidth is false', () => {
|
||||
@ -118,7 +118,7 @@ describe('Flowchart v2', () => {
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
expect(width).to.be.within(290 * 0.95 - 1, 290 * 1.05);
|
||||
expect(width).to.be.within(446 * 0.95 - 1, 446 * 1.05);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
@ -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)', () => {
|
||||
@ -990,7 +1047,9 @@ end
|
||||
A --lb3--> TOP --lb4--> B
|
||||
B1 --lb5--> B2
|
||||
`,
|
||||
{ flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } } }
|
||||
{
|
||||
flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } },
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -733,7 +733,7 @@ describe('Graph', () => {
|
||||
});
|
||||
it('38: should render a flowchart when useMaxWidth is true (default)', () => {
|
||||
renderGraph(
|
||||
`graph TD
|
||||
`flowchart TD
|
||||
A[Christmas] -->|Get money| B(Go shopping)
|
||||
B --> C{Let me think}
|
||||
C -->|One| D[Laptop]
|
||||
@ -751,7 +751,7 @@ describe('Graph', () => {
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
expect(maxWidthValue).to.be.within(300 * 0.9, 300 * 1.1);
|
||||
expect(maxWidthValue).to.be.within(446 * 0.9, 446 * 1.1);
|
||||
});
|
||||
});
|
||||
it('39: should render a flowchart when useMaxWidth is false', () => {
|
||||
@ -770,7 +770,7 @@ describe('Graph', () => {
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±10%
|
||||
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
expect(width).to.be.within(300 * 0.9, 300 * 1.1);
|
||||
expect(width).to.be.within(446 * 0.9, 446 * 1.1);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
@ -905,13 +905,16 @@ graph TD
|
||||
it('67: should be able to style default node independently', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
flowchart TD
|
||||
flowchart TD
|
||||
classDef default fill:#a34
|
||||
hello --> default
|
||||
|
||||
style default stroke:#000,stroke-width:4px
|
||||
`,
|
||||
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||
{
|
||||
flowchart: { htmlLabels: true },
|
||||
securityLevel: 'loose',
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -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,560 @@ 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 } }
|
||||
);
|
||||
});
|
||||
it('73: should render a simple gitgraph with three branches and tagged merge commit using switch instead of checkout', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph
|
||||
commit id: "1"
|
||||
commit id: "2"
|
||||
branch nice_feature
|
||||
switch nice_feature
|
||||
commit id: "3"
|
||||
switch main
|
||||
commit id: "4"
|
||||
switch nice_feature
|
||||
branch very_nice_feature
|
||||
switch very_nice_feature
|
||||
commit id: "5"
|
||||
switch main
|
||||
commit id: "6"
|
||||
switch nice_feature
|
||||
commit id: "7"
|
||||
switch main
|
||||
merge nice_feature id: "12345" tag: "my merge commit"
|
||||
switch very_nice_feature
|
||||
commit id: "8"
|
||||
switch main
|
||||
commit id: "9"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('74: should render commits for more than 8 branches using switch instead of checkout', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gitGraph
|
||||
switch main
|
||||
%% Make sure to manually set the ID of all commits, for consistent visual tests
|
||||
commit id: "1-abcdefg"
|
||||
switch main
|
||||
branch branch1
|
||||
commit id: "2-abcdefg"
|
||||
switch main
|
||||
merge branch1
|
||||
branch branch2
|
||||
commit id: "3-abcdefg"
|
||||
switch main
|
||||
merge branch2
|
||||
branch branch3
|
||||
commit id: "4-abcdefg"
|
||||
switch main
|
||||
merge branch3
|
||||
branch branch4
|
||||
commit id: "5-abcdefg"
|
||||
switch main
|
||||
merge branch4
|
||||
branch branch5
|
||||
commit id: "6-abcdefg"
|
||||
switch main
|
||||
merge branch5
|
||||
branch branch6
|
||||
commit id: "7-abcdefg"
|
||||
switch main
|
||||
merge branch6
|
||||
branch branch7
|
||||
commit id: "8-abcdefg"
|
||||
switch main
|
||||
merge branch7
|
||||
branch branch8
|
||||
commit id: "9-abcdefg"
|
||||
switch main
|
||||
merge branch8
|
||||
branch branch9
|
||||
commit id: "10-abcdefg"
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('75: should render a gitGraph with multiple tags on a merge commit on bottom-to-top orientation', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph BT:
|
||||
commit id: "ZERO"
|
||||
branch develop
|
||||
commit id:"A"
|
||||
checkout main
|
||||
commit id:"ONE"
|
||||
checkout develop
|
||||
commit id:"B"
|
||||
checkout main
|
||||
merge develop id:"Release 1.0" type:HIGHLIGHT tag: "SAML v2.0" tag: "OpenID v1.1"
|
||||
commit id:"TWO"
|
||||
checkout develop
|
||||
commit id:"C"`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
it('76: should render a gitGraph with multiple tags on a merge commit on left-to-right orientation', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph
|
||||
commit id: "ZERO"
|
||||
branch develop
|
||||
commit id:"A"
|
||||
checkout main
|
||||
commit id:"ONE"
|
||||
checkout develop
|
||||
commit id:"B"
|
||||
checkout main
|
||||
merge develop id:"Release 1.0" type:HIGHLIGHT tag: "SAML v2.0" tag: "OpenID v1.1"
|
||||
commit id:"TWO"
|
||||
checkout develop
|
||||
commit id:"C"`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
76
cypress/integration/rendering/packet.spec.ts
Normal file
76
cypress/integration/rendering/packet.spec.ts
Normal file
@ -0,0 +1,76 @@
|
||||
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 simple packet diagram without ranges', () => {
|
||||
imgSnapshotTest(
|
||||
`packet-beta
|
||||
0: "h"
|
||||
1: "i"
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
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"
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
@ -1,4 +1,4 @@
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe('Quadrant Chart', () => {
|
||||
it('should render if only chart type is provided', () => {
|
||||
@ -8,7 +8,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a complete quadrant chart', () => {
|
||||
imgSnapshotTest(
|
||||
@ -30,7 +29,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render without points', () => {
|
||||
imgSnapshotTest(
|
||||
@ -46,7 +44,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should able to render y-axix on right side', () => {
|
||||
imgSnapshotTest(
|
||||
@ -63,7 +60,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should able to render x-axix on bottom', () => {
|
||||
imgSnapshotTest(
|
||||
@ -80,7 +76,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should able to render x-axix on bottom and y-axis on right', () => {
|
||||
imgSnapshotTest(
|
||||
@ -97,7 +92,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render without title', () => {
|
||||
imgSnapshotTest(
|
||||
@ -112,7 +106,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should use all the config', () => {
|
||||
imgSnapshotTest(
|
||||
@ -135,7 +128,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should use all the theme variable', () => {
|
||||
imgSnapshotTest(
|
||||
@ -158,7 +150,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render x-axis labels in the center, if x-axis has two labels', () => {
|
||||
imgSnapshotTest(
|
||||
@ -180,7 +171,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render y-axis labels in the center, if y-axis has two labels', () => {
|
||||
imgSnapshotTest(
|
||||
@ -202,7 +192,6 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render both axes labels on the left and bottom, if both axes have only one label', () => {
|
||||
imgSnapshotTest(
|
||||
@ -224,6 +213,52 @@ describe('Quadrant Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('it should render data points with styles', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
quadrantChart
|
||||
title Reach and engagement of campaigns
|
||||
x-axis Reach -->
|
||||
y-axis Engagement -->
|
||||
quadrant-1 We should expand
|
||||
quadrant-2 Need to promote
|
||||
quadrant-3 Re-evaluate
|
||||
quadrant-4 May be improved
|
||||
Campaign A: [0.3, 0.6] radius: 20
|
||||
Campaign B: [0.45, 0.23] color: #ff0000
|
||||
Campaign C: [0.57, 0.69] stroke-color: #ff00ff
|
||||
Campaign D: [0.78, 0.34] stroke-width: 3px
|
||||
Campaign E: [0.40, 0.34] radius: 20, color: #ff0000 , stroke-color : #ff00ff, stroke-width : 3px
|
||||
Campaign F: [0.35, 0.78] stroke-width: 3px , color: #ff0000, radius: 20, stroke-color: #ff00ff
|
||||
Campaign G: [0.22, 0.22] stroke-width: 3px , color: #309708 , radius : 20 , stroke-color: #5060ff
|
||||
Campaign H: [0.22, 0.44]
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('it should render data points with styles + classes', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
quadrantChart
|
||||
title Reach and engagement of campaigns
|
||||
x-axis Reach -->
|
||||
y-axis Engagement -->
|
||||
quadrant-1 We should expand
|
||||
quadrant-2 Need to promote
|
||||
quadrant-3 Re-evaluate
|
||||
quadrant-4 May be improved
|
||||
Campaign A:::class1: [0.3, 0.6] radius: 20
|
||||
Campaign B: [0.45, 0.23] color: #ff0000
|
||||
Campaign C: [0.57, 0.69] stroke-color: #ff00ff
|
||||
Campaign D:::class2: [0.78, 0.34] stroke-width: 3px
|
||||
Campaign E:::class2: [0.40, 0.34] radius: 20, color: #ff0000, stroke-color: #ff00ff, stroke-width: 3px
|
||||
Campaign F:::class1: [0.35, 0.78]
|
||||
classDef class1 color: #908342, radius : 10, stroke-color: #310085, stroke-width: 10px
|
||||
classDef class2 color: #f00fff, radius : 10
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@ -44,6 +44,5 @@ describe('Requirement diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
});
|
||||
|
@ -1,8 +1,6 @@
|
||||
/// <reference types="Cypress" />
|
||||
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
context('Sequence diagram', () => {
|
||||
describe('Sequence diagram', () => {
|
||||
it('should render a sequence diagram with boxes', () => {
|
||||
renderGraph(
|
||||
`
|
||||
@ -68,6 +66,19 @@ context('Sequence diagram', () => {
|
||||
{ sequence: { actorFontFamily: 'courier' } }
|
||||
);
|
||||
});
|
||||
it('should render bidirectional arrows', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
Alice<<->>John: Hello John, how are you?
|
||||
Alice<<-->>John: Hi Alice, I can hear you!
|
||||
John<<->>Alice: This also works the other way
|
||||
John<<-->>Alice: Yes
|
||||
Alice->John: Test
|
||||
John->>Alice: Still works
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should handle different line breaks', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
@ -231,7 +242,7 @@ context('Sequence diagram', () => {
|
||||
`
|
||||
);
|
||||
});
|
||||
context('font settings', () => {
|
||||
describe('font settings', () => {
|
||||
it('should render different note fonts when configured', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
@ -328,7 +339,7 @@ context('Sequence diagram', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
context('auth width scaling', () => {
|
||||
describe('auth width scaling', () => {
|
||||
it('should render long actor descriptions', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
@ -375,7 +386,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 +405,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(
|
||||
@ -461,6 +475,18 @@ context('Sequence diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should render notes over actors and participant', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
actor Alice
|
||||
participant Charlie
|
||||
note over Alice: some note
|
||||
note over Charlie: other note
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should render long messages from an actor to the left to one to the right', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
@ -502,7 +528,7 @@ context('Sequence diagram', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
context('background rects', () => {
|
||||
describe('background rects', () => {
|
||||
it('should render a single and nested rects', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
@ -782,7 +808,7 @@ context('Sequence diagram', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
context('directives', () => {
|
||||
describe('directives', () => {
|
||||
it('should override config with directive settings', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
@ -807,11 +833,14 @@ 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' },
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
context('links', () => {
|
||||
describe('links', () => {
|
||||
it('should support actor links', () => {
|
||||
renderGraph(
|
||||
`
|
||||
@ -827,7 +856,7 @@ context('Sequence diagram', () => {
|
||||
);
|
||||
cy.get('#actor0_popup').should((popupMenu) => {
|
||||
const style = popupMenu.attr('style');
|
||||
expect(style).to.undefined;
|
||||
// expect(style).to.undefined;
|
||||
});
|
||||
cy.get('#root-0').click();
|
||||
cy.get('#actor0_popup').should((popupMenu) => {
|
||||
@ -858,7 +887,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', () => {
|
||||
@ -899,7 +931,7 @@ context('Sequence diagram', () => {
|
||||
);
|
||||
});
|
||||
});
|
||||
context('svg size', () => {
|
||||
describe('svg size', () => {
|
||||
it('should render a sequence diagram when useMaxWidth is true (default)', () => {
|
||||
renderGraph(
|
||||
`
|
||||
@ -978,7 +1010,7 @@ context('Sequence diagram', () => {
|
||||
});
|
||||
});
|
||||
});
|
||||
context('render after error', () => {
|
||||
describe('render after error', () => {
|
||||
it('should render diagram after fixing destroy participant error', () => {
|
||||
cy.on('uncaught:exception', (err) => {
|
||||
return false;
|
||||
|
@ -8,7 +8,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 1, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a simple state diagrams', () => {
|
||||
imgSnapshotTest(
|
||||
@ -20,7 +19,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a long descriptions instead of id when available', () => {
|
||||
imgSnapshotTest(
|
||||
@ -32,7 +30,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a long descriptions with additional descriptions', () => {
|
||||
imgSnapshotTest(
|
||||
@ -44,7 +41,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a single state with short descriptions', () => {
|
||||
imgSnapshotTest(
|
||||
@ -55,7 +51,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a transition descriptions with new lines', () => {
|
||||
imgSnapshotTest(
|
||||
@ -69,7 +64,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a state with a note', () => {
|
||||
imgSnapshotTest(
|
||||
@ -83,7 +77,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a state with on the left side when so specified', () => {
|
||||
imgSnapshotTest(
|
||||
@ -97,7 +90,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a state with a note together with another state', () => {
|
||||
imgSnapshotTest(
|
||||
@ -113,7 +105,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a note with multiple lines in it', () => {
|
||||
imgSnapshotTest(
|
||||
@ -156,7 +147,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a simple state diagrams 2', () => {
|
||||
imgSnapshotTest(
|
||||
@ -169,7 +159,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a simple state diagrams with labels', () => {
|
||||
imgSnapshotTest(
|
||||
@ -185,7 +174,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render state descriptions', () => {
|
||||
imgSnapshotTest(
|
||||
@ -198,7 +186,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render composite states', () => {
|
||||
imgSnapshotTest(
|
||||
@ -217,7 +204,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render multiple composite states', () => {
|
||||
imgSnapshotTest(
|
||||
@ -287,7 +273,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render concurrency states', () => {
|
||||
imgSnapshotTest(
|
||||
@ -311,7 +296,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('v2 should render a state with states in it', () => {
|
||||
imgSnapshotTest(
|
||||
@ -558,6 +542,43 @@ stateDiagram-v2
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
});
|
||||
it(' can have styles applied ', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
stateDiagram-v2
|
||||
AState
|
||||
style AState fill:#636,border:1px solid red,color:white;
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
});
|
||||
it(' should let styles take preceedence over classes', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
stateDiagram-v2
|
||||
AState: Should NOT be white
|
||||
BState
|
||||
classDef exampleStyleClass fill:#fff,color: blue;
|
||||
class AState,BState exampleStyleClass
|
||||
style AState fill:#636,border:1px solid red,color:white;
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
});
|
||||
it(' should allow styles to take effect in stubgraphs', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
stateDiagram
|
||||
state roundWithTitle {
|
||||
C: Black with white text
|
||||
}
|
||||
D: Black with white text
|
||||
|
||||
style C,D stroke:#00f, fill:black, color:white
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
});
|
||||
});
|
||||
it('1433: should render a simple state diagram with a title', () => {
|
||||
imgSnapshotTest(
|
||||
@ -567,6 +588,20 @@ title: simple state diagram
|
||||
stateDiagram-v2
|
||||
[*] --> State1
|
||||
State1 --> [*]
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should align dividers correctly', () => {
|
||||
imgSnapshotTest(
|
||||
`stateDiagram-v2
|
||||
state s2 {
|
||||
s3
|
||||
--
|
||||
s4
|
||||
--
|
||||
55
|
||||
}
|
||||
`,
|
||||
{}
|
||||
);
|
||||
|
@ -10,7 +10,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a long descriptions instead of id when available', () => {
|
||||
imgSnapshotTest(
|
||||
@ -22,7 +21,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a long descriptions with additional descriptions', () => {
|
||||
imgSnapshotTest(
|
||||
@ -34,7 +32,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a single state with short descriptions', () => {
|
||||
imgSnapshotTest(
|
||||
@ -45,7 +42,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a transition descriptions with new lines', () => {
|
||||
imgSnapshotTest(
|
||||
@ -59,7 +55,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a state with a note', () => {
|
||||
imgSnapshotTest(
|
||||
@ -73,7 +68,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a state with on the left side when so specified', () => {
|
||||
imgSnapshotTest(
|
||||
@ -87,7 +81,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a state with a note together with another state', () => {
|
||||
imgSnapshotTest(
|
||||
@ -103,7 +96,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a note with multiple lines in it', () => {
|
||||
imgSnapshotTest(
|
||||
@ -146,7 +138,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a simple state diagrams 2', () => {
|
||||
imgSnapshotTest(
|
||||
@ -159,7 +150,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a simple state diagrams with labels', () => {
|
||||
imgSnapshotTest(
|
||||
@ -175,7 +165,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render state descriptions', () => {
|
||||
imgSnapshotTest(
|
||||
@ -188,7 +177,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render composite states', () => {
|
||||
imgSnapshotTest(
|
||||
@ -207,7 +195,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render multiple composit states', () => {
|
||||
imgSnapshotTest(
|
||||
@ -277,7 +264,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render concurrency states', () => {
|
||||
imgSnapshotTest(
|
||||
@ -301,7 +287,6 @@ describe('State diagram', () => {
|
||||
`,
|
||||
{ logLevel: 0, fontFamily: 'courier' }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a state with states in it', () => {
|
||||
imgSnapshotTest(
|
||||
|
@ -10,7 +10,6 @@ describe('themeCSS balancing, it', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should not allow unbalanced CSS definitions 2', () => {
|
||||
imgSnapshotTest(
|
||||
@ -21,7 +20,6 @@ describe('themeCSS balancing, it', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
});
|
||||
|
||||
@ -45,7 +43,6 @@ describe('Pie Chart', () => {
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a flowchart diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@ -70,7 +67,6 @@ describe('Pie Chart', () => {
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a new flowchart diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@ -96,7 +92,6 @@ describe('Pie Chart', () => {
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a sequence diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@ -125,7 +120,6 @@ describe('Pie Chart', () => {
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('should render a class diagram', () => {
|
||||
@ -175,7 +169,6 @@ describe('Pie Chart', () => {
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a state diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@ -210,7 +203,6 @@ stateDiagram
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a state diagram (v2)', () => {
|
||||
imgSnapshotTest(
|
||||
@ -245,7 +237,6 @@ stateDiagram-v2
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a er diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@ -266,7 +257,6 @@ erDiagram
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a user journey diagram', () => {
|
||||
imgSnapshotTest(
|
||||
@ -287,7 +277,6 @@ erDiagram
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('should render a gantt diagram', () => {
|
||||
cy.clock(new Date('2014-01-06').getTime());
|
||||
@ -326,7 +315,6 @@ erDiagram
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -9,7 +9,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Should render a complete chart', () => {
|
||||
imgSnapshotTest(
|
||||
@ -35,7 +34,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('y-axis title not required', () => {
|
||||
imgSnapshotTest(
|
||||
@ -48,7 +46,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Should render a chart without y-axis with different range', () => {
|
||||
imgSnapshotTest(
|
||||
@ -60,7 +57,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('x axis title not required', () => {
|
||||
imgSnapshotTest(
|
||||
@ -72,7 +68,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Multiple plots can be rendered', () => {
|
||||
imgSnapshotTest(
|
||||
@ -87,7 +82,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Decimals and negative numbers are supported', () => {
|
||||
imgSnapshotTest(
|
||||
@ -98,7 +92,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Render spark line with "plotReservedSpacePercent"', () => {
|
||||
imgSnapshotTest(
|
||||
@ -116,7 +109,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Render spark bar without displaying other property', () => {
|
||||
imgSnapshotTest(
|
||||
@ -143,7 +135,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Should use all the config from directive', () => {
|
||||
imgSnapshotTest(
|
||||
@ -158,7 +149,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Should use all the config from yaml', () => {
|
||||
imgSnapshotTest(
|
||||
@ -199,7 +189,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Render with show axis title false', () => {
|
||||
imgSnapshotTest(
|
||||
@ -221,7 +210,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Render with show axis label false', () => {
|
||||
imgSnapshotTest(
|
||||
@ -243,7 +231,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Render with show axis tick false', () => {
|
||||
imgSnapshotTest(
|
||||
@ -265,7 +252,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Render with show axis line false', () => {
|
||||
imgSnapshotTest(
|
||||
@ -287,7 +273,6 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('Render all the theme color', () => {
|
||||
imgSnapshotTest(
|
||||
@ -317,6 +302,17 @@ describe('XY Chart', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should use the correct distances between data points', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
xychart-beta
|
||||
x-axis 0 --> 2
|
||||
line [0, 1, 0, 1]
|
||||
bar [1, 0, 1, 0]
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
});
|
||||
|
@ -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 {
|
||||
|
@ -27,7 +27,7 @@ const code3 = `flowchart TD
|
||||
A(<img scr='https://iconscout.com/ms-icon-310x310.png' width='20' height='20' />)
|
||||
B(<b>Bold text!</b>)`;
|
||||
|
||||
if (location.href.match('test-html-escaping')) {
|
||||
if (/test-html-escaping/.exec(location.href)) {
|
||||
code = code3;
|
||||
}
|
||||
|
||||
|
@ -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"
|
||||
|
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