mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-08-19 08:16:42 +02:00
Compare commits
10 Commits
4743-timel
...
sidv/runTi
Author | SHA1 | Date | |
---|---|---|---|
![]() |
b4be53ff04 | ||
![]() |
93dee55ade | ||
![]() |
781945325d | ||
![]() |
dc476233ba | ||
![]() |
eb6c92b0d9 | ||
![]() |
c6cf5953a1 | ||
![]() |
32db724752 | ||
![]() |
6702d41840 | ||
![]() |
441deaffc9 | ||
![]() |
af53a968f6 |
@@ -1,9 +1,3 @@
|
||||
export interface PackageOptions {
|
||||
name: string;
|
||||
packageName: string;
|
||||
file: string;
|
||||
}
|
||||
|
||||
/**
|
||||
* Shared common options for both ESBuild and Vite
|
||||
*/
|
||||
@@ -28,14 +22,9 @@ export const packageOptions = {
|
||||
packageName: 'mermaid-zenuml',
|
||||
file: 'detector.ts',
|
||||
},
|
||||
'mermaid-layout-elk': {
|
||||
name: 'mermaid-layout-elk',
|
||||
packageName: 'mermaid-layout-elk',
|
||||
file: 'layouts.ts',
|
||||
'mermaid-flowchart-elk': {
|
||||
name: 'mermaid-flowchart-elk',
|
||||
packageName: 'mermaid-flowchart-elk',
|
||||
file: 'detector.ts',
|
||||
},
|
||||
examples: {
|
||||
name: 'mermaid-examples',
|
||||
packageName: 'examples',
|
||||
file: 'index.ts',
|
||||
},
|
||||
} as const satisfies Record<string, PackageOptions>;
|
||||
} as const;
|
||||
|
@@ -1,7 +1,6 @@
|
||||
import jison from 'jison';
|
||||
|
||||
export const transformJison = (src: string): string => {
|
||||
// @ts-ignore - Jison is not typed properly
|
||||
const parser = new jison.Generator(src, {
|
||||
moduleType: 'js',
|
||||
'token-stack': true,
|
||||
|
@@ -19,15 +19,12 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [
|
||||
'xyChart',
|
||||
'requirement',
|
||||
'mindmap',
|
||||
'kanban',
|
||||
'timeline',
|
||||
'gitGraph',
|
||||
'c4',
|
||||
'sankey',
|
||||
'block',
|
||||
'packet',
|
||||
'architecture',
|
||||
'radar',
|
||||
] as const;
|
||||
|
||||
/**
|
||||
|
@@ -1,4 +1,3 @@
|
||||
/* eslint-disable no-console */
|
||||
import { packageOptions } from './common.js';
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
@@ -6,20 +5,11 @@ 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());
|
||||
}
|
||||
out.length > 0 && console.log(out.toString());
|
||||
} catch (e) {
|
||||
if (e.stdout.length > 0) {
|
||||
console.error(e.stdout.toString());
|
||||
}
|
||||
if (e.stderr.length > 0) {
|
||||
console.error(e.stderr.toString());
|
||||
}
|
||||
// Exit the build process if we are in CI
|
||||
if (process.env.CI) {
|
||||
throw new Error(`Failed to build types for ${packageName}`);
|
||||
}
|
||||
console.error(e);
|
||||
e.stdout.length > 0 && console.error(e.stdout.toString());
|
||||
e.stderr.length > 0 && console.error(e.stderr.toString());
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -1,8 +0,0 @@
|
||||
# Changesets
|
||||
|
||||
Hello and welcome! This folder has been automatically generated by `@changesets/cli`, a build tool that works
|
||||
with multi-package repos, or single-package repos to help you version and publish your code. You can
|
||||
find the full documentation for it [in our repository](https://github.com/changesets/changesets)
|
||||
|
||||
We have a quick list of common questions to get you started engaging with this project in
|
||||
[our documentation](https://github.com/changesets/changesets/blob/main/docs/common-questions.md)
|
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"$schema": "https://unpkg.com/@changesets/config@3.0.0/schema.json",
|
||||
"changelog": ["@changesets/changelog-github", { "repo": "mermaid-js/mermaid" }],
|
||||
"commit": false,
|
||||
"fixed": [],
|
||||
"linked": [],
|
||||
"access": "public",
|
||||
"baseBranch": "master",
|
||||
"updateInternalDependencies": "patch",
|
||||
"bumpVersionsWithWorkspaceProtocolOnly": true,
|
||||
"ignore": ["@mermaid-js/docs", "@mermaid-js/webpack-test", "@mermaid-js/mermaid-example-diagram"]
|
||||
}
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': minor
|
||||
---
|
||||
|
||||
feat: Add `getRegisteredDiagramsMetadata` to `mermaid`, which returns all the registered diagram IDs in mermaid
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': major
|
||||
---
|
||||
|
||||
Currently, HTML tags such as <em>, <strong>, <sup>, <a>, <ul>, and <li> are supported in Flowchart and Class diagram labels but not in Timeline diagrams. This change introduces support for basic HTML formatting in Timeline labels, enabling richer text formatting and better usability for multi-line content like descriptions, footnotes, and styled annotations
|
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'@mermaid-js/examples': minor
|
||||
---
|
||||
|
||||
feat: Add examples for diagrams in the `@mermaid-js/examples` package
|
@@ -1,7 +0,0 @@
|
||||
---
|
||||
'@mermaid-js/examples': patch
|
||||
'mermaid': patch
|
||||
'@mermaid-js/parser': patch
|
||||
---
|
||||
|
||||
chore: Move packet diagram out of beta
|
@@ -1,7 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix(timeline): fix loading `leftMargin` from config
|
||||
|
||||
The `timeline.leftMargin` config value should now correctly control the size of the left margin, instead of being ignored.
|
3
.commitlintrc.json
Normal file
3
.commitlintrc.json
Normal file
@@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": ["@commitlint/config-conventional"]
|
||||
}
|
@@ -13,7 +13,6 @@ bqstring
|
||||
BQUOTE
|
||||
bramp
|
||||
BRKT
|
||||
brotli
|
||||
callbackargs
|
||||
callbackname
|
||||
classdef
|
||||
@@ -26,10 +25,8 @@ concat
|
||||
controlx
|
||||
controly
|
||||
CSSCLASS
|
||||
curv
|
||||
CYLINDEREND
|
||||
CYLINDERSTART
|
||||
DAGA
|
||||
datakey
|
||||
DEND
|
||||
descr
|
||||
@@ -47,16 +44,15 @@ edgesep
|
||||
EMPTYSTR
|
||||
enddate
|
||||
ERDIAGRAM
|
||||
eslint
|
||||
flatmap
|
||||
forwardable
|
||||
frontmatter
|
||||
funs
|
||||
gantt
|
||||
GENERICTYPE
|
||||
getBoundarys
|
||||
grammr
|
||||
graphtype
|
||||
halign
|
||||
iife
|
||||
interp
|
||||
introdcued
|
||||
@@ -68,7 +64,6 @@ Kaufmann
|
||||
keyify
|
||||
LABELPOS
|
||||
LABELTYPE
|
||||
layoutstop
|
||||
lcov
|
||||
LEFTOF
|
||||
Lexa
|
||||
@@ -88,14 +83,13 @@ NODIR
|
||||
NSTR
|
||||
outdir
|
||||
Qcontrolx
|
||||
QSTR
|
||||
reinit
|
||||
rels
|
||||
reqs
|
||||
rewritelinks
|
||||
rgba
|
||||
runtimes
|
||||
RIGHTOF
|
||||
roughjs
|
||||
sankey
|
||||
sequencenumber
|
||||
shrc
|
||||
@@ -115,17 +109,13 @@ strikethrough
|
||||
stringifying
|
||||
struct
|
||||
STYLECLASS
|
||||
STYLEDEF
|
||||
STYLEOPTS
|
||||
subcomponent
|
||||
subcomponents
|
||||
subconfig
|
||||
SUBROUTINEEND
|
||||
SUBROUTINESTART
|
||||
Subschemas
|
||||
substr
|
||||
SVGG
|
||||
SVGSVG
|
||||
TAGEND
|
||||
TAGSTART
|
||||
techn
|
||||
@@ -136,13 +126,11 @@ titlevalue
|
||||
topbar
|
||||
TRAPEND
|
||||
TRAPSTART
|
||||
treemap
|
||||
ts-nocheck
|
||||
tsdoc
|
||||
typeof
|
||||
typestr
|
||||
unshift
|
||||
urlsafe
|
||||
verifymethod
|
||||
VERIFYMTHD
|
||||
WARN_DOCSDIR_DOESNT_MATCH
|
||||
|
@@ -2,10 +2,7 @@
|
||||
Ashish Jain
|
||||
cpettitt
|
||||
Dong Cai
|
||||
knsv
|
||||
Knut Sveidqvist
|
||||
Nikolay Rozhkov
|
||||
Peng Xiao
|
||||
Per Brolin
|
||||
Sidharth Vinod
|
||||
subhash-halder
|
||||
Vinod Sidharth
|
||||
|
@@ -28,9 +28,6 @@ dictionaryDefinitions:
|
||||
- name: suggestions
|
||||
words:
|
||||
- none
|
||||
- disp
|
||||
- subproc
|
||||
- tria
|
||||
suggestWords:
|
||||
- seperator:separator
|
||||
- vertice:vertex
|
||||
|
@@ -20,19 +20,14 @@ dagre-d3
|
||||
Deepdwn
|
||||
Docsify
|
||||
Docsy
|
||||
Doctave
|
||||
DokuWiki
|
||||
dompurify
|
||||
elkjs
|
||||
fcose
|
||||
fontawesome
|
||||
Fonticons
|
||||
Forgejo
|
||||
Foswiki
|
||||
Gitea
|
||||
graphlib
|
||||
Grav
|
||||
icones
|
||||
iconify
|
||||
Inkdrop
|
||||
jiti
|
||||
@@ -59,17 +54,13 @@ presetAttributify
|
||||
pyplot
|
||||
redmine
|
||||
rehype
|
||||
roughjs
|
||||
rscratch
|
||||
shiki
|
||||
Slidev
|
||||
sparkline
|
||||
sphinxcontrib
|
||||
ssim
|
||||
stylis
|
||||
Swimm
|
||||
tsbuildinfo
|
||||
tseslint
|
||||
Tuleap
|
||||
Typora
|
||||
unocss
|
||||
|
@@ -1,31 +1,26 @@
|
||||
Adamiecki
|
||||
arrowend
|
||||
Bendpoints
|
||||
bmatrix
|
||||
braintree
|
||||
catmull
|
||||
compositTitleSize
|
||||
curv
|
||||
doublecircle
|
||||
elems
|
||||
gantt
|
||||
gitgraph
|
||||
gzipped
|
||||
handDrawn
|
||||
kanban
|
||||
knsv
|
||||
Knut
|
||||
marginx
|
||||
marginy
|
||||
Markdownish
|
||||
mermaidchart
|
||||
mermaidjs
|
||||
mindmap
|
||||
mindmaps
|
||||
mrtree
|
||||
multigraph
|
||||
nodesep
|
||||
NOTEGROUP
|
||||
Pinterest
|
||||
procs
|
||||
rankdir
|
||||
ranksep
|
||||
rect
|
||||
@@ -34,6 +29,7 @@ sandboxed
|
||||
siebling
|
||||
statediagram
|
||||
substate
|
||||
Sveidqvist
|
||||
unfixable
|
||||
Viewbox
|
||||
viewports
|
||||
|
@@ -1,7 +1 @@
|
||||
BRANDES
|
||||
circo
|
||||
handDrawn
|
||||
KOEPF
|
||||
neato
|
||||
newbranch
|
||||
validify
|
||||
|
@@ -1,18 +1,14 @@
|
||||
import { build } from 'esbuild';
|
||||
import { cp, mkdir, readFile, rename, writeFile } from 'node:fs/promises';
|
||||
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';
|
||||
import { MermaidBuildOptions, defaultOptions, getBuildConfig } from './util.js';
|
||||
|
||||
const shouldVisualize = process.argv.includes('--visualize');
|
||||
|
||||
const buildPackage = async (entryName: keyof typeof packageOptions) => {
|
||||
const commonOptions: MermaidBuildOptions = {
|
||||
...defaultOptions,
|
||||
options: packageOptions[entryName],
|
||||
} as const;
|
||||
const buildConfigs: MermaidBuildOptions[] = [
|
||||
const commonOptions = { ...defaultOptions, entryName } as const;
|
||||
const buildConfigs = [
|
||||
// package.mjs
|
||||
{ ...commonOptions },
|
||||
// package.min.mjs
|
||||
@@ -31,27 +27,6 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => {
|
||||
// mermaid.js
|
||||
{ ...iifeOptions },
|
||||
// mermaid.min.js
|
||||
{ ...iifeOptions, minify: true, metafile: shouldVisualize },
|
||||
// mermaid.tiny.min.js
|
||||
{
|
||||
...iifeOptions,
|
||||
minify: true,
|
||||
includeLargeFeatures: false,
|
||||
metafile: shouldVisualize,
|
||||
sourcemap: false,
|
||||
}
|
||||
);
|
||||
}
|
||||
if (entryName === 'mermaid-zenuml') {
|
||||
const iifeOptions: MermaidBuildOptions = {
|
||||
...commonOptions,
|
||||
format: 'iife',
|
||||
globalName: 'mermaid-zenuml',
|
||||
};
|
||||
buildConfigs.push(
|
||||
// mermaid-zenuml.js
|
||||
{ ...iifeOptions },
|
||||
// mermaid-zenuml.min.js
|
||||
{ ...iifeOptions, minify: true, metafile: shouldVisualize }
|
||||
);
|
||||
}
|
||||
@@ -60,11 +35,11 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => {
|
||||
|
||||
if (shouldVisualize) {
|
||||
for (const { metafile } of results) {
|
||||
if (!metafile?.outputs) {
|
||||
if (!metafile) {
|
||||
continue;
|
||||
}
|
||||
const fileName = Object.keys(metafile.outputs)
|
||||
.find((file) => !file.includes('chunks') && file.endsWith('js'))!
|
||||
.filter((file) => !file.includes('chunks') && file.endsWith('js'))[0]
|
||||
.replace('dist/', '');
|
||||
// Upload metafile into https://esbuild.github.io/analyze/
|
||||
await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile));
|
||||
@@ -73,35 +48,18 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => {
|
||||
};
|
||||
|
||||
const handler = (e) => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error(e);
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
const buildTinyMermaid = async () => {
|
||||
await mkdir('./packages/tiny/dist', { recursive: true });
|
||||
await rename(
|
||||
'./packages/mermaid/dist/mermaid.tiny.min.js',
|
||||
'./packages/tiny/dist/mermaid.tiny.js'
|
||||
);
|
||||
// Copy version from mermaid's package.json to tiny's package.json
|
||||
const mermaidPkg = JSON.parse(await readFile('./packages/mermaid/package.json', 'utf8'));
|
||||
const tinyPkg = JSON.parse(await readFile('./packages/tiny/package.json', 'utf8'));
|
||||
tinyPkg.version = mermaidPkg.version;
|
||||
|
||||
await writeFile('./packages/tiny/package.json', JSON.stringify(tinyPkg, null, 2) + '\n');
|
||||
await cp('./packages/mermaid/CHANGELOG.md', './packages/tiny/CHANGELOG.md');
|
||||
};
|
||||
|
||||
const main = async () => {
|
||||
await generateLangium();
|
||||
await mkdir('stats', { recursive: true });
|
||||
await mkdir('stats').catch(() => {});
|
||||
const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[];
|
||||
// it should build `parser` before `mermaid` because it's a dependency
|
||||
for (const pkg of packageNames) {
|
||||
await buildPackage(pkg).catch(handler);
|
||||
}
|
||||
await buildTinyMermaid();
|
||||
};
|
||||
|
||||
void main();
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { readFile } from 'node:fs/promises';
|
||||
import { transformJison } from '../.build/jisonTransformer.js';
|
||||
import type { Plugin } from 'esbuild';
|
||||
import { Plugin } from 'esbuild';
|
||||
|
||||
export const jisonPlugin: Plugin = {
|
||||
name: 'jison',
|
||||
|
@@ -1,52 +1,34 @@
|
||||
/* 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 type { NextFunction, Request, Response } from 'express';
|
||||
import cors from 'cors';
|
||||
import { getBuildConfig, defaultOptions } from './util.js';
|
||||
import { context } from 'esbuild';
|
||||
import chokidar from 'chokidar';
|
||||
import { generateLangium } from '../.build/generateLangium.js';
|
||||
import { defaultOptions, getBuildConfig } from './util.js';
|
||||
import { packageOptions } from '../.build/common.js';
|
||||
|
||||
const configs = Object.values(packageOptions).map(({ packageName }) =>
|
||||
getBuildConfig({
|
||||
...defaultOptions,
|
||||
minify: false,
|
||||
core: false,
|
||||
options: packageOptions[packageName],
|
||||
})
|
||||
getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: packageName })
|
||||
);
|
||||
const mermaidIIFEConfig = getBuildConfig({
|
||||
...defaultOptions,
|
||||
minify: false,
|
||||
core: false,
|
||||
options: packageOptions.mermaid,
|
||||
entryName: 'mermaid',
|
||||
format: 'iife',
|
||||
});
|
||||
configs.push(mermaidIIFEConfig);
|
||||
|
||||
const contexts = await Promise.all(
|
||||
configs.map(async (config) => ({ config, context: await context(config) }))
|
||||
);
|
||||
const contexts = await Promise.all(configs.map((config) => 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);
|
||||
console.time('Rebuild time');
|
||||
await Promise.all(contexts.map((ctx) => ctx.rebuild())).catch((e) => console.error(e));
|
||||
console.timeEnd('Rebuild time');
|
||||
};
|
||||
|
||||
let clients: { id: number; response: Response }[] = [];
|
||||
function eventsHandler(request: Request, response: Response) {
|
||||
function eventsHandler(request: Request, response: Response, next: NextFunction) {
|
||||
const headers = {
|
||||
'Content-Type': 'text/event-stream',
|
||||
Connection: 'keep-alive',
|
||||
@@ -63,20 +45,19 @@ function eventsHandler(request: Request, response: Response) {
|
||||
});
|
||||
}
|
||||
|
||||
let timeoutID: NodeJS.Timeout | undefined = undefined;
|
||||
let timeoutId: NodeJS.Timeout | undefined = undefined;
|
||||
|
||||
/**
|
||||
* Debounce file change events to avoid rebuilding multiple times.
|
||||
*/
|
||||
function handleFileChange() {
|
||||
if (timeoutID !== undefined) {
|
||||
clearTimeout(timeoutID);
|
||||
if (timeoutId !== undefined) {
|
||||
clearTimeout(timeoutId);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
timeoutID = setTimeout(async () => {
|
||||
timeoutId = setTimeout(async () => {
|
||||
await rebuildAll();
|
||||
sendEventsToAll();
|
||||
timeoutID = undefined;
|
||||
timeoutId = undefined;
|
||||
}, 100);
|
||||
}
|
||||
|
||||
@@ -93,16 +74,15 @@ async function createServer() {
|
||||
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')) {
|
||||
if (/\.langium$/.test(path)) {
|
||||
await generateLangium();
|
||||
}
|
||||
console.log(`${path} changed. Rebuilding...`);
|
||||
handleFileChange();
|
||||
});
|
||||
|
||||
@@ -119,4 +99,4 @@ async function createServer() {
|
||||
});
|
||||
}
|
||||
|
||||
void createServer();
|
||||
createServer();
|
||||
|
@@ -3,26 +3,24 @@ import { fileURLToPath } from 'url';
|
||||
import type { BuildOptions } from 'esbuild';
|
||||
import { readFileSync } from 'fs';
|
||||
import jsonSchemaPlugin from './jsonSchemaPlugin.js';
|
||||
import type { PackageOptions } from '../.build/common.js';
|
||||
import { packageOptions } from '../.build/common.js';
|
||||
import { jisonPlugin } from './jisonPlugin.js';
|
||||
|
||||
const __dirname = fileURLToPath(new URL('.', import.meta.url));
|
||||
|
||||
export interface MermaidBuildOptions extends BuildOptions {
|
||||
export interface MermaidBuildOptions {
|
||||
minify: boolean;
|
||||
core: boolean;
|
||||
metafile: boolean;
|
||||
format: 'esm' | 'iife';
|
||||
options: PackageOptions;
|
||||
includeLargeFeatures: boolean;
|
||||
entryName: keyof typeof packageOptions;
|
||||
}
|
||||
|
||||
export const defaultOptions: Omit<MermaidBuildOptions, 'entryName' | 'options'> = {
|
||||
export const defaultOptions: Omit<MermaidBuildOptions, 'entryName'> = {
|
||||
minify: false,
|
||||
metafile: false,
|
||||
core: false,
|
||||
format: 'esm',
|
||||
includeLargeFeatures: true,
|
||||
} as const;
|
||||
|
||||
const buildOptions = (override: BuildOptions): BuildOptions => {
|
||||
@@ -41,18 +39,12 @@ const buildOptions = (override: BuildOptions): BuildOptions => {
|
||||
};
|
||||
};
|
||||
|
||||
const getFileName = (
|
||||
fileName: string,
|
||||
{ core, format, minify, includeLargeFeatures }: MermaidBuildOptions
|
||||
) => {
|
||||
const getFileName = (fileName: string, { core, format, minify }: MermaidBuildOptions) => {
|
||||
if (core) {
|
||||
fileName += '.core';
|
||||
} else if (format === 'esm') {
|
||||
fileName += '.esm';
|
||||
}
|
||||
if (!includeLargeFeatures) {
|
||||
fileName += '.tiny';
|
||||
}
|
||||
if (minify) {
|
||||
fileName += '.min';
|
||||
}
|
||||
@@ -60,29 +52,20 @@ const getFileName = (
|
||||
};
|
||||
|
||||
export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
|
||||
const {
|
||||
core,
|
||||
format,
|
||||
options: { name, file, packageName },
|
||||
globalName = 'mermaid',
|
||||
includeLargeFeatures,
|
||||
...rest
|
||||
} = options;
|
||||
|
||||
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({
|
||||
...rest,
|
||||
let output: BuildOptions = buildOptions({
|
||||
absWorkingDir: resolve(__dirname, `../packages/${packageName}`),
|
||||
entryPoints: {
|
||||
[outFileName]: `src/${file}`,
|
||||
},
|
||||
globalName,
|
||||
metafile,
|
||||
minify,
|
||||
logLevel: 'info',
|
||||
chunkNames: `chunks/${outFileName}/[name]-[hash]`,
|
||||
define: {
|
||||
// This needs to be stringified for esbuild
|
||||
includeLargeFeatures: `${includeLargeFeatures}`,
|
||||
'import.meta.vitest': 'undefined',
|
||||
},
|
||||
});
|
||||
@@ -101,12 +84,11 @@ export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
|
||||
if (format === 'iife') {
|
||||
output.format = 'iife';
|
||||
output.splitting = false;
|
||||
const originalGlobalName = output.globalName ?? 'mermaid';
|
||||
output.globalName = `__esbuild_esm_mermaid_nm[${JSON.stringify(originalGlobalName)}]`;
|
||||
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[${JSON.stringify(originalGlobalName)}] = globalThis.${output.globalName}.default;`,
|
||||
js: 'globalThis.mermaid = globalThis.__esbuild_esm_mermaid.default;',
|
||||
};
|
||||
output.outExtension = { '.js': '.js' };
|
||||
} else {
|
||||
|
11
.eslintignore
Normal file
11
.eslintignore
Normal file
@@ -0,0 +1,11 @@
|
||||
dist/**
|
||||
.github/**
|
||||
docs/Setup.md
|
||||
cypress.config.js
|
||||
cypress/plugins/index.js
|
||||
coverage
|
||||
*.json
|
||||
node_modules
|
||||
|
||||
# autogenereated by langium-cli
|
||||
generated/
|
189
.eslintrc.cjs
Normal file
189
.eslintrc.cjs
Normal file
@@ -0,0 +1,189 @@
|
||||
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,
|
||||
},
|
||||
},
|
||||
],
|
||||
};
|
2
.github/ISSUE_TEMPLATE/config.yml
vendored
2
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -4,7 +4,7 @@ contact_links:
|
||||
url: https://github.com/mermaid-js/mermaid/discussions
|
||||
about: Ask the Community questions or share your own graphs in our discussions.
|
||||
- name: Discord
|
||||
url: https://discord.gg/sKeNQX4Wtj
|
||||
url: https://discord.gg/AgrbSrBer3
|
||||
about: Join our Community on Discord for Help and a casual chat.
|
||||
- name: Documentation
|
||||
url: https://mermaid.js.org
|
||||
|
2
.github/ISSUE_TEMPLATE/theme_proposal.yml
vendored
2
.github/ISSUE_TEMPLATE/theme_proposal.yml
vendored
@@ -29,7 +29,7 @@ body:
|
||||
label: Colors
|
||||
description: |-
|
||||
A detailed list of the different colour values to use.
|
||||
See the [list of currently used variable names](https://mermaid-js.github.io/mermaid/#/theming?id=theme-variables-reference-table)
|
||||
A list of currently used variable names can be found [here](https://mermaid-js.github.io/mermaid/#/theming?id=theme-variables-reference-table)
|
||||
placeholder: |-
|
||||
- background: #f4f4f4
|
||||
- primaryColor: #fff4dd
|
||||
|
19
.github/lychee.toml
vendored
19
.github/lychee.toml
vendored
@@ -40,23 +40,8 @@ exclude = [
|
||||
# BundlePhobia has frequent downtime
|
||||
"https://bundlephobia.com",
|
||||
|
||||
# Chrome webstore migration issue. Temporary
|
||||
"https://chromewebstore.google.com",
|
||||
|
||||
# Drupal 403
|
||||
"https://(www.)?drupal.org",
|
||||
|
||||
# Phbpp 403
|
||||
"https://(www.)?phpbb.com",
|
||||
|
||||
# Swimm returns 404, even though the link is valid
|
||||
"https://docs.swimm.io",
|
||||
|
||||
# Timeout
|
||||
"https://huehive.co",
|
||||
"https://foswiki.org",
|
||||
"https://www.gnu.org",
|
||||
"https://mermaid-preview.com"
|
||||
# Chrome webstore redirect issue
|
||||
"https://chromewebstore.google.com"
|
||||
]
|
||||
|
||||
# Exclude all private IPs from checking.
|
||||
|
2
.github/pull_request_template.md
vendored
2
.github/pull_request_template.md
vendored
@@ -15,4 +15,4 @@ Make sure you
|
||||
- [ ] :book: have read the [contribution guidelines](https://mermaid.js.org/community/contributing.html)
|
||||
- [ ] :computer: have added necessary unit/e2e tests.
|
||||
- [ ] :notebook: have added documentation. Make sure [`MERMAID_RELEASE_VERSION`](https://mermaid.js.org/community/contributing.html#update-documentation) is used for all new features.
|
||||
- [ ] :butterfly: If your PR makes a change that should be noted in one or more packages' changelogs, generate a changeset by running `pnpm changeset` and following the prompts. Changesets that add features should be `minor` and those that fix bugs should be `patch`. Please prefix changeset messages with `feat:`, `fix:`, or `chore:`.
|
||||
- [ ] :bookmark: targeted `develop` branch
|
||||
|
36
.github/release-drafter.yml
vendored
Normal file
36
.github/release-drafter.yml
vendored
Normal file
@@ -0,0 +1,36 @@
|
||||
name-template: '$NEXT_PATCH_VERSION'
|
||||
tag-template: '$NEXT_PATCH_VERSION'
|
||||
categories:
|
||||
- title: '🚨 **Breaking Changes**'
|
||||
labels:
|
||||
- 'Breaking Change'
|
||||
- title: '🚀 Features'
|
||||
labels:
|
||||
- 'Type: Enhancement'
|
||||
- 'feature' # deprecated, new PRs shouldn't have this
|
||||
- title: '🐛 Bug Fixes'
|
||||
labels:
|
||||
- 'Type: Bug / Error'
|
||||
- 'fix' # deprecated, new PRs shouldn't have this
|
||||
- title: '🧰 Maintenance'
|
||||
labels:
|
||||
- 'Type: Other'
|
||||
- 'chore' # deprecated, new PRs shouldn't have this
|
||||
- title: '⚡️ Performance'
|
||||
labels:
|
||||
- 'Type: Performance'
|
||||
- title: '📚 Documentation'
|
||||
labels:
|
||||
- 'Area: Documentation'
|
||||
change-template: '- $TITLE (#$NUMBER) @$AUTHOR'
|
||||
sort-by: title
|
||||
sort-direction: ascending
|
||||
exclude-labels:
|
||||
- 'Skip changelog'
|
||||
no-changes-template: 'This release contains minor changes and bugfixes.'
|
||||
template: |
|
||||
# Release Notes
|
||||
|
||||
$CHANGES
|
||||
|
||||
🎉 **Thanks to all contributors helping with this release!** 🎉
|
2
.github/stale.yml
vendored
2
.github/stale.yml
vendored
@@ -15,5 +15,5 @@ markComment: >
|
||||
If you are still interested in this issue and it is still relevant you can comment to revive it.
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: >
|
||||
This issue has been automatically closed due to a lack of activity.
|
||||
This issue has been been automatically closed due to a lack of activity.
|
||||
This is done to maintain a clean list of issues that the community is interested in developing.
|
||||
|
45
.github/workflows/autofix.yml
vendored
45
.github/workflows/autofix.yml
vendored
@@ -1,45 +0,0 @@
|
||||
name: autofix.ci # needed to securely identify the workflow
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches-ignore:
|
||||
- 'renovate/**'
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
jobs:
|
||||
autofix:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
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@551dded8c6cc8a1054039c8bc0b8b48c51dfc6ef # main
|
8
.github/workflows/build-docs.yml
vendored
8
.github/workflows/build-docs.yml
vendored
@@ -8,8 +8,6 @@ on:
|
||||
pull_request:
|
||||
merge_group:
|
||||
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@@ -18,12 +16,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- uses: pnpm/action-setup@v2
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
|
49
.github/workflows/build.yml
vendored
Normal file
49
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,49 @@
|
||||
name: Build
|
||||
|
||||
on:
|
||||
push: {}
|
||||
merge_group:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- ready_for_review
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
build-mermaid:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
# 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: Run Build
|
||||
run: pnpm run build
|
||||
|
||||
- name: Upload Mermaid Build as Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mermaid-build
|
||||
path: packages/mermaid/dist
|
||||
|
||||
- name: Upload Mermaid Mindmap Build as Artifact
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: mermaid-mindmap-build
|
||||
path: packages/mermaid-mindmap/dist
|
2
.github/workflows/check-readme-in-sync.yml
vendored
2
.github/workflows/check-readme-in-sync.yml
vendored
@@ -18,7 +18,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Check for difference in README.md and docs/README.md
|
||||
run: |
|
||||
|
26
.github/workflows/checks.yml
vendored
Normal file
26
.github/workflows/checks.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
||||
on:
|
||||
push:
|
||||
merge_group:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- ready_for_review
|
||||
|
||||
name: Static analysis on Test files
|
||||
|
||||
jobs:
|
||||
check-tests:
|
||||
runs-on: ubuntu-latest
|
||||
name: check tests
|
||||
if: github.repository_owner == 'mermaid-js'
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- uses: testomatio/check-tests@stable
|
||||
with:
|
||||
framework: cypress
|
||||
tests: './cypress/e2e/**/**.spec.js'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
has-tests-label: true
|
11
.github/workflows/codeql.yml
vendored
11
.github/workflows/codeql.yml
vendored
@@ -11,9 +11,6 @@ on:
|
||||
- synchronize
|
||||
- ready_for_review
|
||||
|
||||
permissions: # added using https://github.com/step-security/secure-repo
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
analyze:
|
||||
name: Analyze
|
||||
@@ -32,11 +29,11 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
uses: github/codeql-action/init@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
uses: github/codeql-action/init@v2
|
||||
with:
|
||||
config-file: ./.github/codeql/codeql-config.yml
|
||||
languages: ${{ matrix.language }}
|
||||
@@ -48,7 +45,7 @@ jobs:
|
||||
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
|
||||
# If this step fails, then you should remove it and run the build manually (see below)
|
||||
- name: Autobuild
|
||||
uses: github/codeql-action/autobuild@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
uses: github/codeql-action/autobuild@v2
|
||||
|
||||
# ℹ️ Command-line programs to run using the OS shell.
|
||||
# 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
|
||||
@@ -62,4 +59,4 @@ jobs:
|
||||
# make release
|
||||
|
||||
- name: Perform CodeQL Analysis
|
||||
uses: github/codeql-action/analyze@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
uses: github/codeql-action/analyze@v2
|
||||
|
4
.github/workflows/dependency-review.yml
vendored
4
.github/workflows/dependency-review.yml
vendored
@@ -15,6 +15,6 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: 'Checkout Repository'
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@v4
|
||||
- name: 'Dependency Review'
|
||||
uses: actions/dependency-review-action@3b139cfc5fae8b618d3eae3675e383bb1769c019 # v4.5.0
|
||||
uses: actions/dependency-review-action@v3
|
||||
|
14
.github/workflows/e2e-applitools.yml
vendored
14
.github/workflows/e2e-applitools.yml
vendored
@@ -11,8 +11,6 @@ on:
|
||||
default: master
|
||||
description: 'Parent branch to use for PRs'
|
||||
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
@@ -32,31 +30,29 @@ jobs:
|
||||
run: |
|
||||
echo "::error,title=Not using Applitools::APPLITOOLS_API_KEY is empty, disabling Applitools for this run."
|
||||
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- uses: pnpm/action-setup@v2
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
|
||||
- if: ${{ env.USE_APPLI }}
|
||||
name: Notify applitools of new batch
|
||||
# Copied from docs https://applitools.com/docs/topics/integrations/github-integration-ci-setup.html
|
||||
run: curl -L -d '' -X POST "$APPLITOOLS_SERVER_URL/api/externals/github/push?apiKey=$APPLITOOLS_API_KEY&CommitSha=$GITHUB_SHA&BranchName=${APPLITOOLS_BRANCH}$&ParentBranchName=$APPLITOOLS_PARENT_BRANCH"
|
||||
env:
|
||||
# e.g. mermaid-js/mermaid/my-branch
|
||||
APPLITOOLS_BRANCH: ${{ github.repository }}/${{ github.ref_name }}
|
||||
APPLITOOLS_PARENT_BRANCH: ${{ github.event.inputs.parent_branch }}
|
||||
APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }}
|
||||
APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com'
|
||||
uses: wei/curl@012398a392d02480afa2720780031f8621d5f94c
|
||||
with:
|
||||
args: -X POST "$APPLITOOLS_SERVER_URL/api/externals/github/push?apiKey=$APPLITOOLS_API_KEY&CommitSha=$GITHUB_SHA&BranchName=${APPLITOOLS_BRANCH}$&ParentBranchName=$APPLITOOLS_PARENT_BRANCH"
|
||||
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
uses: cypress-io/github-action@v4
|
||||
id: cypress
|
||||
with:
|
||||
start: pnpm run dev
|
||||
|
70
.github/workflows/e2e-timings.yml
vendored
70
.github/workflows/e2e-timings.yml
vendored
@@ -1,70 +0,0 @@
|
||||
name: E2E - Generate Timings
|
||||
|
||||
on:
|
||||
# run this workflow every night at 3am
|
||||
schedule:
|
||||
- cron: '28 3 * * *'
|
||||
# or when the user triggers it from GitHub Actions page
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
jobs:
|
||||
timings:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1
|
||||
options: --user 1001
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
- name: Install dependencies
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
with:
|
||||
runTests: false
|
||||
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
id: cypress
|
||||
with:
|
||||
install: false
|
||||
start: pnpm run dev:coverage
|
||||
wait-on: 'http://localhost:9000'
|
||||
browser: chrome
|
||||
publish-summary: false
|
||||
env:
|
||||
VITEST_COVERAGE: true
|
||||
CYPRESS_COMMIT: ${{ github.sha }}
|
||||
SPLIT: 1
|
||||
SPLIT_INDEX: 0
|
||||
SPLIT_FILE: 'cypress/timings.json'
|
||||
|
||||
- name: Compare timings
|
||||
id: compare
|
||||
run: |
|
||||
OUTPUT=$(pnpm tsx scripts/compare-timings.ts)
|
||||
echo "$OUTPUT" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
echo "output<<EOF" >> $GITHUB_OUTPUT
|
||||
echo "$OUTPUT" >> $GITHUB_OUTPUT
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Commit and create pull request
|
||||
uses: peter-evans/create-pull-request@889dce9eaba7900ce30494f5e1ac7220b27e5c81
|
||||
with:
|
||||
add-paths: |
|
||||
cypress/timings.json
|
||||
commit-message: 'chore: update E2E timings'
|
||||
branch: update-timings
|
||||
title: Update E2E Timings
|
||||
body: ${{ steps.compare.outputs.output }}
|
||||
delete-branch: true
|
||||
sign-commits: true
|
202
.github/workflows/e2e.yml
vendored
202
.github/workflows/e2e.yml
vendored
@@ -1,35 +1,26 @@
|
||||
# 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:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
- master
|
||||
- release/**
|
||||
branches-ignore:
|
||||
- 'gh-readonly-queue/**'
|
||||
pull_request:
|
||||
merge_group:
|
||||
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: write
|
||||
|
||||
env:
|
||||
# For PRs and MergeQueues, the target commit is used, and for push events to non-develop branches, github.event.previous is used if available. Otherwise, 'develop' is used.
|
||||
targetHash: >-
|
||||
${{
|
||||
github.event.pull_request.base.sha ||
|
||||
github.event.merge_group.base_sha ||
|
||||
(
|
||||
(
|
||||
(github.event_name == 'push' && github.ref == 'refs/heads/develop') ||
|
||||
github.event.before == '0000000000000000000000000000000000000000'
|
||||
) && 'develop'
|
||||
) ||
|
||||
github.event.before
|
||||
}}
|
||||
RUN_VISUAL_TEST: >-
|
||||
${{ github.repository == 'mermaid-js/mermaid' && (github.event_name != 'pull_request' || !startsWith(github.head_ref, 'renovate/')) }}
|
||||
# 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) }}
|
||||
|
||||
jobs:
|
||||
cache:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -37,40 +28,56 @@ jobs:
|
||||
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1
|
||||
options: --user 1001
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
- name: Cache snapshots
|
||||
id: cache-snapshot
|
||||
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
save-always: true
|
||||
path: ./cypress/snapshots
|
||||
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
|
||||
|
||||
# If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots.
|
||||
- name: Switch to base branch
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ env.targetHash }}
|
||||
|
||||
- name: Install dependencies
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
uses: cypress-io/github-action@v6
|
||||
with:
|
||||
# just perform install
|
||||
runTests: false
|
||||
|
||||
- name: Calculate bundle size
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true'}}
|
||||
- name: Build
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' && github.event_name == 'pull_request' }}
|
||||
run: |
|
||||
pnpm run build:viz
|
||||
mkdir -p cypress/snapshots/stats/base
|
||||
mv stats cypress/snapshots/stats/base
|
||||
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@v6
|
||||
id: cypress-snapshot-gen
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
|
||||
with:
|
||||
install: false
|
||||
start: pnpm run dev
|
||||
wait-on: 'http://localhost:9000'
|
||||
browser: chrome
|
||||
|
||||
- name: Move runtime data
|
||||
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
|
||||
run: |
|
||||
mv cypress/snapshots/runtimes/current cypress/snapshots/runtimes/base
|
||||
|
||||
e2e:
|
||||
runs-on: ubuntu-latest
|
||||
container:
|
||||
@@ -80,45 +87,60 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
containers: [1, 2, 3, 4, 5]
|
||||
containers: [1, 2, 3, 4]
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- uses: pnpm/action-setup@v2
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version-file: '.node-version'
|
||||
|
||||
# These cached snapshots are downloaded, providing the reference snapshots.
|
||||
- name: Cache snapshots
|
||||
id: cache-snapshot
|
||||
uses: actions/cache/restore@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
|
||||
uses: actions/cache/restore@v3
|
||||
with:
|
||||
path: ./cypress/snapshots
|
||||
key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
|
||||
|
||||
- name: Install dependencies
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
uses: cypress-io/github-action@v6
|
||||
with:
|
||||
runTests: false
|
||||
|
||||
- name: Output size diff
|
||||
if: ${{ matrix.containers == 1 }}
|
||||
- name: Build
|
||||
id: size
|
||||
if: ${{ github.event_name == 'pull_request' && 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"
|
||||
{
|
||||
echo 'size_diff<<EOF'
|
||||
npx tsx scripts/size.ts
|
||||
echo EOF
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
# Size diff only needs to be posted from one job, on PRs.
|
||||
- name: Comment PR size difference
|
||||
if: ${{ github.event_name == 'pull_request' && matrix.containers == 1 }}
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
with:
|
||||
message: |
|
||||
${{ steps.size.outputs.size_diff }}
|
||||
comment_tag: size-diff
|
||||
|
||||
# Install NPM dependencies, cache them correctly
|
||||
# and run all Cypress tests
|
||||
- name: Cypress run
|
||||
uses: cypress-io/github-action@18a6541367f4580a515371905f499a27a44e8dbe # v6.7.12
|
||||
uses: cypress-io/github-action@v6
|
||||
id: cypress
|
||||
# If CYPRESS_RECORD_KEY is set, run in parallel on all containers
|
||||
# Otherwise (e.g. if running from fork), we run on a single container only
|
||||
if: ${{ ( env.CYPRESS_RECORD_KEY != '' ) || ( matrix.containers == 1 ) }}
|
||||
with:
|
||||
install: false
|
||||
start: pnpm run dev:coverage
|
||||
@@ -126,20 +148,15 @@ jobs:
|
||||
browser: chrome
|
||||
# Disable recording if we don't have an API key
|
||||
# e.g. if this action was run from a fork
|
||||
record: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.CYPRESS_RECORD_KEY != '' }}
|
||||
record: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
|
||||
parallel: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
|
||||
env:
|
||||
ARGOS_PARALLEL: ${{ env.RUN_VISUAL_TEST == 'true' }}
|
||||
ARGOS_PARALLEL_TOTAL: ${{ env.RUN_VISUAL_TEST == 'true' && strategy.job-total || 1 }}
|
||||
ARGOS_PARALLEL_INDEX: ${{ env.RUN_VISUAL_TEST == 'true' && matrix.containers || 1 }}
|
||||
CYPRESS_COMMIT: ${{ github.sha }}
|
||||
CYPRESS_RECORD_KEY: ${{ env.RUN_VISUAL_TEST == 'true' && secrets.CYPRESS_RECORD_KEY || ''}}
|
||||
SPLIT: ${{ strategy.job-total }}
|
||||
SPLIT_INDEX: ${{ strategy.job-index }}
|
||||
SPLIT_FILE: 'cypress/timings.json'
|
||||
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
|
||||
VITEST_COVERAGE: true
|
||||
CYPRESS_COMMIT: ${{ github.sha }}
|
||||
|
||||
- name: Upload Coverage to Codecov
|
||||
uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1
|
||||
uses: codecov/codecov-action@v3
|
||||
# Run step only pushes to develop and pull_requests
|
||||
if: ${{ steps.cypress.conclusion == 'success' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/develop')}}
|
||||
with:
|
||||
@@ -149,3 +166,86 @@ 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:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js 18.x
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 18.x
|
||||
|
||||
# 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
|
||||
|
||||
- name: Build
|
||||
id: runtime
|
||||
if: ${{ needs.e2e.result != 'failure' && github.event_name == 'pull_request' }}
|
||||
run: |
|
||||
mv ./snapshots/runtimes/current ./snapshots/runtimes/head
|
||||
npm config set ignore-scripts true
|
||||
pnpm install --frozen-lockfile
|
||||
{
|
||||
echo 'runtime_diff<<EOF'
|
||||
npx tsx scripts/runTime.ts ./snapshots
|
||||
echo EOF
|
||||
} >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Comment PR runtime difference
|
||||
if: ${{ github.event_name == 'pull_request' }}
|
||||
uses: thollander/actions-comment-pull-request@v2
|
||||
with:
|
||||
message: |
|
||||
${{ steps.runtime.outputs.runtime_diff }}
|
||||
comment_tag: size-diff
|
||||
|
||||
# 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 }}"
|
||||
|
8
.github/workflows/issue-triage.yml
vendored
8
.github/workflows/issue-triage.yml
vendored
@@ -4,17 +4,11 @@ on:
|
||||
issues:
|
||||
types: [opened]
|
||||
|
||||
permissions: # added using https://github.com/step-security/secure-repo
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
permissions:
|
||||
issues: write # for andymckay/labeler to label issues
|
||||
pull-requests: write # for andymckay/labeler to label PRs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: andymckay/labeler@e6c4322d0397f3240f0e7e30a33b5c5df2d39e90 # 1.0.4
|
||||
- uses: andymckay/labeler@1.0.4
|
||||
with:
|
||||
repo-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
add-labels: 'Status: Triage'
|
||||
|
9
.github/workflows/link-checker.yml
vendored
9
.github/workflows/link-checker.yml
vendored
@@ -19,9 +19,6 @@ on:
|
||||
# * is a special character in YAML so you have to quote this string
|
||||
- cron: '30 8 * * *'
|
||||
|
||||
permissions: # added using https://github.com/step-security/secure-repo
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
link-checker:
|
||||
runs-on: ubuntu-latest
|
||||
@@ -29,17 +26,17 @@ jobs:
|
||||
# lychee only uses the GITHUB_TOKEN to avoid rate-limiting
|
||||
contents: read
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Restore lychee cache
|
||||
uses: actions/cache@0c907a75c2c80ebcb7f088228285e798b750cf8f # v4.2.1
|
||||
uses: actions/cache@v3
|
||||
with:
|
||||
path: .lycheecache
|
||||
key: cache-lychee-${{ github.sha }}
|
||||
restore-keys: cache-lychee-
|
||||
|
||||
- name: Link Checker
|
||||
uses: lycheeverse/lychee-action@f613c4a64e50d792e0b31ec34bbcbba12263c6a6 # v2.3.0
|
||||
uses: lycheeverse/lychee-action@v1.9.3
|
||||
with:
|
||||
args: >-
|
||||
--config .github/lychee.toml
|
||||
|
35
.github/workflows/lint.yml
vendored
35
.github/workflows/lint.yml
vendored
@@ -4,32 +4,26 @@ on:
|
||||
push:
|
||||
merge_group:
|
||||
pull_request:
|
||||
types:
|
||||
- opened
|
||||
- synchronize
|
||||
- ready_for_review
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
|
||||
jobs:
|
||||
docker-lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: hadolint/hadolint-action@54c9adbab1582c2ef04b2016b760714a4bfde3cf # v3.1.0
|
||||
with:
|
||||
verbose: true
|
||||
lint:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- uses: pnpm/action-setup@v2
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
@@ -89,9 +83,14 @@ jobs:
|
||||
continue-on-error: ${{ github.event_name == 'push' }}
|
||||
run: pnpm run docs:verify
|
||||
|
||||
- uses: testomatio/check-tests@0ea638fcec1820cf2e7b9854fdbdd04128a55bd4 # stable
|
||||
- name: Rebuild Docs
|
||||
if: ${{ steps.verifyDocs.outcome == 'failure' && github.event_name == 'push' }}
|
||||
working-directory: ./packages/mermaid
|
||||
run: pnpm run docs:build
|
||||
|
||||
- name: Commit changes
|
||||
uses: EndBug/add-and-commit@v9
|
||||
if: ${{ steps.verifyDocs.outcome == 'failure' && github.event_name == 'push' }}
|
||||
with:
|
||||
framework: cypress
|
||||
tests: './cypress/e2e/**/**.spec.js'
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
has-tests-label: true
|
||||
message: 'Update docs'
|
||||
add: 'docs/*'
|
||||
|
28
.github/workflows/pr-labeler.yml
vendored
28
.github/workflows/pr-labeler.yml
vendored
@@ -22,36 +22,10 @@ jobs:
|
||||
pull-requests: write # write permission is required to label PRs
|
||||
steps:
|
||||
- name: Label PR
|
||||
uses: release-drafter/release-drafter@b1476f6e6eb133afa41ed8589daba6dc69b4d3f5 # v6.1.0
|
||||
uses: release-drafter/release-drafter@v5
|
||||
with:
|
||||
config-name: pr-labeler.yml
|
||||
disable-autolabeler: false
|
||||
disable-releaser: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Add "Sponsored by MermaidChart" label
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const prNumber = context.payload.pull_request.number;
|
||||
const { data: commits } = await github.rest.pulls.listCommits({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber,
|
||||
});
|
||||
|
||||
const isSponsored = commits.every(
|
||||
(c) => c.commit.author.email?.endsWith('@mermaidchart.com')
|
||||
);
|
||||
|
||||
if (isSponsored) {
|
||||
console.log('PR is sponsored. Adding label.');
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: prNumber,
|
||||
labels: ['Sponsored by MermaidChart'],
|
||||
});
|
||||
}
|
||||
|
12
.github/workflows/publish-docs.yml
vendored
12
.github/workflows/publish-docs.yml
vendored
@@ -23,12 +23,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- uses: pnpm/action-setup@v2
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
@@ -37,13 +37,13 @@ jobs:
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Setup Pages
|
||||
uses: actions/configure-pages@983d7736d9b0ae728b81ab479565c72886d7745b # v5.0.0
|
||||
uses: actions/configure-pages@v3
|
||||
|
||||
- name: Run Build
|
||||
run: pnpm --filter mermaid run docs:build:vitepress
|
||||
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1
|
||||
uses: actions/upload-pages-artifact@v1
|
||||
with:
|
||||
path: packages/mermaid/src/vitepress/.vitepress/dist
|
||||
|
||||
@@ -56,4 +56,4 @@ jobs:
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5
|
||||
uses: actions/deploy-pages@v2
|
||||
|
23
.github/workflows/release-draft.yml
vendored
Normal file
23
.github/workflows/release-draft.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
name: Draft Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
draft-release:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write # write permission is required to create a github release
|
||||
pull-requests: read # required to read PR titles/labels
|
||||
steps:
|
||||
- name: Draft Release
|
||||
uses: release-drafter/release-drafter@v5
|
||||
with:
|
||||
disable-autolabeler: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
@@ -9,14 +9,14 @@ jobs:
|
||||
publish-preview:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- uses: pnpm/action-setup@v2
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
CYPRESS_CACHE_FOLDER: .cache/Cypress
|
||||
|
||||
- name: Install Json
|
||||
run: npm i json@11.0.0 --global
|
||||
run: npm i json --global
|
||||
|
||||
- name: Publish
|
||||
working-directory: ./packages/mermaid
|
||||
|
43
.github/workflows/release-preview.yml
vendored
43
.github/workflows/release-preview.yml
vendored
@@ -1,43 +0,0 @@
|
||||
name: Preview release
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [develop]
|
||||
types: [opened, synchronize, labeled, ready_for_review]
|
||||
|
||||
concurrency:
|
||||
group: ${{ github.workflow }}-${{ github.event.number }}
|
||||
cancel-in-progress: true
|
||||
|
||||
permissions:
|
||||
contents: read
|
||||
actions: write
|
||||
|
||||
jobs:
|
||||
preview:
|
||||
if: ${{ github.repository_owner == 'mermaid-js' }}
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
id-token: write
|
||||
issues: write
|
||||
pull-requests: write
|
||||
name: Publish preview release
|
||||
timeout-minutes: 5
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
|
||||
- name: Install Packages
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Publish packages
|
||||
run: pnpx pkg-pr-new publish --pnpm './packages/*'
|
47
.github/workflows/release-publish.yml
vendored
Normal file
47
.github/workflows/release-publish.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
||||
name: Publish release
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
publish:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: fregante/setup-git-user@v2
|
||||
|
||||
- uses: pnpm/action-setup@v2
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
|
||||
- name: Install Packages
|
||||
run: |
|
||||
pnpm install --frozen-lockfile
|
||||
npm i json --global
|
||||
env:
|
||||
CYPRESS_CACHE_FOLDER: .cache/Cypress
|
||||
|
||||
- name: Prepare release
|
||||
run: |
|
||||
VERSION=${GITHUB_REF:10}
|
||||
echo "Preparing release $VERSION"
|
||||
git checkout -t origin/release/$VERSION
|
||||
npm version --no-git-tag-version --allow-same-version $VERSION
|
||||
git add package.json
|
||||
git commit -nm "Bump version $VERSION"
|
||||
git checkout -t origin/master
|
||||
git merge -m "Release $VERSION" --no-ff release/$VERSION
|
||||
git push --no-verify
|
||||
|
||||
- name: Publish
|
||||
run: |
|
||||
npm set //registry.npmjs.org/:_authToken $NPM_TOKEN
|
||||
npm publish
|
||||
env:
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
46
.github/workflows/release.yml
vendored
46
.github/workflows/release.yml
vendored
@@ -1,46 +0,0 @@
|
||||
name: Release
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
concurrency: ${{ github.workflow }}-${{ github.ref }}
|
||||
|
||||
permissions: # added using https://github.com/step-security/secure-repo
|
||||
contents: read
|
||||
|
||||
jobs:
|
||||
release:
|
||||
if: github.repository == 'mermaid-js/mermaid'
|
||||
permissions:
|
||||
contents: write # to create release (changesets/action)
|
||||
id-token: write # OpenID Connect token needed for provenance
|
||||
pull-requests: write # to create pull request (changesets/action)
|
||||
name: Release
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout Repo
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
|
||||
- name: Install Packages
|
||||
run: pnpm install --frozen-lockfile
|
||||
|
||||
- name: Create Release Pull Request or Publish to npm
|
||||
id: changesets
|
||||
uses: changesets/action@c8bada60c408975afd1a20b3db81d6eee6789308 # v1.4.9
|
||||
with:
|
||||
version: pnpm changeset:version
|
||||
publish: pnpm changeset:publish
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
|
||||
NPM_CONFIG_PROVENANCE: true
|
37
.github/workflows/scorecard.yml
vendored
37
.github/workflows/scorecard.yml
vendored
@@ -1,37 +0,0 @@
|
||||
name: Scorecard supply-chain security
|
||||
on:
|
||||
branch_protection_rule:
|
||||
push:
|
||||
branches:
|
||||
- develop
|
||||
schedule:
|
||||
- cron: 29 15 * * 0
|
||||
permissions: read-all
|
||||
jobs:
|
||||
analysis:
|
||||
name: Scorecard analysis
|
||||
permissions:
|
||||
id-token: write
|
||||
security-events: write
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
with:
|
||||
persist-credentials: false
|
||||
- name: Run analysis
|
||||
uses: ossf/scorecard-action@f49aabe0b5af0936a0987cfb85d86b75731b0186 # v2.4.1
|
||||
with:
|
||||
results_file: results.sarif
|
||||
results_format: sarif
|
||||
publish_results: true
|
||||
- name: Upload artifact
|
||||
uses: actions/upload-artifact@4cec3d8aa04e39d1a68397de0c4cd6fb9dce8ec1 # v4.6.1
|
||||
with:
|
||||
name: SARIF file
|
||||
path: results.sarif
|
||||
retention-days: 5
|
||||
- name: Upload to code-scanning
|
||||
uses: github/codeql-action/upload-sarif@b56ba49b26e50535fa1e7f7db0f4f7b4bf65d80d # v3.28.10
|
||||
with:
|
||||
sarif_file: results.sarif
|
12
.github/workflows/test.yml
vendored
12
.github/workflows/test.yml
vendored
@@ -9,13 +9,13 @@ jobs:
|
||||
unit-test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- uses: pnpm/action-setup@v2
|
||||
# uses version from "packageManager" field in package.json
|
||||
|
||||
- name: Setup Node.js
|
||||
uses: actions/setup-node@1d0ff469b7ec7b3cb9d8673fde0c81c44821de2a # v4.2.0
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
cache: pnpm
|
||||
node-version-file: '.node-version'
|
||||
@@ -38,12 +38,8 @@ jobs:
|
||||
run: |
|
||||
pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts --coverage
|
||||
|
||||
- name: Verify out-of-tree build with TypeScript
|
||||
run: |
|
||||
pnpm test:check:tsc
|
||||
|
||||
- name: Upload Coverage to Codecov
|
||||
uses: codecov/codecov-action@13ce06bfc6bbe3ecf90edbbf1bc32fe5978ca1d3 # v5.3.1
|
||||
uses: codecov/codecov-action@v3
|
||||
# Run step only pushes to develop and pull_requests
|
||||
if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' }}
|
||||
with:
|
||||
|
2
.github/workflows/unlock-reopened-issues.yml
vendored
2
.github/workflows/unlock-reopened-issues.yml
vendored
@@ -8,6 +8,6 @@ jobs:
|
||||
triage:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: Dunning-Kruger/unlock-issues@b06b7f7e5c3f2eaa1c6d5d89f40930e4d6d9699e # v1
|
||||
- uses: Dunning-Kruger/unlock-issues@v1
|
||||
with:
|
||||
repo-token: '${{ secrets.GITHUB_TOKEN }}'
|
||||
|
8
.github/workflows/update-browserlist.yml
vendored
8
.github/workflows/update-browserlist.yml
vendored
@@ -8,18 +8,18 @@ jobs:
|
||||
update-browser-list:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
- uses: actions/checkout@v4
|
||||
- uses: pnpm/action-setup@v2
|
||||
- run: npx update-browserslist-db@latest
|
||||
- name: Commit changes
|
||||
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4
|
||||
uses: EndBug/add-and-commit@v9
|
||||
with:
|
||||
author_name: ${{ github.actor }}
|
||||
author_email: ${{ github.actor }}@users.noreply.github.com
|
||||
message: 'chore: update browsers list'
|
||||
push: false
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@67ccf781d68cd99b580ae25a5c18a1cc84ffff1f # v7.0.6
|
||||
uses: peter-evans/create-pull-request@v5
|
||||
with:
|
||||
branch: update-browserslist
|
||||
title: Update Browserslist
|
||||
|
70
.github/workflows/validate-lockfile.yml
vendored
70
.github/workflows/validate-lockfile.yml
vendored
@@ -1,70 +0,0 @@
|
||||
name: Validate pnpm-lock.yaml
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'pnpm-lock.yaml'
|
||||
- '**/package.json'
|
||||
- '.github/workflows/validate-lockfile.yml'
|
||||
|
||||
jobs:
|
||||
validate-lockfile:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
|
||||
- name: Validate pnpm-lock.yaml entries
|
||||
id: validate # give this step an ID so we can reference its outputs
|
||||
run: |
|
||||
issues=()
|
||||
|
||||
# 1) No tarball references
|
||||
if grep -qF 'tarball:' pnpm-lock.yaml; then
|
||||
issues+=("• Tarball references found (forbidden)")
|
||||
fi
|
||||
|
||||
# 2) No unwanted vitepress paths
|
||||
if grep -qF 'packages/mermaid/src/vitepress' pnpm-lock.yaml; then
|
||||
issues+=("• Disallowed path 'packages/mermaid/src/vitepress' present. Run `rm -rf packages/mermaid/src/vitepress && pnpm install` to regenerate.")
|
||||
fi
|
||||
|
||||
# 3) Lockfile only changes when package.json changes
|
||||
git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }} > changed.txt
|
||||
if grep -q '^pnpm-lock.yaml$' changed.txt && ! grep -q 'package.json' changed.txt; then
|
||||
issues+=("• pnpm-lock.yaml changed without any package.json modification")
|
||||
fi
|
||||
|
||||
# If any issues, output them and fail
|
||||
if [ ${#issues[@]} -gt 0 ]; then
|
||||
# Use the new GITHUB_OUTPUT approach to set a multiline output
|
||||
{
|
||||
echo "errors<<EOF"
|
||||
printf '%s\n' "${issues[@]}"
|
||||
echo "EOF"
|
||||
} >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Comment on PR if validation failed
|
||||
if: failure()
|
||||
uses: peter-evans/create-or-update-comment@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body: |
|
||||
The following issue(s) were detected:
|
||||
${{ steps.validate.outputs.errors }}
|
||||
|
||||
Please address these and push an update.
|
||||
|
||||
_Posted automatically by GitHub Actions_
|
4
.gitignore
vendored
4
.gitignore
vendored
@@ -29,13 +29,14 @@ Gemfile.lock
|
||||
|
||||
cypress/screenshots/
|
||||
cypress/snapshots/
|
||||
cypress/runtimes/
|
||||
|
||||
# eslint --cache file
|
||||
.eslintcache
|
||||
.tsbuildinfo
|
||||
tsconfig.tsbuildinfo
|
||||
|
||||
#knsv*.html
|
||||
knsv*.html
|
||||
local*.html
|
||||
stats/
|
||||
|
||||
@@ -48,7 +49,6 @@ demos/dev/**
|
||||
!/demos/dev/example.html
|
||||
!/demos/dev/reload.js
|
||||
tsx-0/**
|
||||
vite.config.ts.timestamp-*
|
||||
|
||||
# autogenereated by langium-cli
|
||||
generated/
|
||||
|
@@ -1,2 +0,0 @@
|
||||
ignored:
|
||||
- DL3002 # TODO: Last USER should not be root
|
4
.husky/commit-msg
Executable file
4
.husky/commit-msg
Executable file
@@ -0,0 +1,4 @@
|
||||
#!/bin/sh
|
||||
# . "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
# npx --no-install commitlint --edit $1
|
@@ -1,2 +1,4 @@
|
||||
#!/usr/bin/env sh
|
||||
NODE_OPTIONS="--max_old_space_size=8192" pnpm run pre-commit
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
pnpm run pre-commit
|
||||
|
@@ -1 +1 @@
|
||||
22.14.0
|
||||
v20.11.1
|
||||
|
@@ -16,5 +16,3 @@ 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,6 +3,5 @@
|
||||
"printWidth": 100,
|
||||
"singleQuote": true,
|
||||
"useTabs": false,
|
||||
"tabWidth": 2,
|
||||
"trailingComma": "es5"
|
||||
"tabWidth": 2
|
||||
}
|
||||
|
@@ -1,5 +1,4 @@
|
||||
import type { InlineConfig } from 'vite';
|
||||
import { build, type PluginOption } from 'vite';
|
||||
import { build, InlineConfig, type PluginOption } from 'vite';
|
||||
import { resolve } from 'path';
|
||||
import { fileURLToPath } from 'url';
|
||||
import jisonPlugin from './jisonPlugin.js';
|
||||
@@ -47,10 +46,9 @@ interface BuildOptions {
|
||||
|
||||
export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions): InlineConfig => {
|
||||
const external: (string | RegExp)[] = ['require', 'fs', 'path'];
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(entryName, packageOptions[entryName]);
|
||||
const { name, file, packageName } = packageOptions[entryName];
|
||||
const output: OutputOptions = [
|
||||
let output: OutputOptions = [
|
||||
{
|
||||
name,
|
||||
format: 'esm',
|
||||
@@ -85,6 +83,7 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
|
||||
plugins: [
|
||||
jisonPlugin(),
|
||||
jsonSchemaPlugin(), // handles `.schema.yaml` files
|
||||
// @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite
|
||||
typescript({ compilerOptions: { declaration: false } }),
|
||||
istanbul({
|
||||
exclude: ['node_modules', 'test/', '__mocks__', 'generated'],
|
||||
@@ -94,10 +93,6 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
|
||||
}),
|
||||
...visualizerOptions(packageName, core),
|
||||
],
|
||||
define: {
|
||||
// Needs to be string
|
||||
includeLargeFeatures: 'true',
|
||||
},
|
||||
};
|
||||
|
||||
if (watch && config.build) {
|
||||
@@ -126,10 +121,10 @@ await generateLangium();
|
||||
|
||||
if (watch) {
|
||||
await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' }));
|
||||
void build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' }));
|
||||
build(getBuildConfig({ minify: false, watch, core: false, entryName: 'mermaid' }));
|
||||
if (!mermaidOnly) {
|
||||
void build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' }));
|
||||
void build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-zenuml' }));
|
||||
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' }));
|
||||
build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-zenuml' }));
|
||||
}
|
||||
} else if (visualize) {
|
||||
await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' }));
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import type { PluginOption } from 'vite';
|
||||
import { PluginOption } from 'vite';
|
||||
import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js';
|
||||
|
||||
/**
|
||||
|
@@ -23,9 +23,8 @@ async function createServer() {
|
||||
app.use(express.static('cypress/platform'));
|
||||
|
||||
app.listen(9000, () => {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log(`Listening on http://localhost:9000`);
|
||||
});
|
||||
}
|
||||
|
||||
void createServer();
|
||||
createServer();
|
||||
|
@@ -256,7 +256,7 @@ mermaid.run({
|
||||
- Problem showing graph with php on localhost [\#502](https://github.com/knsv/mermaid/issues/502)
|
||||
- logLevel's option doesnt work at 7.0.0 [\#501](https://github.com/knsv/mermaid/issues/501)
|
||||
- How do I get the log for a render or parse attempt? [\#500](https://github.com/knsv/mermaid/issues/500)
|
||||
- Mermaid neutral style to built in latest release [\#499](https://github.com/knsv/mermaid/issues/499)
|
||||
- Mermaid neutral style style to built in latest release [\#499](https://github.com/knsv/mermaid/issues/499)
|
||||
- Any plans for adding a typescript definition file? [\#495](https://github.com/knsv/mermaid/issues/495)
|
||||
- Gantt diagrams too narrow [\#493](https://github.com/knsv/mermaid/issues/493)
|
||||
- Flowchart edge labels placement [\#490](https://github.com/knsv/mermaid/issues/490)
|
||||
@@ -833,7 +833,7 @@ mermaid.run({
|
||||
- Merge pull request \#1 from knsv/master [\#96](https://github.com/knsv/mermaid/pull/96) ([gkchic](https://github.com/gkchic))
|
||||
- Removed duplicated section in flowchart docs [\#94](https://github.com/knsv/mermaid/pull/94) ([kaime](https://github.com/kaime))
|
||||
- Grammar changes to sequence page [\#93](https://github.com/knsv/mermaid/pull/93) ([gkchic](https://github.com/gkchic))
|
||||
- GitHub buttons [\#89](https://github.com/knsv/mermaid/pull/89) ([gkchic](https://github.com/gkchic))
|
||||
- Github buttons [\#89](https://github.com/knsv/mermaid/pull/89) ([gkchic](https://github.com/gkchic))
|
||||
- Template change [\#88](https://github.com/knsv/mermaid/pull/88) ([gkchic](https://github.com/gkchic))
|
||||
|
||||
## [0.3.1](https://github.com/knsv/mermaid/tree/0.3.1) (2015-01-05)
|
||||
@@ -1002,4 +1002,4 @@ mermaid.run({
|
||||
|
||||
## [0.1.0](https://github.com/knsv/mermaid/tree/0.1.0) (2014-11-16)
|
||||
|
||||
\* _This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/GitHub-Changelog-Generator)_
|
||||
\* _This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)_
|
||||
|
15
Dockerfile
15
Dockerfile
@@ -1,13 +1,2 @@
|
||||
FROM node:22.12.0-alpine3.19@sha256:40dc4b415c17b85bea9be05314b4a753f45a4e1716bb31c01182e6c53d51a654
|
||||
|
||||
USER 0:0
|
||||
|
||||
RUN corepack enable \
|
||||
&& corepack enable pnpm
|
||||
|
||||
RUN apk add --no-cache git~=2.43.4 \
|
||||
&& git config --add --system safe.directory /mermaid
|
||||
|
||||
ENV NODE_OPTIONS="--max_old_space_size=8192"
|
||||
|
||||
EXPOSE 9000 3333
|
||||
FROM node:20.11.1-alpine3.19 AS base
|
||||
RUN wget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.shrc" SHELL="$(which sh)" sh -
|
||||
|
@@ -1,7 +0,0 @@
|
||||
{
|
||||
"drips": {
|
||||
"ethereum": {
|
||||
"ownedBy": "0x0831DDFe60d009d9448CC976157b539089aB821E"
|
||||
}
|
||||
}
|
||||
}
|
44
README.md
44
README.md
@@ -15,7 +15,7 @@ Generate diagrams from markdown-like text.
|
||||
<a href="https://mermaid.live/"><b>Live Editor!</b></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://mermaid.js.org">📖 Documentation</a> | <a href="https://mermaid.js.org/intro/">🚀 Getting Started</a> | <a href="https://www.jsdelivr.com/package/npm/mermaid">🌐 CDN</a> | <a href="https://discord.gg/sKeNQX4Wtj" title="Discord invite">🙌 Join Us</a>
|
||||
<a href="https://mermaid.js.org">📖 Documentation</a> | <a href="https://mermaid.js.org/intro/">🚀 Getting Started</a> | <a href="https://www.jsdelivr.com/package/npm/mermaid">🌐 CDN</a> | <a href="https://discord.gg/AgrbSrBer3" title="Discord invite">🙌 Join Us</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="./README.zh-CN.md">简体中文</a>
|
||||
@@ -33,10 +33,8 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai
|
||||
[](https://app.codecov.io/github/mermaid-js/mermaid/tree/develop)
|
||||
[](https://www.jsdelivr.com/package/npm/mermaid)
|
||||
[](https://www.npmjs.com/package/mermaid)
|
||||
[](https://discord.gg/sKeNQX4Wtj)
|
||||
[](https://discord.gg/AgrbSrBer3)
|
||||
[](https://twitter.com/mermaidjs_)
|
||||
[](https://argos-ci.com?utm_source=mermaid&utm_campaign=oss)
|
||||
[](https://securityscorecards.dev/viewer/?uri=github.com/mermaid-js/mermaid)
|
||||
|
||||
<img src="./img/header.png" alt="" />
|
||||
|
||||
@@ -44,7 +42,7 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai
|
||||
|
||||
**Thanks to all involved, people committing pull requests, people answering questions! 🙏**
|
||||
|
||||
<a href="https://mermaid.js.org/landing/"><img src="https://github.com/mermaid-js/mermaid/blob/master/docs/intro/img/book-banner-post-release.jpg" alt='Banner for "The Official Guide to Mermaid.js" book'></a>
|
||||
<a href="https://mermaid.js.org/landing/"><img src="https://github.com/mermaid-js/mermaid/blob/master/docs/intro/img/book-banner-post-release.jpg" alt="Explore Mermaid.js in depth, with real-world examples, tips & tricks from the creator... The first official book on Mermaid is available for purchase. Check it out!"></a>
|
||||
|
||||
## Table of content
|
||||
|
||||
@@ -83,10 +81,6 @@ You can also use Mermaid within [GitHub](https://github.blog/2022-02-14-include-
|
||||
|
||||
For a more detailed introduction to Mermaid and some of its more basic uses, look to the [Beginner's Guide](https://mermaid.js.org/intro/getting-started.html), [Usage](https://mermaid.js.org/config/usage.html) and [Tutorials](https://mermaid.js.org/ecosystem/tutorials.html).
|
||||
|
||||
Our PR Visual Regression Testing is powered by [Argos](https://argos-ci.com/?utm_source=mermaid&utm_campaign=oss) with their generous Open Source plan. It makes the process of reviewing PRs with visual changes a breeze.
|
||||
|
||||
[](https://argos-ci.com?utm_source=mermaid&utm_campaign=oss)
|
||||
|
||||
In our release process we rely heavily on visual regression tests using [applitools](https://applitools.com/). Applitools is a great service which has been easy to use and integrate with our tests.
|
||||
|
||||
<a href="https://applitools.com/">
|
||||
@@ -253,34 +247,6 @@ pie
|
||||
|
||||
### Git graph [experimental - <a href="https://mermaid.live/edit#pako:eNqNkMFugzAMhl8F-VyVAR1tOW_aA-zKxSSGRCMJCk6lCvHuNZPKZdM0n-zf3_8r8QIqaIIGMqnB8kfEybQ--y4VnLP8-9RF9Mpkmm40hmlnDKmvkPiH_kfS7nFo_VN0FAf6XwocQGgxa_nGsm1bYEOOWmik1dRjGrmF1q-Cpkkj07u2HCI0PY4zHQATh8-7V9BwTPSE3iwOEd1OjQE1iWkBvk_bzQY7s0Sq4Hs7bHqKo8iGeZqbPN_WR7mpSd1RHpvPVhuMbG7XOq_L-oJlRfW5wteq0qorrpe-PBW9Pr8UJcK6rg-BLYPQ">live editor</a>]
|
||||
|
||||
```
|
||||
gitGraph
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
merge develop
|
||||
commit
|
||||
commit
|
||||
```
|
||||
|
||||
```mermaid
|
||||
gitGraph
|
||||
commit
|
||||
commit
|
||||
branch develop
|
||||
checkout develop
|
||||
commit
|
||||
commit
|
||||
checkout main
|
||||
merge develop
|
||||
commit
|
||||
commit
|
||||
```
|
||||
|
||||
### Bar chart (using gantt chart) [<a href="https://mermaid.js.org/syntax/gantt.html">docs</a> - <a href="https://mermaid.live/edit#pako:eNptkU1vhCAQhv8KIenNugiI4rkf6bmXpvEyFVxJFDYyNt1u9r8X63Z7WQ9m5pknLzieaBeMpQ3dg0dsPUkPOhwteXZIXmJcbCT3xMAxkuh8Z8kIEclyMIB209fqKcwTICFvG4IvFy_oLrZ-g9F26ILfQgvNFN94VaRXQ1iWqpumZBcu1J8p1E1TXDx59eQNr5LyEqjJn6hv5QnGNlxevZJmdLLpy5xJSzut45biYCfb0iaVxvawjNjS1p-TCguG16PvaIPzYjO67e3BwX6GiTY9jPFKH43DMF_hGMDY1J4oHg-_f8hFTJFd8L3br3yZx4QHxENsdrt1nO8dDstH3oVpF50ZYMbhU6ud4qoGLqyqBJRCmO6j0HXPZdGbihUc6Pmc0QP49xD-b5X69ZQv2gjO81IwzWqhC1lKrjJ6pA3nVS7SMiVjrKirWlYp5fs3osgrWeo00lorLWvOzz8JVbXm">live editor</a>]
|
||||
|
||||
```
|
||||
@@ -447,7 +413,7 @@ For public sites, it can be precarious to retrieve text from users on the intern
|
||||
|
||||
As an extra level of security for sites with external users we are happy to introduce a new security level in which the diagram is rendered in a sandboxed iframe preventing javascript in the code from being executed. This is a great step forward for better security.
|
||||
|
||||
_Unfortunately you cannot have a cake and eat it at the same time which in this case means that some of the interactive functionality gets blocked along with the possible malicious code._
|
||||
_Unfortunately you can not have a cake and eat it at the same time which in this case means that some of the interactive functionality gets blocked along with the possible malicious code._
|
||||
|
||||
## Reporting vulnerabilities
|
||||
|
||||
@@ -463,7 +429,7 @@ A quick note from Knut Sveidqvist:
|
||||
>
|
||||
> _Thank you to [Tyler Long](https://github.com/tylerlong) who has been a collaborator since April 2017._
|
||||
>
|
||||
> _Thank you to the ever-growing list of [contributors](https://github.com/mermaid-js/mermaid/graphs/contributors) that brought the project this far!_
|
||||
> _Thank you to the ever-growing list of [contributors](https://github.com/knsv/mermaid/graphs/contributors) that brought the project this far!_
|
||||
|
||||
---
|
||||
|
||||
|
@@ -15,7 +15,7 @@ Mermaid
|
||||
<a href="https://mermaid.live/"><b>实时编辑器!</b></a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="https://mermaid.js.org">📖 文档</a> | <a href="https://mermaid.js.org/intro/">🚀 入门</a> | <a href="https://www.jsdelivr.com/package/npm/mermaid">🌐 CDN</a> | <a href="https://discord.gg/sKeNQX4Wtj" title="Discord invite">🙌 加入我们</a>
|
||||
<a href="https://mermaid.js.org">📖 文档</a> | <a href="https://mermaid.js.org/intro/">🚀 入门</a> | <a href="https://www.jsdelivr.com/package/npm/mermaid">🌐 CDN</a> | <a href="https://discord.gg/AgrbSrBer3" title="Discord invite">🙌 加入我们</a>
|
||||
</p>
|
||||
<p align="center">
|
||||
<a href="./README.md">English</a>
|
||||
@@ -34,7 +34,7 @@ Mermaid
|
||||
[](https://app.codecov.io/github/mermaid-js/mermaid/tree/develop)
|
||||
[](https://www.jsdelivr.com/package/npm/mermaid)
|
||||
[](https://www.npmjs.com/package/mermaid)
|
||||
[](https://discord.gg/sKeNQX4Wtj)
|
||||
[](https://discord.gg/AgrbSrBer3)
|
||||
[](https://twitter.com/mermaidjs_)
|
||||
|
||||
<img src="./img/header.png" alt="" />
|
||||
@@ -43,13 +43,13 @@ Mermaid
|
||||
|
||||
**感谢所有参与进来提交 PR,解答疑问的人们! 🙏**
|
||||
|
||||
<a href="https://mermaid.js.org/landing/"><img src="https://github.com/mermaid-js/mermaid/blob/master/docs/intro/img/book-banner-post-release.jpg" alt='Banner for "The Official Guide to Mermaid.js" book'></a>
|
||||
<a href="https://mermaid.js.org/landing/"><img src="https://github.com/mermaid-js/mermaid/blob/master/docs/intro/img/book-banner-post-release.jpg" alt="Explore Mermaid.js in depth, with real-world examples, tips & tricks from the creator... The first official book on Mermaid is available for purchase. Check it out!"></a>
|
||||
|
||||
## 关于 Mermaid
|
||||
|
||||
<!-- <Main description> -->
|
||||
|
||||
Mermaid 是一个基于 JavaScript 的图表绘制工具,通过解析类 Markdown 的文本语法来实现图表的创建和动态修改。Mermaid 诞生的主要目的是让文档的更新能够及时跟上开发进度。
|
||||
Mermaid 是一个基于 Javascript 的图表绘制工具,通过解析类 Markdown 的文本语法来实现图表的创建和动态修改。Mermaid 诞生的主要目的是让文档的更新能够及时跟上开发进度。
|
||||
|
||||
> Doc-Rot 是 Mermaid 致力于解决的一个难题。
|
||||
|
||||
@@ -358,7 +358,7 @@ _很不幸的是,鱼与熊掌不可兼得,在这个场景下它意味着在
|
||||
|
||||
> _特别感谢 [d3](https://d3js.org/) 和 [dagre-d3](https://github.com/cpettitt/dagre-d3) 这两个优秀的项目,它们提供了图形布局和绘图工具库!_ > _同样感谢 [js-sequence-diagram](https://bramp.github.io/js-sequence-diagrams) 提供了时序图语法的使用。 感谢 Jessica Peter 提供了甘特图渲染的灵感。_ > _感谢 [Tyler Long](https://github.com/tylerlong) 从 2017 年四月开始成为了项目的合作者。_
|
||||
>
|
||||
> _感谢越来越多的 [贡献者们](https://github.com/mermaid-js/mermaid/graphs/contributors),没有你们,就没有这个项目的今天!_
|
||||
> _感谢越来越多的 [贡献者们](https://github.com/knsv/mermaid/graphs/contributors),没有你们,就没有这个项目的今天!_
|
||||
|
||||
---
|
||||
|
||||
|
@@ -1,10 +1,9 @@
|
||||
import eyesPlugin from '@applitools/eyes-cypress';
|
||||
import { registerArgosTask } from '@argos-ci/cypress/task';
|
||||
import coverage from '@cypress/code-coverage/task.js';
|
||||
import { defineConfig } from 'cypress';
|
||||
import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin.js';
|
||||
import cypressSplit from 'cypress-split';
|
||||
|
||||
import fs from 'fs';
|
||||
import path from 'path';
|
||||
import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin';
|
||||
import coverage from '@cypress/code-coverage/task';
|
||||
import eyesPlugin from '@applitools/eyes-cypress';
|
||||
export default eyesPlugin(
|
||||
defineConfig({
|
||||
projectId: 'n2sma2',
|
||||
@@ -14,22 +13,29 @@ export default eyesPlugin(
|
||||
specPattern: 'cypress/integration/**/*.{js,ts}',
|
||||
setupNodeEvents(on, config) {
|
||||
coverage(on, config);
|
||||
cypressSplit(on, config);
|
||||
on('before:browser:launch', (browser, launchOptions) => {
|
||||
if (browser.name === 'chrome' && browser.isHeadless) {
|
||||
launchOptions.args.push('--window-size=1440,1024', '--force-device-scale-factor=1');
|
||||
}
|
||||
return launchOptions;
|
||||
});
|
||||
on('task', {
|
||||
recordRenderTime({ fileName, testName, timeTaken }) {
|
||||
const resultsPath = path.join('cypress', 'snapshots', 'runtimes', 'current');
|
||||
if (!fs.existsSync(resultsPath)) {
|
||||
fs.mkdirSync(resultsPath, { recursive: true });
|
||||
}
|
||||
fs.appendFileSync(
|
||||
path.join(resultsPath, `${fileName}.csv`),
|
||||
`${testName},${timeTaken}\n`
|
||||
);
|
||||
return true;
|
||||
},
|
||||
});
|
||||
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.RUN_VISUAL_TEST === 'true';
|
||||
|
||||
if (config.env.useArgos) {
|
||||
registerArgosTask(on, config);
|
||||
} else {
|
||||
addMatchImageSnapshotPlugin(on, config);
|
||||
}
|
||||
// do not forget to return the changed config object!
|
||||
return config;
|
||||
},
|
||||
|
@@ -29,14 +29,13 @@ export const mermaidUrl = (
|
||||
options: CypressMermaidConfig,
|
||||
api: boolean
|
||||
): string => {
|
||||
options.handDrawnSeed = 1;
|
||||
const codeObject: CodeObject = {
|
||||
code: graphStr,
|
||||
mermaid: options,
|
||||
};
|
||||
const objStr: string = JSON.stringify(codeObject);
|
||||
let url = `http://localhost:9000/e2e.html?graph=${utf8ToB64(objStr)}`;
|
||||
if (api && typeof graphStr === 'string') {
|
||||
if (api) {
|
||||
url = `http://localhost:9000/xss.html?graph=${graphStr}`;
|
||||
}
|
||||
|
||||
@@ -55,15 +54,16 @@ export const imgSnapshotTest = (
|
||||
): void => {
|
||||
const options: CypressMermaidConfig = {
|
||||
..._options,
|
||||
fontFamily: _options.fontFamily ?? 'courier',
|
||||
fontFamily: _options.fontFamily || 'courier',
|
||||
// @ts-ignore TODO: Fix type of fontSize
|
||||
fontSize: _options.fontSize ?? '16px',
|
||||
fontSize: _options.fontSize || '16px',
|
||||
sequence: {
|
||||
...(_options.sequence ?? {}),
|
||||
...(_options.sequence || {}),
|
||||
actorFontFamily: 'courier',
|
||||
noteFontFamily: _options.sequence?.noteFontFamily
|
||||
? _options.sequence.noteFontFamily
|
||||
: 'courier',
|
||||
noteFontFamily:
|
||||
_options.sequence && _options.sequence.noteFontFamily
|
||||
? _options.sequence.noteFontFamily
|
||||
: 'courier',
|
||||
messageFontFamily: 'courier',
|
||||
},
|
||||
};
|
||||
@@ -74,7 +74,7 @@ export const imgSnapshotTest = (
|
||||
|
||||
export const urlSnapshotTest = (
|
||||
url: string,
|
||||
options: CypressMermaidConfig = {},
|
||||
options: CypressMermaidConfig,
|
||||
_api = false,
|
||||
validation?: any
|
||||
): void => {
|
||||
@@ -95,22 +95,8 @@ export const openURLAndVerifyRendering = (
|
||||
options: CypressMermaidConfig,
|
||||
validation?: any
|
||||
): void => {
|
||||
const name: string = (options.name ?? cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
|
||||
|
||||
cy.visit(url);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
cy.get('svg').should('be.visible');
|
||||
|
||||
if (validation) {
|
||||
cy.get('svg').should(validation);
|
||||
}
|
||||
|
||||
verifyScreenshot(name);
|
||||
};
|
||||
|
||||
export const verifyScreenshot = (name: string): void => {
|
||||
const useAppli: boolean = Cypress.env('useAppli');
|
||||
const useArgos: boolean = Cypress.env('useArgos');
|
||||
const name: string = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
|
||||
|
||||
if (useAppli) {
|
||||
cy.log(`Opening eyes ${Cypress.spec.name} --- ${name}`);
|
||||
@@ -120,22 +106,30 @@ export const verifyScreenshot = (name: string): void => {
|
||||
batchName: Cypress.spec.name,
|
||||
batchId: batchId + Cypress.spec.name,
|
||||
});
|
||||
}
|
||||
|
||||
cy.visit(url);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
cy.window().then((win) => {
|
||||
cy.task('recordRenderTime', {
|
||||
fileName: Cypress.spec.name,
|
||||
testName: name,
|
||||
// @ts-ignore Dynamically added property.
|
||||
timeTaken: win.renderTime,
|
||||
});
|
||||
});
|
||||
cy.get('svg').should('be.visible');
|
||||
|
||||
if (validation) {
|
||||
cy.get('svg').should(validation);
|
||||
}
|
||||
|
||||
if (useAppli) {
|
||||
cy.log(`Check eyes ${Cypress.spec.name}`);
|
||||
cy.eyesCheckWindow('Click!');
|
||||
cy.log(`Closing eyes ${Cypress.spec.name}`);
|
||||
cy.eyesClose();
|
||||
} else if (useArgos) {
|
||||
cy.argosScreenshot(name, {
|
||||
threshold: 0.01,
|
||||
});
|
||||
} else {
|
||||
cy.matchImageSnapshot(name);
|
||||
}
|
||||
};
|
||||
|
||||
export const verifyNumber = (value: number, expected: number, deltaPercent = 10): void => {
|
||||
expect(value).to.be.within(
|
||||
expected * (1 - deltaPercent / 100),
|
||||
expected * (1 + deltaPercent / 100)
|
||||
);
|
||||
};
|
||||
|
@@ -1,4 +1,4 @@
|
||||
import { renderGraph, verifyScreenshot } from '../../helpers/util.ts';
|
||||
import { renderGraph } from '../../helpers/util.ts';
|
||||
describe('Configuration', () => {
|
||||
describe('arrowMarkerAbsolute', () => {
|
||||
it('should handle default value false of arrowMarkerAbsolute', () => {
|
||||
@@ -69,9 +69,7 @@ describe('Configuration', () => {
|
||||
.and('include', 'url(#');
|
||||
});
|
||||
});
|
||||
// This has been broken for a long time, but something about the Cypress environment was
|
||||
// rewriting the URL to be relative, causing the test to incorrectly pass.
|
||||
it.skip('should handle arrowMarkerAbsolute explicitly set to "false" as false', () => {
|
||||
it('should handle arrowMarkerAbsolute explicitly set to "false" as false', () => {
|
||||
renderGraph(
|
||||
`graph TD
|
||||
A[Christmas] -->|Get money| B(Go shopping)
|
||||
@@ -114,58 +112,17 @@ describe('Configuration', () => {
|
||||
.first()
|
||||
.should('have.attr', 'marker-end')
|
||||
.should('exist')
|
||||
.and('include', 'url(http\\:\\/\\/localhost');
|
||||
.and('include', 'url(http://localhost');
|
||||
});
|
||||
});
|
||||
it('should not taint the initial configuration when using multiple directives', () => {
|
||||
const url = 'http://localhost:9000/regression/issue-1874.html';
|
||||
cy.visit(url);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
verifyScreenshot(
|
||||
|
||||
cy.get('svg');
|
||||
cy.matchImageSnapshot(
|
||||
'configuration.spec-should-not-taint-initial-configuration-when-using-multiple-directives'
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('suppressErrorRendering', () => {
|
||||
beforeEach(() => {
|
||||
cy.on('uncaught:exception', (err, runnable) => {
|
||||
return !err.message.includes('Parse error on line');
|
||||
});
|
||||
});
|
||||
|
||||
it('should not render error diagram if suppressErrorRendering is set', () => {
|
||||
const url = 'http://localhost:9000/suppressError.html?suppressErrorRendering=true';
|
||||
cy.visit(url);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
cy.get('#test')
|
||||
.find('svg')
|
||||
.should(($svg) => {
|
||||
// all failing diagrams should not appear!
|
||||
expect($svg).to.have.length(2);
|
||||
// none of the diagrams should be error diagrams
|
||||
expect($svg).to.not.contain('Syntax error');
|
||||
});
|
||||
verifyScreenshot(
|
||||
'configuration.spec-should-not-render-error-diagram-if-suppressErrorRendering-is-set'
|
||||
);
|
||||
});
|
||||
|
||||
it('should render error diagram if suppressErrorRendering is not set', () => {
|
||||
const url = 'http://localhost:9000/suppressError.html';
|
||||
cy.visit(url);
|
||||
cy.window().should('have.property', 'rendered', true);
|
||||
cy.get('#test')
|
||||
.find('svg')
|
||||
.should(($svg) => {
|
||||
// all five diagrams should be rendered
|
||||
expect($svg).to.have.length(5);
|
||||
// some of the diagrams should be error diagrams
|
||||
expect($svg).to.contain('Syntax error');
|
||||
});
|
||||
verifyScreenshot(
|
||||
'configuration.spec-should-render-error-diagram-if-suppressErrorRendering-is-not-set'
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
14
cypress/integration/other/flowchart-elk.spec.js
Normal file
14
cypress/integration/other/flowchart-elk.spec.js
Normal file
@@ -0,0 +1,14 @@
|
||||
import { urlSnapshotTest, openURLAndVerifyRendering } from '../../helpers/util.ts';
|
||||
|
||||
describe('Flowchart elk', () => {
|
||||
it('should use dagre as fallback', () => {
|
||||
urlSnapshotTest('http://localhost:9000/flow-elk.html', {
|
||||
name: 'flow-elk fallback to dagre',
|
||||
});
|
||||
});
|
||||
it('should allow overriding with external package', () => {
|
||||
urlSnapshotTest('http://localhost:9000/flow-elk.html?elk=true', {
|
||||
name: 'flow-elk overriding dagre with elk',
|
||||
});
|
||||
});
|
||||
});
|
@@ -20,7 +20,7 @@ describe('Interaction', () => {
|
||||
});
|
||||
|
||||
it('Graph: should handle a click on a node with a bound url', () => {
|
||||
// When there is a URL, `cy.contains()` selects the `a` tag instead of the `span` tag. The .node is a child of `a`, so we have to use `find()` instead of `parent`.
|
||||
// When there is a URL, cy.contains selects the a tag instead of the span. The .node is a child of a, so we have to use find instead of parent.
|
||||
cy.contains('URLTest1').find('.node').click();
|
||||
cy.location().should(({ href }) => {
|
||||
expect(href).to.eq('http://localhost:9000/empty.html');
|
||||
@@ -146,7 +146,7 @@ describe('Interaction', () => {
|
||||
});
|
||||
});
|
||||
|
||||
describe('Interaction - security level other, misspelling', () => {
|
||||
describe('Interaction - security level other, missspelling', () => {
|
||||
beforeEach(() => {
|
||||
cy.visit('http://localhost:9000/click_security_other.html');
|
||||
});
|
||||
|
@@ -10,6 +10,7 @@ describe('XSS', () => {
|
||||
cy.wait(1000).then(() => {
|
||||
cy.get('.mermaid').should('exist');
|
||||
});
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('should not allow tags in the css', () => {
|
||||
@@ -136,9 +137,4 @@ describe('XSS', () => {
|
||||
cy.wait(1000);
|
||||
cy.get('#the-malware').should('not.exist');
|
||||
});
|
||||
it('should sanitize backticks block diagram labels properly', () => {
|
||||
cy.visit('http://localhost:9000/xss25.html');
|
||||
cy.wait(1000);
|
||||
cy.get('#the-malware').should('not.exist');
|
||||
});
|
||||
});
|
||||
|
@@ -11,27 +11,6 @@ describe('Git Graph diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('Should render subgraphs with title margins and edge labels', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart LR
|
||||
|
||||
subgraph TOP
|
||||
direction TB
|
||||
subgraph B1
|
||||
direction RL
|
||||
i1 --lb1-->f1
|
||||
end
|
||||
subgraph B2
|
||||
direction BT
|
||||
i2 --lb2-->f2
|
||||
end
|
||||
end
|
||||
A --lb3--> TOP --lb4--> B
|
||||
B1 --lb5--> B2
|
||||
`,
|
||||
{ flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } } }
|
||||
);
|
||||
});
|
||||
// it(`ultraFastTest`, function () {
|
||||
// // Navigate to the url we want to test
|
||||
// // ⭐️ Note to see visual bugs, run the test using the above URL for the 1st run.
|
||||
|
@@ -1,252 +0,0 @@
|
||||
import { imgSnapshotTest, urlSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe.skip('architecture diagram', () => {
|
||||
it('should render a simple architecture diagram with groups', () => {
|
||||
imgSnapshotTest(
|
||||
`architecture-beta
|
||||
group api(cloud)[API]
|
||||
|
||||
service db(database)[Database] in api
|
||||
service disk1(disk)[Storage] in api
|
||||
service disk2(disk)[Storage] in api
|
||||
service server(server)[Server] in api
|
||||
service gateway(internet)[Gateway]
|
||||
|
||||
db L--R server
|
||||
disk1 T--B server
|
||||
disk2 T--B db
|
||||
server T--B gateway
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render a simple architecture diagram with titleAndAccessibilities', () => {
|
||||
imgSnapshotTest(
|
||||
`architecture-beta
|
||||
title Simple Architecture Diagram
|
||||
accTitle: Accessibility Title
|
||||
accDescr: Accessibility Description
|
||||
group api(cloud)[API]
|
||||
|
||||
service db(database)[Database] in api
|
||||
service disk1(disk)[Storage] in api
|
||||
service disk2(disk)[Storage] in api
|
||||
service server(server)[Server] in api
|
||||
|
||||
db:L -- R:server
|
||||
disk1:T -- B:server
|
||||
disk2:T -- B:db
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render an architecture diagram with groups within groups', () => {
|
||||
imgSnapshotTest(
|
||||
`architecture-beta
|
||||
group api[API]
|
||||
group public[Public API] in api
|
||||
group private[Private API] in api
|
||||
|
||||
service serv1(server)[Server] in public
|
||||
|
||||
service serv2(server)[Server] in private
|
||||
service db(database)[Database] in private
|
||||
|
||||
service gateway(internet)[Gateway] in api
|
||||
|
||||
serv1 B--T serv2
|
||||
serv2 L--R db
|
||||
serv1 L--R gateway
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render an architecture diagram with the fallback icon', () => {
|
||||
imgSnapshotTest(
|
||||
`architecture-beta
|
||||
service unknown(iconnamedoesntexist)[Unknown Icon]
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render an architecture diagram with split directioning', () => {
|
||||
imgSnapshotTest(
|
||||
`architecture-beta
|
||||
service db(database)[Database]
|
||||
service s3(disk)[Storage]
|
||||
service serv1(server)[Server 1]
|
||||
service serv2(server)[Server 2]
|
||||
service disk(disk)[Disk]
|
||||
|
||||
db L--R s3
|
||||
serv1 L--T s3
|
||||
serv2 L--B s3
|
||||
serv1 T--B disk
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render an architecture diagram with directional arrows', () => {
|
||||
imgSnapshotTest(
|
||||
`architecture-beta
|
||||
service servC(server)[Server 1]
|
||||
service servL(server)[Server 2]
|
||||
service servR(server)[Server 3]
|
||||
service servT(server)[Server 4]
|
||||
service servB(server)[Server 5]
|
||||
|
||||
servC (L--R) servL
|
||||
servC (R--L) servR
|
||||
servC (T--B) servT
|
||||
servC (B--T) servB
|
||||
|
||||
servL (T--L) servT
|
||||
servL (B--L) servB
|
||||
servR (T--R) servT
|
||||
servR (B--R) servB
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render an architecture diagram with group edges', () => {
|
||||
imgSnapshotTest(
|
||||
`architecture-beta
|
||||
group left_group(cloud)[Left]
|
||||
group right_group(cloud)[Right]
|
||||
group top_group(cloud)[Top]
|
||||
group bottom_group(cloud)[Bottom]
|
||||
group center_group(cloud)[Center]
|
||||
|
||||
service left_disk(disk)[Disk] in left_group
|
||||
service right_disk(disk)[Disk] in right_group
|
||||
service top_disk(disk)[Disk] in top_group
|
||||
service bottom_disk(disk)[Disk] in bottom_group
|
||||
service center_disk(disk)[Disk] in center_group
|
||||
|
||||
left_disk{group} (R--L) center_disk{group}
|
||||
right_disk{group} (L--R) center_disk{group}
|
||||
top_disk{group} (B--T) center_disk{group}
|
||||
bottom_disk{group} (T--B) center_disk{group}
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render an architecture diagram with edge labels', () => {
|
||||
imgSnapshotTest(
|
||||
`architecture-beta
|
||||
service servC(server)[Server 1]
|
||||
service servL(server)[Server 2]
|
||||
service servR(server)[Server 3]
|
||||
service servT(server)[Server 4]
|
||||
service servB(server)[Server 5]
|
||||
|
||||
servC L-[Label]-R servL
|
||||
servC R-[Label]-L servR
|
||||
servC T-[Label]-B servT
|
||||
servC B-[Label]-T servB
|
||||
|
||||
servL T-[Label]-L servT
|
||||
servL B-[Label]-L servB
|
||||
servR T-[Label]-R servT
|
||||
servR B-[Label]-R servB
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render an architecture diagram with simple junction edges', () => {
|
||||
imgSnapshotTest(
|
||||
`architecture-beta
|
||||
service left_disk(disk)[Disk]
|
||||
service top_disk(disk)[Disk]
|
||||
service bottom_disk(disk)[Disk]
|
||||
service top_gateway(internet)[Gateway]
|
||||
service bottom_gateway(internet)[Gateway]
|
||||
junction juncC
|
||||
junction juncR
|
||||
|
||||
left_disk R--L juncC
|
||||
top_disk B--T juncC
|
||||
bottom_disk T--B juncC
|
||||
juncC R--L juncR
|
||||
top_gateway B--T juncR
|
||||
bottom_gateway T--B juncR
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render an architecture diagram with complex junction edges', () => {
|
||||
imgSnapshotTest(
|
||||
`architecture-beta
|
||||
group left
|
||||
group right
|
||||
service left_disk(disk)[Disk] in left
|
||||
service top_disk(disk)[Disk] in left
|
||||
service bottom_disk(disk)[Disk] in left
|
||||
service top_gateway(internet)[Gateway] in right
|
||||
service bottom_gateway(internet)[Gateway] in right
|
||||
junction juncC in left
|
||||
junction juncR in right
|
||||
|
||||
left_disk R--L juncC
|
||||
top_disk B--T juncC
|
||||
bottom_disk T--B juncC
|
||||
|
||||
|
||||
top_gateway (B--T juncR
|
||||
bottom_gateway (T--B juncR
|
||||
|
||||
juncC{group} R--L) juncR{group}
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('should render an architecture diagram with a reasonable height', () => {
|
||||
imgSnapshotTest(
|
||||
`architecture-beta
|
||||
group federated(cloud)[Federated Environment]
|
||||
service server1(server)[System] in federated
|
||||
service edge(server)[Edge Device] in federated
|
||||
server1:R -- L:edge
|
||||
|
||||
group on_prem(cloud)[Hub]
|
||||
service firewall(server)[Firewall Device] in on_prem
|
||||
service server(server)[Server] in on_prem
|
||||
firewall:R -- L:server
|
||||
|
||||
service db1(database)[db1] in on_prem
|
||||
service db2(database)[db2] in on_prem
|
||||
service db3(database)[db3] in on_prem
|
||||
service db4(database)[db4] in on_prem
|
||||
service db5(database)[db5] in on_prem
|
||||
service db6(database)[db6] in on_prem
|
||||
|
||||
junction mid in on_prem
|
||||
server:B -- T:mid
|
||||
|
||||
junction 1Leftofmid in on_prem
|
||||
1Leftofmid:R -- L:mid
|
||||
1Leftofmid:B -- T:db1
|
||||
|
||||
junction 2Leftofmid in on_prem
|
||||
2Leftofmid:R -- L:1Leftofmid
|
||||
2Leftofmid:B -- T:db2
|
||||
|
||||
junction 3Leftofmid in on_prem
|
||||
3Leftofmid:R -- L:2Leftofmid
|
||||
3Leftofmid:B -- T:db3
|
||||
|
||||
junction 1RightOfMid in on_prem
|
||||
mid:R -- L:1RightOfMid
|
||||
1RightOfMid:B -- T:db4
|
||||
|
||||
junction 2RightOfMid in on_prem
|
||||
1RightOfMid:R -- L:2RightOfMid
|
||||
2RightOfMid:B -- T:db5
|
||||
|
||||
junction 3RightOfMid in on_prem
|
||||
2RightOfMid:R -- L:3RightOfMid
|
||||
3RightOfMid:B -- T:db6
|
||||
|
||||
edge:R -- L:firewall
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
// Skipped as the layout is not deterministic, and causes issues in E2E tests.
|
||||
describe.skip('architecture - external', () => {
|
||||
it('should allow adding external icons', () => {
|
||||
urlSnapshotTest('http://localhost:9000/architecture-external.html');
|
||||
});
|
||||
});
|
@@ -14,7 +14,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL2: should handle columns statement in sub-blocks', () => {
|
||||
it('BL2: should handle colums statement in sub-blocks', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
id1["Hello"]
|
||||
@@ -30,7 +30,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL3: should align block widths and handle columns statement in sub-blocks', () => {
|
||||
it('BL3: should align block widths and handle colums statement in sub-blocks', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
block
|
||||
@@ -46,7 +46,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL4: should align block widths and handle columns statements in deeper sub-blocks then 1 level', () => {
|
||||
it('BL4: should align block widths and handle colums statements in deeper sub-blocks then 1 level', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 1
|
||||
@@ -66,7 +66,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL5: should align block widths and handle columns statements in deeper sub-blocks then 1 level (alt)', () => {
|
||||
it('BL5: should align block widths and handle colums statements in deeper sub-blocks then 1 level (alt)', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 1
|
||||
@@ -236,7 +236,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL17: width alignment - blocks should be equal in width', () => {
|
||||
it('BL16: width alignment - blocks shold be equal in width', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A("This is the text")
|
||||
@@ -247,7 +247,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL18: block types 1 - square, rounded and circle', () => {
|
||||
it('BL17: block types 1 - square, rounded and circle', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A["square"]
|
||||
@@ -258,7 +258,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL19: block types 2 - odd, diamond and hexagon', () => {
|
||||
it('BL18: block types 2 - odd, diamond and hexagon', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A>"rect_left_inv_arrow"]
|
||||
@@ -269,7 +269,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL20: block types 3 - stadium', () => {
|
||||
it('BL19: block types 3 - stadium', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A(["stadium"])
|
||||
@@ -278,7 +278,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL21: block types 4 - lean right, lean left, trapezoid and inv trapezoid', () => {
|
||||
it('BL20: 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('BL22: block types 1 - square, rounded and circle', () => {
|
||||
it('BL21: block types 1 - square, rounded and circle', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A["square"]
|
||||
@@ -301,7 +301,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL23: sizing - it should be possible to make a block wider', () => {
|
||||
it('BL22: sizing - it should be possible to make a block wider', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
A("rounded"):2
|
||||
@@ -312,7 +312,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL24: sizing - it should be possible to make a composite block wider', () => {
|
||||
it('BL23: sizing - it should be possible to make a composite block wider', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
block:2
|
||||
@@ -324,7 +324,7 @@ describe('Block diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('BL25: block in the middle with space on each side', () => {
|
||||
it('BL24: block in the middle with space on each side', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 3
|
||||
@@ -335,7 +335,7 @@ describe('Block diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('BL26: space and an edge', () => {
|
||||
it('BL25: space and an edge', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 5
|
||||
@@ -345,7 +345,7 @@ describe('Block diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('BL27: block sizes for regular blocks', () => {
|
||||
it('BL26: block sizes for regular blocks', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 3
|
||||
@@ -354,7 +354,7 @@ describe('Block diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('BL28: composite block with a set width - f should use the available space', () => {
|
||||
it('BL27: composite block with a set width - f should use the available space', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 3
|
||||
@@ -363,12 +363,11 @@ describe('Block diagram', () => {
|
||||
f
|
||||
end
|
||||
g
|
||||
`,
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('BL29: composite block with a set width - f and g should split the available space', () => {
|
||||
it('BL23: composite block with a set width - f and g should split the available space', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 3
|
||||
@@ -380,7 +379,7 @@ describe('Block diagram', () => {
|
||||
h
|
||||
i
|
||||
j
|
||||
`,
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
@@ -1,7 +1,7 @@
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('C4 diagram', () => {
|
||||
it('C4.1 should render a simple C4Context diagram', () => {
|
||||
it('should render a simple C4Context diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
C4Context
|
||||
@@ -30,8 +30,9 @@ describe('C4 diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('C4.2 should render a simple C4Container diagram', () => {
|
||||
it('should render a simple C4Container diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
C4Container
|
||||
@@ -49,8 +50,9 @@ describe('C4 diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('C4.3 should render a simple C4Component diagram', () => {
|
||||
it('should render a simple C4Component diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
C4Component
|
||||
@@ -67,8 +69,9 @@ describe('C4 diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('C4.4 should render a simple C4Dynamic diagram', () => {
|
||||
it('should render a simple C4Dynamic diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
C4Dynamic
|
||||
@@ -90,8 +93,9 @@ describe('C4 diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
it('C4.5 should render a simple C4Deployment diagram', () => {
|
||||
it('should render a simple C4Deployment diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
C4Deployment
|
||||
@@ -113,5 +117,6 @@ describe('C4 diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
});
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -76,7 +76,7 @@ describe('Class diagram V2', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('2.1 should render a simple class diagram with different visibilities', () => {
|
||||
it('should render a simple class diagram with different visibilities', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
classDiagram-v2
|
||||
@@ -93,7 +93,7 @@ describe('Class diagram V2', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('3: should render multiple class diagrams', () => {
|
||||
it('should render multiple class diagrams', () => {
|
||||
imgSnapshotTest(
|
||||
[
|
||||
`
|
||||
@@ -581,63 +581,4 @@ class C13["With Città foreign language"]
|
||||
{ logLevel: 1, flowchart: { htmlLabels: false } }
|
||||
);
|
||||
});
|
||||
|
||||
it('renders a class diagram with a generic class in a namespace', () => {
|
||||
const diagramDefinition = `
|
||||
classDiagram-v2
|
||||
namespace Company.Project.Module {
|
||||
class GenericClass~T~ {
|
||||
+addItem(item: T)
|
||||
+getItem() T
|
||||
}
|
||||
}
|
||||
`;
|
||||
|
||||
imgSnapshotTest(diagramDefinition);
|
||||
});
|
||||
|
||||
it('renders a class diagram with nested namespaces and relationships', () => {
|
||||
const diagramDefinition = `
|
||||
classDiagram-v2
|
||||
namespace Company.Project.Module.SubModule {
|
||||
class Report {
|
||||
+generatePDF(data: List)
|
||||
+generateCSV(data: List)
|
||||
}
|
||||
}
|
||||
namespace Company.Project.Module {
|
||||
class Admin {
|
||||
+generateReport()
|
||||
}
|
||||
}
|
||||
Admin --> Report : generates
|
||||
`;
|
||||
|
||||
imgSnapshotTest(diagramDefinition);
|
||||
});
|
||||
|
||||
it('renders a class diagram with multiple classes and relationships in a namespace', () => {
|
||||
const diagramDefinition = `
|
||||
classDiagram-v2
|
||||
namespace Company.Project.Module {
|
||||
class User {
|
||||
+login(username: String, password: String)
|
||||
+logout()
|
||||
}
|
||||
class Admin {
|
||||
+addUser(user: User)
|
||||
+removeUser(user: User)
|
||||
+generateReport()
|
||||
}
|
||||
class Report {
|
||||
+generatePDF(reportData: List)
|
||||
+generateCSV(reportData: List)
|
||||
}
|
||||
}
|
||||
Admin --> User : manages
|
||||
Admin --> Report : generates
|
||||
`;
|
||||
|
||||
imgSnapshotTest(diagramDefinition);
|
||||
});
|
||||
});
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -32,6 +32,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{ logLevel: 1 }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('2: should render a simple class diagrams with cardinality', () => {
|
||||
@@ -60,6 +61,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('3: should render a simple class diagram with different visibilities', () => {
|
||||
@@ -77,6 +79,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('4: should render a simple class diagram with comments', () => {
|
||||
@@ -106,6 +109,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('5: should render a simple class diagram with abstract method', () => {
|
||||
@@ -117,6 +121,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('6: should render a simple class diagram with static method', () => {
|
||||
@@ -128,6 +133,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('7: should render a simple class diagram with Generic class', () => {
|
||||
@@ -147,6 +153,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('8: should render a simple class diagram with Generic class and relations', () => {
|
||||
@@ -167,6 +174,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('9: should render a simple class diagram with clickable link', () => {
|
||||
@@ -188,6 +196,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('10: should render a simple class diagram with clickable callback', () => {
|
||||
@@ -209,6 +218,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('11: should render a simple class diagram with return type on method', () => {
|
||||
@@ -223,6 +233,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('12: should render a simple class diagram with generic types', () => {
|
||||
@@ -238,6 +249,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('13: should render a simple class diagram with css classes applied', () => {
|
||||
@@ -255,6 +267,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('14: should render a simple class diagram with css classes applied directly', () => {
|
||||
@@ -270,6 +283,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('15: should render a simple class diagram with css classes applied to multiple classes', () => {
|
||||
@@ -284,6 +298,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('16: should render multiple class diagrams', () => {
|
||||
@@ -336,6 +351,7 @@ describe('Class diagram', () => {
|
||||
],
|
||||
{}
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
// it('17: should render a class diagram when useMaxWidth is true (default)', () => {
|
||||
@@ -405,6 +421,7 @@ describe('Class diagram', () => {
|
||||
`,
|
||||
{ logLevel: 1 }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('should render class diagram with newlines in title', () => {
|
||||
@@ -422,6 +439,7 @@ describe('Class diagram', () => {
|
||||
+quack()
|
||||
}
|
||||
`);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('should render class diagram with many newlines in title', () => {
|
||||
@@ -429,7 +447,7 @@ describe('Class diagram', () => {
|
||||
classDiagram
|
||||
class \`This\nTitle\nHas\nMany\nNewlines\` {
|
||||
+String Also
|
||||
-String Many
|
||||
-Stirng Many
|
||||
#int Members
|
||||
+And()
|
||||
-Many()
|
||||
@@ -443,7 +461,7 @@ describe('Class diagram', () => {
|
||||
classDiagram
|
||||
class \`This\nTitle\nHas\nMany\nNewlines\` {
|
||||
+String Also
|
||||
-String Many
|
||||
-Stirng Many
|
||||
#int Members
|
||||
+And()
|
||||
-Many()
|
||||
@@ -459,7 +477,7 @@ describe('Class diagram', () => {
|
||||
namespace testingNamespace {
|
||||
class \`This\nTitle\nHas\nMany\nNewlines\` {
|
||||
+String Also
|
||||
-String Many
|
||||
-Stirng Many
|
||||
#int Members
|
||||
+And()
|
||||
-Many()
|
||||
|
@@ -1,652 +0,0 @@
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
const testOptions = [
|
||||
{ description: '', options: { logLevel: 1 } },
|
||||
{ description: 'ELK: ', options: { logLevel: 1, layout: 'elk' } },
|
||||
{ description: 'HD: ', options: { logLevel: 1, look: 'handDrawn' } },
|
||||
];
|
||||
|
||||
describe('Entity Relationship Diagram Unified', () => {
|
||||
testOptions.forEach(({ description, options }) => {
|
||||
it(`${description}should render a simple ER diagram`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
CUSTOMER ||--o{ ORDER : places
|
||||
ORDER ||--|{ LINE-ITEM : contains
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render a simple ER diagram without htmlLabels`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
CUSTOMER ||--o{ ORDER : places
|
||||
ORDER ||--|{ LINE-ITEM : contains
|
||||
`,
|
||||
{ ...options, htmlLabels: false }
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render an ER diagram with a recursive relationship`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
CUSTOMER ||..o{ CUSTOMER : refers
|
||||
CUSTOMER ||--o{ ORDER : places
|
||||
ORDER ||--|{ LINE-ITEM : contains
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render an ER diagram with multiple relationships between the same two entities`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
CUSTOMER ||--|{ ADDRESS : "invoiced at"
|
||||
CUSTOMER ||--|{ ADDRESS : "receives goods at"
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render a cyclical ER diagram`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
A ||--|{ B : likes
|
||||
B ||--|{ C : likes
|
||||
C ||--|{ A : likes
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render a not-so-simple ER diagram`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
CUSTOMER }|..|{ DELIVERY-ADDRESS : has
|
||||
CUSTOMER ||--o{ ORDER : places
|
||||
CUSTOMER ||--o{ INVOICE : "liable for"
|
||||
DELIVERY-ADDRESS ||--o{ ORDER : receives
|
||||
INVOICE ||--|{ ORDER : covers
|
||||
ORDER ||--|{ ORDER-ITEM : includes
|
||||
PRODUCT-CATEGORY ||--|{ PRODUCT : contains
|
||||
PRODUCT ||--o{ ORDER-ITEM : "ordered in"
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render a not-so-simple ER diagram without htmlLabels`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
CUSTOMER }|..|{ DELIVERY-ADDRESS : has
|
||||
CUSTOMER ||--o{ ORDER : places
|
||||
CUSTOMER ||--o{ INVOICE : "liable for"
|
||||
DELIVERY-ADDRESS ||--o{ ORDER : receives
|
||||
INVOICE ||--|{ ORDER : covers
|
||||
ORDER ||--|{ ORDER-ITEM : includes
|
||||
PRODUCT-CATEGORY ||--|{ PRODUCT : contains
|
||||
PRODUCT ||--o{ ORDER-ITEM : "ordered in"
|
||||
`,
|
||||
{ ...options, htmlLabels: false }
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render multiple ER diagrams`, () => {
|
||||
imgSnapshotTest(
|
||||
[
|
||||
`
|
||||
erDiagram
|
||||
CUSTOMER ||--o{ ORDER : places
|
||||
ORDER ||--|{ LINE-ITEM : contains
|
||||
`,
|
||||
`
|
||||
erDiagram
|
||||
CUSTOMER ||--o{ ORDER : places
|
||||
ORDER ||--|{ LINE-ITEM : contains
|
||||
`,
|
||||
],
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render an ER diagram with blank or empty labels`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
BOOK }|..|{ AUTHOR : ""
|
||||
BOOK }|..|{ GENRE : " "
|
||||
AUTHOR }|..|{ GENRE : " "
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities that have no relationships`, () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
DEAD_PARROT
|
||||
HERMIT
|
||||
RECLUSE
|
||||
SOCIALITE }o--o{ SOCIALITE : "interacts with"
|
||||
RECLUSE }o--o{ SOCIALITE : avoids
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with and without attributes`, () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
BOOK { string title }
|
||||
AUTHOR }|..|{ BOOK : writes
|
||||
BOOK { float price }
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with generic and array attributes`, () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
BOOK {
|
||||
string title
|
||||
string[] authors
|
||||
type~T~ type
|
||||
}
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with generic and array attributes without htmlLabels`, () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
BOOK {
|
||||
string title
|
||||
string[] authors
|
||||
type~T~ type
|
||||
}
|
||||
`,
|
||||
{ ...options, htmlLabels: false }
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with length in attributes type`, () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
CLUSTER {
|
||||
varchar(99) name
|
||||
string(255) description
|
||||
}
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with length in attributes type without htmlLabels`, () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
CLUSTER {
|
||||
varchar(99) name
|
||||
string(255) description
|
||||
}
|
||||
`,
|
||||
{ ...options, htmlLabels: false }
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities and attributes with big and small entity names`, () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
PRIVATE_FINANCIAL_INSTITUTION {
|
||||
string name
|
||||
int turnover
|
||||
}
|
||||
PRIVATE_FINANCIAL_INSTITUTION ||..|{ EMPLOYEE : employs
|
||||
EMPLOYEE { bool officer_of_firm }
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities and attributes with big and small entity names without htmlLabels`, () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
PRIVATE_FINANCIAL_INSTITUTION {
|
||||
string name
|
||||
int turnover
|
||||
}
|
||||
PRIVATE_FINANCIAL_INSTITUTION ||..|{ EMPLOYEE : employs
|
||||
EMPLOYEE { bool officer_of_firm }
|
||||
`,
|
||||
{ ...options, htmlLabels: false }
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with attributes that begin with asterisk`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
BOOK {
|
||||
int *id
|
||||
string name
|
||||
varchar(99) summary
|
||||
}
|
||||
BOOK }o..o{ STORE : soldBy
|
||||
STORE {
|
||||
int *id
|
||||
string name
|
||||
varchar(50) address
|
||||
}
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with attributes that begin with asterisk without htmlLabels`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
BOOK {
|
||||
int *id
|
||||
string name
|
||||
varchar(99) summary
|
||||
}
|
||||
BOOK }o..o{ STORE : soldBy
|
||||
STORE {
|
||||
int *id
|
||||
string name
|
||||
varchar(50) address
|
||||
}
|
||||
`,
|
||||
{ ...options, htmlLabels: false }
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with keys`, () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
AUTHOR_WITH_LONG_ENTITY_NAME {
|
||||
string name PK
|
||||
}
|
||||
AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
|
||||
BOOK {
|
||||
float price
|
||||
string author FK
|
||||
string title PK
|
||||
}
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with keys without htmlLabels`, () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
AUTHOR_WITH_LONG_ENTITY_NAME {
|
||||
string name PK
|
||||
}
|
||||
AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
|
||||
BOOK {
|
||||
float price
|
||||
string author FK
|
||||
string title PK
|
||||
}
|
||||
`,
|
||||
{ ...options, htmlLabels: false }
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with comments`, () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
AUTHOR_WITH_LONG_ENTITY_NAME {
|
||||
string name "comment"
|
||||
}
|
||||
AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
|
||||
BOOK {
|
||||
string author
|
||||
string title "author comment"
|
||||
float price "price comment"
|
||||
}
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with comments without htmlLabels`, () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
AUTHOR_WITH_LONG_ENTITY_NAME {
|
||||
string name "comment"
|
||||
}
|
||||
AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
|
||||
BOOK {
|
||||
string author
|
||||
string title "author comment"
|
||||
float price "price comment"
|
||||
}
|
||||
`,
|
||||
{ ...options, htmlLabels: false }
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with keys and comments`, () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
AUTHOR_WITH_LONG_ENTITY_NAME {
|
||||
string name PK "comment"
|
||||
}
|
||||
AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
|
||||
BOOK {
|
||||
string description
|
||||
float price "price comment"
|
||||
string title PK "title comment"
|
||||
string author FK
|
||||
}
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with keys and comments without htmlLabels`, () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
AUTHOR_WITH_LONG_ENTITY_NAME {
|
||||
string name PK "comment"
|
||||
}
|
||||
AUTHOR_WITH_LONG_ENTITY_NAME }|..|{ BOOK : writes
|
||||
BOOK {
|
||||
string description
|
||||
float price "price comment"
|
||||
string title PK "title comment"
|
||||
string author FK
|
||||
}
|
||||
`,
|
||||
{ ...options, htmlLabels: false }
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with aliases`, () => {
|
||||
renderGraph(
|
||||
`
|
||||
erDiagram
|
||||
T1 one or zero to one or more T2 : test
|
||||
T2 one or many optionally to zero or one T3 : test
|
||||
T3 zero or more to zero or many T4 : test
|
||||
T4 many(0) to many(1) T5 : test
|
||||
T5 many optionally to one T6 : test
|
||||
T6 only one optionally to only one T1 : test
|
||||
T4 0+ to 1+ T6 : test
|
||||
T1 1 to 1 T3 : test
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render a simple ER diagram with a title`, () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
title: simple ER diagram
|
||||
---
|
||||
erDiagram
|
||||
CUSTOMER ||--o{ ORDER : places
|
||||
ORDER ||--|{ LINE-ITEM : contains
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with entity name aliases`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
p[Person] {
|
||||
varchar(64) firstName
|
||||
varchar(64) lastName
|
||||
}
|
||||
c["Customer Account"] {
|
||||
varchar(128) email
|
||||
}
|
||||
p ||--o| c : has
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render relationship labels with line breaks`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
p[Person] {
|
||||
string firstName
|
||||
string lastName
|
||||
}
|
||||
a["Customer Account"] {
|
||||
string email
|
||||
}
|
||||
|
||||
b["Customer Account Secondary"] {
|
||||
string email
|
||||
}
|
||||
|
||||
c["Customer Account Tertiary"] {
|
||||
string email
|
||||
}
|
||||
|
||||
d["Customer Account Nth"] {
|
||||
string email
|
||||
}
|
||||
|
||||
p ||--o| a : "has<br />one"
|
||||
p ||--o| b : "has<br />one<br />two"
|
||||
p ||--o| c : "has<br />one<br/>two<br />three"
|
||||
p ||--o| d : "has<br />one<br />two<br/>three<br />...<br/>Nth"
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render an ER diagram with unicode text`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
_**testẽζ➕Ø😀㌕ぼ**_ {
|
||||
*__List~List~int~~sdfds__* **driversLicense** PK "***The l😀icense #***"
|
||||
*string(99)~T~~~~~~* firstName "Only __99__ <br>characters are a<br>llowed dsfsdfsdfsdfs"
|
||||
string last*Name*
|
||||
string __phone__ UK
|
||||
int _age_
|
||||
}
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render an ER diagram with unicode text without htmlLabels`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
_**testẽζ➕Ø😀㌕ぼ**_ {
|
||||
*__List~List~int~~sdfds__* **driversLicense** PK "***The l😀icense #***"
|
||||
*string(99)~T~~~~~~* firstName "Only __99__ <br>characters are a<br>llowed dsfsdfsdfsdfs"
|
||||
string last*Name*
|
||||
string __phone__ UK
|
||||
int _age_
|
||||
}
|
||||
`,
|
||||
{ ...options, htmlLabels: false }
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render an ER diagram with relationships with unicode text`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
person[😀] {
|
||||
string *first*Name
|
||||
string _**last**Name_
|
||||
}
|
||||
a["*Customer Account*"] {
|
||||
**string** ema*i*l
|
||||
}
|
||||
person ||--o| a : __hẽ😀__
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render an ER diagram with relationships with unicode text without htmlLabels`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
person[😀] {
|
||||
string *first*Name
|
||||
string _**last**Name_
|
||||
}
|
||||
a["*Customer Account*"] {
|
||||
**string** ema*i*l
|
||||
}
|
||||
person ||--o| a : __hẽ😀__
|
||||
`,
|
||||
{ ...options, htmlLabels: false }
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render an ER diagram with TB direction`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
direction TB
|
||||
CAR ||--|{ NAMED-DRIVER : allows
|
||||
PERSON ||..o{ NAMED-DRIVER : is
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render an ER diagram with BT direction`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
direction BT
|
||||
CAR ||--|{ NAMED-DRIVER : allows
|
||||
PERSON ||..o{ NAMED-DRIVER : is
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render an ER diagram with LR direction`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
direction LR
|
||||
CAR ||--|{ NAMED-DRIVER : allows
|
||||
PERSON ||..o{ NAMED-DRIVER : is
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render an ER diagram with RL direction`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
direction RL
|
||||
CAR ||--|{ NAMED-DRIVER : allows
|
||||
PERSON ||..o{ NAMED-DRIVER : is
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with styles applied from style statement`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
c[CUSTOMER]
|
||||
p[PERSON]
|
||||
style c,p fill:#f9f,stroke:blue, color:grey, font-size:24px,font-weight:bold
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with styles applied from style statement without htmlLabels`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
c[CUSTOMER]
|
||||
p[PERSON]
|
||||
style c,p fill:#f9f,stroke:blue, color:grey, font-size:24px,font-weight:bold
|
||||
`,
|
||||
{ ...options, htmlLabels: false }
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with styles applied from class statement`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
c[CUSTOMER]
|
||||
p[PERSON]:::blue
|
||||
classDef bold font-size:24px, font-weight: bold
|
||||
classDef blue stroke:lightblue, color: #0000FF
|
||||
class c,p bold
|
||||
`,
|
||||
options
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with styles applied from class statement without htmlLabels`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
c[CUSTOMER]
|
||||
p[PERSON]:::blue
|
||||
classDef bold font-size:24px, font-weight: bold
|
||||
classDef blue stroke:lightblue, color: #0000FF
|
||||
class c,p bold
|
||||
`,
|
||||
{ ...options, htmlLabels: false }
|
||||
);
|
||||
});
|
||||
|
||||
it(`${description}should render entities with styles applied from the default class and other styles`, () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
c[CUSTOMER]
|
||||
p[PERSON]:::blue
|
||||
classDef blue stroke:lightblue, color: #0000FF
|
||||
classDef default fill:pink
|
||||
style c color:green
|
||||
`,
|
||||
{ ...options }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
@@ -109,8 +109,8 @@ describe('Entity Relationship Diagram', () => {
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±6%
|
||||
expect(maxWidthValue).to.be.within(140 * 0.96, 140 * 1.06);
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
expect(maxWidthValue).to.be.within(140 * 0.95, 140 * 1.05);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -125,8 +125,8 @@ describe('Entity Relationship Diagram', () => {
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±6%
|
||||
expect(width).to.be.within(140 * 0.96, 140 * 1.06);
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
expect(width).to.be.within(140 * 0.95, 140 * 1.05);
|
||||
// expect(svg).to.have.attr('height', '465');
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
@@ -218,6 +218,7 @@ describe('Entity Relationship Diagram', () => {
|
||||
`,
|
||||
{ loglevel: 1 }
|
||||
);
|
||||
cy.get('svg');
|
||||
});
|
||||
|
||||
it('should render entities with keys', () => {
|
||||
@@ -321,37 +322,4 @@ ORDER ||--|{ LINE-ITEM : contains
|
||||
{ logLevel: 1 }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render relationship labels with line breaks', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
p[Person] {
|
||||
string firstName
|
||||
string lastName
|
||||
}
|
||||
a["Customer Account"] {
|
||||
string email
|
||||
}
|
||||
|
||||
b["Customer Account Secondary"] {
|
||||
string email
|
||||
}
|
||||
|
||||
c["Customer Account Tertiary"] {
|
||||
string email
|
||||
}
|
||||
|
||||
d["Customer Account Nth"] {
|
||||
string email
|
||||
}
|
||||
|
||||
p ||--o| a : "has<br />one"
|
||||
p ||--o| b : "has<br />one<br />two"
|
||||
p ||--o| c : "has<br />one<br/>two<br />three"
|
||||
p ||--o| d : "has<br />one<br />two<br/>three<br />...<br/>Nth"
|
||||
`,
|
||||
{ logLevel: 1 }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -3,7 +3,7 @@ import { imgSnapshotTest } from '../../helpers/util';
|
||||
describe('Error Diagrams', () => {
|
||||
beforeEach(() => {
|
||||
cy.on('uncaught:exception', (err) => {
|
||||
expect(err.message).to.include('error');
|
||||
expect(err.message).to.include('Parse error');
|
||||
// return false to prevent the error from
|
||||
// failing this test
|
||||
return false;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
import { imgSnapshotTest, renderGraph, verifyNumber } from '../../helpers/util.ts';
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('Flowchart ELK', () => {
|
||||
describe.skip('Flowchart ELK', () => {
|
||||
it('1-elk: should render a simple flowchart', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart-elk TD
|
||||
@@ -109,7 +109,7 @@ describe('Flowchart ELK', () => {
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
verifyNumber(maxWidthValue, 380);
|
||||
expect(maxWidthValue).to.be.within(230 * 0.95, 230 * 1.05);
|
||||
});
|
||||
});
|
||||
it('8-elk: should render a flowchart when useMaxWidth is false', () => {
|
||||
@@ -128,7 +128,7 @@ describe('Flowchart ELK', () => {
|
||||
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);
|
||||
verifyNumber(width, 380);
|
||||
expect(width).to.be.within(230 * 0.95, 230 * 1.05);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
@@ -208,13 +208,13 @@ describe('Flowchart ELK', () => {
|
||||
`flowchart-elk TB
|
||||
internet
|
||||
nat
|
||||
router
|
||||
routeur
|
||||
lb1
|
||||
lb2
|
||||
compute1
|
||||
compute2
|
||||
subgraph project
|
||||
router
|
||||
routeur
|
||||
nat
|
||||
subgraph subnet1
|
||||
compute1
|
||||
@@ -225,8 +225,8 @@ describe('Flowchart ELK', () => {
|
||||
lb2
|
||||
end
|
||||
end
|
||||
internet --> router
|
||||
router --> subnet1 & subnet2
|
||||
internet --> routeur
|
||||
routeur --> subnet1 & subnet2
|
||||
subnet1 & subnet2 --> nat --> internet
|
||||
`,
|
||||
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||
@@ -443,7 +443,7 @@ flowchart-elk TD
|
||||
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||
);
|
||||
});
|
||||
it('63-elk: title on subgraphs should be themeable', () => {
|
||||
it('63-elk: title on subgraphs should be themable', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
%%{init:{"theme":"base", "themeVariables": {"primaryColor":"#411d4e", "titleColor":"white", "darkMode":true}}}%%
|
||||
@@ -692,7 +692,7 @@ A --> B
|
||||
{}
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const edges = svg[0].querySelectorAll('.edges > path');
|
||||
const edges = svg.querySelectorAll('.edges > path');
|
||||
edges.forEach((edge) => {
|
||||
expect(edge).to.have.class('flowchart-link');
|
||||
});
|
||||
@@ -739,7 +739,7 @@ NL\`") --"\`1o **bold**\`"--> c
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it.skip('Wrapping long text with a new line', () => {
|
||||
it('Wrapping long text with a new line', () => {
|
||||
imgSnapshotTest(
|
||||
`%%{init: {"flowchart": {"htmlLabels": true}} }%%
|
||||
flowchart-elk LR
|
||||
@@ -837,216 +837,6 @@ subgraph "\`**Two**\`"
|
||||
in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog")
|
||||
end
|
||||
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('Sub graphs', () => {
|
||||
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 } }
|
||||
);
|
||||
});
|
||||
it('6080: should handle diamond shape intersections', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
subgraph s1["Untitled subgraph"]
|
||||
n1["Evaluate"]
|
||||
n2["Option 1"]
|
||||
n3["Option 2"]
|
||||
n4["fa:fa-car Option 3"]
|
||||
end
|
||||
subgraph s2["Untitled subgraph"]
|
||||
n5["Evaluate"]
|
||||
n6["Option 1"]
|
||||
n7["Option 2"]
|
||||
n8["fa:fa-car Option 3"]
|
||||
end
|
||||
A["Start"] -- Some text --> B("Continue")
|
||||
B --> C{"Evaluate"}
|
||||
C -- One --> D["Option 1"]
|
||||
C -- Two --> E["Option 2"]
|
||||
C -- Three --> F["fa:fa-car Option 3"]
|
||||
n1 -- One --> n2
|
||||
n1 -- Two --> n3
|
||||
n1 -- Three --> n4
|
||||
n5 -- One --> n6
|
||||
n5 -- Two --> n7
|
||||
n5 -- Three --> n8
|
||||
n1@{ shape: diam}
|
||||
n2@{ shape: rect}
|
||||
n3@{ shape: rect}
|
||||
n4@{ shape: rect}
|
||||
n5@{ shape: diam}
|
||||
n6@{ shape: rect}
|
||||
n7@{ shape: rect}
|
||||
n8@{ shape: rect}
|
||||
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('6088-1: should handle diamond shape intersections', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
subgraph S2
|
||||
subgraph s1["APA"]
|
||||
D{"Use the editor"}
|
||||
end
|
||||
|
||||
|
||||
D -- Mermaid js --> I{"fa:fa-code Text"}
|
||||
D --> I
|
||||
D --> I
|
||||
|
||||
end
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('6088-2: should handle diamond shape intersections', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
a
|
||||
subgraph s0["APA"]
|
||||
subgraph s8["APA"]
|
||||
subgraph s1["APA"]
|
||||
D{"X"}
|
||||
E[Q]
|
||||
end
|
||||
subgraph s3["BAPA"]
|
||||
F[Q]
|
||||
I
|
||||
end
|
||||
D --> I
|
||||
D --> I
|
||||
D --> I
|
||||
|
||||
I{"X"}
|
||||
end
|
||||
end
|
||||
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('6088-3: should handle diamond shape intersections', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
a
|
||||
D{"Use the editor"}
|
||||
|
||||
D -- Mermaid js --> I{"fa:fa-code Text"}
|
||||
D-->I
|
||||
D-->I
|
||||
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('6088-4: should handle diamond shape intersections', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
subgraph s1["Untitled subgraph"]
|
||||
n1["Evaluate"]
|
||||
n2["Option 1"]
|
||||
n3["Option 2"]
|
||||
n4["fa:fa-car Option 3"]
|
||||
end
|
||||
subgraph s2["Untitled subgraph"]
|
||||
n5["Evaluate"]
|
||||
n6["Option 1"]
|
||||
n7["Option 2"]
|
||||
n8["fa:fa-car Option 3"]
|
||||
end
|
||||
A["Start"] -- Some text --> B("Continue")
|
||||
B --> C{"Evaluate"}
|
||||
C -- One --> D["Option 1"]
|
||||
C -- Two --> E["Option 2"]
|
||||
C -- Three --> F["fa:fa-car Option 3"]
|
||||
n1 -- One --> n2
|
||||
n1 -- Two --> n3
|
||||
n1 -- Three --> n4
|
||||
n5 -- One --> n6
|
||||
n5 -- Two --> n7
|
||||
n5 -- Three --> n8
|
||||
n1@{ shape: diam}
|
||||
n2@{ shape: rect}
|
||||
n3@{ shape: rect}
|
||||
n4@{ shape: rect}
|
||||
n5@{ shape: diam}
|
||||
n6@{ shape: rect}
|
||||
n7@{ shape: rect}
|
||||
n8@{ shape: rect}
|
||||
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
|
||||
it('6088-5: should handle diamond shape intersections', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
A{A} --> B & C
|
||||
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
});
|
||||
it('6088-6: should handle diamond shape intersections', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart LR
|
||||
A{A} --> B & C
|
||||
subgraph "subbe"
|
||||
A
|
||||
end
|
||||
|
||||
`,
|
||||
{ flowchart: { titleTopMargin: 0 } }
|
||||
);
|
||||
@@ -1054,41 +844,3 @@ flowchart LR
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
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');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
File diff suppressed because it is too large
Load Diff
@@ -1,28 +0,0 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
const themes = ['default', 'forest', 'dark', 'base', 'neutral'];
|
||||
|
||||
describe('when rendering flowchart with icons', () => {
|
||||
for (const theme of themes) {
|
||||
it(`should render icons from fontawesome library on theme ${theme}`, () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TD
|
||||
A("fab:fa-twitter Twitter") --> B("fab:fa-facebook Facebook")
|
||||
B --> C("fa:fa-coffee Coffee")
|
||||
C --> D("fa:fa-car Car")
|
||||
D --> E("fab:fa-github GitHub")
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
});
|
||||
|
||||
it(`should render registered icons on theme ${theme}`, () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TD
|
||||
A("fa:fa-bell Bell")
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
@@ -1,142 +0,0 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
const aliasSet1 = ['process', 'rect', 'proc', 'rectangle'] as const;
|
||||
|
||||
const aliasSet2 = ['event', 'rounded'] as const;
|
||||
|
||||
const aliasSet3 = ['stadium', 'pill', 'terminal'] as const;
|
||||
|
||||
const aliasSet4 = ['fr-rect', 'subproc', 'subprocess', 'framed-rectangle', 'subroutine'] as const;
|
||||
|
||||
const aliasSet5 = ['db', 'database', 'cylinder', 'cyl'] as const;
|
||||
|
||||
const aliasSet6 = ['diam', 'decision', 'diamond'] as const;
|
||||
|
||||
const aliasSet7 = ['hex', 'hexagon', 'prepare'] as const;
|
||||
|
||||
const aliasSet8 = ['lean-r', 'lean-right', 'in-out'] as const;
|
||||
|
||||
const aliasSet9 = ['lean-l', 'lean-left', 'out-in'] as const;
|
||||
|
||||
const aliasSet10 = ['trap-b', 'trapezoid-bottom', 'priority'] as const;
|
||||
|
||||
const aliasSet11 = ['trap-t', 'trapezoid-top', 'manual'] as const;
|
||||
|
||||
const aliasSet12 = ['dbl-circ', 'double-circle'] as const;
|
||||
|
||||
const aliasSet13 = ['notched-rectangle', 'card', 'notch-rect'] as const;
|
||||
|
||||
const aliasSet14 = [
|
||||
'lin-rect',
|
||||
'lined-rectangle',
|
||||
'lin-proc',
|
||||
'lined-process',
|
||||
'shaded-process',
|
||||
] as const;
|
||||
|
||||
const aliasSet15 = ['sm-circ', 'small-circle', 'start'] as const;
|
||||
|
||||
const aliasSet16 = ['fr-circ', 'framed-circle', 'stop'] as const;
|
||||
|
||||
const aliasSet17 = ['fork', 'join'] as const;
|
||||
// brace-r', 'braces'
|
||||
const aliasSet18 = ['comment', 'brace-l'] as const;
|
||||
|
||||
const aliasSet19 = ['bolt', 'com-link', 'lightning-bolt'] as const;
|
||||
|
||||
const aliasSet20 = ['doc', 'document'] as const;
|
||||
|
||||
const aliasSet21 = ['delay', 'half-rounded-rectangle'] as const;
|
||||
|
||||
const aliasSet22 = ['h-cyl', 'das', 'horizontal-cylinder'] as const;
|
||||
|
||||
const aliasSet23 = ['lin-cyl', 'disk', 'lined-cylinder'] as const;
|
||||
|
||||
const aliasSet24 = ['curv-trap', 'display', 'curved-trapezoid'] as const;
|
||||
|
||||
const aliasSet25 = ['div-rect', 'div-proc', 'divided-rectangle', 'divided-process'] as const;
|
||||
|
||||
const aliasSet26 = ['extract', 'tri', 'triangle'] as const;
|
||||
|
||||
const aliasSet27 = ['win-pane', 'internal-storage', 'window-pane'] as const;
|
||||
|
||||
const aliasSet28 = ['f-circ', 'junction', 'filled-circle'] as const;
|
||||
|
||||
const aliasSet29 = ['lin-doc', 'lined-document'] as const;
|
||||
|
||||
const aliasSet30 = ['notch-pent', 'loop-limit', 'notched-pentagon'] as const;
|
||||
|
||||
const aliasSet31 = ['flip-tri', 'manual-file', 'flipped-triangle'] as const;
|
||||
|
||||
const aliasSet32 = ['sl-rect', 'manual-input', 'sloped-rectangle'] as const;
|
||||
|
||||
const aliasSet33 = ['docs', 'documents', 'st-doc', 'stacked-document'] as const;
|
||||
|
||||
const aliasSet34 = ['procs', 'processes', 'st-rect', 'stacked-rectangle'] as const;
|
||||
|
||||
const aliasSet35 = ['flag', 'paper-tape'] as const;
|
||||
|
||||
const aliasSet36 = ['bow-rect', 'stored-data', 'bow-tie-rectangle'] as const;
|
||||
|
||||
const aliasSet37 = ['cross-circ', 'summary', 'crossed-circle'] as const;
|
||||
|
||||
const aliasSet38 = ['tag-doc', 'tagged-document'] as const;
|
||||
|
||||
const aliasSet39 = ['tag-rect', 'tag-proc', 'tagged-rectangle', 'tagged-process'] as const;
|
||||
|
||||
const aliasSet40 = ['collate', 'hourglass'] as const;
|
||||
|
||||
// Aggregate all alias sets into a single array
|
||||
const aliasSets = [
|
||||
aliasSet1,
|
||||
aliasSet2,
|
||||
aliasSet3,
|
||||
aliasSet4,
|
||||
aliasSet5,
|
||||
aliasSet6,
|
||||
aliasSet7,
|
||||
aliasSet8,
|
||||
aliasSet9,
|
||||
aliasSet10,
|
||||
aliasSet11,
|
||||
aliasSet12,
|
||||
aliasSet13,
|
||||
aliasSet14,
|
||||
aliasSet15,
|
||||
aliasSet16,
|
||||
aliasSet17,
|
||||
aliasSet18,
|
||||
aliasSet19,
|
||||
aliasSet20,
|
||||
aliasSet21,
|
||||
aliasSet22,
|
||||
aliasSet23,
|
||||
aliasSet24,
|
||||
aliasSet25,
|
||||
aliasSet26,
|
||||
aliasSet27,
|
||||
aliasSet28,
|
||||
aliasSet29,
|
||||
aliasSet30,
|
||||
aliasSet31,
|
||||
aliasSet32,
|
||||
aliasSet33,
|
||||
aliasSet34,
|
||||
aliasSet35,
|
||||
aliasSet36,
|
||||
aliasSet37,
|
||||
aliasSet38,
|
||||
aliasSet39,
|
||||
] as const;
|
||||
|
||||
aliasSets.forEach((aliasSet) => {
|
||||
describe(`Test ${aliasSet.join(',')} `, () => {
|
||||
it(`All ${aliasSet.join(',')} should render same shape`, () => {
|
||||
let flowchartCode = `flowchart \n`;
|
||||
aliasSet.forEach((alias, index) => {
|
||||
flowchartCode += ` n${index}@{ shape: ${alias}, label: "${alias}" }\n`;
|
||||
});
|
||||
imgSnapshotTest(flowchartCode);
|
||||
});
|
||||
});
|
||||
});
|
@@ -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(440 * 0.95, 440 * 1.05);
|
||||
expect(maxWidthValue).to.be.within(290 * 0.95 - 1, 290 * 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(440 * 0.95, 440 * 1.05);
|
||||
expect(width).to.be.within(290 * 0.95 - 1, 290 * 1.05);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
@@ -198,13 +198,13 @@ describe('Flowchart v2', () => {
|
||||
`flowchart TB
|
||||
internet
|
||||
nat
|
||||
router
|
||||
routeur
|
||||
lb1
|
||||
lb2
|
||||
compute1
|
||||
compute2
|
||||
subgraph project
|
||||
router
|
||||
routeur
|
||||
nat
|
||||
subgraph subnet1
|
||||
compute1
|
||||
@@ -215,8 +215,8 @@ describe('Flowchart v2', () => {
|
||||
lb2
|
||||
end
|
||||
end
|
||||
internet --> router
|
||||
router --> subnet1 & subnet2
|
||||
internet --> routeur
|
||||
routeur --> subnet1 & subnet2
|
||||
subnet1 & subnet2 --> nat --> internet
|
||||
`,
|
||||
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||
@@ -433,7 +433,7 @@ flowchart TD
|
||||
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||
);
|
||||
});
|
||||
it('63: title on subgraphs should be themeable', () => {
|
||||
it('63: title on subgraphs should be themable', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
%%{init:{"theme":"base", "themeVariables": {"primaryColor":"#411d4e", "titleColor":"white", "darkMode":true}}}%%
|
||||
@@ -699,7 +699,7 @@ A --> B
|
||||
{ flowchart: { titleTopMargin: 10 } }
|
||||
);
|
||||
});
|
||||
it('3192: It should be possible to render flowcharts with invisible edges', () => {
|
||||
it('3192: It should be possieble to render flowcharts with invisible edges', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
title: Simple flowchart with invisible edges
|
||||
@@ -760,51 +760,6 @@ 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', () => {
|
||||
@@ -949,18 +904,6 @@ 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)', () => {
|
||||
@@ -1047,69 +990,7 @@ end
|
||||
A --lb3--> TOP --lb4--> B
|
||||
B1 --lb5--> B2
|
||||
`,
|
||||
{
|
||||
flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } },
|
||||
}
|
||||
);
|
||||
});
|
||||
it('Should render self-loops', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart
|
||||
A --> A
|
||||
subgraph B
|
||||
B1 --> B1
|
||||
end
|
||||
subgraph C
|
||||
subgraph C1
|
||||
C2 --> C2
|
||||
subgraph D
|
||||
D1 --> D1
|
||||
end
|
||||
D --> D
|
||||
end
|
||||
C1 --> C1
|
||||
end
|
||||
`,
|
||||
{
|
||||
flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } },
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('New @ syntax for node metadata edge cases', () => {
|
||||
it('should be possible to use @ syntax to add labels on multi nodes', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TB
|
||||
n2["label for n2"] & n4@{ label: "label for n4"} & n5@{ label: "label for n5"}
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should be possible to use @ syntax to add labels with trail spaces and &', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TB
|
||||
n2["label for n2"] & n4@{ label: "label for n4"} & n5@{ label: "label for n5"}
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should be possible to use @ syntax to add labels with trail spaces', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TB
|
||||
n2["label for n2"]
|
||||
n4@{ label: "label for n4"}
|
||||
n5@{ label: "label for n5"}
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should be possible to use @ syntax to add labels with trail spaces and edge/link', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TD
|
||||
A["A"] --> B["for B"] & C@{ label: "for c"} & E@{label : "for E"}
|
||||
D@{label: "for D"}
|
||||
`,
|
||||
{}
|
||||
{ flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } } }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -733,7 +733,7 @@ describe('Graph', () => {
|
||||
});
|
||||
it('38: should render a flowchart when useMaxWidth is true (default)', () => {
|
||||
renderGraph(
|
||||
`flowchart TD
|
||||
`graph 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(446 * 0.9, 446 * 1.1);
|
||||
expect(maxWidthValue).to.be.within(300 * 0.9, 300 * 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(446 * 0.9, 446 * 1.1);
|
||||
expect(width).to.be.within(300 * 0.9, 300 * 1.1);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
@@ -895,7 +895,7 @@ graph TD
|
||||
imgSnapshotTest(
|
||||
`
|
||||
graph TD
|
||||
classDef default fill:#a34,stroke:#000,stroke-width:4px,color:#fff
|
||||
classDef default fill:#a34,stroke:#000,stroke-width:4px,color:#fff
|
||||
hello --> default
|
||||
`,
|
||||
{ htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
|
||||
@@ -905,72 +905,13 @@ 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
|
||||
`,
|
||||
{
|
||||
flowchart: { htmlLabels: true },
|
||||
securityLevel: 'loose',
|
||||
}
|
||||
);
|
||||
});
|
||||
it('#6369: edge color should affect arrow head', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
flowchart LR
|
||||
A --> B
|
||||
A --> C
|
||||
C --> D
|
||||
|
||||
linkStyle 0 stroke:#D50000
|
||||
linkStyle 2 stroke:#D50000
|
||||
`,
|
||||
{
|
||||
flowchart: { htmlLabels: true },
|
||||
securityLevel: 'loose',
|
||||
}
|
||||
);
|
||||
});
|
||||
it('68: should honor subgraph direction when inheritDir is false', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
%%{init: {"flowchart": { "inheritDir": false }}}%%
|
||||
flowchart TB
|
||||
direction LR
|
||||
subgraph A
|
||||
direction TB
|
||||
a --> b
|
||||
end
|
||||
subgraph B
|
||||
c --> d
|
||||
end
|
||||
`,
|
||||
{
|
||||
fontFamily: 'courier',
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('69: should inherit global direction when inheritDir is true', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
%%{init: {"flowchart": { "inheritDir": true }}}%%
|
||||
flowchart TB
|
||||
direction LR
|
||||
subgraph A
|
||||
direction TB
|
||||
a --> b
|
||||
end
|
||||
subgraph B
|
||||
c --> d
|
||||
end
|
||||
`,
|
||||
{
|
||||
fontFamily: 'courier',
|
||||
}
|
||||
{ htmlLabels: true, 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
|
||||
@@ -117,7 +117,7 @@ describe('Gantt diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should FAIL rendering a gantt chart for issue #1060 with invalid date', () => {
|
||||
it('should FAIL redering a gantt chart for issue #1060 with invalid date', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gantt
|
||||
@@ -358,23 +358,6 @@ describe('Gantt diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a gantt diagram with a vert tag', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gantt
|
||||
title A Gantt Diagram
|
||||
dateFormat ss
|
||||
axisFormat %Ss
|
||||
|
||||
section Section
|
||||
A task : a1, 00, 6s
|
||||
Milestone : vert, 01,
|
||||
section Another
|
||||
Task in sec : 06, 3s
|
||||
another task : 3s
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render a gantt diagram with tick is 2 milliseconds', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
@@ -590,28 +573,7 @@ describe('Gantt diagram', () => {
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render a gantt diagram excluding 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 excluding 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(
|
||||
`
|
||||
@@ -688,7 +650,7 @@ describe('Gantt diagram', () => {
|
||||
title Gantt Digram
|
||||
dateFormat YYYY-MM-DD
|
||||
section Section
|
||||
;A task with a semicolon :a1, 2014-01-01, 30d
|
||||
;A task with a semiclon :a1, 2014-01-01, 30d
|
||||
Another task :after a1 , 20d
|
||||
section Another
|
||||
Task in sec :2014-01-12 , 12d
|
||||
|
@@ -11,7 +11,7 @@ describe('Git Graph diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('2: should render a simple gitgraph with commit on main branch with id', () => {
|
||||
it('2: should render a simple gitgraph with commit on main branch with Id', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph
|
||||
commit id: "One"
|
||||
@@ -253,7 +253,7 @@ describe('Git Graph diagram', () => {
|
||||
`
|
||||
gitGraph
|
||||
checkout main
|
||||
%% Make sure to manually set the id of all commits, for consistent visual tests
|
||||
%% Make sure to manually set the ID of all commits, for consistent visual tests
|
||||
commit id: "1-abcdefg"
|
||||
checkout main
|
||||
branch branch1
|
||||
@@ -343,7 +343,7 @@ gitGraph
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('16: should render a simple gitgraph with commit on main branch with id | Vertical Branch', () => {
|
||||
it('16: should render a simple gitgraph with commit on main branch with Id | Vertical Branch', () => {
|
||||
imgSnapshotTest(
|
||||
`gitGraph TB:
|
||||
commit id: "One"
|
||||
@@ -585,7 +585,7 @@ gitGraph
|
||||
`
|
||||
gitGraph TB:
|
||||
checkout main
|
||||
%% Make sure to manually set the id of all commits, for consistent visual tests
|
||||
%% Make sure to manually set the ID of all commits, for consistent visual tests
|
||||
commit id: "1-abcdefg"
|
||||
checkout main
|
||||
branch branch1
|
||||
@@ -1013,560 +1013,4 @@ 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"`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
@@ -1,143 +0,0 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util';
|
||||
|
||||
const looks = ['classic', 'handDrawn'] as const;
|
||||
const directions = [
|
||||
'TB',
|
||||
//'BT',
|
||||
'LR',
|
||||
// 'RL'
|
||||
] as const;
|
||||
const forms = [undefined, 'square', 'circle', 'rounded'] as const;
|
||||
const labelPos = [undefined, 't', 'b'] as const;
|
||||
|
||||
looks.forEach((look) => {
|
||||
directions.forEach((direction) => {
|
||||
forms.forEach((form) => {
|
||||
labelPos.forEach((pos) => {
|
||||
describe(`Test iconShape in ${form ? `${form} form,` : ''} ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => {
|
||||
it(`without label`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell'`;
|
||||
if (form) {
|
||||
flowchartCode += `, form: '${form}'`;
|
||||
}
|
||||
flowchartCode += ` }\n`;
|
||||
imgSnapshotTest(flowchartCode, { look });
|
||||
});
|
||||
|
||||
it(`with label`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is a label for icon shape'`;
|
||||
if (form) {
|
||||
flowchartCode += `, form: '${form}'`;
|
||||
}
|
||||
if (pos) {
|
||||
flowchartCode += `, pos: '${pos}'`;
|
||||
}
|
||||
flowchartCode += ` }\n`;
|
||||
imgSnapshotTest(flowchartCode, { look });
|
||||
});
|
||||
|
||||
it(`with very long label`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is a very very very very very long long long label for icon shape'`;
|
||||
if (form) {
|
||||
flowchartCode += `, form: '${form}'`;
|
||||
}
|
||||
if (pos) {
|
||||
flowchartCode += `, pos: '${pos}'`;
|
||||
}
|
||||
flowchartCode += ` }\n`;
|
||||
imgSnapshotTest(flowchartCode, { look });
|
||||
});
|
||||
|
||||
it(`with markdown htmlLabels:true`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is **bold** </br>and <strong>strong</strong> for icon shape'`;
|
||||
if (form) {
|
||||
flowchartCode += `, form: '${form}'`;
|
||||
}
|
||||
if (pos) {
|
||||
flowchartCode += `, pos: '${pos}'`;
|
||||
}
|
||||
flowchartCode += ` }\n`;
|
||||
imgSnapshotTest(flowchartCode, { look });
|
||||
});
|
||||
|
||||
it(`with markdown htmlLabels:false`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is **bold** </br>and <strong>strong</strong> for icon shape'`;
|
||||
if (form) {
|
||||
flowchartCode += `, form: '${form}'`;
|
||||
}
|
||||
if (pos) {
|
||||
flowchartCode += `, pos: '${pos}'`;
|
||||
}
|
||||
flowchartCode += ` }\n`;
|
||||
imgSnapshotTest(flowchartCode, {
|
||||
look,
|
||||
htmlLabels: false,
|
||||
flowchart: { htmlLabels: false },
|
||||
});
|
||||
});
|
||||
|
||||
it(`with styles`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'new icon shape'`;
|
||||
if (form) {
|
||||
flowchartCode += `, form: '${form}'`;
|
||||
}
|
||||
if (pos) {
|
||||
flowchartCode += `, pos: '${pos}'`;
|
||||
}
|
||||
flowchartCode += ` }\n`;
|
||||
flowchartCode += ` style nAA fill:#f9f,stroke:#333,stroke-width:4px \n`;
|
||||
imgSnapshotTest(flowchartCode, { look });
|
||||
});
|
||||
|
||||
it(`with classDef`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`;
|
||||
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'new icon shape'`;
|
||||
if (form) {
|
||||
flowchartCode += `, form: '${form}'`;
|
||||
}
|
||||
if (pos) {
|
||||
flowchartCode += `, pos: '${pos}'`;
|
||||
}
|
||||
flowchartCode += ` }\n`;
|
||||
flowchartCode += ` nAA:::customClazz\n`;
|
||||
imgSnapshotTest(flowchartCode, { look });
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test iconShape with different h', () => {
|
||||
it('with different h', () => {
|
||||
let flowchartCode = `flowchart TB\n`;
|
||||
const icon = 'fa:bell';
|
||||
const iconHeight = 64;
|
||||
flowchartCode += ` nA --> nAA@{ icon: '${icon}', label: 'icon with different h', h: ${iconHeight} }\n`;
|
||||
imgSnapshotTest(flowchartCode);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Test colored iconShape', () => {
|
||||
it('with no styles', () => {
|
||||
let flowchartCode = `flowchart TB\n`;
|
||||
const icon = 'fluent-emoji:tropical-fish';
|
||||
flowchartCode += ` nA --> nAA@{ icon: '${icon}', form: 'square', label: 'icon with color' }\n`;
|
||||
imgSnapshotTest(flowchartCode);
|
||||
});
|
||||
|
||||
it('with styles', () => {
|
||||
let flowchartCode = `flowchart TB\n`;
|
||||
const icon = 'fluent-emoji:tropical-fish';
|
||||
flowchartCode += ` nA --> nAA@{ icon: '${icon}', form: 'square', label: 'icon with color' }\n`;
|
||||
flowchartCode += ` style nAA fill:#f9f,stroke:#333,stroke-width:4px \n`;
|
||||
imgSnapshotTest(flowchartCode);
|
||||
});
|
||||
});
|
@@ -1,103 +0,0 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util';
|
||||
|
||||
const looks = ['classic', 'handDrawn'] as const;
|
||||
const directions = [
|
||||
'TB',
|
||||
//'BT',
|
||||
'LR',
|
||||
// 'RL'
|
||||
] as const;
|
||||
const labelPos = [undefined, 't', 'b'] as const;
|
||||
|
||||
looks.forEach((look) => {
|
||||
directions.forEach((direction) => {
|
||||
labelPos.forEach((pos) => {
|
||||
describe(`Test imageShape in ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => {
|
||||
it(`without label`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', w: '100', h: '100' }\n`;
|
||||
imgSnapshotTest(flowchartCode, { look });
|
||||
});
|
||||
|
||||
it(`with label`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a label for image shape'`;
|
||||
|
||||
flowchartCode += `, w: '100', h: '200'`;
|
||||
if (pos) {
|
||||
flowchartCode += `, pos: '${pos}'`;
|
||||
}
|
||||
flowchartCode += ` }\n`;
|
||||
imgSnapshotTest(flowchartCode, { look });
|
||||
});
|
||||
|
||||
it(`with very long label`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a very very very very very long long long label for image shape'`;
|
||||
|
||||
flowchartCode += `, w: '100', h: '250'`;
|
||||
if (pos) {
|
||||
flowchartCode += `, pos: '${pos}'`;
|
||||
}
|
||||
flowchartCode += ` }\n`;
|
||||
imgSnapshotTest(flowchartCode, { look });
|
||||
});
|
||||
|
||||
it(`with markdown htmlLabels:true`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold** </br>and <strong>strong</strong> for image shape'`;
|
||||
|
||||
flowchartCode += `, w: '550', h: '200'`;
|
||||
if (pos) {
|
||||
flowchartCode += `, pos: '${pos}'`;
|
||||
}
|
||||
flowchartCode += ` }\n`;
|
||||
imgSnapshotTest(flowchartCode, { look, htmlLabels: true });
|
||||
});
|
||||
|
||||
it(`with markdown htmlLabels:false`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold** </br>and <strong>strong</strong> for image shape'`;
|
||||
flowchartCode += `, w: '250', h: '200'`;
|
||||
|
||||
if (pos) {
|
||||
flowchartCode += `, pos: '${pos}'`;
|
||||
}
|
||||
flowchartCode += ` }\n`;
|
||||
imgSnapshotTest(flowchartCode, {
|
||||
look,
|
||||
htmlLabels: false,
|
||||
flowchart: { htmlLabels: false },
|
||||
});
|
||||
});
|
||||
|
||||
it(`with styles`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`;
|
||||
flowchartCode += `, w: '550', h: '200'`;
|
||||
|
||||
if (pos) {
|
||||
flowchartCode += `, pos: '${pos}'`;
|
||||
}
|
||||
flowchartCode += ` }\n`;
|
||||
flowchartCode += ` style A fill:#f9f,stroke:#333,stroke-width:4px \n`;
|
||||
imgSnapshotTest(flowchartCode, { look });
|
||||
});
|
||||
|
||||
it(`with classDef`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#000000,stroke-dasharray: 5 5\n`;
|
||||
flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`;
|
||||
|
||||
flowchartCode += `, w: '500', h: '550'`;
|
||||
if (pos) {
|
||||
flowchartCode += `, pos: '${pos}'`;
|
||||
}
|
||||
flowchartCode += ` }\n`;
|
||||
flowchartCode += ` A:::customClazz\n`;
|
||||
imgSnapshotTest(flowchartCode, { look });
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
@@ -63,199 +63,4 @@ section Checkout from website
|
||||
{ journey: { useMaxWidth: false } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should initialize with a left margin of 150px for user journeys', () => {
|
||||
renderGraph(
|
||||
`
|
||||
---
|
||||
config:
|
||||
journey:
|
||||
maxLabelWidth: 320
|
||||
---
|
||||
journey
|
||||
title User Journey Example
|
||||
section Onboarding
|
||||
Sign Up: 5:
|
||||
Browse Features: 3:
|
||||
Use Core Functionality: 4:
|
||||
section Engagement
|
||||
Browse Features: 3
|
||||
Use Core Functionality: 4
|
||||
`,
|
||||
{ journey: { useMaxWidth: true } }
|
||||
);
|
||||
|
||||
let diagramStartX;
|
||||
|
||||
cy.contains('foreignobject', 'Sign Up').then(($diagram) => {
|
||||
diagramStartX = parseFloat($diagram.attr('x'));
|
||||
expect(diagramStartX).to.be.closeTo(150, 2);
|
||||
});
|
||||
});
|
||||
|
||||
it('should maintain sufficient space between legend and diagram when legend labels are longer', () => {
|
||||
renderGraph(
|
||||
`journey
|
||||
title Web hook life cycle
|
||||
section Darkoob
|
||||
Make preBuilt:5: Darkoob user
|
||||
register slug : 5: Darkoob userf deliberately increasing the size of this label to check if distance between legend and diagram is maintained
|
||||
Map slug to a Prebuilt Job:5: Darkoob user
|
||||
section External Service
|
||||
set Darkoob slug as hook for an Event : 5 : admin Exjjjnjjjj qwerty
|
||||
listen to the events : 5 : External Service
|
||||
call darkoob endpoint : 5 : External Service
|
||||
section Darkoob
|
||||
check for inputs : 5 : DarkoobAPI
|
||||
run the prebuilt job : 5 : DarkoobAPI
|
||||
`,
|
||||
{ journey: { useMaxWidth: true } }
|
||||
);
|
||||
|
||||
let LabelEndX, diagramStartX;
|
||||
|
||||
// Get right edge of the legend
|
||||
cy.contains('tspan', 'Darkoob userf').then((textBox) => {
|
||||
const bbox = textBox[0].getBBox();
|
||||
LabelEndX = bbox.x + bbox.width;
|
||||
});
|
||||
|
||||
// Get left edge of the diagram
|
||||
cy.contains('foreignobject', 'Make preBuilt').then((rect) => {
|
||||
diagramStartX = parseFloat(rect.attr('x'));
|
||||
});
|
||||
|
||||
// Assert right edge of the diagram is greater than or equal to the right edge of the label
|
||||
cy.then(() => {
|
||||
expect(diagramStartX).to.be.gte(LabelEndX);
|
||||
});
|
||||
});
|
||||
|
||||
it('should wrap a single long word with hyphenation', () => {
|
||||
renderGraph(
|
||||
`
|
||||
---
|
||||
config:
|
||||
journey:
|
||||
maxLabelWidth: 100
|
||||
---
|
||||
journey
|
||||
title Long Word Test
|
||||
section Test
|
||||
VeryLongWord: 5: Supercalifragilisticexpialidocious
|
||||
`,
|
||||
{ journey: { useMaxWidth: true } }
|
||||
);
|
||||
|
||||
// Verify that the line ends with a hyphen, indicating proper hyphenation for words exceeding maxLabelWidth.
|
||||
cy.get('tspan').then((tspans) => {
|
||||
const hasHyphen = [...tspans].some((t) => t.textContent.trim().endsWith('-'));
|
||||
return expect(hasHyphen).to.be.true;
|
||||
});
|
||||
});
|
||||
|
||||
it('should wrap text on whitespace without adding hyphens', () => {
|
||||
renderGraph(
|
||||
`
|
||||
---
|
||||
config:
|
||||
journey:
|
||||
maxLabelWidth: 200
|
||||
---
|
||||
journey
|
||||
title Whitespace Test
|
||||
section Test
|
||||
TextWithSpaces: 5: Gustavo Fring is played by Giancarlo Esposito and is a character in Breaking Bad.
|
||||
`,
|
||||
{ journey: { useMaxWidth: true } }
|
||||
);
|
||||
|
||||
// Verify that none of the text spans end with a hyphen.
|
||||
cy.get('tspan').each(($el) => {
|
||||
const text = $el.text();
|
||||
expect(text.trim()).not.to.match(/-$/);
|
||||
});
|
||||
});
|
||||
|
||||
it('should wrap long labels into multiple lines, keep them under max width, and maintain margins', () => {
|
||||
renderGraph(
|
||||
`
|
||||
---
|
||||
config:
|
||||
journey:
|
||||
maxLabelWidth: 320
|
||||
---
|
||||
journey
|
||||
title User Journey Example
|
||||
section Onboarding
|
||||
Sign Up: 5: This is a long label that will be split into multiple lines to test the wrapping functionality
|
||||
Browse Features: 3: This is another long label that will be split into multiple lines to test the wrapping functionality
|
||||
Use Core Functionality: 4: This is yet another long label that will be split into multiple lines to test the wrapping functionality
|
||||
section Engagement
|
||||
Browse Features: 3
|
||||
Use Core Functionality: 4
|
||||
`,
|
||||
{ journey: { useMaxWidth: true } }
|
||||
);
|
||||
|
||||
let diagramStartX, maxLineWidth;
|
||||
|
||||
// Get the diagram's left edge x-coordinate
|
||||
cy.contains('foreignobject', 'Sign Up')
|
||||
.then(($diagram) => {
|
||||
diagramStartX = parseFloat($diagram.attr('x'));
|
||||
})
|
||||
.then(() => {
|
||||
cy.get('text.legend').then(($lines) => {
|
||||
// Check that there are multiple lines
|
||||
expect($lines.length).to.be.equal(9);
|
||||
|
||||
// Check that all lines are under the maxLabelWidth
|
||||
$lines.each((index, el) => {
|
||||
const bbox = el.getBBox();
|
||||
expect(bbox.width).to.be.lte(320);
|
||||
maxLineWidth = Math.max(maxLineWidth || 0, bbox.width);
|
||||
});
|
||||
|
||||
/** The expected margin between the diagram and the legend is 150px, as defined by
|
||||
* conf.leftMargin in user-journey-config.js
|
||||
*/
|
||||
expect(diagramStartX - maxLineWidth).to.be.closeTo(150, 2);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('should correctly render the user journey diagram title with the specified styling', () => {
|
||||
renderGraph(
|
||||
`---
|
||||
config:
|
||||
journey:
|
||||
titleColor: "#2900A5"
|
||||
titleFontFamily: "Times New Roman"
|
||||
titleFontSize: "5rem"
|
||||
---
|
||||
|
||||
journey
|
||||
title User Journey Example
|
||||
section Onboarding
|
||||
Sign Up: 5: John, Shahir
|
||||
Complete Profile: 4: John
|
||||
section Engagement
|
||||
Browse Features: 3: John
|
||||
Use Core Functionality: 4: John
|
||||
section Retention
|
||||
Revisit Application: 5: John
|
||||
Invite Friends: 3: John
|
||||
|
||||
size: 2rem
|
||||
`
|
||||
);
|
||||
|
||||
cy.get('text').contains('User Journey Example').as('title');
|
||||
cy.get('@title').then(($title) => {
|
||||
expect($title).to.have.attr('fill', '#2900A5');
|
||||
expect($title).to.have.attr('font-family', 'Times New Roman');
|
||||
expect($title).to.have.attr('font-size', '5rem');
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@@ -1,136 +0,0 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe('Kanban diagram', () => {
|
||||
it('1: should render a kanban with a single section', () => {
|
||||
imgSnapshotTest(
|
||||
`kanban
|
||||
id1[Todo]
|
||||
docs[Create Documentation]
|
||||
docs[Create Blog about the new diagram]
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('2: should render a kanban with multiple sections', () => {
|
||||
imgSnapshotTest(
|
||||
`kanban
|
||||
id1[Todo]
|
||||
docs[Create Documentation]
|
||||
id2
|
||||
docs[Create Blog about the new diagram]
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('3: should render a kanban with a single wrapping node', () => {
|
||||
imgSnapshotTest(
|
||||
`kanban
|
||||
id1[Todo]
|
||||
id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping]
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('4: should handle the height of a section with a wrapping node at the end', () => {
|
||||
imgSnapshotTest(
|
||||
`kanban
|
||||
id1[Todo]
|
||||
id2[One line]
|
||||
id3[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping]
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('5: should handle the height of a section with a wrapping node at the top', () => {
|
||||
imgSnapshotTest(
|
||||
`kanban
|
||||
id1[Todo]
|
||||
id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping]
|
||||
id3[One line]
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('6: should handle the height of a section with a wrapping node in the middle', () => {
|
||||
imgSnapshotTest(
|
||||
`kanban
|
||||
id1[Todo]
|
||||
id2[One line]
|
||||
id3[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping]
|
||||
id4[One line]
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('6: should handle assignments', () => {
|
||||
imgSnapshotTest(
|
||||
`kanban
|
||||
id1[Todo]
|
||||
docs[Create Documentation]
|
||||
id2[In progress]
|
||||
docs[Create Blog about the new diagram]@{ assigned: 'knsv' }
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('7: should handle prioritization', () => {
|
||||
imgSnapshotTest(
|
||||
`kanban
|
||||
id2[In progress]
|
||||
vh[Very High]@{ priority: 'Very High' }
|
||||
h[High]@{ priority: 'High' }
|
||||
m[Default priority]
|
||||
l[Low]@{ priority: 'Low' }
|
||||
vl[Very Low]@{ priority: 'Very Low' }
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('7: should handle external tickets', () => {
|
||||
imgSnapshotTest(
|
||||
`kanban
|
||||
id1[Todo]
|
||||
docs[Create Documentation]
|
||||
id2[In progress]
|
||||
docs[Create Blog about the new diagram]@{ ticket: MC-2037 }
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('8: should handle assignments, prioritization and tickets ids in the same item', () => {
|
||||
imgSnapshotTest(
|
||||
`kanban
|
||||
id2[In progress]
|
||||
docs[Create Blog about the new diagram]@{ priority: 'Very Low', ticket: MC-2037, assigned: 'knsv' }
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('10: Full example', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
kanban:
|
||||
ticketBaseUrl: 'https://abc123.atlassian.net/browse/#TICKET#'
|
||||
---
|
||||
kanban
|
||||
id1[Todo]
|
||||
docs[Create Documentation]
|
||||
docs[Create Blog about the new diagram]
|
||||
id7[In progress]
|
||||
id6[Create renderer so that it works in all cases. We also add some extra text here for testing purposes. And some more just for the extra flare.]
|
||||
id8[Design grammar]@{ assigned: 'knsv' }
|
||||
id9[Ready for deploy]
|
||||
id10[Ready for test]
|
||||
id11[Done]
|
||||
id5[define getData]
|
||||
id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char]@{ ticket: MC-2036, priority: 'Very High'}
|
||||
id3[Update DB function]@{ ticket: MC-2037, assigned: knsv, priority: 'High' }
|
||||
id4[Create parsing tests]@{ ticket: MC-2038, assigned: 'K.Sveidqvist', priority: 'High' }
|
||||
id66[last item]@{ priority: 'Very Low', assigned: 'knsv' }
|
||||
id12[Can't reproduce]
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user