Compare commits

..

25 Commits

Author SHA1 Message Date
Sidharth Vinod
4f9cf4f9fc Merge branch 'develop' of https://github.com/mermaid-js/mermaid into xychart
* 'develop' of https://github.com/mermaid-js/mermaid: (546 commits)
  rebuild
  chore: Use string templates
  chore: Update docs
  chore: Fix docs
  chore: Add argos token to cypress config.
  chore: Remove cy.get('svg') calls
  chore: fix Argos parallel
  chore: Support local screenshot testing without applitools or argos
  chore: Skip checking drupal links
  chore: Remove reference screenshot generation from E2E
  chore: Remove cytoscape patch.
  chore(argos): disable matchImageSnapshot
  chore(argos): put parallel mode only when necessary
  chore(argos): setup parallel mode
  chore: setup Argos Visual Testing on E2E
  Fixed linters
  Added more specs for elk detector
  Fixed wrong elk detector, check only beginning of the line for diagram keywords
  Removed unused patch
  Fix cytoscape patch
  ...
2024-06-21 10:24:58 +05:30
Sidharth Vinod
90be8dedf6 Merge pull request #5167 from camueller/feature/xychart_multiple_datasets
xychart: support for multiple datasets added
2024-02-05 13:06:45 +05:30
Sidharth Vinod
f1490ff679 Merge branch 'develop' into feature/xychart_multiple_datasets 2024-01-31 17:09:56 +05:30
Axel Müller
25160d9688 axis calculation fixed for mix of line and bar charts 2024-01-27 17:11:40 +01:00
Axel Müller
533a921ef5 axis calculation fixed 2024-01-27 15:21:27 +01:00
Axel Müller
3bef03f568 Merge branch 'develop' into feature/xychart_multiple_datasets 2024-01-27 14:07:51 +01:00
Axel Müller
737f4f0cf3 axis calculation fixed 2024-01-27 14:06:30 +01:00
Axel Müller
71e5a2b3a3 Merge branch 'develop' into feature/xychart_multiple_datasets 2024-01-24 19:13:49 +01:00
Axel Müller
54f1435839 axis calculation fixed 2024-01-24 19:07:00 +01:00
Axel Müller
48a20c5cb8 more tests added 2024-01-22 15:59:33 +01:00
Axel Müller
5f4f1cc08d Merge branch 'develop' into feature/xychart_multiple_datasets 2024-01-20 10:25:55 +01:00
Axel Müller
da0a4ae37d multiple line charts fixed 2024-01-20 08:46:39 +01:00
Axel Müller
2972012059 use edge case for better coverage 2024-01-16 18:41:30 +01:00
Axel Müller
cf641ba4fd Merge branch 'develop' into feature/xychart_multiple_datasets 2024-01-16 18:17:32 +01:00
Axel Müller
39e5064019 Merge branch 'develop' into feature/xychart_multiple_datasets 2024-01-13 13:47:26 +01:00
Axel Müller
7830d0c4bf fix 0 values 2024-01-13 13:39:55 +01:00
Axel Müller
60d34bdc72 fix missing values 2024-01-13 13:30:18 +01:00
Axel Müller
3262a06a8e fix 0 values 2024-01-13 11:54:14 +01:00
Axel Müller
506314598e review findings 2024-01-13 07:39:58 +01:00
Axel Müller
25a9479acf documentation updated 2024-01-08 17:13:59 +01:00
Axel Müller
1273f440a8 e2e tests added 2024-01-08 16:41:53 +01:00
Axel Müller
e1d085925e parser fixed for > 2 datasets
some unit tests added
2024-01-07 17:10:36 +01:00
Axel Müller
39d175314c formatting fixed 2024-01-07 07:33:32 +01:00
Axel Müller
17426f0a97 unit tests fixed 2024-01-07 07:21:04 +01:00
Axel Müller
a36fa7cd2f support for multiple datasets added 2023-12-27 12:13:30 +01:00
495 changed files with 16214 additions and 44216 deletions

View File

@@ -1,9 +1,3 @@
export interface PackageOptions {
name: string;
packageName: string;
file: string;
}
/** /**
* Shared common options for both ESBuild and Vite * Shared common options for both ESBuild and Vite
*/ */
@@ -28,9 +22,9 @@ export const packageOptions = {
packageName: 'mermaid-zenuml', packageName: 'mermaid-zenuml',
file: 'detector.ts', file: 'detector.ts',
}, },
'mermaid-layout-elk': { 'mermaid-flowchart-elk': {
name: 'mermaid-layout-elk', name: 'mermaid-flowchart-elk',
packageName: 'mermaid-layout-elk', packageName: 'mermaid-flowchart-elk',
file: 'layouts.ts', file: 'detector.ts',
}, },
} as const satisfies Record<string, PackageOptions>; } as const;

View File

@@ -1,7 +1,6 @@
import jison from 'jison'; import jison from 'jison';
export const transformJison = (src: string): string => { export const transformJison = (src: string): string => {
// @ts-ignore - Jison is not typed properly
const parser = new jison.Generator(src, { const parser = new jison.Generator(src, {
moduleType: 'js', moduleType: 'js',
'token-stack': true, 'token-stack': true,

View File

@@ -19,14 +19,12 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [
'xyChart', 'xyChart',
'requirement', 'requirement',
'mindmap', 'mindmap',
'kanban',
'timeline', 'timeline',
'gitGraph', 'gitGraph',
'c4', 'c4',
'sankey', 'sankey',
'block', 'block',
'packet', 'packet',
'architecture',
] as const; ] as const;
/** /**

View File

@@ -1,4 +1,3 @@
/* eslint-disable no-console */
import { packageOptions } from './common.js'; import { packageOptions } from './common.js';
import { execSync } from 'child_process'; import { execSync } from 'child_process';
@@ -6,17 +5,11 @@ const buildType = (packageName: string) => {
console.log(`Building types for ${packageName}`); console.log(`Building types for ${packageName}`);
try { try {
const out = execSync(`tsc -p ./packages/${packageName}/tsconfig.json --emitDeclarationOnly`); const out = execSync(`tsc -p ./packages/${packageName}/tsconfig.json --emitDeclarationOnly`);
if (out.length > 0) { out.length > 0 && console.log(out.toString());
console.log(out.toString());
}
} catch (e) { } catch (e) {
console.error(e); console.error(e);
if (e.stdout.length > 0) { e.stdout.length > 0 && console.error(e.stdout.toString());
console.error(e.stdout.toString()); e.stderr.length > 0 && console.error(e.stderr.toString());
}
if (e.stderr.length > 0) {
console.error(e.stderr.toString());
}
} }
}; };

View File

@@ -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)

View File

@@ -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"]
}

View File

@@ -13,7 +13,6 @@ bqstring
BQUOTE BQUOTE
bramp bramp
BRKT BRKT
brotli
callbackargs callbackargs
callbackname callbackname
classdef classdef
@@ -26,10 +25,8 @@ concat
controlx controlx
controly controly
CSSCLASS CSSCLASS
curv
CYLINDEREND CYLINDEREND
CYLINDERSTART CYLINDERSTART
DAGA
datakey datakey
DEND DEND
descr descr
@@ -56,7 +53,6 @@ GENERICTYPE
getBoundarys getBoundarys
grammr grammr
graphtype graphtype
halign
iife iife
interp interp
introdcued introdcued
@@ -68,7 +64,6 @@ Kaufmann
keyify keyify
LABELPOS LABELPOS
LABELTYPE LABELTYPE
layoutstop
lcov lcov
LEFTOF LEFTOF
Lexa Lexa
@@ -94,7 +89,6 @@ reqs
rewritelinks rewritelinks
rgba rgba
RIGHTOF RIGHTOF
roughjs
sankey sankey
sequencenumber sequencenumber
shrc shrc
@@ -114,17 +108,13 @@ strikethrough
stringifying stringifying
struct struct
STYLECLASS STYLECLASS
STYLEDEF
STYLEOPTS STYLEOPTS
subcomponent subcomponent
subcomponents subcomponents
subconfig
SUBROUTINEEND SUBROUTINEEND
SUBROUTINESTART SUBROUTINESTART
Subschemas Subschemas
substr substr
SVGG
SVGSVG
TAGEND TAGEND
TAGSTART TAGSTART
techn techn
@@ -135,13 +125,11 @@ titlevalue
topbar topbar
TRAPEND TRAPEND
TRAPSTART TRAPSTART
treemap
ts-nocheck ts-nocheck
tsdoc tsdoc
typeof typeof
typestr typestr
unshift unshift
urlsafe
verifymethod verifymethod
VERIFYMTHD VERIFYMTHD
WARN_DOCSDIR_DOESNT_MATCH WARN_DOCSDIR_DOESNT_MATCH

View File

@@ -4,6 +4,5 @@ cpettitt
Dong Cai Dong Cai
Nikolay Rozhkov Nikolay Rozhkov
Peng Xiao Peng Xiao
Per Brolin
subhash-halder subhash-halder
Vinod Sidharth Vinod Sidharth

View File

@@ -28,9 +28,6 @@ dictionaryDefinitions:
- name: suggestions - name: suggestions
words: words:
- none - none
- disp
- subproc
- tria
suggestWords: suggestWords:
- seperator:separator - seperator:separator
- vertice:vertex - vertice:vertex

View File

@@ -20,17 +20,14 @@ dagre-d3
Deepdwn Deepdwn
Docsify Docsify
Docsy Docsy
Doctave
DokuWiki DokuWiki
dompurify dompurify
elkjs elkjs
fcose
fontawesome fontawesome
Foswiki Foswiki
Gitea Gitea
graphlib graphlib
Grav Grav
icones
iconify iconify
Inkdrop Inkdrop
jiti jiti
@@ -57,17 +54,13 @@ presetAttributify
pyplot pyplot
redmine redmine
rehype rehype
roughjs
rscratch rscratch
shiki
Slidev
sparkline sparkline
sphinxcontrib sphinxcontrib
ssim ssim
stylis stylis
Swimm Swimm
tsbuildinfo tsbuildinfo
tseslint
Tuleap Tuleap
Typora Typora
unocss unocss

View File

@@ -1,18 +1,14 @@
Adamiecki Adamiecki
arrowend arrowend
Bendpoints
bmatrix bmatrix
braintree braintree
catmull catmull
compositTitleSize compositTitleSize
curv
doublecircle doublecircle
elems elems
gantt gantt
gitgraph gitgraph
gzipped gzipped
handDrawn
kanban
knsv knsv
Knut Knut
marginx marginx
@@ -21,12 +17,10 @@ Markdownish
mermaidjs mermaidjs
mindmap mindmap
mindmaps mindmaps
mrtree
multigraph multigraph
nodesep nodesep
NOTEGROUP NOTEGROUP
Pinterest Pinterest
procs
rankdir rankdir
ranksep ranksep
rect rect

View File

@@ -1,7 +1 @@
BRANDES
circo
handDrawn
KOEPF
neato
newbranch newbranch
validify

View File

@@ -2,17 +2,13 @@ import { build } from 'esbuild';
import { mkdir, writeFile } from 'node:fs/promises'; import { mkdir, writeFile } from 'node:fs/promises';
import { packageOptions } from '../.build/common.js'; import { packageOptions } from '../.build/common.js';
import { generateLangium } from '../.build/generateLangium.js'; import { generateLangium } from '../.build/generateLangium.js';
import type { MermaidBuildOptions } from './util.js'; import { MermaidBuildOptions, defaultOptions, getBuildConfig } from './util.js';
import { defaultOptions, getBuildConfig } from './util.js';
const shouldVisualize = process.argv.includes('--visualize'); const shouldVisualize = process.argv.includes('--visualize');
const buildPackage = async (entryName: keyof typeof packageOptions) => { const buildPackage = async (entryName: keyof typeof packageOptions) => {
const commonOptions: MermaidBuildOptions = { const commonOptions = { ...defaultOptions, entryName } as const;
...defaultOptions, const buildConfigs = [
options: packageOptions[entryName],
} as const;
const buildConfigs: MermaidBuildOptions[] = [
// package.mjs // package.mjs
{ ...commonOptions }, { ...commonOptions },
// package.min.mjs // package.min.mjs
@@ -39,11 +35,11 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => {
if (shouldVisualize) { if (shouldVisualize) {
for (const { metafile } of results) { for (const { metafile } of results) {
if (!metafile?.outputs) { if (!metafile) {
continue; continue;
} }
const fileName = Object.keys(metafile.outputs) 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/', ''); .replace('dist/', '');
// Upload metafile into https://esbuild.github.io/analyze/ // Upload metafile into https://esbuild.github.io/analyze/
await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile)); await writeFile(`stats/${fileName}.meta.json`, JSON.stringify(metafile));
@@ -52,14 +48,13 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => {
}; };
const handler = (e) => { const handler = (e) => {
// eslint-disable-next-line no-console
console.error(e); console.error(e);
process.exit(1); process.exit(1);
}; };
const main = async () => { const main = async () => {
await generateLangium(); await generateLangium();
await mkdir('stats', { recursive: true }); await mkdir('stats').catch(() => {});
const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[]; const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[];
// it should build `parser` before `mermaid` because it's a dependency // it should build `parser` before `mermaid` because it's a dependency
for (const pkg of packageNames) { for (const pkg of packageNames) {

View File

@@ -1,6 +1,6 @@
import { readFile } from 'node:fs/promises'; import { readFile } from 'node:fs/promises';
import { transformJison } from '../.build/jisonTransformer.js'; import { transformJison } from '../.build/jisonTransformer.js';
import type { Plugin } from 'esbuild'; import { Plugin } from 'esbuild';
export const jisonPlugin: Plugin = { export const jisonPlugin: Plugin = {
name: 'jison', name: 'jison',

View File

@@ -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 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 { generateLangium } from '../.build/generateLangium.js';
import { defaultOptions, getBuildConfig } from './util.js'; import { packageOptions } from '../.build/common.js';
const configs = Object.values(packageOptions).map(({ packageName }) => const configs = Object.values(packageOptions).map(({ packageName }) =>
getBuildConfig({ getBuildConfig({ ...defaultOptions, minify: false, core: false, entryName: packageName })
...defaultOptions,
minify: false,
core: false,
options: packageOptions[packageName],
})
); );
const mermaidIIFEConfig = getBuildConfig({ const mermaidIIFEConfig = getBuildConfig({
...defaultOptions, ...defaultOptions,
minify: false, minify: false,
core: false, core: false,
options: packageOptions.mermaid, entryName: 'mermaid',
format: 'iife', format: 'iife',
}); });
configs.push(mermaidIIFEConfig); configs.push(mermaidIIFEConfig);
const contexts = await Promise.all( const contexts = await Promise.all(configs.map((config) => context(config)));
configs.map(async (config) => ({ config, context: await context(config) }))
);
let rebuildCounter = 1;
const rebuildAll = async () => { const rebuildAll = async () => {
const buildNumber = rebuildCounter++; console.time('Rebuild time');
const timeLabel = `Rebuild ${buildNumber} Time (total)`; await Promise.all(contexts.map((ctx) => ctx.rebuild())).catch((e) => console.error(e));
console.time(timeLabel); console.timeEnd('Rebuild time');
await Promise.all(
contexts.map(async ({ config, context }) => {
const buildVariant = `Rebuild ${buildNumber} Time (${Object.keys(config.entryPoints!)[0]} ${config.format})`;
console.time(buildVariant);
await context.rebuild();
console.timeEnd(buildVariant);
})
).catch((e) => console.error(e));
console.timeEnd(timeLabel);
}; };
let clients: { id: number; response: Response }[] = []; let clients: { id: number; response: Response }[] = [];
function eventsHandler(request: Request, response: Response) { function eventsHandler(request: Request, response: Response, next: NextFunction) {
const headers = { const headers = {
'Content-Type': 'text/event-stream', 'Content-Type': 'text/event-stream',
Connection: 'keep-alive', 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. * Debounce file change events to avoid rebuilding multiple times.
*/ */
function handleFileChange() { function handleFileChange() {
if (timeoutID !== undefined) { if (timeoutId !== undefined) {
clearTimeout(timeoutID); clearTimeout(timeoutId);
} }
// eslint-disable-next-line @typescript-eslint/no-misused-promises timeoutId = setTimeout(async () => {
timeoutID = setTimeout(async () => {
await rebuildAll(); await rebuildAll();
sendEventsToAll(); sendEventsToAll();
timeoutID = undefined; timeoutId = undefined;
}, 100); }, 100);
} }
@@ -93,16 +74,15 @@ async function createServer() {
ignoreInitial: true, ignoreInitial: true,
ignored: [/node_modules/, /dist/, /docs/, /coverage/], ignored: [/node_modules/, /dist/, /docs/, /coverage/],
}) })
// eslint-disable-next-line @typescript-eslint/no-misused-promises
.on('all', async (event, path) => { .on('all', async (event, path) => {
// Ignore other events. // Ignore other events.
if (!['add', 'change'].includes(event)) { if (!['add', 'change'].includes(event)) {
return; return;
} }
console.log(`${path} changed. Rebuilding...`); if (/\.langium$/.test(path)) {
if (path.endsWith('.langium')) {
await generateLangium(); await generateLangium();
} }
console.log(`${path} changed. Rebuilding...`);
handleFileChange(); handleFileChange();
}); });
@@ -119,4 +99,4 @@ async function createServer() {
}); });
} }
void createServer(); createServer();

View File

@@ -3,20 +3,20 @@ import { fileURLToPath } from 'url';
import type { BuildOptions } from 'esbuild'; import type { BuildOptions } from 'esbuild';
import { readFileSync } from 'fs'; import { readFileSync } from 'fs';
import jsonSchemaPlugin from './jsonSchemaPlugin.js'; import jsonSchemaPlugin from './jsonSchemaPlugin.js';
import type { PackageOptions } from '../.build/common.js'; import { packageOptions } from '../.build/common.js';
import { jisonPlugin } from './jisonPlugin.js'; import { jisonPlugin } from './jisonPlugin.js';
const __dirname = fileURLToPath(new URL('.', import.meta.url)); const __dirname = fileURLToPath(new URL('.', import.meta.url));
export interface MermaidBuildOptions extends BuildOptions { export interface MermaidBuildOptions {
minify: boolean; minify: boolean;
core: boolean; core: boolean;
metafile: boolean; metafile: boolean;
format: 'esm' | 'iife'; format: 'esm' | 'iife';
options: PackageOptions; entryName: keyof typeof packageOptions;
} }
export const defaultOptions: Omit<MermaidBuildOptions, 'entryName' | 'options'> = { export const defaultOptions: Omit<MermaidBuildOptions, 'entryName'> = {
minify: false, minify: false,
metafile: false, metafile: false,
core: false, core: false,
@@ -52,16 +52,11 @@ const getFileName = (fileName: string, { core, format, minify }: MermaidBuildOpt
}; };
export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => { export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
const { const { core, entryName, metafile, format, minify } = options;
core,
metafile,
format,
minify,
options: { name, file, packageName },
} = options;
const external: string[] = ['require', 'fs', 'path']; const external: string[] = ['require', 'fs', 'path'];
const { name, file, packageName } = packageOptions[entryName];
const outFileName = getFileName(name, options); const outFileName = getFileName(name, options);
const output: BuildOptions = buildOptions({ let output: BuildOptions = buildOptions({
absWorkingDir: resolve(__dirname, `../packages/${packageName}`), absWorkingDir: resolve(__dirname, `../packages/${packageName}`),
entryPoints: { entryPoints: {
[outFileName]: `src/${file}`, [outFileName]: `src/${file}`,

1
.eslintignore Symbolic link
View File

@@ -0,0 +1 @@
.gitignore

190
.eslintrc.cjs Normal file
View File

@@ -0,0 +1,190 @@
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: 2022,
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-legacy',
'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/consistent-type-definitions': 'error',
'@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,
},
},
],
};

5
.github/lychee.toml vendored
View File

@@ -44,10 +44,7 @@ exclude = [
"https://chromewebstore.google.com", "https://chromewebstore.google.com",
# Drupal 403 # Drupal 403
"https://(www.)?drupal.org", "https://www.drupal.org"
# Swimm returns 404, eventhough the link is valid
"https://docs.swimm.io"
] ]
# Exclude all private IPs from checking. # Exclude all private IPs from checking.

View File

@@ -15,4 +15,4 @@ Make sure you
- [ ] :book: have read the [contribution guidelines](https://mermaid.js.org/community/contributing.html) - [ ] :book: have read the [contribution guidelines](https://mermaid.js.org/community/contributing.html)
- [ ] :computer: have added necessary unit/e2e tests. - [ ] :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. - [ ] :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
View 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!** 🎉

View File

@@ -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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
# uses version from "packageManager" field in package.json
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
cache: pnpm
node-version-file: '.node-version'
- name: Install Packages
run: |
pnpm install --frozen-lockfile
env:
CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Fix Linting
shell: bash
run: pnpm -w run lint:fix
- name: Sync `./src/config.type.ts` with `./src/schemas/config.schema.yaml`
shell: bash
run: pnpm run --filter mermaid types:build-config
- name: Build Docs
working-directory: ./packages/mermaid
run: pnpm run docs:build
- uses: autofix-ci/action@ff86a557419858bb967097bfc916833f5647fa8c # main

View File

@@ -8,8 +8,6 @@ on:
pull_request: pull_request:
merge_group: merge_group:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions: permissions:
contents: read contents: read
@@ -18,12 +16,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - uses: pnpm/action-setup@v2
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version-file: '.node-version' node-version-file: '.node-version'

49
.github/workflows/build.yml vendored Normal file
View 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@v4
with:
name: mermaid-build
path: packages/mermaid/dist
- name: Upload Mermaid Mindmap Build as Artifact
uses: actions/upload-artifact@v4
with:
name: mermaid-mindmap-build
path: packages/mermaid-mindmap/dist

View File

@@ -18,7 +18,7 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 uses: actions/checkout@v4
- name: Check for difference in README.md and docs/README.md - name: Check for difference in README.md and docs/README.md
run: | run: |

26
.github/workflows/checks.yml vendored Normal file
View 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

View File

@@ -11,9 +11,6 @@ on:
- synchronize - synchronize
- ready_for_review - ready_for_review
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs: jobs:
analyze: analyze:
name: Analyze name: Analyze
@@ -32,11 +29,11 @@ jobs:
steps: steps:
- name: Checkout repository - name: Checkout repository
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 uses: actions/checkout@v4
# Initializes the CodeQL tools for scanning. # Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL - name: Initialize CodeQL
uses: github/codeql-action/init@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12 uses: github/codeql-action/init@v3
with: with:
config-file: ./.github/codeql/codeql-config.yml config-file: ./.github/codeql/codeql-config.yml
languages: ${{ matrix.language }} languages: ${{ matrix.language }}
@@ -48,7 +45,7 @@ jobs:
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java). # 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) # If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild - name: Autobuild
uses: github/codeql-action/autobuild@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12 uses: github/codeql-action/autobuild@v3
# Command-line programs to run using the OS shell. # 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 # 📚 See https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#jobsjob_idstepsrun
@@ -62,4 +59,4 @@ jobs:
# make release # make release
- name: Perform CodeQL Analysis - name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12 uses: github/codeql-action/analyze@v3

View File

@@ -15,6 +15,6 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: 'Checkout Repository' - name: 'Checkout Repository'
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 uses: actions/checkout@v4
- name: 'Dependency Review' - name: 'Dependency Review'
uses: actions/dependency-review-action@5a2ce3f5b92ee19cbb1541a4984c76d921601d7c # v4.3.4 uses: actions/dependency-review-action@v4

View File

@@ -11,8 +11,6 @@ on:
default: master default: master
description: 'Parent branch to use for PRs' description: 'Parent branch to use for PRs'
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions: permissions:
contents: read contents: read
@@ -32,13 +30,13 @@ jobs:
run: | run: |
echo "::error,title=Not using Applitools::APPLITOOLS_API_KEY is empty, disabling Applitools for this run." echo "::error,title=Not using Applitools::APPLITOOLS_API_KEY is empty, disabling Applitools for this run."
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 uses: actions/setup-node@v4
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
@@ -54,7 +52,7 @@ jobs:
APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com' APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com'
- name: Cypress run - name: Cypress run
uses: cypress-io/github-action@d79d2d530a66e641eb4a5f227e13bc985c60b964 # v4.2.2 uses: cypress-io/github-action@v4
id: cypress id: cypress
with: with:
start: pnpm run dev start: pnpm run dev

View File

@@ -1,53 +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
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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
with:
node-version-file: '.node-version'
- name: Install dependencies
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
with:
runTests: false
- name: Cypress run
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6
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: Commit changes
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4
with:
add: 'cypress/timings.json'
author_name: 'github-actions[bot]'
author_email: '41898282+github-actions[bot]@users.noreply.github.com'
message: 'chore: update E2E timings'

View File

@@ -2,15 +2,11 @@ name: E2E
on: on:
push: push:
branches: branches-ignore:
- develop - 'gh-readonly-queue/**'
- master
- release/**
pull_request: pull_request:
merge_group: merge_group:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions: permissions:
contents: read contents: read
@@ -35,15 +31,15 @@ jobs:
image: cypress/browsers:node-20.11.0-chrome-121.0.6167.85-1-ff-120.0-edge-121.0.2277.83-1 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 options: --user 1001
steps: steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - uses: pnpm/action-setup@v2
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 uses: actions/setup-node@v4
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
- name: Cache snapshots - name: Cache snapshots
id: cache-snapshot id: cache-snapshot
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 uses: actions/cache@v4
with: with:
save-always: true save-always: true
path: ./cypress/snapshots path: ./cypress/snapshots
@@ -52,13 +48,13 @@ jobs:
# If a snapshot for a given Hash is not found, we checkout that commit, run the tests and cache the snapshots. # 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 - name: Switch to base branch
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 uses: actions/checkout@v4
with: with:
ref: ${{ env.targetHash }} ref: ${{ env.targetHash }}
- name: Install dependencies - name: Install dependencies
if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }} if: ${{ steps.cache-snapshot.outputs.cache-hit != 'true' }}
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6 uses: cypress-io/github-action@v6
with: with:
# just perform install # just perform install
runTests: false runTests: false
@@ -79,28 +75,28 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
containers: [1, 2, 3, 4, 5] containers: [1, 2, 3, 4]
steps: steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 uses: actions/setup-node@v4
with: with:
node-version-file: '.node-version' node-version-file: '.node-version'
# These cached snapshots are downloaded, providing the reference snapshots. # These cached snapshots are downloaded, providing the reference snapshots.
- name: Cache snapshots - name: Cache snapshots
id: cache-snapshot id: cache-snapshot
uses: actions/cache/restore@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 uses: actions/cache/restore@v4
with: with:
path: ./cypress/snapshots path: ./cypress/snapshots
key: ${{ runner.os }}-snapshots-${{ env.targetHash }} key: ${{ runner.os }}-snapshots-${{ env.targetHash }}
- name: Install dependencies - name: Install dependencies
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6 uses: cypress-io/github-action@v6
with: with:
runTests: false runTests: false
@@ -116,8 +112,11 @@ jobs:
# Install NPM dependencies, cache them correctly # Install NPM dependencies, cache them correctly
# and run all Cypress tests # and run all Cypress tests
- name: Cypress run - name: Cypress run
uses: cypress-io/github-action@0da3c06ed8217b912deea9d8ee69630baed1737e # v6.7.6 uses: cypress-io/github-action@v6
id: cypress 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: with:
install: false install: false
start: pnpm run dev:coverage start: pnpm run dev:coverage
@@ -126,20 +125,18 @@ jobs:
# Disable recording if we don't have an API key # Disable recording if we don't have an API key
# e.g. if this action was run from a fork # e.g. if this action was run from a fork
record: ${{ secrets.CYPRESS_RECORD_KEY != '' }} record: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
parallel: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
env: env:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }} CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
VITEST_COVERAGE: true VITEST_COVERAGE: true
CYPRESS_COMMIT: ${{ github.sha }} CYPRESS_COMMIT: ${{ github.sha }}
ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }} ARGOS_TOKEN: ${{ secrets.ARGOS_TOKEN }}
ARGOS_PARALLEL: true ARGOS_PARALLEL: ${{ secrets.CYPRESS_RECORD_KEY != '' }}
ARGOS_PARALLEL_TOTAL: ${{ strategy.job-total }} ARGOS_PARALLEL_TOTAL: 4
ARGOS_PARALLEL_INDEX: ${{ matrix.containers }} ARGOS_PARALLEL_INDEX: ${{ matrix.containers }}
SPLIT: ${{ strategy.job-total }}
SPLIT_INDEX: ${{ strategy.job-index }}
SPLIT_FILE: 'cypress/timings.json'
- name: Upload Coverage to Codecov - name: Upload Coverage to Codecov
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 uses: codecov/codecov-action@v4
# Run step only pushes to develop and pull_requests # Run step only pushes to develop and pull_requests
if: ${{ steps.cypress.conclusion == 'success' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/develop')}} if: ${{ steps.cypress.conclusion == 'success' && (github.event_name == 'pull_request' || github.ref == 'refs/heads/develop')}}
with: with:

View File

@@ -4,17 +4,11 @@ on:
issues: issues:
types: [opened] types: [opened]
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs: jobs:
triage: triage:
permissions:
issues: write # for andymckay/labeler to label issues
pull-requests: write # for andymckay/labeler to label PRs
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: andymckay/labeler@e6c4322d0397f3240f0e7e30a33b5c5df2d39e90 # 1.0.4 - uses: andymckay/labeler@1.0.4
with: with:
repo-token: '${{ secrets.GITHUB_TOKEN }}' repo-token: '${{ secrets.GITHUB_TOKEN }}'
add-labels: 'Status: Triage' add-labels: 'Status: Triage'

View File

@@ -19,9 +19,6 @@ on:
# * is a special character in YAML so you have to quote this string # * is a special character in YAML so you have to quote this string
- cron: '30 8 * * *' - cron: '30 8 * * *'
permissions: # added using https://github.com/step-security/secure-repo
contents: read
jobs: jobs:
link-checker: link-checker:
runs-on: ubuntu-latest runs-on: ubuntu-latest
@@ -29,17 +26,17 @@ jobs:
# lychee only uses the GITHUB_TOKEN to avoid rate-limiting # lychee only uses the GITHUB_TOKEN to avoid rate-limiting
contents: read contents: read
steps: steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/checkout@v4
- name: Restore lychee cache - name: Restore lychee cache
uses: actions/cache@0c45773b623bea8c8e75f6c82b208c3cf94ea4f9 # v4.0.2 uses: actions/cache@v4
with: with:
path: .lycheecache path: .lycheecache
key: cache-lychee-${{ github.sha }} key: cache-lychee-${{ github.sha }}
restore-keys: cache-lychee- restore-keys: cache-lychee-
- name: Link Checker - name: Link Checker
uses: lycheeverse/lychee-action@c053181aa0c3d17606addfe97a9075a32723548a # v1.9.3 uses: lycheeverse/lychee-action@v1.9.3
with: with:
args: >- args: >-
--config .github/lychee.toml --config .github/lychee.toml

View File

@@ -4,32 +4,26 @@ on:
push: push:
merge_group: merge_group:
pull_request: pull_request:
types:
- opened
- synchronize
- ready_for_review
workflow_dispatch: workflow_dispatch:
concurrency: ${{ github.workflow }}-${{ github.ref }}
permissions: permissions:
contents: write contents: write
jobs: jobs:
docker-lint:
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
- uses: hadolint/hadolint-action@54c9adbab1582c2ef04b2016b760714a4bfde3cf # v3.1.0
with:
verbose: true
lint: lint:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version-file: '.node-version' node-version-file: '.node-version'
@@ -89,9 +83,14 @@ jobs:
continue-on-error: ${{ github.event_name == 'push' }} continue-on-error: ${{ github.event_name == 'push' }}
run: pnpm run docs:verify 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: with:
framework: cypress message: 'Update docs'
tests: './cypress/e2e/**/**.spec.js' add: 'docs/*'
token: ${{ secrets.GITHUB_TOKEN }}
has-tests-label: true

View File

@@ -22,7 +22,7 @@ jobs:
pull-requests: write # write permission is required to label PRs pull-requests: write # write permission is required to label PRs
steps: steps:
- name: Label PR - name: Label PR
uses: release-drafter/release-drafter@3f0f87098bd6b5c5b9a36d49c41d998ea58f9348 # v6.0.0 uses: release-drafter/release-drafter@v6
with: with:
config-name: pr-labeler.yml config-name: pr-labeler.yml
disable-autolabeler: false disable-autolabeler: false

View File

@@ -23,12 +23,12 @@ jobs:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - uses: pnpm/action-setup@v2
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version-file: '.node-version' node-version-file: '.node-version'
@@ -37,13 +37,13 @@ jobs:
run: pnpm install --frozen-lockfile run: pnpm install --frozen-lockfile
- name: Setup Pages - name: Setup Pages
uses: actions/configure-pages@1f0c5cde4bc74cd7e1254d0cb4de8d49e9068c7d # v4.0.0 uses: actions/configure-pages@v4
- name: Run Build - name: Run Build
run: pnpm --filter mermaid run docs:build:vitepress run: pnpm --filter mermaid run docs:build:vitepress
- name: Upload artifact - name: Upload artifact
uses: actions/upload-pages-artifact@56afc609e74202658d3ffba0e8f6dda462b719fa # v3.0.1 uses: actions/upload-pages-artifact@v3
with: with:
path: packages/mermaid/src/vitepress/.vitepress/dist path: packages/mermaid/src/vitepress/.vitepress/dist
@@ -56,4 +56,4 @@ jobs:
steps: steps:
- name: Deploy to GitHub Pages - name: Deploy to GitHub Pages
id: deployment id: deployment
uses: actions/deploy-pages@d6db90164ac5ed86f2b6aed7e0febac5b3c0c03e # v4.0.5 uses: actions/deploy-pages@v4

23
.github/workflows/release-draft.yml vendored Normal file
View 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@v6
with:
disable-autolabeler: true
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}

View File

@@ -9,14 +9,14 @@ jobs:
publish-preview: publish-preview:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/checkout@v4
with: with:
fetch-depth: 0 fetch-depth: 0
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - uses: pnpm/action-setup@v2
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version-file: '.node-version' node-version-file: '.node-version'
@@ -28,7 +28,7 @@ jobs:
CYPRESS_CACHE_FOLDER: .cache/Cypress CYPRESS_CACHE_FOLDER: .cache/Cypress
- name: Install Json - name: Install Json
run: npm i json@11.0.0 --global run: npm i json --global
- name: Publish - name: Publish
working-directory: ./packages/mermaid working-directory: ./packages/mermaid

View File

@@ -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@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
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
View 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 }}

View File

@@ -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@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0
- name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4
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@3de3850952bec538fde60aac71731376e57b9b57 # v1.4.8
with:
version: pnpm changeset:version
publish: pnpm changeset:publish
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
NPM_TOKEN: ${{ secrets.NPM_TOKEN }}
NPM_CONFIG_PROVENANCE: true

View File

@@ -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@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7
with:
persist-credentials: false
- name: Run analysis
uses: ossf/scorecard-action@dc50aa9510b46c811795eb24b2f1ba02a914e534 # v2.3.3
with:
results_file: results.sarif
results_format: sarif
publish_results: true
- name: Upload artifact
uses: actions/upload-artifact@97a0fba1372883ab732affbe8f94b823f91727db # v3.pre.node20
with:
name: SARIF file
path: results.sarif
retention-days: 5
- name: Upload to code-scanning
uses: github/codeql-action/upload-sarif@c36620d31ac7c881962c3d9dd939c40ec9434f2b # v3.26.12
with:
sarif_file: results.sarif

View File

@@ -9,13 +9,13 @@ jobs:
unit-test: unit-test:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - uses: pnpm/action-setup@v2
# uses version from "packageManager" field in package.json # uses version from "packageManager" field in package.json
- name: Setup Node.js - name: Setup Node.js
uses: actions/setup-node@0a44ba7841725637a19e28fa30b79a866c81b0a6 # v4.0.4 uses: actions/setup-node@v4
with: with:
cache: pnpm cache: pnpm
node-version-file: '.node-version' node-version-file: '.node-version'
@@ -38,12 +38,8 @@ jobs:
run: | run: |
pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts --coverage 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 - name: Upload Coverage to Codecov
uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 uses: codecov/codecov-action@v4
# Run step only pushes to develop and pull_requests # Run step only pushes to develop and pull_requests
if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' }} if: ${{ github.event_name == 'pull_request' || github.ref == 'refs/heads/develop' }}
with: with:

View File

@@ -8,6 +8,6 @@ jobs:
triage: triage:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: Dunning-Kruger/unlock-issues@b06b7f7e5c3f2eaa1c6d5d89f40930e4d6d9699e # v1 - uses: Dunning-Kruger/unlock-issues@v1
with: with:
repo-token: '${{ secrets.GITHUB_TOKEN }}' repo-token: '${{ secrets.GITHUB_TOKEN }}'

View File

@@ -8,18 +8,18 @@ jobs:
update-browser-list: update-browser-list:
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4.1.7 - uses: actions/checkout@v4
- uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 - uses: pnpm/action-setup@v2
- run: npx update-browserslist-db@latest - run: npx update-browserslist-db@latest
- name: Commit changes - name: Commit changes
uses: EndBug/add-and-commit@a94899bca583c204427a224a7af87c02f9b325d5 # v9.1.4 uses: EndBug/add-and-commit@v9
with: with:
author_name: ${{ github.actor }} author_name: ${{ github.actor }}
author_email: ${{ github.actor }}@users.noreply.github.com author_email: ${{ github.actor }}@users.noreply.github.com
message: 'chore: update browsers list' message: 'chore: update browsers list'
push: false push: false
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@c5a7806660adbe173f04e3e038b0ccdcd758773c # v6.1.0 uses: peter-evans/create-pull-request@v6
with: with:
branch: update-browserslist branch: update-browserslist
title: Update Browserslist title: Update Browserslist

2
.gitignore vendored
View File

@@ -35,7 +35,7 @@ cypress/snapshots/
.tsbuildinfo .tsbuildinfo
tsconfig.tsbuildinfo tsconfig.tsbuildinfo
#knsv*.html knsv*.html
local*.html local*.html
stats/ stats/

View File

@@ -1,2 +0,0 @@
ignored:
- DL3002 # TODO: Last USER should not be root

View File

@@ -1,2 +1,4 @@
#!/usr/bin/env sh #!/bin/sh
. "$(dirname "$0")/_/husky.sh"
NODE_OPTIONS="--max_old_space_size=8192" pnpm run pre-commit NODE_OPTIONS="--max_old_space_size=8192" pnpm run pre-commit

View File

@@ -16,5 +16,3 @@ generated/
# Ignore the files creates in /demos/dev except for example.html # Ignore the files creates in /demos/dev except for example.html
demos/dev/** demos/dev/**
!/demos/dev/example.html !/demos/dev/example.html
# TODO: Lots of errors to fix
cypress/platform/state-refactor.html

View File

@@ -1,5 +1,4 @@
import type { InlineConfig } from 'vite'; import { build, InlineConfig, type PluginOption } from 'vite';
import { build, type PluginOption } from 'vite';
import { resolve } from 'path'; import { resolve } from 'path';
import { fileURLToPath } from 'url'; import { fileURLToPath } from 'url';
import jisonPlugin from './jisonPlugin.js'; import jisonPlugin from './jisonPlugin.js';
@@ -47,10 +46,9 @@ interface BuildOptions {
export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions): InlineConfig => { export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions): InlineConfig => {
const external: (string | RegExp)[] = ['require', 'fs', 'path']; const external: (string | RegExp)[] = ['require', 'fs', 'path'];
// eslint-disable-next-line no-console
console.log(entryName, packageOptions[entryName]); console.log(entryName, packageOptions[entryName]);
const { name, file, packageName } = packageOptions[entryName]; const { name, file, packageName } = packageOptions[entryName];
const output: OutputOptions = [ let output: OutputOptions = [
{ {
name, name,
format: 'esm', format: 'esm',
@@ -85,6 +83,7 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
plugins: [ plugins: [
jisonPlugin(), jisonPlugin(),
jsonSchemaPlugin(), // handles `.schema.yaml` files jsonSchemaPlugin(), // handles `.schema.yaml` files
// @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite
typescript({ compilerOptions: { declaration: false } }), typescript({ compilerOptions: { declaration: false } }),
istanbul({ istanbul({
exclude: ['node_modules', 'test/', '__mocks__', 'generated'], exclude: ['node_modules', 'test/', '__mocks__', 'generated'],
@@ -122,10 +121,10 @@ await generateLangium();
if (watch) { if (watch) {
await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' })); 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) { if (!mermaidOnly) {
void build(getBuildConfig({ minify: false, watch, entryName: 'mermaid-example-diagram' })); 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-zenuml' }));
} }
} else if (visualize) { } else if (visualize) {
await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' })); await build(getBuildConfig({ minify: false, watch, core: false, entryName: 'parser' }));

View File

@@ -1,4 +1,4 @@
import type { PluginOption } from 'vite'; import { PluginOption } from 'vite';
import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js'; import { getDefaults, getSchema, loadSchema } from '../.build/jsonSchema.js';
/** /**

View File

@@ -23,9 +23,8 @@ async function createServer() {
app.use(express.static('cypress/platform')); app.use(express.static('cypress/platform'));
app.listen(9000, () => { app.listen(9000, () => {
// eslint-disable-next-line no-console
console.log(`Listening on http://localhost:9000`); console.log(`Listening on http://localhost:9000`);
}); });
} }
void createServer(); createServer();

View File

@@ -1,13 +1,2 @@
FROM node:20.12.2-alpine3.19@sha256:7a91aa397f2e2dfbfcdad2e2d72599f374e0b0172be1d86eeb73f1d33f36a4b2 FROM node:20.12.2-alpine3.19 AS base
RUN wget -qO- https://get.pnpm.io/install.sh | ENV="$HOME/.shrc" SHELL="$(which sh)" sh -
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

View File

@@ -35,8 +35,7 @@ Try Live Editor previews of future releases: <a href="https://develop.git.mermai
[![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid) [![NPM Downloads](https://img.shields.io/npm/dm/mermaid)](https://www.npmjs.com/package/mermaid)
[![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/AgrbSrBer3) [![Join our Discord!](https://img.shields.io/static/v1?message=join%20chat&color=9cf&logo=discord&label=discord)](https://discord.gg/AgrbSrBer3)
[![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_) [![Twitter Follow](https://img.shields.io/badge/Social-mermaidjs__-blue?style=social&logo=X)](https://twitter.com/mermaidjs_)
[![Covered by Argos Visual Testing](https://argos-ci.com/badge.svg)](https://argos-ci.com?utm_source=mermaid&utm_campaign=oss) [![Covered by Argos Visual Testing](https://argos-ci.com/badge.svg)](https://argos-ci.com)
[![OpenSSF Scorecard](https://api.securityscorecards.dev/projects/github.com/mermaid-js/mermaid/badge)](https://securityscorecards.dev/viewer/?uri=github.com/mermaid-js/mermaid)
<img src="./img/header.png" alt="" /> <img src="./img/header.png" alt="" />
@@ -83,10 +82,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). 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.
[![Covered by Argos Visual Testing](https://argos-ci.com/badge-large.svg)](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. 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/"> <a href="https://applitools.com/">

View File

@@ -1,9 +1,8 @@
import eyesPlugin from '@applitools/eyes-cypress';
import { registerArgosTask } from '@argos-ci/cypress/task';
import coverage from '@cypress/code-coverage/task';
import { defineConfig } from 'cypress'; import { defineConfig } from 'cypress';
import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin'; import { addMatchImageSnapshotPlugin } from 'cypress-image-snapshot/plugin';
import cypressSplit from 'cypress-split'; import coverage from '@cypress/code-coverage/task';
import eyesPlugin from '@applitools/eyes-cypress';
import { registerArgosTask } from '@argos-ci/cypress/task';
export default eyesPlugin( export default eyesPlugin(
defineConfig({ defineConfig({
@@ -14,7 +13,6 @@ export default eyesPlugin(
specPattern: 'cypress/integration/**/*.{js,ts}', specPattern: 'cypress/integration/**/*.{js,ts}',
setupNodeEvents(on, config) { setupNodeEvents(on, config) {
coverage(on, config); coverage(on, config);
cypressSplit(on, config);
on('before:browser:launch', (browser, launchOptions) => { on('before:browser:launch', (browser, launchOptions) => {
if (browser.name === 'chrome' && browser.isHeadless) { if (browser.name === 'chrome' && browser.isHeadless) {
launchOptions.args.push('--window-size=1440,1024', '--force-device-scale-factor=1'); launchOptions.args.push('--window-size=1440,1024', '--force-device-scale-factor=1');

View File

@@ -29,14 +29,13 @@ export const mermaidUrl = (
options: CypressMermaidConfig, options: CypressMermaidConfig,
api: boolean api: boolean
): string => { ): string => {
options.handDrawnSeed = 1;
const codeObject: CodeObject = { const codeObject: CodeObject = {
code: graphStr, code: graphStr,
mermaid: options, mermaid: options,
}; };
const objStr: string = JSON.stringify(codeObject); const objStr: string = JSON.stringify(codeObject);
let url = `http://localhost:9000/e2e.html?graph=${utf8ToB64(objStr)}`; 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}`; url = `http://localhost:9000/xss.html?graph=${graphStr}`;
} }
@@ -55,15 +54,16 @@ export const imgSnapshotTest = (
): void => { ): void => {
const options: CypressMermaidConfig = { const options: CypressMermaidConfig = {
..._options, ..._options,
fontFamily: _options.fontFamily ?? 'courier', fontFamily: _options.fontFamily || 'courier',
// @ts-ignore TODO: Fix type of fontSize // @ts-ignore TODO: Fix type of fontSize
fontSize: _options.fontSize ?? '16px', fontSize: _options.fontSize || '16px',
sequence: { sequence: {
...(_options.sequence ?? {}), ...(_options.sequence || {}),
actorFontFamily: 'courier', actorFontFamily: 'courier',
noteFontFamily: _options.sequence?.noteFontFamily noteFontFamily:
? _options.sequence.noteFontFamily _options.sequence && _options.sequence.noteFontFamily
: 'courier', ? _options.sequence.noteFontFamily
: 'courier',
messageFontFamily: 'courier', messageFontFamily: 'courier',
}, },
}; };
@@ -74,7 +74,7 @@ export const imgSnapshotTest = (
export const urlSnapshotTest = ( export const urlSnapshotTest = (
url: string, url: string,
options: CypressMermaidConfig = {}, options: CypressMermaidConfig,
_api = false, _api = false,
validation?: any validation?: any
): void => { ): void => {
@@ -95,7 +95,7 @@ export const openURLAndVerifyRendering = (
options: CypressMermaidConfig, options: CypressMermaidConfig,
validation?: any validation?: any
): void => { ): void => {
const name: string = (options.name ?? cy.state('runnable').fullTitle()).replace(/\s+/g, '-'); const name: string = (options.name || cy.state('runnable').fullTitle()).replace(/\s+/g, '-');
cy.visit(url); cy.visit(url);
cy.window().should('have.property', 'rendered', true); cy.window().should('have.property', 'rendered', true);
@@ -125,9 +125,7 @@ export const verifyScreenshot = (name: string): void => {
cy.log(`Closing eyes ${Cypress.spec.name}`); cy.log(`Closing eyes ${Cypress.spec.name}`);
cy.eyesClose(); cy.eyesClose();
} else if (useArgos) { } else if (useArgos) {
cy.argosScreenshot(name, { cy.argosScreenshot(name);
threshold: 0.01,
});
} else { } else {
cy.matchImageSnapshot(name); cy.matchImageSnapshot(name);
} }

View 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',
});
});
});

View File

@@ -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 () { // it(`ultraFastTest`, function () {
// // Navigate to the url we want to test // // Navigate to the url we want to test
// // ⭐️ Note to see visual bugs, run the test using the above URL for the 1st run. // // ⭐️ Note to see visual bugs, run the test using the above URL for the 1st run.

View File

@@ -1,181 +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 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}
`
);
});
});
// 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');
});
});

View File

@@ -236,7 +236,7 @@ describe('Block diagram', () => {
); );
}); });
it('BL17: width alignment - blocks shold be equal in width', () => { it('BL16: width alignment - blocks shold be equal in width', () => {
imgSnapshotTest( imgSnapshotTest(
`block-beta `block-beta
A("This is the text") 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( imgSnapshotTest(
`block-beta `block-beta
A["square"] 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( imgSnapshotTest(
`block-beta `block-beta
A>"rect_left_inv_arrow"] 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( imgSnapshotTest(
`block-beta `block-beta
A(["stadium"]) 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( imgSnapshotTest(
`block-beta `block-beta
A[/"lean right"/] 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( imgSnapshotTest(
`block-beta `block-beta
A["square"] 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( imgSnapshotTest(
`block-beta `block-beta
A("rounded"):2 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( imgSnapshotTest(
`block-beta `block-beta
block:2 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( imgSnapshotTest(
`block-beta `block-beta
columns 3 columns 3
@@ -335,7 +335,7 @@ describe('Block diagram', () => {
{} {}
); );
}); });
it('BL26: space and an edge', () => { it('BL25: space and an edge', () => {
imgSnapshotTest( imgSnapshotTest(
`block-beta `block-beta
columns 5 columns 5
@@ -345,7 +345,7 @@ describe('Block diagram', () => {
{} {}
); );
}); });
it('BL27: block sizes for regular blocks', () => { it('BL26: block sizes for regular blocks', () => {
imgSnapshotTest( imgSnapshotTest(
`block-beta `block-beta
columns 3 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( imgSnapshotTest(
`block-beta `block-beta
columns 3 columns 3
@@ -363,12 +363,11 @@ describe('Block diagram', () => {
f f
end end
g g
`, `,
{} {}
); );
}); });
it('BL23: composite block with a set width - f and g should split the available space', () => {
it('BL29: composite block with a set width - f and g should split the available space', () => {
imgSnapshotTest( imgSnapshotTest(
`block-beta `block-beta
columns 3 columns 3
@@ -380,7 +379,7 @@ describe('Block diagram', () => {
h h
i i
j j
`, `,
{} {}
); );
}); });

View File

@@ -1,7 +1,7 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
describe('C4 diagram', () => { describe('C4 diagram', () => {
it('C4.1 should render a simple C4Context diagram', () => { it('should render a simple C4Context diagram', () => {
imgSnapshotTest( imgSnapshotTest(
` `
C4Context C4Context
@@ -31,7 +31,7 @@ describe('C4 diagram', () => {
{} {}
); );
}); });
it('C4.2 should render a simple C4Container diagram', () => { it('should render a simple C4Container diagram', () => {
imgSnapshotTest( imgSnapshotTest(
` `
C4Container C4Container
@@ -50,7 +50,7 @@ describe('C4 diagram', () => {
{} {}
); );
}); });
it('C4.3 should render a simple C4Component diagram', () => { it('should render a simple C4Component diagram', () => {
imgSnapshotTest( imgSnapshotTest(
` `
C4Component C4Component
@@ -68,7 +68,7 @@ describe('C4 diagram', () => {
{} {}
); );
}); });
it('C4.4 should render a simple C4Dynamic diagram', () => { it('should render a simple C4Dynamic diagram', () => {
imgSnapshotTest( imgSnapshotTest(
` `
C4Dynamic C4Dynamic
@@ -91,7 +91,7 @@ describe('C4 diagram', () => {
{} {}
); );
}); });
it('C4.5 should render a simple C4Deployment diagram', () => { it('should render a simple C4Deployment diagram', () => {
imgSnapshotTest( imgSnapshotTest(
` `
C4Deployment C4Deployment

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@@ -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( imgSnapshotTest(
` `
classDiagram-v2 classDiagram-v2
@@ -93,7 +93,7 @@ describe('Class diagram V2', () => {
); );
}); });
it('3: should render multiple class diagrams', () => { it('should render multiple class diagrams', () => {
imgSnapshotTest( imgSnapshotTest(
[ [
` `
@@ -581,63 +581,4 @@ class C13["With Città foreign language"]
{ logLevel: 1, flowchart: { htmlLabels: false } } { 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

View File

@@ -321,37 +321,4 @@ ORDER ||--|{ LINE-ITEM : contains
{ logLevel: 1 } { 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 }
);
});
}); });

View File

@@ -3,7 +3,7 @@ import { imgSnapshotTest } from '../../helpers/util';
describe('Error Diagrams', () => { describe('Error Diagrams', () => {
beforeEach(() => { beforeEach(() => {
cy.on('uncaught:exception', (err) => { 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 // return false to prevent the error from
// failing this test // failing this test
return false; return false;

View File

@@ -837,26 +837,6 @@ subgraph "\`**Two**\`"
in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog") in the hat\`") -- "\`1o **ipa**\`" --> d("The dog in the hog")
end end
`,
{ flowchart: { titleTopMargin: 0 } }
);
});
it('Sub graphs and markdown strings', () => {
imgSnapshotTest(
`---
config:
layout: elk
---
flowchart LR
subgraph subgraph_ko6czgs5u["Untitled subgraph"]
D["Option 1"]
end
C{"Evaluate"} -- One --> D
C -- Two --> E(("Option 2"))
D --> E
A["A"]
`, `,
{ flowchart: { titleTopMargin: 0 } } { flowchart: { titleTopMargin: 0 } }
); );
@@ -875,7 +855,7 @@ describe('Title and arrow styling #4813', () => {
flowchart LR flowchart LR
A-->B A-->B
A-->C`, A-->C`,
{ layout: 'elk' } { flowchart: { defaultRenderer: 'elk' } }
); );
cy.get('svg').should((svg) => { cy.get('svg').should((svg) => {
const title = svg[0].querySelector('text'); const title = svg[0].querySelector('text');
@@ -891,14 +871,15 @@ describe('Title and arrow styling #4813', () => {
B-.-oC B-.-oC
C==xD C==xD
D ~~~ A`, D ~~~ A`,
{ layout: 'elk' } { flowchart: { defaultRenderer: 'elk' } }
); );
cy.get('svg').should((svg) => { cy.get('svg').should((svg) => {
const edges = svg[0].querySelectorAll('.edges path'); const edges = svg[0].querySelectorAll('.edges path');
expect(edges[0].getAttribute('class')).to.contain('edge-pattern-solid'); console.log(edges);
expect(edges[1].getAttribute('class')).to.contain('edge-pattern-dotted'); expect(edges[0]).to.have.attr('pattern', 'solid');
expect(edges[2].getAttribute('class')).to.contain('edge-thickness-thick'); expect(edges[1]).to.have.attr('pattern', 'dotted');
expect(edges[3].getAttribute('class')).to.contain('edge-thickness-invisible'); expect(edges[2]).to.have.css('stroke-width', '3.5px');
expect(edges[3]).to.have.css('stroke-width', '1.5px');
}); });
}); });
}); });

File diff suppressed because it is too large Load Diff

View File

@@ -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);
});
});
});

View File

@@ -99,7 +99,7 @@ describe('Flowchart v2', () => {
const style = svg.attr('style'); const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/); expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
expect(maxWidthValue).to.be.within(417 * 0.95, 417 * 1.05); expect(maxWidthValue).to.be.within(290 * 0.95 - 1, 290 * 1.05);
}); });
}); });
it('8: should render a flowchart when useMaxWidth is false', () => { it('8: should render a flowchart when useMaxWidth is false', () => {
@@ -118,7 +118,7 @@ describe('Flowchart v2', () => {
const width = parseFloat(svg.attr('width')); const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±5% // 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(height).to.be.within(446 * 0.95, 446 * 1.05);
expect(width).to.be.within(417 * 0.95, 417 * 1.05); expect(width).to.be.within(290 * 0.95 - 1, 290 * 1.05);
expect(svg).to.not.have.attr('style'); expect(svg).to.not.have.attr('style');
}); });
}); });
@@ -786,7 +786,7 @@ A ~~~ B
`--- `---
title: Subgraph nodeSpacing and rankSpacing example title: Subgraph nodeSpacing and rankSpacing example
config: config:
flowchart: flowchart:
nodeSpacing: 250 nodeSpacing: 250
rankSpacing: 250 rankSpacing: 250
--- ---
@@ -1047,32 +1047,7 @@ end
A --lb3--> TOP --lb4--> B A --lb3--> TOP --lb4--> B
B1 --lb5--> B2 B1 --lb5--> B2
`, `,
{ { flowchart: { subGraphTitleMargin: { top: 10, bottom: 5 } } }
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 } },
}
); );
}); });
}); });

View File

@@ -733,7 +733,7 @@ describe('Graph', () => {
}); });
it('38: should render a flowchart when useMaxWidth is true (default)', () => { it('38: should render a flowchart when useMaxWidth is true (default)', () => {
renderGraph( renderGraph(
`flowchart TD `graph TD
A[Christmas] -->|Get money| B(Go shopping) A[Christmas] -->|Get money| B(Go shopping)
B --> C{Let me think} B --> C{Let me think}
C -->|One| D[Laptop] C -->|One| D[Laptop]
@@ -751,7 +751,7 @@ describe('Graph', () => {
const style = svg.attr('style'); const style = svg.attr('style');
expect(style).to.match(/^max-width: [\d.]+px;$/); expect(style).to.match(/^max-width: [\d.]+px;$/);
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); 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', () => { it('39: should render a flowchart when useMaxWidth is false', () => {
@@ -770,7 +770,7 @@ describe('Graph', () => {
const width = parseFloat(svg.attr('width')); const width = parseFloat(svg.attr('width'));
// use within because the absolute value can be slightly different depending on the environment ±10% // 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(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'); expect(svg).to.not.have.attr('style');
}); });
}); });
@@ -905,16 +905,13 @@ graph TD
it('67: should be able to style default node independently', () => { it('67: should be able to style default node independently', () => {
imgSnapshotTest( imgSnapshotTest(
` `
flowchart TD flowchart TD
classDef default fill:#a34 classDef default fill:#a34
hello --> default hello --> default
style default stroke:#000,stroke-width:4px style default stroke:#000,stroke-width:4px
`, `,
{ { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' }
flowchart: { htmlLabels: true },
securityLevel: 'loose',
}
); );
}); });
}); });

View File

@@ -1532,41 +1532,5 @@ gitGraph TB:
{} {}
); );
}); });
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"`,
{}
);
}); });
}); });

View File

@@ -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);
});
});

View File

@@ -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 });
});
});
});
});
});

View File

@@ -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 assigments', () => {
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 som 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]
`,
{}
);
});
});

View File

@@ -1,146 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util.ts';
const looks = ['classic', 'handDrawn'] as const;
const directions = [
'TB',
//'BT',
'LR',
//'RL'
] as const;
const newShapesSet1 = [
'triangle',
'sloped-rectangle',
'horizontal-cylinder',
'flipped-triangle',
'hourglass',
] as const;
const newShapesSet2 = [
'tagged-rectangle',
'documents',
'lightning-bolt',
'filled-circle',
'window-pane',
] as const;
const newShapesSet3 = [
'curved-trapezoid',
'bow-rect',
'tagged-document',
'divided-rectangle',
'crossed-circle',
] as const;
const newShapesSet4 = [
'document',
'notched-pentagon',
'lined-cylinder',
'stacked-document',
'half-rounded-rectangle',
] as const;
const newShapesSet5 = [
'lined-document',
'tagged-document',
'brace-l',
'comment',
'braces',
'brace-r',
] as const;
const newShapesSet6 = ['brace-r', 'braces'] as const;
// Aggregate all shape sets into a single array
const newShapesSets = [
newShapesSet1,
newShapesSet2,
newShapesSet3,
newShapesSet4,
newShapesSet5,
newShapesSet6,
];
looks.forEach((look) => {
directions.forEach((direction) => {
newShapesSets.forEach((newShapesSet) => {
describe(`Test ${newShapesSet.join(', ')} in ${look} look and dir ${direction}`, () => {
it(`without label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape} }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`connect all shapes with each other`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`;
});
for (let i = 0; i < newShapesSet.length; i++) {
for (let j = i + 1; j < newShapesSet.length; j++) {
flowchartCode += ` n${i}${i} --> n${j}${j}\n`;
}
}
if (!(direction === 'TB' && look === 'handDrawn' && newShapesSet === newShapesSet1)) {
//skip this test, works in real. Need to look
imgSnapshotTest(flowchartCode, { look });
}
});
it(`with very long label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a very very very very very long long long label for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:true`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:false`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, {
look,
htmlLabels: false,
flowchart: { htmlLabels: false },
});
});
it(`with styles`, () => {
let flowchartCode = `flowchart ${direction}\n`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`;
flowchartCode += ` style n${index}${index} 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`;
newShapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`;
flowchartCode += ` n${index}${index}:::customClazz\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
});
});
});
});

View File

@@ -1,107 +0,0 @@
import { imgSnapshotTest } from '../../helpers/util';
const looks = ['classic', 'handDrawn'] as const;
const directions = [
'TB',
//'BT',
'LR',
//'RL'
] as const;
const shapesSet1 = ['text', 'card', 'lin-rect', 'diamond', 'hexagon'] as const;
// removing labelRect, need have alias for it
const shapesSet2 = ['rounded', 'rect', 'start', 'stop'] as const;
const shapesSet3 = ['fork', 'choice', 'note', 'stadium', 'odd'] as const;
const shapesSet4 = ['subroutine', 'cylinder', 'circle', 'doublecircle', 'odd'] as const;
const shapesSet5 = ['anchor', 'lean-r', 'lean-l', 'trap-t', 'trap-b'] as const;
// Aggregate all shape sets into a single array
const shapesSets = [shapesSet1, shapesSet2, shapesSet3, shapesSet4, shapesSet5] as const;
looks.forEach((look) => {
directions.forEach((direction) => {
shapesSets.forEach((shapesSet) => {
describe(`Test ${shapesSet.join(', ')} in ${look} look and dir ${direction}`, () => {
it(`without label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape} }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`connect all shapes with each other`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index}${index}@{ shape: ${newShape}, label: 'This is a label for ${newShape} shape' }\n`;
});
for (let i = 0; i < shapesSet.length; i++) {
for (let j = i + 1; j < shapesSet.length; j++) {
flowchartCode += ` n${i}${i} --> n${j}${j}\n`;
}
}
imgSnapshotTest(flowchartCode, { look });
});
it(`with very long label`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a very very very very very long long long label for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:true`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
it(`with markdown htmlLabels:false`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold** </br>and <strong>strong</strong> for ${newShape} shape' }\n`;
});
imgSnapshotTest(flowchartCode, {
look,
htmlLabels: false,
flowchart: { htmlLabels: false },
});
});
it(`with styles`, () => {
let flowchartCode = `flowchart ${direction}\n`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`;
flowchartCode += ` style n${index}${index} 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`;
shapesSet.forEach((newShape, index) => {
flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new ${newShape} shape' }\n`;
flowchartCode += ` n${index}${index}:::customClazz\n`;
});
imgSnapshotTest(flowchartCode, { look });
});
});
});
});
});

View File

@@ -10,15 +10,6 @@ describe('packet structure', () => {
); );
}); });
it('should render a simple packet diagram without ranges', () => {
imgSnapshotTest(
`packet-beta
0: "h"
1: "i"
`
);
});
it('should render a complex packet diagram', () => { it('should render a complex packet diagram', () => {
imgSnapshotTest( imgSnapshotTest(
`packet-beta `packet-beta

View File

@@ -1,6 +1,8 @@
// <reference types="Cypress" />
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
describe('Sequence diagram', () => { context('Sequence diagram', () => {
it('should render a sequence diagram with boxes', () => { it('should render a sequence diagram with boxes', () => {
renderGraph( renderGraph(
` `
@@ -242,7 +244,7 @@ describe('Sequence diagram', () => {
` `
); );
}); });
describe('font settings', () => { context('font settings', () => {
it('should render different note fonts when configured', () => { it('should render different note fonts when configured', () => {
imgSnapshotTest( imgSnapshotTest(
` `
@@ -339,7 +341,7 @@ describe('Sequence diagram', () => {
); );
}); });
}); });
describe('auth width scaling', () => { context('auth width scaling', () => {
it('should render long actor descriptions', () => { it('should render long actor descriptions', () => {
imgSnapshotTest( imgSnapshotTest(
` `
@@ -528,7 +530,7 @@ describe('Sequence diagram', () => {
); );
}); });
}); });
describe('background rects', () => { context('background rects', () => {
it('should render a single and nested rects', () => { it('should render a single and nested rects', () => {
imgSnapshotTest( imgSnapshotTest(
` `
@@ -808,7 +810,7 @@ describe('Sequence diagram', () => {
); );
}); });
}); });
describe('directives', () => { context('directives', () => {
it('should override config with directive settings', () => { it('should override config with directive settings', () => {
imgSnapshotTest( imgSnapshotTest(
` `
@@ -840,7 +842,7 @@ describe('Sequence diagram', () => {
); );
}); });
}); });
describe('links', () => { context('links', () => {
it('should support actor links', () => { it('should support actor links', () => {
renderGraph( renderGraph(
` `
@@ -856,7 +858,7 @@ describe('Sequence diagram', () => {
); );
cy.get('#actor0_popup').should((popupMenu) => { cy.get('#actor0_popup').should((popupMenu) => {
const style = popupMenu.attr('style'); const style = popupMenu.attr('style');
// expect(style).to.undefined; expect(style).to.undefined;
}); });
cy.get('#root-0').click(); cy.get('#root-0').click();
cy.get('#actor0_popup').should((popupMenu) => { cy.get('#actor0_popup').should((popupMenu) => {
@@ -931,7 +933,7 @@ describe('Sequence diagram', () => {
); );
}); });
}); });
describe('svg size', () => { context('svg size', () => {
it('should render a sequence diagram when useMaxWidth is true (default)', () => { it('should render a sequence diagram when useMaxWidth is true (default)', () => {
renderGraph( renderGraph(
` `
@@ -1010,7 +1012,7 @@ describe('Sequence diagram', () => {
}); });
}); });
}); });
describe('render after error', () => { context('render after error', () => {
it('should render diagram after fixing destroy participant error', () => { it('should render diagram after fixing destroy participant error', () => {
cy.on('uncaught:exception', (err) => { cy.on('uncaught:exception', (err) => {
return false; return false;

View File

@@ -542,43 +542,6 @@ stateDiagram-v2
{ logLevel: 0, fontFamily: 'courier' } { logLevel: 0, fontFamily: 'courier' }
); );
}); });
it(' can have styles applied ', () => {
imgSnapshotTest(
`
stateDiagram-v2
AState
style AState fill:#636,border:1px solid red,color:white;
`,
{ logLevel: 0, fontFamily: 'courier' }
);
});
it(' should let styles take preceedence over classes', () => {
imgSnapshotTest(
`
stateDiagram-v2
AState: Should NOT be white
BState
classDef exampleStyleClass fill:#fff,color: blue;
class AState,BState exampleStyleClass
style AState fill:#636,border:1px solid red,color:white;
`,
{ logLevel: 0, fontFamily: 'courier' }
);
});
it(' should allow styles to take effect in stubgraphs', () => {
imgSnapshotTest(
`
stateDiagram
state roundWithTitle {
C: Black with white text
}
D: Black with white text
style C,D stroke:#00f, fill:black, color:white
`,
{ logLevel: 0, fontFamily: 'courier' }
);
});
}); });
it('1433: should render a simple state diagram with a title', () => { it('1433: should render a simple state diagram with a title', () => {
imgSnapshotTest( imgSnapshotTest(
@@ -588,20 +551,6 @@ title: simple state diagram
stateDiagram-v2 stateDiagram-v2
[*] --> State1 [*] --> State1
State1 --> [*] State1 --> [*]
`,
{}
);
});
it('should align dividers correctly', () => {
imgSnapshotTest(
`stateDiagram-v2
state s2 {
s3
--
s4
--
55
}
`, `,
{} {}
); );

View File

@@ -1,18 +1,19 @@
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
describe('XY Chart', () => { describe('XY Chart', () => {
it('should render the simplest possible chart', () => { describe('single dataset', () => {
imgSnapshotTest( it('should render the simplest possible chart', () => {
` imgSnapshotTest(
`
xychart-beta xychart-beta
line [10, 30, 20] line [10, 30, 20]
`, `,
{} {}
); );
}); });
it('Should render a complete chart', () => { it('Should render a complete chart', () => {
imgSnapshotTest( imgSnapshotTest(
` `
xychart-beta xychart-beta
title "Sales Revenue" title "Sales Revenue"
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
@@ -20,82 +21,68 @@ describe('XY Chart', () => {
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`, `,
{} {}
); );
}); });
it('Should render a chart without title', () => { it('Should render a chart without title', () => {
imgSnapshotTest( imgSnapshotTest(
` `
xychart-beta xychart-beta
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis "Revenue (in $)" 4000 --> 11000 y-axis "Revenue (in $)" 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`, `,
{} {}
); );
}); });
it('y-axis title not required', () => { it('y-axis title not required', () => {
imgSnapshotTest( imgSnapshotTest(
` `
xychart-beta xychart-beta
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
y-axis 4000 --> 11000 y-axis 4000 --> 11000
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`, `,
{} {}
); );
}); });
it('Should render a chart without y-axis with different range', () => { it('Should render a chart without y-axis with different range', () => {
imgSnapshotTest( imgSnapshotTest(
` `
xychart-beta xychart-beta
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000] bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000]
line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800] line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800]
`, `,
{} {}
); );
}); });
it('x axis title not required', () => { it('x axis title not required', () => {
imgSnapshotTest( imgSnapshotTest(
` `
xychart-beta xychart-beta
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec] x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000] bar [5000, 6000, 7500, 8200, 9500, 10500, 14000, 3200, 9200, 9900, 3400, 6000]
line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800] line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800]
`, `,
{} {}
); );
}); });
it('Multiple plots can be rendered', () => { it('Decimals and negative numbers are supported', () => {
imgSnapshotTest( imgSnapshotTest(
` `
xychart-beta
line [23, 46, 77, 34]
line [45, 32, 33, 12]
bar [87, 54, 99, 85]
line [78, 88, 22, 4]
line [22, 29, 75, 33]
bar [52, 96, 35, 10]
`,
{}
);
});
it('Decimals and negative numbers are supported', () => {
imgSnapshotTest(
`
xychart-beta xychart-beta
y-axis -2.4 --> 3.5 y-axis -2.4 --> 3.5
line [+1.3, .6, 2.4, -.34] line [+1.3, .6, 2.4, -.34]
`, `,
{} {}
); );
}); });
it('Render spark line with "plotReservedSpacePercent"', () => { it('Render spark line with "plotReservedSpacePercent"', () => {
imgSnapshotTest( imgSnapshotTest(
` `
--- ---
config: config:
theme: dark theme: dark
@@ -107,12 +94,12 @@ describe('XY Chart', () => {
xychart-beta xychart-beta
line [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800] line [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
`, `,
{} {}
); );
}); });
it('Render spark bar without displaying other property', () => { it('Render spark bar without displaying other property', () => {
imgSnapshotTest( imgSnapshotTest(
` `
--- ---
config: config:
theme: dark theme: dark
@@ -133,12 +120,12 @@ describe('XY Chart', () => {
xychart-beta xychart-beta
bar [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800] bar [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
`, `,
{} {}
); );
}); });
it('Should use all the config from directive', () => { it('Should use all the config from directive', () => {
imgSnapshotTest( imgSnapshotTest(
` `
%%{init: {"xyChart": {"width": 1000, "height": 600, "titlePadding": 5, "titleFontSize": 10, "xAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5}, "yAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5}, "plotBorderWidth": 5, "chartOrientation": "horizontal", "plotReservedSpacePercent": 60 }}}%% %%{init: {"xyChart": {"width": 1000, "height": 600, "titlePadding": 5, "titleFontSize": 10, "xAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5}, "yAxis": {"labelFontSize": "20", "labelPadding": 10, "titleFontSize": 30, "titlePadding": 20, "tickLength": 10, "tickWidth": 5}, "plotBorderWidth": 5, "chartOrientation": "horizontal", "plotReservedSpacePercent": 60 }}}%%
xychart-beta xychart-beta
title "Sales Revenue" title "Sales Revenue"
@@ -147,12 +134,12 @@ describe('XY Chart', () => {
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`, `,
{} {}
); );
}); });
it('Should use all the config from yaml', () => { it('Should use all the config from yaml', () => {
imgSnapshotTest( imgSnapshotTest(
` `
--- ---
config: config:
theme: forest theme: forest
@@ -187,12 +174,12 @@ describe('XY Chart', () => {
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`, `,
{} {}
); );
}); });
it('Render with show axis title false', () => { it('Render with show axis title false', () => {
imgSnapshotTest( imgSnapshotTest(
` `
--- ---
config: config:
xyChart: xyChart:
@@ -208,12 +195,12 @@ describe('XY Chart', () => {
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`, `,
{} {}
); );
}); });
it('Render with show axis label false', () => { it('Render with show axis label false', () => {
imgSnapshotTest( imgSnapshotTest(
` `
--- ---
config: config:
xyChart: xyChart:
@@ -229,12 +216,12 @@ describe('XY Chart', () => {
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`, `,
{} {}
); );
}); });
it('Render with show axis tick false', () => { it('Render with show axis tick false', () => {
imgSnapshotTest( imgSnapshotTest(
` `
--- ---
config: config:
xyChart: xyChart:
@@ -250,12 +237,12 @@ describe('XY Chart', () => {
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`, `,
{} {}
); );
}); });
it('Render with show axis line false', () => { it('Render with show axis line false', () => {
imgSnapshotTest( imgSnapshotTest(
` `
--- ---
config: config:
xyChart: xyChart:
@@ -271,12 +258,12 @@ describe('XY Chart', () => {
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`, `,
{} {}
); );
}); });
it('Render all the theme color', () => { it('Render all the theme color', () => {
imgSnapshotTest( imgSnapshotTest(
` `
--- ---
config: config:
themeVariables: themeVariables:
@@ -300,19 +287,110 @@ describe('XY Chart', () => {
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
`, `,
{} {}
); );
});
}); });
it('should use the correct distances between data points', () => {
imgSnapshotTest( describe('multiple datasets', () => {
` describe('vertical', () => {
it('should render bar diagram for 3 datasets', () => {
imgSnapshotTest(
`
xychart-beta xychart-beta
x-axis 0 --> 2 title "Basic xychart with multiple datasets"
line [0, 1, 0, 1] x-axis "Relevant categories" [category1, "category 2", category3, category4]
bar [1, 0, 1, 0] y-axis Animals 0 --> 160
bar "dogs" [0, 20, 40, 30]
bar "cats" [20, 40, 0, 30]
bar "birds" [30, 60, 50, 30]
`, `,
{} {}
); );
cy.get('svg'); cy.get('svg');
});
it('should render line diagram for 3 datasets', () => {
imgSnapshotTest(
`
xychart-beta
title "Basic xychart with multiple datasets"
x-axis "Relevant categories" [category1, "category 2", category3, category4]
y-axis Animals 0 --> 160
line "dogs" [0, 20, 40, 30]
line "cats" [20, 40, 0, 30]
line "birds" [30, 60, 50, 30]
`,
{}
);
cy.get('svg');
});
it('should render a mix of multiple bar and line plots', () => {
imgSnapshotTest(
`
xychart-beta
line [23, 46, 77, 34]
line [45, 32, 33, 12]
bar [87, 54, 99, 85]
line [78, 88, 22, 4]
line [22, 29, 75, 33]
bar [52, 96, 35, 10]
`,
{}
);
cy.get('svg');
});
});
describe('horizontal', () => {
it('should render bar diagram for 3 datasets', () => {
imgSnapshotTest(
`
xychart-beta horizontal
title "Basic xychart with multiple datasets"
x-axis "Relevant categories" [category1, "category 2", category3, category4]
y-axis Animals 0 --> 160
bar "dogs" [0, 20, 40, 30]
bar "cats" [20, 40, 0, 30]
bar "birds" [30, 60, 50, 30]
`,
{}
);
cy.get('svg');
});
it('should render line diagram for 3 datasets', () => {
imgSnapshotTest(
`
xychart-beta horizontal
title "Basic xychart with multiple datasets"
x-axis "Relevant categories" [category1, "category 2", category3, category4]
y-axis Animals 0 --> 160
line "dogs" [0, 20, 40, 30]
line "cats" [20, 40, 0, 30]
line "birds" [30, 60, 50, 30]
`,
{}
);
cy.get('svg');
});
it('should render a mix of multiple bar and line plots', () => {
imgSnapshotTest(
`
xychart-beta horizontal
line [23, 46, 77, 34]
line [45, 32, 33, 12]
bar [87, 54, 99, 85]
line [78, 88, 22, 4]
line [22, 29, 75, 33]
bar [52, 96, 35, 10]
`,
{}
);
cy.get('svg');
});
});
}); });
}); });

View File

@@ -1,52 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Architecture Mermaid Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
<style>
div.mermaid {
/* font-family: 'trebuchet ms', verdana, arial; */
font-family: 'Courier New', Courier, monospace !important;
}
</style>
</head>
<body>
<h2>External Icons Demo</h2>
<pre class="mermaid">
architecture-beta
service s3(logos:aws-s3)[Cloud Store]
service ec2(logos:aws-ec2)[Server]
service api(logos:aws-api-gateway)[Api Gateway]
service fa(fa:image)[Font Awesome Icon]
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.initialize({
startOnLoad: false,
logLevel: 0,
});
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos/icons.json').then((res) => res.json()),
},
{
name: 'fa',
loader: () =>
fetch('https://unpkg.com/@iconify-json/fa6-regular/icons.json').then((res) =>
res.json()
),
},
]);
await mermaid.run();
if (window.Cypress) {
window.rendered = true;
}
</script>
</body>
</html>

View File

@@ -27,7 +27,7 @@ const code3 = `flowchart TD
A(<img scr='https://iconscout.com/ms-icon-310x310.png' width='20' height='20' />) A(<img scr='https://iconscout.com/ms-icon-310x310.png' width='20' height='20' />)
B(<b>Bold text!</b>)`; B(<b>Bold text!</b>)`;
if (/test-html-escaping/.exec(location.href)) { if (location.href.match('test-html-escaping')) {
code = code3; code = code3;
} }

View File

@@ -1,866 +0,0 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
rel="stylesheet"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style>
body {
font-family: 'Arial';
}
table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
th,
td {
border: 1px solid black;
padding: 10px;
text-align: center;
vertical-align: middle;
}
.separator {
height: 20px;
background-color: #f0f0f0;
}
.vertical-header {
text-align: center;
}
.collapsible {
background-color: #f9f9f9;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.active,
.collapsible:hover {
background-color: #ccc;
}
.collapsible:after {
content: '\002B';
color: #777;
font-weight: bold;
float: right;
margin-left: 2px;
}
.active:after {
content: '\2212';
}
.content {
padding: 0 5px;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
background-color: #f1f1f1;
}
.content .pre-scrollable {
max-height: 200px;
overflow-y: scroll;
}
</style>
</head>
<body>
<table>
<tr>
<th></th>
<!-- Placeholder for the top left corner -->
<th>Dagre</th>
<th>Dagre with rough</th>
<th>ELK</th>
<th>ELK with rough</th>
</tr>
<tr>
<th class="vertical-header">
<button class="collapsible">Stadium shape</button>
<div class="content">
<div class="pre-scrollable">
<pre>
flowchart LR
id1([This is the text in the box])
</pre
>
</div>
</div>
</th>
<td>
<pre id="diagram1" class="mermaid">
flowchart LR
id1([This is the text in the box])
</pre
>
</td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
flowchart LR
id1([This is the text in the box])
</pre
>
</td>
<td>
<pre id="diagram3" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
flowchart LR
id1([This is the text in the box])
</pre
>
</td>
<td>
<pre id="diagram4" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
flowchart LR
id1([This is the text in the box])
</pre
>
</td>
</tr>
<!-- Separator row -->
<tr class="separator">
<td colspan="5"></td>
<!-- This cell spans all columns including the vertical header -->
</tr>
<tr>
<th class="vertical-header">
<button class="collapsible">Sub-Routine shape</button>
<div class="content">
<div class="pre-scrollable">
<pre>
flowchart LR
id1[[This is the text in the box]]
</pre
>
</div>
</div>
</th>
<td>
<pre id="diagram5" class="mermaid">
flowchart LR
id1[[This is the text in the box]]
</pre
>
</td>
<td>
<pre id="diagram6" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
flowchart LR
id1[[This is the text in the box]]
</pre
>
</td>
<td>
<pre id="diagram7" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
flowchart LR
id1[[This is the text in the box]]
</pre
>
</td>
<td>
<pre id="diagram8" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
flowchart LR
id1[[This is the text in the box]]
</pre
>
</td>
</tr>
<!-- Separator row -->
<tr class="separator">
<td colspan="5"></td>
<!-- This cell spans all columns including the vertical header -->
</tr>
<tr>
<th class="vertical-header">
<button class="collapsible">Cylindrical shape</button>
<div class="content">
<div class="pre-scrollable">
<pre>
flowchart LR
id1[(Database)]
</pre
>
</div>
</div>
</th>
<td>
<pre id="diagram9" class="mermaid">
flowchart LR
id1[(Database)]
</pre
>
</td>
<td>
<pre id="diagram10" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
flowchart LR
id1[(Database)]
</pre
>
</td>
<td>
<pre id="diagram11" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
flowchart LR
id1[(Database)]
</pre
>
</td>
<td>
<pre id="diagram12" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
flowchart LR
id1[(Database)]
</pre
>
</td>
</tr>
<!-- Separator row -->
<tr class="separator">
<td colspan="5"></td>
<!-- This cell spans all columns including the vertical header -->
</tr>
<tr>
<th class="vertical-header">
<button class="collapsible">Circle shape</button>
<div class="content">
<div class="pre-scrollable">
<pre>
flowchart LR
id1((This is the text in the circle))
</pre
>
</div>
</div>
</th>
<td>
<pre id="diagram13" class="mermaid">
flowchart LR
id1((This is the text in the circle))
</pre
>
</td>
<td>
<pre id="diagram14" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
flowchart LR
id1((This is the text in the circle))
</pre
>
</td>
<td>
<pre id="diagram15" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
flowchart LR
id1((This is the text in the circle))
</pre
>
</td>
<td>
<pre id="diagram16" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
flowchart LR
id1((This is the text in the circle))
</pre
>
</td>
</tr>
<!-- Separator row -->
<tr class="separator">
<td colspan="5"></td>
<!-- This cell spans all columns including the vertical header -->
</tr>
<tr>
<th class="vertical-header">
<button class="collapsible">Double Circle shape</button>
<div class="content">
<div class="pre-scrollable">
<pre>
flowchart TD
id1(((This is the text in the circle)))
</pre
>
</div>
</div>
</th>
<td>
<pre id="diagram17" class="mermaid">
flowchart TD
id1(((This is the text in the circle)))
</pre
>
</td>
<td>
<pre id="diagram18" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
flowchart TD
id1(((This is the text in the circle)))
</pre
>
</td>
<td>
<pre id="diagram19" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
flowchart TD
id1(((This is the text in the circle)))
</pre
>
</td>
<td>
<pre id="diagram20" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
flowchart TD
id1(((This is the text in the circle)))
</pre
>
</td>
</tr>
<!-- Separator row -->
<tr class="separator">
<td colspan="5"></td>
<!-- This cell spans all columns including the vertical header -->
</tr>
<tr>
<th class="vertical-header">
<button class="collapsible">Asymmetric shape</button>
<div class="content">
<div class="pre-scrollable">
<pre>
flowchart LR
id1>This is the text in the box]
</pre
>
</div>
</div>
</th>
<td>
<pre id="diagram21" class="mermaid">
flowchart LR
id1>This is the text in the box]
</pre
>
</td>
<td>
<pre id="diagram22" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
flowchart LR
id1>This is the text in the box]
</pre
>
</td>
<td>
<pre id="diagram23" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
flowchart LR
id1>This is the text in the box]
</pre
>
</td>
<td>
<pre id="diagram24" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
flowchart LR
id1>This is the text in the box]
</pre
>
</td>
</tr>
<!-- Separator row -->
<tr class="separator">
<td colspan="5"></td>
<!-- This cell spans all columns including the vertical header -->
</tr>
<tr>
<th class="vertical-header">
<button class="collapsible">Rhombus/Diamond/Question shape</button>
<div class="content">
<div class="pre-scrollable">
<pre>
flowchart LR
id1{This is the text in the box}
</pre
>
</div>
</div>
</th>
<td>
<pre id="diagram25" class="mermaid">
flowchart LR
id1{This is the text in the box}
</pre
>
</td>
<td>
<pre id="diagram26" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
flowchart LR
id1{This is the text in the box}
</pre
>
</td>
<td>
<pre id="diagram27" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
flowchart LR
id1{This is the text in the box}
</pre
>
</td>
<td>
<pre id="diagram28" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
flowchart LR
id1{This is the text in the box}
</pre
>
</td>
</tr>
<!-- Separator row -->
<tr class="separator">
<td colspan="5"></td>
<!-- This cell spans all columns including the vertical header -->
</tr>
<tr>
<th class="vertical-header">
<button class="collapsible">Hexagon shape</button>
<div class="content">
<div class="pre-scrollable">
<pre>
flowchart LR
id1{{This is the text in the box}}
</pre
>
</div>
</div>
</th>
<td>
<pre id="diagram29" class="mermaid">
flowchart LR
id1{{This is the text in the box}}
</pre
>
</td>
<td>
<pre id="diagram31" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
flowchart LR
id1{{This is the text in the box}}
</pre
>
</td>
<td>
<pre id="diagram32" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
flowchart LR
id1{{This is the text in the box}}
</pre
>
</td>
</tr>
<!-- Separator row -->
<tr class="separator">
<td colspan="5"></td>
<!-- This cell spans all columns including the vertical header -->
</tr>
<tr>
<th class="vertical-header">
<button class="collapsible">Parallelogram shape</button>
<div class="content">
<div class="pre-scrollable">
<pre>
flowchart TD
id1[/This is the text in the box/]
</pre
>
</div>
</div>
</th>
<td>
<pre id="diagram33" class="mermaid">
flowchart TD
id1[/This is the text in the box/]
</pre
>
</td>
<td>
<pre id="diagram34" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
flowchart TD
id1[/This is the text in the box/]
</pre
>
</td>
<td>
<pre id="diagram35" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
flowchart TD
id1[/This is the text in the box/]
</pre
>
</td>
<td>
<pre id="diagram36" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
flowchart TD
id1[/This is the text in the box/]
</pre
>
</td>
</tr>
<!-- Separator row -->
<tr class="separator">
<td colspan="5"></td>
<!-- This cell spans all columns including the vertical header -->
</tr>
<tr>
<th class="vertical-header">
<button class="collapsible">Parallelogram Alt shape</button>
<div class="content">
<div class="pre-scrollable">
<pre>
flowchart TD
id1[\This is the text in the box\]
</pre
>
</div>
</div>
</th>
<td>
<pre id="diagram37" class="mermaid">
flowchart TD
id1[\This is the text in the box\]
</pre
>
</td>
<td>
<pre id="diagram38" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
flowchart TD
id1[\This is the text in the box\]
</pre
>
</td>
<td>
<pre id="diagram39" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
flowchart TD
id1[\This is the text in the box\]
</pre
>
</td>
<td>
<pre id="diagram40" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
flowchart TD
id1[\This is the text in the box\]
</pre
>
</td>
</tr>
<!-- Separator row -->
<tr class="separator">
<td colspan="5"></td>
<!-- This cell spans all columns including the vertical header -->
</tr>
<tr>
<th class="vertical-header">
<button class="collapsible">Trapezoid shape</button>
<div class="content">
<div class="pre-scrollable">
<pre>
flowchart TD
A[/Christmas\]
</pre
>
</div>
</div>
</th>
<td>
<pre id="diagram41" class="mermaid">
flowchart TD
A[/Christmas\]
</pre
>
</td>
<td>
<pre id="diagram42" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
flowchart TD
A[/Christmas\]
</pre
>
</td>
<td>
<pre id="diagram43" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
flowchart TD
A[/Christmas\]
</pre
>
</td>
<td>
<pre id="diagram44" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
flowchart TD
A[/Christmas\]
</pre
>
</td>
</tr>
<!-- Separator row -->
<tr class="separator">
<td colspan="5"></td>
<!-- This cell spans all columns including the vertical header -->
</tr>
<tr>
<th class="vertical-header">
<button class="collapsible">Trapezoid Alt shape</button>
<div class="content">
<div class="pre-scrollable">
<pre>
flowchart TD
A[\Christmas/]
</pre
>
</div>
</div>
</th>
<td>
<pre id="diagram45" class="mermaid">
flowchart TD
A[\Christmas/]
</pre
>
</td>
<td>
<pre id="diagram46" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
flowchart TD
A[\Christmas/]
</pre
>
</td>
<td>
<pre id="diagram47" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
flowchart TD
A[\Christmas/]
</pre
>
</td>
<td>
<pre id="diagram48" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
flowchart TD
A[\Christmas/]
</pre
>
</td>
</tr>
<!-- Separator row -->
<tr class="separator">
<td colspan="5"></td>
<!-- This cell spans all columns including the vertical header -->
</tr>
<tr>
<th class="vertical-header">
<button class="collapsible">Rect with rounded corner</button>
<div class="content">
<div class="pre-scrollable">
<pre>
flowchart LR
id1(This is the text in the box)
</pre
>
</div>
</div>
</th>
<td>
<pre id="diagram49" class="mermaid">
flowchart LR
id1(This is the text in the box)
</pre
>
</td>
<td>
<pre id="diagram50" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
flowchart LR
id1(This is the text in the box)
</pre
>
</td>
<td>
<pre id="diagram51" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
flowchart LR
id1(This is the text in the box)
</pre
>
</td>
<td>
<pre id="diagram52" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
flowchart LR
id1(This is the text in the box)
</pre
>
</td>
</tr>
<!-- Separator row -->
<tr class="separator">
<td colspan="5"></td>
<!-- This cell spans all columns including the vertical header -->
</tr>
<tr>
<th class="vertical-header">
<button class="collapsible">Rect with sharp corner</button>
<div class="content">
<div class="pre-scrollable">
<pre>
flowchart LR
id1[This is the text in the box]
</pre
>
</div>
</div>
</th>
<td>
<pre id="diagram53" class="mermaid">
flowchart LR
id1[This is the text in the box]
</pre
>
</td>
<td>
<pre id="diagram54" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
flowchart LR
id1[This is the text in the box]
</pre
>
</td>
<td>
<pre id="diagram55" class="mermaid">
%%{init: {"handDrawn": false, "layout": "elk"} }%%
flowchart LR
id1[This is the text in the box]
</pre
>
</td>
<td>
<pre id="diagram56" class="mermaid">
%%{init: {"look": "handDrawn", "layout": "elk"} }%%
flowchart LR
id1[This is the text in the box]
</pre
>
</td>
</tr>
<!-- Separator row -->
<tr class="separator">
<td colspan="5"></td>
<!-- This cell spans all columns including the vertical header -->
</tr>
</table>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {};
mermaid.initialize({
handDrawn: false,
mergeEdges: true,
layout: 'dagre',
flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
fontFamily: 'Kalam',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
messageFontFamily: 'courier',
},
fontSize: 16,
logLevel: 0,
});
function callback() {
alert('It worked');
}
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);
};
let coll = document.getElementsByClassName('collapsible');
for (const element of coll) {
element.addEventListener('click', function () {
this.classList.toggle('active');
let content = this.nextElementSibling;
if (content.style.maxHeight) {
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + 'px';
}
});
}
</script>
</body>
</html>

View File

@@ -1,191 +0,0 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
rel="stylesheet"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style>
body {
font-family: 'Arial';
}
table {
width: 100%;
border-collapse: collapse;
table-layout: fixed;
}
th,
td {
border: 1px solid black;
padding: 10px;
text-align: center;
vertical-align: middle;
}
.separator {
height: 20px;
background-color: #f0f0f0;
}
.vertical-header {
text-align: center;
}
.collapsible {
background-color: #f9f9f9;
color: #444;
cursor: pointer;
padding: 18px;
width: 100%;
border: none;
text-align: left;
outline: none;
font-size: 15px;
}
.active,
.collapsible:hover {
background-color: #ccc;
}
.collapsible:after {
content: '\002B';
color: #777;
font-weight: bold;
float: right;
margin-left: 2px;
}
.active:after {
content: '\2212';
}
.content {
padding: 0 5px;
max-height: 0;
overflow: hidden;
transition: max-height 0.2s ease-out;
background-color: #f1f1f1;
}
.content .pre-scrollable {
max-height: 200px;
overflow-y: scroll;
}
</style>
</head>
<body>
<table>
<tr>
<th></th>
<!-- Placeholder for the top left corner -->
<th>State rough</th>
<th>Flowchart rough</th>
</tr>
<tr>
<th class="vertical-header">
<button class="collapsible">Stadium shape</button>
<div class="content">
<div class="pre-scrollable">
<pre>
flowchart LR
id1([This is the text in the box])
</pre
>
</div>
</div>
</th>
<td>
<pre id="diagram1" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
stateDiagram-v2
stateA
</pre
>
</td>
<td>
<pre id="diagram2" class="mermaid">
%%{init: {"look": "handDrawn"} }%%
flowchart LR
id1[[This is the text in the box]]
</pre
>
</td>
</tr>
</table>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {};
mermaid.initialize({
handDrawn: false,
mergeEdges: true,
layout: 'dagre',
flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
fontFamily: 'Kalam',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
messageFontFamily: 'courier',
},
fontSize: 16,
logLevel: 0,
});
function callback() {
alert('It worked');
}
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);
};
let coll = document.getElementsByClassName('collapsible');
for (const element of coll) {
element.addEventListener('click', function () {
this.classList.toggle('active');
let content = this.nextElementSibling;
if (content.style.maxHeight) {
content.style.maxHeight = null;
} else {
content.style.maxHeight = content.scrollHeight + 'px';
}
});
}
</script>
</body>
</html>

View File

@@ -1,433 +0,0 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
rel="stylesheet"
/>
<style>
body {
/* background: rgb(221, 208, 208); */
/* background:#333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 {
color: grey;
}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
background-color: #efefef;
background-image: radial-gradient(#fff 51%, transparent 91%),
radial-gradient(#fff 51%, transparent 91%);
background-size: 20px 20px;
background-position:
0 0,
10px 10px;
background-repeat: repeat;
}
.malware {
position: fixed;
bottom: 0;
left: 0;
right: 0;
height: 150px;
background: red;
color: black;
display: flex;
display: flex;
justify-content: center;
align-items: center;
font-family: monospace;
font-size: 72px;
}
/* tspan {
font-size: 6px !important;
} */
</style>
</head>
<body>
<pre id="diagram" class="mermaid">
stateDiagram-v2
[*] --> Still
Still --> [*]
Still --> Moving
Moving --> Still
Moving --> Crash
Crash --> [*] </pre
>
<pre id="diagram" class="mermaid2">
flowchart RL
subgraph "`one`"
a1 -- l1 --> a2
a1 -- l2 --> a2
end
</pre>
<pre id="diagram" class="mermaid">
flowchart RL
subgraph "`one`"
a1 -- l1 --> a2
a1 -- l2 --> a2
end
</pre>
<pre id="diagram" class="mermaid2">
flowchart
id["`A root with a long text that wraps to keep the node size in check. A root with a long text that wraps to keep the node size in check`"]</pre
>
<pre id="diagram" class="mermaid2">
flowchart LR
A[A text that needs to be wrapped wraps to another line]
B[A text that needs to be<br/>wrapped wraps to another line]
C["`A text that needs to be wrapped to another line`"]</pre>
<pre id="diagram" class="mermaid2">
flowchart LR
C["`A text
that needs
to be wrapped
in another
way`"]
</pre
>
<pre id="diagram" class="mermaid">
classDiagram-v2
note "I love this diagram!\nDo you love it?"
</pre>
<pre id="diagram" class="mermaid">
stateDiagram-v2
State1: The state with a note with minus - and plus + in it
note left of State1
Important information! You can write
notes with . and in them.
end note </pre
>
<pre id="diagram" class="mermaid2">
mindmap
root
Child3(A node with an icon and with a long text that wraps to keep the node size in check)
</pre
>
<pre id="diagram" class="mermaid2">
%%{init: {"theme": "forest"} }%%
mindmap
id1[**Start2**<br/>end]
id2[**Start2**<br />end]
%% Another comment
id3[**Start2**<br>end] %% Comment
id4[**Start2**<br >end<br >the very end]
</pre>
<pre id="diagram" class="mermaid2">
mindmap
id1["`**Start2**
second line 😎 with long text that is wrapping to the next line`"]
id2["`Child **with bold** text`"]
id3["`Children of which some
is using *italic type of* text`"]
id4[Child]
id5["`Child
Row
and another
`"]
</pre>
<pre id="diagram" class="mermaid2">
mindmap
id1("`**Root**`"]
id2["`A formatted text... with **bold** and *italics*`"]
id3[Regular labels works as usual]
id4["`Emojis and unicode works too: 🤓
शान्तिः سلام 和平 `"]
</pre>
<pre id="diagram" class="mermaid">
%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
flowchart TB
%% I could not figure out how to use double quotes in labels in Mermaid
subgraph ibm[IBM Espresso CPU]
core0[IBM PowerPC Broadway Core 0]
core1[IBM PowerPC Broadway Core 1]
core2[IBM PowerPC Broadway Core 2]
rom[16 KB ROM]
core0 --- core2
rom --> core2
end
subgraph amd["`**AMD** Latte GPU`"]
mem[Memory & I/O Bridge]
dram[DRAM Controller]
edram[32 MB EDRAM MEM1]
rom[512 B SEEPROM]
sata[SATA IF]
exi[EXI]
subgraph gx[GX]
sram[3 MB 1T-SRAM]
end
radeon[AMD Radeon R7xx GX2]
mem --- gx
mem --- radeon
rom --- mem
mem --- sata
mem --- exi
dram --- sata
dram --- exi
end
ddr3[2 GB DDR3 RAM MEM2]
mem --- ddr3
dram --- ddr3
edram --- ddr3
core1 --- mem
exi --- rtc
rtc{{rtc}}
</pre
>
<pre id="diagram" class="mermaid2">
%%{init: {"flowchart": {"defaultRenderer": "elk", "htmlLabels": false}} }%%
flowchart TB
%% I could not figure out how to use double quotes in labels in Mermaid
subgraph ibm[IBM Espresso CPU]
core0[IBM PowerPC Broadway Core 0]
core1[IBM PowerPC Broadway Core 1]
core2[IBM PowerPC Broadway Core 2]
rom[16 KB ROM]
core0 --- core2
rom --> core2
end
subgraph amd["`**AMD** Latte GPU`"]
mem[Memory & I/O Bridge]
dram[DRAM Controller]
edram[32 MB EDRAM MEM1]
rom[512 B SEEPROM]
sata[SATA IF]
exi[EXI]
subgraph gx[GX]
sram[3 MB 1T-SRAM]
end
radeon[AMD Radeon R7xx GX2]
mem --- gx
mem --- radeon
rom --- mem
mem --- sata
mem --- exi
dram --- sata
dram --- exi
end
ddr3[2 GB DDR3 RAM MEM2]
mem --- ddr3
dram --- ddr3
edram --- ddr3
core1 --- mem
exi --- rtc
rtc{{rtc}}
</pre
>
<br />
<pre id="diagram" class="mermaid2">
flowchart TB
%% I could not figure out how to use double quotes in labels in Mermaid
subgraph ibm[IBM Espresso CPU]
core0[IBM PowerPC Broadway Core 0]
core1[IBM PowerPC Broadway Core 1]
core2[IBM PowerPC Broadway Core 2]
rom[16 KB ROM]
core0 --- core2
rom --> core2
end
subgraph amd[AMD Latte GPU]
mem[Memory & I/O Bridge]
dram[DRAM Controller]
edram[32 MB EDRAM MEM1]
rom[512 B SEEPROM]
sata[SATA IF]
exi[EXI]
subgraph gx[GX]
sram[3 MB 1T-SRAM]
end
radeon[AMD Radeon R7xx GX2]
mem --- gx
mem --- radeon
rom --- mem
mem --- sata
mem --- exi
dram --- sata
dram --- exi
end
ddr3[2 GB DDR3 RAM MEM2]
mem --- ddr3
dram --- ddr3
edram --- ddr3
core1 --- mem
exi --- rtc
rtc{{rtc}}
</pre
>
<br />
&nbsp;
<pre id="diagram" class="mermaid2">
flowchart LR
B1 --be be--x B2
B1 --bo bo--o B3
subgraph Ugge
B2
B3
subgraph inner
B4
B5
end
subgraph inner2
subgraph deeper
C4
C5
end
C6
end
B4 --> C4
B3 -- X --> B4
B2 --> inner
C4 --> C5
end
subgraph outer
B6
end
B6 --> B5
</pre
>
<pre id="diagram" class="mermaid2">
sequenceDiagram
Customer->>+Stripe: Makes a payment request
Stripe->>+Bank: Forwards the payment request to the bank
Bank->>+Customer: Asks for authorization
Customer->>+Bank: Provides authorization
Bank->>+Stripe: Sends a response with payment details
Stripe->>+Merchant: Sends a notification of payment receipt
Merchant->>+Stripe: Confirms the payment
Stripe->>+Customer: Sends a confirmation of payment
Customer->>+Merchant: Receives goods or services
</pre
>
<pre id="diagram" class="mermaid2">
mindmap
root((mindmap))
Origins
Long history
::icon(fa fa-book)
Popularisation
British popular psychology author Tony Buzan
Research
On effectiveness<br/>and features
On Automatic creation
Uses
Creative techniques
Strategic planning
Argument mapping
Tools
Pen and paper
Mermaid
</pre>
<br />
<pre id="diagram" class="mermaid2">
example-diagram
</pre>
<!-- <div id="cy"></div> -->
<!-- <script src="http://localhost:9000/packages/mermaid-mindmap/dist/mermaid-mindmap-detector.js"></script> -->
<!-- <script src="./mermaid-example-diagram-detector.js"></script> -->
<!-- <script src="//cdn.jsdelivr.net/npm/mermaid@9.1.7/dist/mermaid.min.js"></script> -->
<!-- <script src="./mermaid.js"></script> -->
<scrpt>
// import mindmap from '../../packages/mermaid-mindmap/src/detector'; // import example from
'../../packages/mermaid-example-diagram/src/mermaid-example-diagram.core.mjs'; import mermaid
from './mermaid.esm.mjs'; // await mermaid.registerExternalDiagrams([example]);
mermaid.parseError = function (err, hash) { // console.error('Mermaid error: ', err); };
mermaid.initialize({ // theme: 'forest', startOnLoad: true, logLevel: 0, flowchart: { //
defaultRenderer: 'elk', useMaxWidth: false, // htmlLabels: false, htmlLabels: true, }, //
htmlLabels: false, gantt: { useMaxWidth: false, }, useMaxWidth: false, }); function callback()
{ alert('It worked'); } mermaid.parseError = function (err, hash) { console.error('In parse
error:'); console.error(err); }; // mermaid.test1('first_slow', 1200).then((r) =>
console.info(r)); // mermaid.test1('second_fast', 200).then((r) => console.info(r)); //
mermaid.test1('third_fast', 200).then((r) => console.info(r)); // mermaid.test1('forth_slow',
1200).then((r) => console.info(r));
</scrpt>
<script
type="text/javascript"
src="https://cdn.jsdelivr.net/npm/mermaid@10.2.0/dist/mermaid.min.js"
></script>
<script type="module">
import mermaid from 'https://cdn.jsdelivr.net/npm/mermaid@10.2.0/dist/mermaid.min.js';
(function () {
mermaid.initialize({ startOnLoad: false });
const elements = document.getElementsByClassName('mermaid');
console.log(elements);
let id = 0;
[...elements].forEach((elem) => {
const insertSvg = function (svgCode) {
elem.innerHTML = svgCode;
};
console.log(atob(elem.innerText));
mermaid.render(`graphDiv-${id++}`, atob(elem.innerText), insertSvg);
});
})();
</script>
</body>
</html>

View File

@@ -4,65 +4,44 @@
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link <link
rel="stylesheet" rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.2/css/font-awesome.min.css"
/> />
<link <link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css" href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet" rel="stylesheet"
/> />
<link
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.min.css"
rel="stylesheet"
/>
<link <link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
rel="stylesheet" rel="stylesheet"
/> />
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style> <style>
body { body {
/* background: rgb(221, 208, 208); */ /* background: rgb(221, 208, 208); */
/* background: #333; */ background: #333;
font-family: 'Arial'; font-family: 'Arial';
/* color: white; */
/* font-size: 18px !important; */ /* font-size: 18px !important; */
} }
h1 { h1 {
color: grey; color: grey;
} }
.mermaid {
border: 1px solid #ddd;
margin: 10px;
}
.mermaid2 { .mermaid2 {
display: none; display: none;
} }
.mermaid svg { .mermaid svg {
/* font-size: 18px !important; */ /* font-size: 18px !important; */
/* background-color: #efefef; */
/* background-color: #efefef; background-color: #333;
background-image: radial-gradient(#fff 51%, transparent 91%), background-image: radial-gradient(#333 51%, transparent 91%),
radial-gradient(#fff 51%, transparent 91%); radial-gradient(#333 51%, transparent 91%);
background-size: 20px 20px; background-size: 20px 20px;
background-position: background-position: 0 0, 10px 10px;
0 0, background-repeat: repeat;
10px 10px; border: 2px solid rgb(131, 142, 205);
background-repeat: repeat; */
} }
.malware { .malware {
position: fixed; position: fixed;
bottom: 0; bottom: 0;
@@ -78,176 +57,546 @@
font-family: monospace; font-family: monospace;
font-size: 72px; font-size: 72px;
} }
pre {
width: 100%;
}
/* tspan { /* tspan {
font-size: 6px !important; font-size: 6px !important;
} */ } */
</style> </style>
</head> </head>
<body> <body>
<pre id="diagram4" class="mermaid"> <pre id="diagram" class="mermaid">
flowchart LR block-beta
nA[Default] --> A@{ icon: 'fa:bell', form: 'rounded' } blockArrowId<["Label"]>(right)
blockArrowId2<["Label"]>(left)
blockArrowId3<["Label"]>(up)
blockArrowId4<["Label"]>(down)
blockArrowId5<["Label"]>(x)
blockArrowId6<["Label"]>(y)
blockArrowId6<["Label"]>(x, down)
</pre>
<pre id="diagram" class="mermaid">
block-beta
block:e:4
columns 2
f
g
end
</pre> </pre>
<pre id="diagram4" class="mermaid"> <pre id="diagram" class="mermaid">
flowchart LR block-beta
nA[Style] --> A@{ icon: 'fa:bell', form: 'rounded' } block:e:4
style A fill:#f9f,stroke:#333,stroke-width:4px columns 2
</pre> f
<pre id="diagram4" class="mermaid"> g
flowchart LR h
nA[Class] --> A@{ icon: 'fa:bell', form: 'rounded' } end
A:::AClass
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
</pre>
<pre id="diagram4" class="mermaid">
flowchart LR
nA[Class] --> A@{ icon: 'logos:aws', form: 'rounded' }
</pre> </pre>
<pre id="diagram4" class="mermaid"> <pre id="diagram" class="mermaid">
flowchart LR block-beta
nA[Default] --> A@{ icon: 'fa:bell', form: 'square' } columns 4
a b c d
block:e:4
columns 2
f
g
h
end
i:4
</pre> </pre>
<pre id="diagram4" class="mermaid"> <pre id="diagram" class="mermaid2">
flowchart LR flowchart LR
nA[Style] --> A@{ icon: 'fa:bell', form: 'square' } X-- "y" -->z
style A fill:#f9f,stroke:#333,stroke-width:4px
</pre> </pre>
<pre id="diagram4" class="mermaid"> <pre id="diagram" class="mermaid2">
flowchart LR block-beta
nA[Class] --> A@{ icon: 'fa:bell', form: 'square' } columns 5
A:::AClass A space B
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px A --x B
</pre> </pre>
<pre id="diagram4" class="mermaid"> <pre id="diagram" class="mermaid2">
flowchart LR block-beta
nA[Class] --> A@{ icon: 'logos:aws', form: 'square' } columns 3
a["A wide one"] b:2 c:2 d
</pre>
<pre id="diagram" class="mermaid2">
block-beta
block:e
f
end
</pre>
<pre id="diagram" class="mermaid2">
block-beta
columns 3
a:3
block:e:3
f
end
g
</pre>
<pre id="diagram" class="mermaid2">
block-beta
columns 3
a:3
block:e:3
f
g
end
h
i
j
</pre> </pre>
<pre id="diagram4" class="mermaid"> <pre id="diagram" class="mermaid2">
block-beta
columns 3
a b:2
block:e:3
f
end
g h i
</pre>
<pre id="diagram" class="mermaid">
block-beta
columns 3
a b c
e:3
f g h
</pre>
<pre id="diagram" class="mermaid">
block-beta
columns 1
db(("DB"))
blockArrowId6<["&nbsp;&nbsp;&nbsp;"]>(down)
block:ID
A
B["A wide one in the middle"]
C
end
space
D
ID --> D
C --> D
style B fill:#f9F,stroke:#333,stroke-width:4px
</pre>
<pre id="diagram" class="mermaid">
block-beta
columns 5
A1:3
A2:1
A3
B1 B2 B3:3
</pre>
<pre id="diagram" class="mermaid2">
block-beta
block
D
E
end
db("This is the text in the box")
</pre>
<pre id="diagram" class="mermaid2">
block-beta
block
D
end
A["A: I am a wide one"]
</pre>
<pre id="diagram" class="mermaid2">
block-beta
A["square"]
B("rounded")
C(("circle"))
</pre>
<pre id="diagram" class="mermaid2">
block-beta
A>"rect_left_inv_arrow"]
B{"diamond"}
C{{"hexagon"}}
</pre>
<pre id="diagram" class="mermaid2">
block-beta
A(["stadium"])
</pre>
<pre id="diagram" class="mermaid2">
block-beta
%% A[["subroutine"]]
%% B[("cylinder")]
C>"surprise"]
</pre>
<pre id="diagram" class="mermaid2">
block-beta
A[/"lean right"/]
B[\"lean left"\]
C[/"trapezoid"\]
D[\"trapezoid"/]
</pre>
<pre id="diagram" class="mermaid2">
flowchart
B
style B fill:#f9F,stroke:#333,stroke-width:4px
</pre>
<pre id="diagram" class="mermaid2">
flowchart LR
a1 -- apa --> b1
</pre>
<pre id="diagram" class="mermaid2">
flowchart RL
subgraph "`one`"
id
end
</pre>
<pre id="diagram" class="mermaid2">
flowchart RL
subgraph "`one`"
a1 -- l1 --> a2
a1 -- l2 --> a2
end
</pre>
<pre id="diagram" class="mermaid2">
flowchart
id["`A root with a long text that wraps to keep the node size in check. A root with a long text that wraps to keep the node size in check`"]</pre
>
<pre id="diagram" class="mermaid2">
flowchart LR flowchart LR
nA[Default] --> A@{ icon: 'fa:bell', form: 'circle' } A[A text that needs to be wrapped wraps to another line]
B[A text that needs to be<br/>wrapped wraps to another line]
C["`A text that needs to be wrapped to another line`"]</pre>
<pre id="diagram" class="mermaid2">
flowchart LR
C["`A text
that needs
to be wrapped
in another
way`"]
</pre
>
<pre id="diagram" class="mermaid2">
classDiagram-v2
note "I love this diagram!\nDo you love it?"
</pre>
<pre id="diagram" class="mermaid2">
stateDiagram-v2
State1: The state with a note with minus - and plus + in it
note left of State1
Important information! You can write
notes with . and in them.
end note </pre
>
<pre id="diagram" class="mermaid2">
mindmap
root
Child3(A node with an icon and with a long text that wraps to keep the node size in check)
</pre
>
<pre id="diagram" class="mermaid2">
%%{init: {"theme": "forest"} }%%
mindmap
id1[**Start2**<br/>end]
id2[**Start2**<br />end]
%% Another comment
id3[**Start2**<br>end] %% Comment
id4[**Start2**<br >end<br >the very end]
</pre>
<pre id="diagram" class="mermaid2">
mindmap
id1["`**Start2**
second line 😎 with long text that is wrapping to the next line`"]
id2["`Child **with bold** text`"]
id3["`Children of which some
is using *italic type of* text`"]
id4[Child]
id5["`Child
Row
and another
`"]
</pre>
<pre id="diagram" class="mermaid2">
mindmap
id1("`**Root**`"]
id2["`A formatted text... with **bold** and *italics*`"]
id3[Regular labels works as usual]
id4["`Emojis and unicode works too: 🤓
शान्तिः سلام 和平 `"]
</pre> </pre>
<pre id="diagram4" class="mermaid"> <pre id="diagram" class="mermaid2">
flowchart LR %%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
nA[Style] --> A@{ icon: 'fa:bell', form: 'circle' } flowchart TB
style A fill:#f9f,stroke:#333,stroke-width:4px %% I could not figure out how to use double quotes in labels in Mermaid
</pre> subgraph ibm[IBM Espresso CPU]
<pre id="diagram4" class="mermaid"> core0[IBM PowerPC Broadway Core 0]
flowchart LR core1[IBM PowerPC Broadway Core 1]
nA[Class] --> A@{ icon: 'fa:bell', form: 'circle' } core2[IBM PowerPC Broadway Core 2]
A:::AClass
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
</pre>
<pre id="diagram4" class="mermaid">
flowchart LR
nA[Class] --> A@{ icon: 'logos:aws', form: 'circle' }
A:::AClass
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
</pre>
<pre id="diagram4" class="mermaid">
flowchart LR
nA[Style] --> A@{ icon: 'logos:aws', form: 'circle' }
style A fill:#f9f,stroke:#333,stroke-width:4px
</pre>
<pre id="diagram4" class="mermaid2">
kanban
id2[In progress]
docs[Create Blog about the new diagram]@{ priority: 'Very Low', ticket: MC-2037, assigned: 'knsv' }
</pre>
<pre id="diagram4" class="mermaid2">
---
config:
kanban:
ticketBaseUrl: 'https://mermaidchart.atlassian.net/browse/#TICKET#'
# sectionWidth: 300
---
kanban
Todo
[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 som extra text here for testing purposes. And some more just for the extra flare.]
id9[Ready for deploy]
id8[Design grammar]@{ assigned: 'knsv' }
id10[Ready for test]
id4[Create parsing tests]@{ ticket: MC-2038, assigned: 'K.Sveidqvist', priority: 'High' }
id66[last item]@{ priority: 'Very Low', assigned: 'knsv' }
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' }
id12[Can't reproduce] rom[16 KB ROM]
id3[Weird flickering in Firefox]
core0 --- core2
rom --> core2
end
subgraph amd["`**AMD** Latte GPU`"]
mem[Memory & I/O Bridge]
dram[DRAM Controller]
edram[32 MB EDRAM MEM1]
rom[512 B SEEPROM]
sata[SATA IF]
exi[EXI]
subgraph gx[GX]
sram[3 MB 1T-SRAM]
end
radeon[AMD Radeon R7xx GX2]
mem --- gx
mem --- radeon
rom --- mem
mem --- sata
mem --- exi
dram --- sata
dram --- exi
end
ddr3[2 GB DDR3 RAM MEM2]
mem --- ddr3
dram --- ddr3
edram --- ddr3
core1 --- mem
exi --- rtc
rtc{{rtc}}
</pre
>
<pre id="diagram" class="mermaid2">
%%{init: {"flowchart": {"defaultRenderer": "elk", "htmlLabels": false}} }%%
flowchart TB
%% I could not figure out how to use double quotes in labels in Mermaid
subgraph ibm[IBM Espresso CPU]
core0[IBM PowerPC Broadway Core 0]
core1[IBM PowerPC Broadway Core 1]
core2[IBM PowerPC Broadway Core 2]
rom[16 KB ROM]
core0 --- core2
rom --> core2
end
subgraph amd["`**AMD** Latte GPU`"]
mem[Memory & I/O Bridge]
dram[DRAM Controller]
edram[32 MB EDRAM MEM1]
rom[512 B SEEPROM]
sata[SATA IF]
exi[EXI]
subgraph gx[GX]
sram[3 MB 1T-SRAM]
end
radeon[AMD Radeon R7xx GX2]
mem --- gx
mem --- radeon
rom --- mem
mem --- sata
mem --- exi
dram --- sata
dram --- exi
end
ddr3[2 GB DDR3 RAM MEM2]
mem --- ddr3
dram --- ddr3
edram --- ddr3
core1 --- mem
exi --- rtc
rtc{{rtc}}
</pre
>
<br />
<pre id="diagram" class="mermaid2">
flowchart TB
%% I could not figure out how to use double quotes in labels in Mermaid
subgraph ibm[IBM Espresso CPU]
core0[IBM PowerPC Broadway Core 0]
core1[IBM PowerPC Broadway Core 1]
core2[IBM PowerPC Broadway Core 2]
rom[16 KB ROM]
core0 --- core2
rom --> core2
end
subgraph amd[AMD Latte GPU]
mem[Memory & I/O Bridge]
dram[DRAM Controller]
edram[32 MB EDRAM MEM1]
rom[512 B SEEPROM]
sata[SATA IF]
exi[EXI]
subgraph gx[GX]
sram[3 MB 1T-SRAM]
end
radeon[AMD Radeon R7xx GX2]
mem --- gx
mem --- radeon
rom --- mem
mem --- sata
mem --- exi
dram --- sata
dram --- exi
end
ddr3[2 GB DDR3 RAM MEM2]
mem --- ddr3
dram --- ddr3
edram --- ddr3
core1 --- mem
exi --- rtc
rtc{{rtc}}
</pre
>
<br />
&nbsp;
<pre id="diagram" class="mermaid2">
flowchart LR
B1 --be be--x B2
B1 --bo bo--o B3
subgraph Ugge
B2
B3
subgraph inner
B4
B5
end
subgraph inner2
subgraph deeper
C4
C5
end
C6
end
B4 --> C4
B3 -- X --> B4
B2 --> inner
C4 --> C5
end
subgraph outer
B6
end
B6 --> B5
</pre
>
<pre id="diagram" class="mermaid2">
sequenceDiagram
Customer->>+Stripe: Makes a payment request
Stripe->>+Bank: Forwards the payment request to the bank
Bank->>+Customer: Asks for authorization
Customer->>+Bank: Provides authorization
Bank->>+Stripe: Sends a response with payment details
Stripe->>+Merchant: Sends a notification of payment receipt
Merchant->>+Stripe: Confirms the payment
Stripe->>+Customer: Sends a confirmation of payment
Customer->>+Merchant: Receives goods or services
</pre
>
<pre id="diagram" class="mermaid2">
mindmap
root((mindmap))
Origins
Long history
::icon(fa fa-book)
Popularisation
British popular psychology author Tony Buzan
Research
On effectiveness<br/>and features
On Automatic creation
Uses
Creative techniques
Strategic planning
Argument mapping
Tools
Pen and paper
Mermaid
</pre> </pre>
<br />
<pre id="diagram" class="mermaid2">
example-diagram
</pre>
<!-- <div id="cy"></div> -->
<!-- <script src="http://localhost:9000/packages/mermaid-mindmap/dist/mermaid-mindmap-detector.js"></script> -->
<!-- <script src="./mermaid-example-diagram-detector.js"></script> -->
<!-- <script src="//cdn.jsdelivr.net/npm/mermaid@9.1.7/dist/mermaid.min.js"></script> -->
<!-- <script src="./mermaid.js"></script> -->
<script type="module"> <script type="module">
// import mindmap from '../../packages/mermaid-mindmap/src/detector';
// import example from '../../packages/mermaid-example-diagram/src/mermaid-example-diagram.core.mjs';
import mermaid from './mermaid.esm.mjs'; import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs'; // await mermaid.registerExternalDiagrams([example]);
const staticBellIconPack = {
prefix: 'fa6-regular',
icons: {
bell: {
body: '<path fill="currentColor" d="M224 0c-17.7 0-32 14.3-32 32v19.2C119 66 64 130.6 64 208v25.4c0 45.4-15.5 89.5-43.8 124.9L5.3 377c-5.8 7.2-6.9 17.1-2.9 25.4S14.8 416 24 416h400c9.2 0 17.6-5.3 21.6-13.6s2.9-18.2-2.9-25.4l-14.9-18.6c-28.3-35.5-43.8-79.6-43.8-125V208c0-77.4-55-142-128-156.8V32c0-17.7-14.3-32-32-32m0 96c61.9 0 112 50.1 112 112v25.4c0 47.9 13.9 94.6 39.7 134.6H72.3c25.8-40 39.7-86.7 39.7-134.6V208c0-61.9 50.1-112 112-112m64 352H160c0 17 6.7 33.3 18.7 45.3S207 512 224 512s33.3-6.7 45.3-18.7S288 465 288 448"/>',
width: 448,
},
},
width: 512,
height: 512,
};
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos@1/icons.json').then((res) => res.json()),
},
{
name: 'fa',
loader: () => staticBellIconPack,
},
]);
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) { mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err); // console.error('Mermaid error: ', err);
};
window.callback = function () {
alert('A callback was triggered');
}; };
// mermaid.initialize({
// // theme: 'forest',
// startOnLoad: true,
// logLevel: 0,
// flowchart: {
// // defaultRenderer: 'elk',
// useMaxWidth: false,
// // htmlLabels: false,
// htmlLabels: true,
// },
// // htmlLabels: false,
// gantt: {
// useMaxWidth: false,
// },
// useMaxWidth: false,
// });
mermaid.initialize({ mermaid.initialize({
// theme: 'base', theme: 'dark',
// theme: 'default', startOnLoad: true,
// theme: 'forest',
// handDrawnSeed: 12,
// look: 'handDrawn',
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// layout: 'dagre',
// layout: 'elk',
// layout: 'fixed',
// htmlLabels: false,
flowchart: { titleTopMargin: 10 },
// fontFamily: 'Caveat',
// fontFamily: 'Kalam',
// fontFamily: 'courier',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
messageFontFamily: 'courier',
},
kanban: {
htmlLabels: false,
},
fontSize: 12,
logLevel: 0, logLevel: 0,
securityLevel: 'loose',
}); });
function callback() { function callback() {
alert('It worked'); alert('It worked');
@@ -256,6 +605,10 @@ kanban
console.error('In parse error:'); console.error('In parse error:');
console.error(err); console.error(err);
}; };
// mermaid.test1('first_slow', 1200).then((r) => console.info(r));
// mermaid.test1('second_fast', 200).then((r) => console.info(r));
// mermaid.test1('third_fast', 200).then((r) => console.info(r));
// mermaid.test1('forth_slow', 1200).then((r) => console.info(r));
</script> </script>
</body> </body>
</html> </html>

View File

@@ -1,4 +1,4 @@
<!doctype html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="utf-8" /> <meta charset="utf-8" />

View File

@@ -1,174 +0,0 @@
<html>
<head>
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
<link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" />
<link
rel="stylesheet"
href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"
/>
<link
href="https://cdn.jsdelivr.net/npm/@mdi/font@6.9.96/css/materialdesignicons.min.css"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap"
rel="stylesheet"
/>
<link rel="preconnect" href="https://fonts.googleapis.com" />
<link rel="preconnect" href="https://fonts.gstatic.com" crossorigin />
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Caveat:wght@400..700&family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<link
href="https://fonts.googleapis.com/css2?family=Kalam:wght@300;400;700&family=Rubik+Mono+One&display=swap"
rel="stylesheet"
/>
<style>
body {
/* background: rgb(221, 208, 208); */
/* background: #333; */
font-family: 'Arial';
/* font-size: 18px !important; */
}
h1 {
color: grey;
}
.mermaid2 {
display: none;
}
.mermaid svg {
/* font-size: 18px !important; */
/* background-color: #efefef;
background-image: radial-gradient(#fff 51%, transparent 91%),
radial-gradient(#fff 51%, transparent 91%);
background-size: 20px 20px;
background-position:
0 0,
10px 10px;
background-repeat: repeat; */
}
</style>
</head>
<body style="display: flex; gap: 2rem; flex-direction: row">
<pre id="diagram4" class="mermaid">
flowchart LR
A@{ icon: "fa:window-minimize", form: circle }
E@{ icon: "fa:window-minimize", form: circle }
B@{ icon: "fa:bell", form: circle }
B2@{ icon: "fa:bell", form: circle }
C@{ icon: "fa:address-book", form: square }
D@{ icon: "fa:star-half", form: square }
A --> E
B --> B2
</pre>
<pre id="diagram4" class="mermaid2">
flowchart TB
A --test2--> B2@{ icon: "fa:bell", form: "rounded", label: "B2 aiduaid uyawduad uaduabd uyduadb", pos: "b" }
B2 --test--> C
D --> B2 --> E
style B2 fill:#f9f,stroke:#333,stroke-width:4px
</pre
>
<pre id="diagram43" class="mermaid2">
flowchart BT
A --test2--> B2@{ icon: "fa:bell", form: "square", label: "B2", pos: "t", h: 40, w: 30 }
B2 --test--> C
D --> B2 --> E
</pre
>
<pre id="diagram4" class="mermaid2">
flowchart BT
A --test2--> B2@{ icon: "fa:bell", label: "B2 awiugdawu uydgayuiwd wuydguy", pos: "b", h: 40, w: 30 }
B2 --test--> C
</pre
>
<pre id="diagram43" class="mermaid2">
flowchart BT
A --test2--> B2@{ icon: "fa:bell", label: "B2 dawuygd ayuwgd uy", pos: "t", h: 40, w: 30 }
B2 --test--> C
</pre
>
<pre id="diagram6" class="mermaid2">
flowchart TB
A --> B2@{ icon: "fa:bell", form: "circle", label: "test augfuyfavf ydvaubfuac", pos: "t", w: 200, h: 100 } --> C
</pre
>
<pre id="diagram6" class="mermaid2">
flowchart TB
A --> B2@{ icon: "fa:bell", form: "circle", label: "test augfuyfavf ydvaubfuac", pos: "b", w: 200, h: 100 } --> C
D --> B2 --> E
</pre
>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos/icons.json').then((res) => res.json()),
},
{
name: 'fa',
loader: () =>
fetch('https://unpkg.com/@iconify-json/fa6-solid/icons.json').then((res) => res.json()),
},
]);
mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err);
};
window.callback = function () {
alert('A callback was triggered');
};
mermaid.initialize({
// theme: 'base',
// handdrawnSeed: 12,
look: 'classic',
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
// 'elk.nodePlacement.strategy': 'SIMPLE',
// 'elk.nodePlacement.strategy': 'LAYERED',
// 'elk.mergeEdges': true,
// layout: 'dagre',
// layout: 'elk',
// layout: 'fixed',
// htmlLabels: false,
flowchart: { titleTopMargin: 10, padding: 0, htmlLabels: true },
// fontFamily: 'Caveat',
// fontFamily: 'Kalam',
fontFamily: 'courier',
sequence: {
actorFontFamily: 'courier',
noteFontFamily: 'courier',
messageFontFamily: 'courier',
},
themeVariables: {
fontSize: 50,
fontFamily: 'courier',
},
logLevel: 0,
securityLevel: 'loose',
});
function callback() {
alert('It worked');
}
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);
};
</script>
</body>
</html>

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,663 +0,0 @@
<html>
<body>
<h1 class="header">Class Nodes</h1>
<div class="node-showcase">
<div class="test">
<h2>Basic Class</h2>
<pre class="mermaid">
---
config:
htmlLabels: false
---
classDiagram
class _Duck_ {
+String beakColor
_+_swim_()a_
__+quack() test__
}
</pre>
</div>
<div class="test">
<h2>Basic Class</h2>
<pre class="mermaid">
---
config:
htmlLabels: false
---
classDiagram
class Class10:::exClass2 {
int[] id
List~int~ ids
test(List~int~ ids) List~bool~
testArray() bool[]
}
</pre>
</div>
<div class="test">
<h2>Basic Class</h2>
<pre class="mermaid">
flowchart TD
Start --> Stop
</pre>
</div>
<div class="test">
<h2>Complex Class</h2>
<pre class="mermaid">
classDiagram
class Square~Shape~{
int id
List~int~ position
setPoints(List~int~ points)
getPoints() List~int~
}
Square : -List~string~ messages
Square : +setMessages(List~string~ messages)
Square : +getMessages() List~string~
Square : +getDistanceMatrix() List~List~int~~
</pre
>
</div>
<div class="test">
<h2>No Attributes</h2>
<pre class="mermaid">
classDiagram
class Duck {
+swim()
+quack()
}
</pre>
</div>
<div class="test">
<h2>No Methods</h2>
<pre class="mermaid">
classDiagram
class Duck {
+String beakColor
}
</pre>
</div>
<div class="test">
<h2>Only Class Name</h2>
<p>Empty line as attribute</p>
<pre class="mermaid">
---
config:
class:
hideEmptyMembersBox: false
---
classDiagram
class Duck {
}
</pre>
</div>
<div class="test">
<h2>Visibility and Types</h2>
<p>(Further tilde testing)</p>
<div class="mermaid">
classDiagram class Duck { ~interface~~~ +String beakColor #swim() ~quack()~~~
-test()~~~~~~~ +deposit(amount) bool }
</div>
</div>
<div class="test">
<h2>Additional Classifiers</h2>
<p>(* Abstract | $ Static)</p>
<div class="mermaid">
classDiagram class Square~Shape~ { int id* List~int~ position* setPoints(List~int~points)*
getPoints()* List~int~ } Square : -List~string~ messages$ Square :
+setMessages(List~string~ messages)* Square : +getMessages()$ List~string~ Square :
+getDistanceMatrix() List~List~int~~$
</div>
</div>
<div class="test">
<h2>Label</h2>
<pre class="mermaid">
classDiagram
class Animal~test~["Animal with a label"]
</pre>
</div>
<div class="test">
<h2>Spacing</h2>
<p>(Fix ensures consistent spacing rules)</p>
<p>(No space or single space?)</p>
<pre class="mermaid">
classDiagram
class ClassName {
-attribute:type
- attribute : type
test
+ GetAttribute() type
+ GetAttribute() type
}
</pre>
</div>
<div class="test">
<h2>Annotation</h2>
<pre class="mermaid">
classDiagram
class Shape
&lt;&lt;interface&gt;&gt; Shape
Shape : noOfVertices
Shape : draw()
</pre>
</div>
<div class="test">
<h2>Long Class Name Text</h2>
<pre class="mermaid">
classDiagram
class ThisIsATestForALongClassName {
&lt;&lt;interface&gt;&gt;
noOfLetters
delete()
}
</pre>
</div>
<div class="test">
<h2>Long Annotation Text</h2>
<pre class="mermaid">
classDiagram
class Shape
&lt;&lt;superlongannotationtext&gt;&gt; Shape
Shape : noOfVertices
Shape : draw()
</pre>
</div>
<div class="test">
<h2>Long Member Text</h2>
<pre class="mermaid">
classDiagram
class Shape
&lt;&lt;interface&gt;&gt; Shape
Shape : noOfVertices
Shape : longtexttestkeepgoingandgoing
Shape : draw()
</pre>
</div>
<div class="test">
<h2>Link</h2>
<pre class="mermaid">
classDiagram
class Shape
link Shape "https://www.github.com" "This is a tooltip for a link"
</pre>
</div>
<div class="test">
<h2>Click</h2>
<pre class="mermaid">
classDiagram
class Shape
click Shape href "https://www.github.com" "This is a tooltip for a link"
</pre>
</div>
<div class="test">
<h2>Hand Drawn</h2>
<pre class="mermaid">
---
config:
look: handDrawn
htmlLabels: true
---
classDiagram
class Hand {
+String beakColor
+swim()
+quack()
}
style Hand fill:#f9f,stroke:#29f,stroke-width:2px
</pre>
</div>
<div class="test">
<h2>Neutral Theme</h2>
<pre class="mermaid">
---
config:
theme: neutral
---
classDiagram
class Duck {
+String beakColor
+swim()
+quack()
}
</pre>
</div>
<div class="test">
<h2>Dark Theme</h2>
<pre class="mermaid">
---
config:
theme: dark
---
classDiagram
class Duck {
+String beakColor
+swim()
+quack()
}
</pre>
</div>
<div class="test">
<h2>Forest Theme</h2>
<pre class="mermaid">
---
config:
theme: forest
---
classDiagram
class Duck {
+String beakColor
+swim()
+quack()
}
</pre>
</div>
<div class="test">
<h2>Base Theme</h2>
<pre class="mermaid">
---
config:
theme: base
---
classDiagram
class Duck {
+String beakColor
+swim()
+quack()
}
</pre>
</div>
<div class="test">
<h2>Custom Theme</h2>
<pre class="mermaid">
%%{
init: {
'theme': 'base',
'themeVariables': {
'primaryColor': '#BB2528',
'primaryTextColor': '#fff',
'primaryBorderColor': '#7C0000',
'lineColor': '#F83d29',
'secondaryColor': '#006100',
'tertiaryColor': '#fff'
}
}
}%%
classDiagram
class Duck {
+String beakColor
+swim()
+quack()
}
Duck--Dog
</pre>
</div>
<div class="test">
<h2>Styling within Diagram</h2>
<pre class="mermaid">
classDiagram
class Duck {
+String beakColor
+swim()
+quack()
}
style Duck fill:#f9f,stroke:#333,stroke-width:8px
</pre>
</div>
<div class="test">
<h2>Styling with classDef Statement</h2>
<pre class="mermaid">
classDiagram
class Duck:::bold {
+String beakColor
+swim()
+quack()
}
class Dog {
+int numTeeth
+bark()
}
cssClass "Duck,Dog" pink
classDef pink fill:#f9f
classDef default color:#f1e
classDef bold stroke:#333,stroke-width:6px,color:#fff
</pre>
</div>
<div class="test">
<h2>Styling with Class in Stylesheet</h2>
<pre class="mermaid">
classDiagram
class Duck {
+String beakColor
+swim()
+quack()
}
class Duck:::styleClass
</pre>
</div>
</div>
<h1 class="header">Diagram Testing</h1>
<div class="diagram-showcase">
<div class="test">
<h2>Class Nodes Only</h2>
<pre class="mermaid">
---
title: Animal example
---
classDiagram
Animal : +int age
Animal : +String gender
Animal: +isMammal()
Animal: +mate()
class Duck{
+String beakColor
+swim()
+quack()
}
class Fish{
-int sizeInFeet
-canEat()
}
class Zebra{
+bool is_wild
+run()
}
</pre>
</div>
<div class="test">
<h2>Class Nodes LR</h2>
<pre class="mermaid">
---
title: Animal example
---
classDiagram
direction LR
Animal : +int age
Animal : +String gender
Animal: +isMammal()
Animal: +mate()
class Duck{
+String beakColor
+swim()
+quack()
}
class Fish{
-int sizeInFeet
-canEat()
}
class Zebra{
+bool is_wild
+run()
}
</pre>
</div>
<div class="test">
<h2>Relations</h2>
<pre class="mermaid">
classDiagram
classA <|-- classB
classC *-- classD
classE o-- classF
classG <-- classH
classI -- classJ
classK <.. classL
classM <|.. classN
classO .. classP
</pre>
</div>
<div class="test">
<h2>Two Way Relation</h2>
<pre class="mermaid">
classDiagram
class Animal {
int size
walk()
}
class Zebra {
int size
walk()
}
Animal o--|> Zebra
</pre>
</div>
<div class="test">
<h2>Relations with Labels</h2>
<pre class="mermaid">
classDiagram
classA <|-- classB : implements
classC *-- classD : composition
classE o-- classF : aggregation
</pre>
</div>
<div class="test">
<h2>Cardinality / Multiplicity</h2>
<pre class="mermaid">
classDiagram
Customer "1" --> "*" Ticket
Student "1" --> "1..*" Course
Galaxy --> "many" Star : Contains
</pre>
</div>
<div class="test">
<h2>Complex Relations with Theme</h2>
<pre class="mermaid">
---
config:
theme: forest
look: handDrawns
layout: elk
---
classDiagram
direction RL
class Student {
-idCard : IdCard
}
class IdCard{
-id : int
-name : string
}
class Bike{
-id : int
-name : string
}
Student "1" o--o "1" IdCard : carries
Student "1" o--o "1" Bike : rides
</pre>
</div>
<div class="test">
<h2>Notes</h2>
<pre class="mermaid">
classDiagram
note "This is a general note"
note for MyClass "This is a note for a class"
class MyClass
</pre>
</div>
<div class="test">
<h2>Namespaces</h2>
<pre class="mermaid">
classDiagram
namespace BaseShapes {
class Triangle
class Rectangle {
double width
double height
}
}
</pre>
</div>
<div class="test">
<h2>Namespaces</h2>
<pre class="mermaid">
---
config:
layout: elk
---
classDiagram
namespace Namespace1 {
class C1
class C2
}
C1 --> C2
class C3
class C4
</pre>
</div>
<div class="test">
<h2>Full Example</h2>
<pre class="mermaid">
---
title: Animal example
config:
layout: dagre
---
classDiagram
note "From Duck till Zebra"
Animal <|--|> Duck
note for Duck "can fly<br>can swim<br>can dive<br>can help in debugging"
Animal <|-- Fish
Animal <|--|> Zebra
Animal : +int age
Animal : +String gender
Animal: +isMammal()
Animal: +mate()
class Duck{
+String beakColor
+swim()
+quack()
}
class Fish{
-int sizeInFeet
-canEat()
}
class Zebra{
+bool is_wild
+run()
}
cssClass "Duck" test
classDef test fill:#f71
%%classDef default fill:#f93
</pre>
</div>
<div class="test">
<h2>Full Example</h2>
<pre class="mermaid">
---
config:
theme: forest
look: handDrawn
---
classDiagram
note for Outside "Note testing"
namespace Test {
class Outside
}
namespace BaseShapes {
class Triangle
class Rectangle {
double width
double height
}
}
Outside <|--|> Rectangle
style Triangle fill:#f9f,stroke:#333,stroke-width:4px
</pre>
</div>
<div class="test">
<pre class="mermaid">
---
config:
look: handDrawn
layout: elk
---
classDiagram
Class01 "1" <|--|> "*" AveryLongClass : Cool
&lt;&lt;interface&gt;&gt; Class01
Class03 "1" *-- "*" Class04
Class05 "1" o-- "many" Class06
Class07 "1" .. "*" Class08
Class09 "1" --> "*" C2 : Where am i?
Class09 "*" --* "*" C3
Class09 "1" --|> "1" Class07
NewClass ()--() Class04
Class09 <|--|> AveryLongClass
Class07 : equals()
Class07 : Object[] elementData
Class01 : size()
Class01 : int chimp
Class01 : int gorilla
Class08 "1" <--> "*" C2: Cool label
class Class10 {
&lt;&lt;service&gt;&gt;
int id
test()
}
Class10 o--o AveryLongClass
Class10 <--> Class07
</pre>
</div>
<div class="test">
<pre class="mermaid">
classDiagram
test ()--() test2
</pre>
</div>
</div>
<script type="module">
import mermaid from './mermaid.esm.mjs';
import layouts from './mermaid-layout-elk.esm.mjs';
mermaid.registerLayoutLoaders(layouts);
mermaid.parseError = function (err, hash) {
console.error('Mermaid error: ', err);
};
mermaid.initialize();
mermaid.parseError = function (err, hash) {
console.error('In parse error:');
console.error(err);
};
</script>
</body>
<style>
.header {
text-decoration: underline;
text-align: center;
}
.node-showcase {
display: grid;
grid-template-columns: 1fr 1fr;
}
.test {
flex-grow: 1;
display: flex;
flex-direction: column;
align-items: center;
gap: 0.4rem;
}
.test > h2 {
margin: 0;
text-align: center;
}
.test > p {
margin-top: -6px;
color: gray;
}
.diagram-showcase {
display: grid;
grid-template-columns: 1fr;
}
.styleClass > * > path {
fill: #ff0000 !important;
stroke: #ffff00 !important;
stroke-width: 4px !important;
stroke-dasharray: 2 !important;
}
</style>
</html>

View File

@@ -1,152 +0,0 @@
{
"durations": [
{
"spec": "cypress/integration/other/configuration.spec.js",
"duration": 4989
},
{
"spec": "cypress/integration/other/external-diagrams.spec.js",
"duration": 1382
},
{
"spec": "cypress/integration/other/ghsa.spec.js",
"duration": 3178
},
{
"spec": "cypress/integration/other/iife.spec.js",
"duration": 1372
},
{
"spec": "cypress/integration/other/interaction.spec.js",
"duration": 8998
},
{
"spec": "cypress/integration/other/rerender.spec.js",
"duration": 1249
},
{
"spec": "cypress/integration/other/xss.spec.js",
"duration": 25664
},
{
"spec": "cypress/integration/rendering/appli.spec.js",
"duration": 1928
},
{
"spec": "cypress/integration/rendering/architecture.spec.ts",
"duration": 2330
},
{
"spec": "cypress/integration/rendering/block.spec.js",
"duration": 11156
},
{
"spec": "cypress/integration/rendering/c4.spec.js",
"duration": 3418
},
{
"spec": "cypress/integration/rendering/classDiagram-v2.spec.js",
"duration": 14866
},
{
"spec": "cypress/integration/rendering/classDiagram.spec.js",
"duration": 9894
},
{
"spec": "cypress/integration/rendering/conf-and-directives.spec.js",
"duration": 5778
},
{
"spec": "cypress/integration/rendering/current.spec.js",
"duration": 1690
},
{
"spec": "cypress/integration/rendering/erDiagram.spec.js",
"duration": 9144
},
{
"spec": "cypress/integration/rendering/errorDiagram.spec.js",
"duration": 1951
},
{
"spec": "cypress/integration/rendering/flowchart-elk.spec.js",
"duration": 2196
},
{
"spec": "cypress/integration/rendering/flowchart-handDrawn.spec.js",
"duration": 21029
},
{
"spec": "cypress/integration/rendering/flowchart-shape-alias.spec.ts",
"duration": 16087
},
{
"spec": "cypress/integration/rendering/flowchart-v2.spec.js",
"duration": 27465
},
{
"spec": "cypress/integration/rendering/flowchart.spec.js",
"duration": 20035
},
{
"spec": "cypress/integration/rendering/gantt.spec.js",
"duration": 11366
},
{
"spec": "cypress/integration/rendering/gitGraph.spec.js",
"duration": 34025
},
{
"spec": "cypress/integration/rendering/iconShape.spec.ts",
"duration": 185902
},
{
"spec": "cypress/integration/rendering/imageShape.spec.ts",
"duration": 41631
},
{
"spec": "cypress/integration/rendering/info.spec.ts",
"duration": 1736
},
{
"spec": "cypress/integration/rendering/journey.spec.js",
"duration": 2247
},
{
"spec": "cypress/integration/rendering/katex.spec.js",
"duration": 2144
},
{
"spec": "cypress/integration/rendering/marker_unique_id.spec.js",
"duration": 1646
},
{
"spec": "cypress/integration/rendering/mindmap.spec.ts",
"duration": 6406
},
{
"spec": "cypress/integration/rendering/newShapes.spec.ts",
"duration": 107219
},
{
"spec": "cypress/integration/rendering/stateDiagram.spec.js",
"duration": 15834
},
{
"spec": "cypress/integration/rendering/theme.spec.js",
"duration": 33240
},
{
"spec": "cypress/integration/rendering/timeline.spec.ts",
"duration": 7122
},
{
"spec": "cypress/integration/rendering/xyChart.spec.js",
"duration": 11127
},
{
"spec": "cypress/integration/rendering/zenuml.spec.js",
"duration": 2391
}
]
}

View File

@@ -1,256 +0,0 @@
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<title>Architecture Mermaid Quick Test Page</title>
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
<style>
div.mermaid {
/* font-family: 'trebuchet ms', verdana, arial; */
font-family: 'Courier New', Courier, monospace !important;
}
</style>
</head>
<body>
<h1>Architecture diagram demo</h1>
<h2>Simple diagram with groups</h2>
<pre class="mermaid">
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
</pre>
<hr />
<h2>Groups within groups</h2>
<pre class="mermaid">
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
</pre>
<hr />
<h2>Default icon (?) from unknown icon name</h2>
<pre class="mermaid">
architecture-beta
service unknown(iconnamedoesntexist)[Unknown Icon]
</pre>
<hr />
<h2>Split Direction</h2>
<pre class="mermaid">
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
</pre>
<hr />
<h2>Arrow Tests</h2>
<pre class="mermaid">
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
</pre>
<pre class="mermaid">
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
servT:L <--> T:servL
servB:L <--> B:servL
servT:R <--> T:servR
servB:R <--> B:servR
</pre>
<hr />
<h2>Group Edges</h2>
<pre class="mermaid">
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}
</pre
>
<hr />
<h2>Edge Label Test</h2>
<pre class="mermaid">
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
</pre>
<pre class="mermaid">
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 that is Long]- R:servL
servC:R -[Label that is Long]- L:servR
servC:T -[Label that is Long]- B:servT
servC:B -[Label that is Long]- T:servB
servL:T -[Label that is Long]- L:servT
servL:B -[Label that is Long]- L:servB
servR:T -[Label that is Long]- R:servT
servR:B -[Label that is Long]- R:servB
</pre>
<hr />
<h2>Junction Demo</h2>
<pre class="mermaid">
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
</pre>
<hr />
<h2>Junction Demo Groups</h2>
<pre class="mermaid">
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}
</pre>
<hr />
<h2>External Icons Demo</h2>
<pre class="mermaid">
architecture-beta
service s3(logos:aws-s3)[Cloud Store]
service ec2(logos:aws-ec2)[Server]
service api(logos:aws-api-gateway)[Api Gateway]
service fa(fa:image)[Font Awesome Icon]
</pre>
<script type="module">
import mermaid from './mermaid.esm.mjs';
mermaid.registerIconPacks([
{
name: 'logos',
loader: () =>
fetch('https://unpkg.com/@iconify-json/logos/icons.json').then((res) => res.json()),
},
{
name: 'fa',
loader: () =>
fetch('https://unpkg.com/@iconify-json/fa6-regular/icons.json').then((res) =>
res.json()
),
},
]);
</script>
</body>
</html>

View File

@@ -159,87 +159,30 @@
class People List~List~Person~~ class People List~List~Person~~
</pre> </pre>
<hr /> <hr />
<pre class="mermaid"> <pre class="mermaid">
classDiagram classDiagram
namespace Company.Project.Module { A1 --> B1
class GenericClass~T~ { namespace A {
+addItem(item: T) class A1 {
+getItem() T +foo : string
}
class A2 {
+bar : int
} }
} }
namespace B {
class B1 {
+foo : bool
}
class B2 {
+bar : float
}
}
A2 --> B2
</pre> </pre>
<hr /> <hr />
<pre class="mermaid">
classDiagram
namespace Company.Project.Module.SubModule {
class Report {
+generatePDF(data: List)
+generateCSV(data: List)
}
}
namespace Company.Project.Module {
class Admin {
+generateReport()
}
}
Admin --> Report : generates
</pre>
<pre class="mermaid">
classDiagram
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
</pre>
<hr />
<pre class="mermaid">
classDiagram
namespace Shapes {
class Shape {
+calculateArea() double
}
class Circle {
+double radius
}
class Square {
+double side
}
}
Shape <|-- Circle
Shape <|-- Square
namespace Vehicles {
class Vehicle {
+String brand
}
class Car {
+int horsepower
}
class Bike {
+boolean hasGears
}
}
Vehicle <|-- Car
Vehicle <|-- Bike
Car --> Circle : "Logo Shape"
Bike --> Square : "Logo Shape"
</pre>
<script type="module"> <script type="module">
import mermaid from './mermaid.esm.mjs'; import mermaid from './mermaid.esm.mjs';
mermaid.initialize({ mermaid.initialize({

View File

@@ -125,35 +125,6 @@
</pre> </pre>
<hr /> <hr />
<pre class="mermaid">
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"
</pre>
<hr />
<pre class="mermaid"> <pre class="mermaid">
erDiagram erDiagram
_customer_order { _customer_order {

View File

@@ -88,9 +88,6 @@
<li> <li>
<h2><a href="./block.html">Layered Blocks</a></h2> <h2><a href="./block.html">Layered Blocks</a></h2>
</li> </li>
<li>
<h2><a href="./architecture.html">Architecture</a></h2>
</li>
</ul> </ul>
</body> </body>
</html> </html>

View File

@@ -238,17 +238,6 @@
Alice-xJohn: Hello John, how are you? Alice-xJohn: Hello John, how are you?
John--xAlice: Great! John--xAlice: Great!
</pre> </pre>
<hr />
<pre class="mermaid">
sequenceDiagram
participant Alice
participant Bob
Alice<<->>Bob: Hello!
Alice<<->>Bob: Wow, we said that at the same time!
Bob<<-->>Alice: Bidirectional Arrows are so cool
</pre>
<script type="module"> <script type="module">
import mermaid from './mermaid.esm.mjs'; import mermaid from './mermaid.esm.mjs';
mermaid.initialize({ mermaid.initialize({

View File

@@ -52,7 +52,7 @@
line [+1.3, .6, 2.4, -.34] line [+1.3, .6, 2.4, -.34]
</pre> </pre>
<h1>XY Charts Bar with multiple category</h1> <h1>XY Charts bar with single dataset</h1>
<pre class="mermaid"> <pre class="mermaid">
xychart-beta xychart-beta
title "Basic xychart with many categories" title "Basic xychart with many categories"
@@ -61,7 +61,28 @@
bar "sample bar" [52, 96, 35, 10, 87, 34, 67, 99] bar "sample bar" [52, 96, 35, 10, 87, 34, 67, 99]
</pre> </pre>
<h1>XY Charts line with multiple category</h1> <h1>XY Charts bar with multiple datasets</h1>
<pre class="mermaid">
xychart-beta
title "Basic xychart with multiple datasets"
x-axis "Relevant categories" [category1, "category 2", category3, category4]
bar "dogs" [0, 60, 40, 30]
bar "cats" [20, 40, 50, 30]
bar "birds" [30, 60, 50, 30]
</pre>
<h1>XY Charts bar horizontal with multiple datasets</h1>
<pre class="mermaid">
xychart-beta horizontal
title "Basic xychart with multiple datasets"
x-axis "Relevant categories" [category1, "category 2", category3, category4]
y-axis Animals 0 --> 160
bar "dogs" [0, 60, 40, 30]
bar "cats" [20, 40, 50, 30]
bar "birds" [30, 60, 50, 30]
</pre>
<h1>XY Charts line single dataset</h1>
<pre class="mermaid"> <pre class="mermaid">
xychart-beta xychart-beta
title "Line chart with many category" title "Line chart with many category"
@@ -70,7 +91,7 @@
line "sample line" [52, 96, 35, 10, 87, 34, 67, 99] line "sample line" [52, 96, 35, 10, 87, 34, 67, 99]
</pre> </pre>
<h1>XY Charts category with large text</h1> <h1>XY Charts bar with large text</h1>
<pre class="mermaid"> <pre class="mermaid">
xychart-beta xychart-beta
title "Basic xychart with many categories with category overlap" title "Basic xychart with many categories with category overlap"

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