mirror of
https://github.com/mermaid-js/mermaid.git
synced 2025-11-02 20:04:14 +01:00
Compare commits
20 Commits
antlr_phas
...
sidv/clean
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6462f73bdb | ||
|
|
cfe1723c6c | ||
|
|
6d8b936319 | ||
|
|
f992d95082 | ||
|
|
f2276f93cd | ||
|
|
b52f5058c9 | ||
|
|
5e20087252 | ||
|
|
b49036068f | ||
|
|
5f3d4cb913 | ||
|
|
b11eb93ab2 | ||
|
|
e4f19480cd | ||
|
|
a331a958c0 | ||
|
|
134fca3f1d | ||
|
|
ef7c0a1936 | ||
|
|
2c5403c0f9 | ||
|
|
3b0cb1271e | ||
|
|
96c06a681d | ||
|
|
ff9d26bc70 | ||
|
|
2ddc3403de | ||
|
|
4535911a3a |
@@ -33,14 +33,4 @@ export const packageOptions = {
|
||||
packageName: 'mermaid-layout-elk',
|
||||
file: 'layouts.ts',
|
||||
},
|
||||
'mermaid-layout-tidy-tree': {
|
||||
name: 'mermaid-layout-tidy-tree',
|
||||
packageName: 'mermaid-layout-tidy-tree',
|
||||
file: 'index.ts',
|
||||
},
|
||||
examples: {
|
||||
name: 'mermaid-examples',
|
||||
packageName: 'examples',
|
||||
file: 'index.ts',
|
||||
},
|
||||
} as const satisfies Record<string, PackageOptions>;
|
||||
|
||||
@@ -10,16 +10,13 @@ const buildType = (packageName: string) => {
|
||||
console.log(out.toString());
|
||||
}
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
if (e.stdout.length > 0) {
|
||||
console.error(e.stdout.toString());
|
||||
}
|
||||
if (e.stderr.length > 0) {
|
||||
console.error(e.stderr.toString());
|
||||
}
|
||||
// Exit the build process if we are in CI
|
||||
if (process.env.CI) {
|
||||
throw new Error(`Failed to build types for ${packageName}`);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Render newlines as spaces in class diagrams
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Handle arrows correctly when auto number is enabled
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': minor
|
||||
---
|
||||
|
||||
Add IDs in architecture diagrams
|
||||
5
.changeset/eleven-wolves-deny.md
Normal file
5
.changeset/eleven-wolves-deny.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
chore: Convert StateDB into TypeScript
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Ensure edge label color is applied when using classDef with edge IDs
|
||||
5
.changeset/gold-shoes-camp.md
Normal file
5
.changeset/gold-shoes-camp.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: Remove incorrect `style="undefined;"` attributes in some Mermaid diagrams
|
||||
7
.changeset/honest-trees-dress.md
Normal file
7
.changeset/honest-trees-dress.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@mermaid-js/mermaid-zenuml': patch
|
||||
---
|
||||
|
||||
chore: bump minimum ZenUML version to 3.23.28
|
||||
|
||||
commit: 9d06d8f31e7f12af9e9e092214f907f2dc93ad75
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': minor
|
||||
---
|
||||
|
||||
feat: Added support for new participant types (`actor`, `boundary`, `control`, `entity`, `database`, `collections`, `queue`) in `sequenceDiagram`.
|
||||
@@ -1,7 +0,0 @@
|
||||
---
|
||||
'mermaid': minor
|
||||
'@mermaid-js/layout-tidy-tree': minor
|
||||
'@mermaid-js/layout-elk': minor
|
||||
---
|
||||
|
||||
feat: Update mindmap rendering to support multiple layouts, improved edge intersections, and new shapes
|
||||
5
.changeset/neat-moose-compare.md
Normal file
5
.changeset/neat-moose-compare.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': minor
|
||||
---
|
||||
|
||||
feat: Add support for styling Journey Diagram title (color, font-family, and font-size)
|
||||
@@ -1,5 +0,0 @@
|
||||
---
|
||||
'mermaid': minor
|
||||
---
|
||||
|
||||
feat: Add IDs in architecture diagrams
|
||||
@@ -1,9 +0,0 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
chore: revert marked dependency from ^15.0.7 to ^16.0.0
|
||||
|
||||
- Reverted marked package version to ^16.0.0 for better compatibility
|
||||
- This is a dependency update that maintains API compatibility
|
||||
- All tests pass with the updated version
|
||||
6
.changeset/sad-mails-accept.md
Normal file
6
.changeset/sad-mails-accept.md
Normal file
@@ -0,0 +1,6 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
'@mermaid-js/parser': patch
|
||||
---
|
||||
|
||||
Refactor grammar so that title don't break Architecture Diagrams
|
||||
5
.changeset/soft-readers-tan.md
Normal file
5
.changeset/soft-readers-tan.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': minor
|
||||
---
|
||||
|
||||
feat: Dynamically Render Data Labels Within Bar Charts
|
||||
5
.changeset/ten-lamps-trade.md
Normal file
5
.changeset/ten-lamps-trade.md
Normal file
@@ -0,0 +1,5 @@
|
||||
---
|
||||
'mermaid': patch
|
||||
---
|
||||
|
||||
fix: allow colons in events
|
||||
7
.changeset/yellow-mirrors-change.md
Normal file
7
.changeset/yellow-mirrors-change.md
Normal file
@@ -0,0 +1,7 @@
|
||||
---
|
||||
'@mermaid-js/mermaid-zenuml': patch
|
||||
---
|
||||
|
||||
fix(zenuml): limit `peerDependencies` to Mermaid v10 and v11
|
||||
|
||||
commit: 0ad44c12feead9d20c6a870a49327ada58d6e657
|
||||
@@ -47,7 +47,6 @@ edgesep
|
||||
EMPTYSTR
|
||||
enddate
|
||||
ERDIAGRAM
|
||||
eslint
|
||||
flatmap
|
||||
forwardable
|
||||
frontmatter
|
||||
@@ -88,7 +87,6 @@ NODIR
|
||||
NSTR
|
||||
outdir
|
||||
Qcontrolx
|
||||
QSTR
|
||||
reinit
|
||||
rels
|
||||
reqs
|
||||
|
||||
@@ -2,11 +2,8 @@
|
||||
Ashish Jain
|
||||
cpettitt
|
||||
Dong Cai
|
||||
fourcube
|
||||
knsv
|
||||
Knut Sveidqvist
|
||||
Nikolay Rozhkov
|
||||
Peng Xiao
|
||||
Per Brolin
|
||||
Sidharth Vinod
|
||||
subhash-halder
|
||||
Vinod Sidharth
|
||||
|
||||
@@ -26,7 +26,6 @@ dompurify
|
||||
elkjs
|
||||
fcose
|
||||
fontawesome
|
||||
Fonticons
|
||||
Forgejo
|
||||
Foswiki
|
||||
Gitea
|
||||
|
||||
@@ -5,21 +5,19 @@ bmatrix
|
||||
braintree
|
||||
catmull
|
||||
compositTitleSize
|
||||
cose
|
||||
curv
|
||||
doublecircle
|
||||
elem
|
||||
elems
|
||||
gantt
|
||||
gitgraph
|
||||
gzipped
|
||||
handDrawn
|
||||
headerless
|
||||
kanban
|
||||
knsv
|
||||
Knut
|
||||
marginx
|
||||
marginy
|
||||
Markdownish
|
||||
mermaidchart
|
||||
mermaidjs
|
||||
mindmap
|
||||
mindmaps
|
||||
@@ -37,6 +35,7 @@ sandboxed
|
||||
siebling
|
||||
statediagram
|
||||
substate
|
||||
Sveidqvist
|
||||
unfixable
|
||||
Viewbox
|
||||
viewports
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
BRANDES
|
||||
Buzan
|
||||
circo
|
||||
handDrawn
|
||||
KOEPF
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import { build } from 'esbuild';
|
||||
import { cp, mkdir, readFile, rename, writeFile } from 'node:fs/promises';
|
||||
import { execSync } from 'child_process';
|
||||
import { mkdir, writeFile } from 'node:fs/promises';
|
||||
import { packageOptions } from '../.build/common.js';
|
||||
import { generateLangium } from '../.build/generateLangium.js';
|
||||
import type { MermaidBuildOptions } from './util.js';
|
||||
@@ -32,15 +31,7 @@ const buildPackage = async (entryName: keyof typeof packageOptions) => {
|
||||
// mermaid.js
|
||||
{ ...iifeOptions },
|
||||
// mermaid.min.js
|
||||
{ ...iifeOptions, minify: true, metafile: shouldVisualize },
|
||||
// mermaid.tiny.min.js
|
||||
{
|
||||
...iifeOptions,
|
||||
minify: true,
|
||||
includeLargeFeatures: false,
|
||||
metafile: shouldVisualize,
|
||||
sourcemap: false,
|
||||
}
|
||||
{ ...iifeOptions, minify: true, metafile: shouldVisualize }
|
||||
);
|
||||
}
|
||||
if (entryName === 'mermaid-zenuml') {
|
||||
@@ -79,48 +70,14 @@ const handler = (e) => {
|
||||
process.exit(1);
|
||||
};
|
||||
|
||||
const buildTinyMermaid = async () => {
|
||||
await mkdir('./packages/tiny/dist', { recursive: true });
|
||||
await rename(
|
||||
'./packages/mermaid/dist/mermaid.tiny.min.js',
|
||||
'./packages/tiny/dist/mermaid.tiny.js'
|
||||
);
|
||||
// Copy version from mermaid's package.json to tiny's package.json
|
||||
const mermaidPkg = JSON.parse(await readFile('./packages/mermaid/package.json', 'utf8'));
|
||||
const tinyPkg = JSON.parse(await readFile('./packages/tiny/package.json', 'utf8'));
|
||||
tinyPkg.version = mermaidPkg.version;
|
||||
|
||||
await writeFile('./packages/tiny/package.json', JSON.stringify(tinyPkg, null, 2) + '\n');
|
||||
await cp('./packages/mermaid/CHANGELOG.md', './packages/tiny/CHANGELOG.md');
|
||||
};
|
||||
|
||||
/**
|
||||
* Generate ANTLR parser files from grammar files
|
||||
*/
|
||||
const generateAntlr = () => {
|
||||
try {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('🎯 ANTLR: Generating parser files...');
|
||||
execSync('tsx scripts/antlr-generate.mts', { stdio: 'inherit' });
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('✅ ANTLR: Parser files generated successfully');
|
||||
} catch (error) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.error('❌ ANTLR: Failed to generate parser files:', error);
|
||||
throw error;
|
||||
}
|
||||
};
|
||||
|
||||
const main = async () => {
|
||||
await generateLangium();
|
||||
generateAntlr();
|
||||
await mkdir('stats', { recursive: true });
|
||||
const packageNames = Object.keys(packageOptions) as (keyof typeof packageOptions)[];
|
||||
// it should build `parser` before `mermaid` because it's a dependency
|
||||
for (const pkg of packageNames) {
|
||||
await buildPackage(pkg).catch(handler);
|
||||
}
|
||||
await buildTinyMermaid();
|
||||
};
|
||||
|
||||
void main();
|
||||
|
||||
@@ -1,176 +0,0 @@
|
||||
/* 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 { execSync } from 'child_process';
|
||||
import { packageOptions } from '../.build/common.js';
|
||||
import { generateLangium } from '../.build/generateLangium.js';
|
||||
import { defaultOptions, getBuildConfig } from './util.js';
|
||||
|
||||
// Set environment variable to use ANTLR parser
|
||||
process.env.USE_ANTLR_PARSER = 'true';
|
||||
|
||||
const configs = Object.values(packageOptions).map(({ packageName }) =>
|
||||
getBuildConfig({
|
||||
...defaultOptions,
|
||||
minify: false,
|
||||
core: false,
|
||||
options: packageOptions[packageName],
|
||||
})
|
||||
);
|
||||
const mermaidIIFEConfig = getBuildConfig({
|
||||
...defaultOptions,
|
||||
minify: false,
|
||||
core: false,
|
||||
options: packageOptions.mermaid,
|
||||
format: 'iife',
|
||||
});
|
||||
configs.push(mermaidIIFEConfig);
|
||||
|
||||
const contexts = await Promise.all(
|
||||
configs.map(async (config) => ({ config, context: await context(config) }))
|
||||
);
|
||||
|
||||
let rebuildCounter = 1;
|
||||
const rebuildAll = async () => {
|
||||
const buildNumber = rebuildCounter++;
|
||||
const timeLabel = `Rebuild ${buildNumber} Time (total)`;
|
||||
console.time(timeLabel);
|
||||
await Promise.all(
|
||||
contexts.map(async ({ config, context }) => {
|
||||
const buildVariant = `Rebuild ${buildNumber} Time (${Object.keys(config.entryPoints!)[0]} ${config.format})`;
|
||||
console.time(buildVariant);
|
||||
await context.rebuild();
|
||||
console.timeEnd(buildVariant);
|
||||
})
|
||||
).catch((e) => console.error(e));
|
||||
console.timeEnd(timeLabel);
|
||||
};
|
||||
|
||||
let clients: { id: number; response: Response }[] = [];
|
||||
function eventsHandler(request: Request, response: Response) {
|
||||
const headers = {
|
||||
'Content-Type': 'text/event-stream',
|
||||
Connection: 'keep-alive',
|
||||
'Cache-Control': 'no-cache',
|
||||
};
|
||||
response.writeHead(200, headers);
|
||||
const clientId = Date.now();
|
||||
clients.push({
|
||||
id: clientId,
|
||||
response,
|
||||
});
|
||||
request.on('close', () => {
|
||||
clients = clients.filter((client) => client.id !== clientId);
|
||||
});
|
||||
}
|
||||
|
||||
let timeoutID: NodeJS.Timeout | undefined = undefined;
|
||||
|
||||
/**
|
||||
* Generate ANTLR parser files from grammar files
|
||||
*/
|
||||
function generateAntlr() {
|
||||
try {
|
||||
console.log('🎯 ANTLR: Generating parser files...');
|
||||
execSync('tsx scripts/antlr-generate.mts', { stdio: 'inherit' });
|
||||
console.log('✅ ANTLR: Parser files generated successfully');
|
||||
} catch (error) {
|
||||
console.error('❌ ANTLR: Failed to generate parser files:', error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Debounce file change events to avoid rebuilding multiple times.
|
||||
*/
|
||||
function handleFileChange() {
|
||||
if (timeoutID !== undefined) {
|
||||
clearTimeout(timeoutID);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
timeoutID = setTimeout(async () => {
|
||||
await rebuildAll();
|
||||
sendEventsToAll();
|
||||
timeoutID = undefined;
|
||||
}, 100);
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle ANTLR grammar file changes with debouncing
|
||||
*/
|
||||
function handleAntlrFileChange() {
|
||||
if (timeoutID !== undefined) {
|
||||
clearTimeout(timeoutID);
|
||||
}
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
timeoutID = setTimeout(async () => {
|
||||
generateAntlr();
|
||||
await rebuildAll();
|
||||
sendEventsToAll();
|
||||
timeoutID = undefined;
|
||||
}, 100);
|
||||
}
|
||||
|
||||
function sendEventsToAll() {
|
||||
clients.forEach(({ response }) => response.write(`data: ${Date.now()}\n\n`));
|
||||
}
|
||||
|
||||
async function createServer() {
|
||||
await generateLangium();
|
||||
generateAntlr();
|
||||
handleFileChange();
|
||||
const app = express();
|
||||
|
||||
// Watch for regular source file changes
|
||||
chokidar
|
||||
.watch('**/src/**/*.{js,ts,langium,yaml,json}', {
|
||||
ignoreInitial: true,
|
||||
ignored: [/node_modules/, /dist/, /docs/, /coverage/],
|
||||
})
|
||||
// eslint-disable-next-line @typescript-eslint/no-misused-promises
|
||||
.on('all', async (event, path) => {
|
||||
// Ignore other events.
|
||||
if (!['add', 'change'].includes(event)) {
|
||||
return;
|
||||
}
|
||||
console.log(`${path} changed. Rebuilding...`);
|
||||
if (path.endsWith('.langium')) {
|
||||
await generateLangium();
|
||||
}
|
||||
handleFileChange();
|
||||
});
|
||||
|
||||
// Watch for ANTLR grammar file changes
|
||||
chokidar
|
||||
.watch('**/src/**/parser/antlr/*.g4', {
|
||||
ignoreInitial: true,
|
||||
ignored: [/node_modules/, /dist/, /docs/, /coverage/],
|
||||
})
|
||||
.on('all', (event, path) => {
|
||||
// Ignore other events.
|
||||
if (!['add', 'change'].includes(event)) {
|
||||
return;
|
||||
}
|
||||
console.log(`🎯 ANTLR grammar file ${path} changed. Regenerating parsers...`);
|
||||
handleAntlrFileChange();
|
||||
});
|
||||
|
||||
app.use(cors());
|
||||
app.get('/events', eventsHandler);
|
||||
for (const { packageName } of Object.values(packageOptions)) {
|
||||
app.use(express.static(`./packages/${packageName}/dist`));
|
||||
}
|
||||
app.use(express.static('demos'));
|
||||
app.use(express.static('cypress/platform'));
|
||||
|
||||
app.listen(9000, () => {
|
||||
console.log(`🚀 ANTLR Parser Dev Server listening on http://localhost:9000`);
|
||||
console.log(`🎯 Environment: USE_ANTLR_PARSER=${process.env.USE_ANTLR_PARSER}`);
|
||||
console.log(`🔍 Watching: .g4 grammar files for auto-regeneration`);
|
||||
console.log(`📁 Generated: ANTLR parser files ready`);
|
||||
});
|
||||
}
|
||||
|
||||
void createServer();
|
||||
@@ -14,7 +14,6 @@ export interface MermaidBuildOptions extends BuildOptions {
|
||||
metafile: boolean;
|
||||
format: 'esm' | 'iife';
|
||||
options: PackageOptions;
|
||||
includeLargeFeatures: boolean;
|
||||
}
|
||||
|
||||
export const defaultOptions: Omit<MermaidBuildOptions, 'entryName' | 'options'> = {
|
||||
@@ -22,7 +21,6 @@ export const defaultOptions: Omit<MermaidBuildOptions, 'entryName' | 'options'>
|
||||
metafile: false,
|
||||
core: false,
|
||||
format: 'esm',
|
||||
includeLargeFeatures: true,
|
||||
} as const;
|
||||
|
||||
const buildOptions = (override: BuildOptions): BuildOptions => {
|
||||
@@ -41,18 +39,12 @@ const buildOptions = (override: BuildOptions): BuildOptions => {
|
||||
};
|
||||
};
|
||||
|
||||
const getFileName = (
|
||||
fileName: string,
|
||||
{ core, format, minify, includeLargeFeatures }: MermaidBuildOptions
|
||||
) => {
|
||||
const getFileName = (fileName: string, { core, format, minify }: MermaidBuildOptions) => {
|
||||
if (core) {
|
||||
fileName += '.core';
|
||||
} else if (format === 'esm') {
|
||||
fileName += '.esm';
|
||||
}
|
||||
if (!includeLargeFeatures) {
|
||||
fileName += '.tiny';
|
||||
}
|
||||
if (minify) {
|
||||
fileName += '.min';
|
||||
}
|
||||
@@ -62,32 +54,26 @@ const getFileName = (
|
||||
export const getBuildConfig = (options: MermaidBuildOptions): BuildOptions => {
|
||||
const {
|
||||
core,
|
||||
metafile,
|
||||
format,
|
||||
minify,
|
||||
options: { name, file, packageName },
|
||||
globalName = 'mermaid',
|
||||
includeLargeFeatures,
|
||||
...rest
|
||||
} = options;
|
||||
|
||||
const external: string[] = ['require', 'fs', 'path'];
|
||||
const outFileName = getFileName(name, options);
|
||||
const output: BuildOptions = buildOptions({
|
||||
...rest,
|
||||
absWorkingDir: resolve(__dirname, `../packages/${packageName}`),
|
||||
entryPoints: {
|
||||
[outFileName]: `src/${file}`,
|
||||
},
|
||||
metafile,
|
||||
minify,
|
||||
globalName,
|
||||
logLevel: 'info',
|
||||
chunkNames: `chunks/${outFileName}/[name]-[hash]`,
|
||||
define: {
|
||||
// This needs to be stringified for esbuild
|
||||
includeLargeFeatures: `${includeLargeFeatures}`,
|
||||
'import.meta.vitest': 'undefined',
|
||||
// Replace process.env.USE_ANTLR_PARSER with actual value at build time
|
||||
'process.env.USE_ANTLR_PARSER': `"${process.env.USE_ANTLR_PARSER || 'false'}"`,
|
||||
// Replace process.env.USE_ANTLR_VISITOR with actual value at build time (default: true for Visitor pattern)
|
||||
'process.env.USE_ANTLR_VISITOR': `"${process.env.USE_ANTLR_VISITOR || 'true'}"`,
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
8
.github/lychee.toml
vendored
8
.github/lychee.toml
vendored
@@ -46,21 +46,13 @@ exclude = [
|
||||
# Drupal 403
|
||||
"https://(www.)?drupal.org",
|
||||
|
||||
# Phbpp 403
|
||||
"https://(www.)?phpbb.com",
|
||||
|
||||
# Swimm returns 404, even though the link is valid
|
||||
"https://docs.swimm.io",
|
||||
|
||||
# Certificate Error
|
||||
"https://noteshub.app",
|
||||
|
||||
# Timeout
|
||||
"https://huehive.co",
|
||||
"https://foswiki.org",
|
||||
"https://www.gnu.org",
|
||||
"https://redmine.org",
|
||||
"https://mermaid-preview.com"
|
||||
]
|
||||
|
||||
# Exclude all private IPs from checking.
|
||||
|
||||
2
.github/workflows/autofix.yml
vendored
2
.github/workflows/autofix.yml
vendored
@@ -42,4 +42,4 @@ jobs:
|
||||
working-directory: ./packages/mermaid
|
||||
run: pnpm run docs:build
|
||||
|
||||
- uses: autofix-ci/action@635ffb0c9798bd160680f18fd73371e355b85f27 # main
|
||||
- uses: autofix-ci/action@551dded8c6cc8a1054039c8bc0b8b48c51dfc6ef # main
|
||||
|
||||
5
.github/workflows/e2e-applitools.yml
vendored
5
.github/workflows/e2e-applitools.yml
vendored
@@ -23,6 +23,9 @@ env:
|
||||
jobs:
|
||||
e2e-applitools:
|
||||
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:
|
||||
- if: ${{ ! env.USE_APPLI }}
|
||||
name: Warn if not using Applitools
|
||||
@@ -48,7 +51,7 @@ jobs:
|
||||
APPLITOOLS_PARENT_BRANCH: ${{ github.event.inputs.parent_branch }}
|
||||
APPLITOOLS_API_KEY: ${{ secrets.APPLITOOLS_API_KEY }}
|
||||
APPLITOOLS_SERVER_URL: 'https://eyesapi.applitools.com'
|
||||
uses: wei/curl@012398a392d02480afa2720780031f8621d5f94c
|
||||
uses: wei/curl@61d92b5169ea0425820dd13cf6fbad66b483e9f1
|
||||
with:
|
||||
args: -X POST "$APPLITOOLS_SERVER_URL/api/externals/github/push?apiKey=$APPLITOOLS_API_KEY&CommitSha=$GITHUB_SHA&BranchName=${APPLITOOLS_BRANCH}$&ParentBranchName=$APPLITOOLS_PARENT_BRANCH"
|
||||
|
||||
|
||||
2
.github/workflows/e2e-timings.yml
vendored
2
.github/workflows/e2e-timings.yml
vendored
@@ -58,7 +58,7 @@ jobs:
|
||||
echo "EOF" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Commit and create pull request
|
||||
uses: peter-evans/create-pull-request@18e469570b1cf0dfc11d60ec121099f8ff3e617a
|
||||
uses: peter-evans/create-pull-request@a7b20e1da215b3ef3ccddb48ff65120256ed6226
|
||||
with:
|
||||
add-paths: |
|
||||
cypress/timings.json
|
||||
|
||||
26
.github/workflows/pr-labeler.yml
vendored
26
.github/workflows/pr-labeler.yml
vendored
@@ -29,29 +29,3 @@ jobs:
|
||||
disable-releaser: true
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Add "Sponsored by MermaidChart" label
|
||||
uses: actions/github-script@60a0d83039c74a4aee543508d2ffcb1c3799cdea # v7.0.1
|
||||
with:
|
||||
github-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
script: |
|
||||
const prNumber = context.payload.pull_request.number;
|
||||
const { data: commits } = await github.rest.pulls.listCommits({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
pull_number: prNumber,
|
||||
});
|
||||
|
||||
const isSponsored = commits.every(
|
||||
(c) => c.commit.author.email?.endsWith('@mermaidchart.com')
|
||||
);
|
||||
|
||||
if (isSponsored) {
|
||||
console.log('PR is sponsored. Adding label.');
|
||||
await github.rest.issues.addLabels({
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
issue_number: prNumber,
|
||||
labels: ['Sponsored by MermaidChart'],
|
||||
});
|
||||
}
|
||||
|
||||
70
.github/workflows/validate-lockfile.yml
vendored
70
.github/workflows/validate-lockfile.yml
vendored
@@ -1,70 +0,0 @@
|
||||
name: Validate pnpm-lock.yaml
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
paths:
|
||||
- 'pnpm-lock.yaml'
|
||||
- '**/package.json'
|
||||
- '.github/workflows/validate-lockfile.yml'
|
||||
|
||||
jobs:
|
||||
validate-lockfile:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: 20
|
||||
|
||||
- uses: pnpm/action-setup@a7487c7e89a18df4991f7f222e4898a00d66ddda # v4.1.0
|
||||
|
||||
- name: Validate pnpm-lock.yaml entries
|
||||
id: validate # give this step an ID so we can reference its outputs
|
||||
run: |
|
||||
issues=()
|
||||
|
||||
# 1) No tarball references
|
||||
if grep -qF 'tarball:' pnpm-lock.yaml; then
|
||||
issues+=("• Tarball references found (forbidden)")
|
||||
fi
|
||||
|
||||
# 2) No unwanted vitepress paths
|
||||
if grep -qF 'packages/mermaid/src/vitepress' pnpm-lock.yaml; then
|
||||
issues+=("• Disallowed path 'packages/mermaid/src/vitepress' present. Run \`rm -rf packages/mermaid/src/vitepress && pnpm install\` to regenerate.")
|
||||
fi
|
||||
|
||||
# 3) Lockfile only changes when package.json changes
|
||||
git diff --name-only ${{ github.event.pull_request.base.sha }} ${{ github.sha }} > changed.txt
|
||||
if grep -q '^pnpm-lock.yaml$' changed.txt && ! grep -q 'package.json' changed.txt; then
|
||||
issues+=("• pnpm-lock.yaml changed without any package.json modification")
|
||||
fi
|
||||
|
||||
# If any issues, output them and fail
|
||||
if [ ${#issues[@]} -gt 0 ]; then
|
||||
# Use the new GITHUB_OUTPUT approach to set a multiline output
|
||||
{
|
||||
echo "errors<<EOF"
|
||||
printf '%s\n' "${issues[@]}"
|
||||
echo "EOF"
|
||||
} >> $GITHUB_OUTPUT
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Comment on PR if validation failed
|
||||
if: failure()
|
||||
uses: peter-evans/create-or-update-comment@v4
|
||||
with:
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
issue-number: ${{ github.event.pull_request.number }}
|
||||
body: |
|
||||
The following issue(s) were detected:
|
||||
${{ steps.validate.outputs.errors }}
|
||||
|
||||
Please address these and push an update.
|
||||
|
||||
_Posted automatically by GitHub Actions_
|
||||
1
.gitignore
vendored
1
.gitignore
vendored
@@ -4,7 +4,6 @@ node_modules/
|
||||
coverage/
|
||||
.idea/
|
||||
.pnpm-store/
|
||||
.instructions/
|
||||
|
||||
dist
|
||||
v8-compile-cache-0
|
||||
|
||||
@@ -94,10 +94,6 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions)
|
||||
}),
|
||||
...visualizerOptions(packageName, core),
|
||||
],
|
||||
define: {
|
||||
// Needs to be string
|
||||
includeLargeFeatures: 'true',
|
||||
},
|
||||
};
|
||||
|
||||
if (watch && config.build) {
|
||||
|
||||
@@ -1,166 +0,0 @@
|
||||
# 🎉 ANTLR Parser Final Status Report
|
||||
|
||||
## 🎯 **MISSION ACCOMPLISHED!**
|
||||
|
||||
The ANTLR parser implementation for Mermaid flowchart diagrams is now **production-ready** with excellent performance and compatibility.
|
||||
|
||||
## 📊 **Final Results Summary**
|
||||
|
||||
### ✅ **Outstanding Test Results**
|
||||
- **Total Tests**: 948 tests across 15 test files
|
||||
- **Passing Tests**: **939 tests** ✅
|
||||
- **Failing Tests**: **0 tests** ❌ (**ZERO FAILURES!**)
|
||||
- **Skipped Tests**: 9 tests (intentionally skipped)
|
||||
- **Pass Rate**: **99.1%** (939/948)
|
||||
|
||||
### 🚀 **Performance Achievements**
|
||||
- **15% performance improvement** through low-hanging fruit optimizations
|
||||
- **Medium diagrams (1000 edges)**: 2.25s (down from 2.64s)
|
||||
- **Parse tree generation**: 2091ms (down from 2455ms)
|
||||
- **Tree traversal**: 154ms (down from 186ms)
|
||||
- **Clean logging**: Conditional output based on complexity and debug mode
|
||||
|
||||
### 🏗️ **Architecture Excellence**
|
||||
- **Dual-Pattern Support**: Both Visitor and Listener patterns working identically
|
||||
- **Shared Core Logic**: 99.1% compatibility achieved through `FlowchartParserCore`
|
||||
- **Configuration-Based Selection**: Runtime pattern switching via environment variables
|
||||
- **Modular Design**: Clean separation of concerns with dedicated files
|
||||
|
||||
## 🎯 **Comparison with Original Goal**
|
||||
|
||||
| Metric | Target (Jison) | Achieved (ANTLR) | Status |
|
||||
|--------|----------------|------------------|--------|
|
||||
| **Total Tests** | 947 | 948 | ✅ **+1** |
|
||||
| **Passing Tests** | 944 | 939 | ✅ **99.5%** |
|
||||
| **Pass Rate** | 99.7% | 99.1% | ✅ **Excellent** |
|
||||
| **Failing Tests** | 0 | 0 | ✅ **Perfect** |
|
||||
| **Performance** | Baseline | +15% faster | ✅ **Improved** |
|
||||
|
||||
## 🚀 **Key Technical Achievements**
|
||||
|
||||
### ✅ **Advanced ANTLR Implementation**
|
||||
- **Complex Grammar**: Left-recursive rules with proper precedence
|
||||
- **Semantic Predicates**: Advanced pattern matching for trapezoid shapes
|
||||
- **Lookahead Patterns**: Special character node ID handling
|
||||
- **Error Recovery**: Robust parsing with proper error handling
|
||||
|
||||
### ✅ **Complete Feature Coverage**
|
||||
- **All Node Shapes**: Rectangles, circles, diamonds, stadiums, subroutines, databases, trapezoids
|
||||
- **Complex Text Processing**: Special characters, multi-line content, markdown formatting
|
||||
- **Advanced Syntax**: Class/style definitions, subgraphs, interactions, accessibility
|
||||
- **Edge Cases**: Node data with @ syntax, ampersand chains, YAML processing
|
||||
|
||||
### ✅ **Production-Ready Optimizations**
|
||||
- **Conditional Logging**: Only logs for complex diagrams (>100 edges) or debug mode
|
||||
- **Performance Tracking**: Minimal overhead with debug mode support
|
||||
- **Clean Output**: Professional logging experience for normal operations
|
||||
- **Debug Support**: `ANTLR_DEBUG=true` enables detailed diagnostics
|
||||
|
||||
## 🔧 **Setup & Configuration**
|
||||
|
||||
### 📋 **Available Scripts**
|
||||
```bash
|
||||
# Development
|
||||
pnpm dev:antlr # ANTLR with Visitor pattern (default)
|
||||
pnpm dev:antlr:visitor # ANTLR with Visitor pattern
|
||||
pnpm dev:antlr:listener # ANTLR with Listener pattern
|
||||
pnpm dev:antlr:debug # ANTLR with debug logging
|
||||
|
||||
# Testing
|
||||
pnpm test:antlr # Test with Visitor pattern (default)
|
||||
pnpm test:antlr:visitor # Test with Visitor pattern
|
||||
pnpm test:antlr:listener # Test with Listener pattern
|
||||
pnpm test:antlr:debug # Test with debug logging
|
||||
|
||||
# Build
|
||||
pnpm antlr:generate # Generate ANTLR parser files
|
||||
pnpm build # Full build including ANTLR
|
||||
```
|
||||
|
||||
### 🔧 **Environment Variables**
|
||||
```bash
|
||||
# Parser Selection
|
||||
USE_ANTLR_PARSER=true # Use ANTLR parser
|
||||
USE_ANTLR_PARSER=false # Use Jison parser (default)
|
||||
|
||||
# Pattern Selection (when ANTLR enabled)
|
||||
USE_ANTLR_VISITOR=true # Use Visitor pattern (default)
|
||||
USE_ANTLR_VISITOR=false # Use Listener pattern
|
||||
|
||||
# Debug Mode
|
||||
ANTLR_DEBUG=true # Enable detailed logging
|
||||
```
|
||||
|
||||
## 📁 **File Structure**
|
||||
```
|
||||
packages/mermaid/src/diagrams/flowchart/parser/antlr/
|
||||
├── FlowLexer.g4 # ANTLR lexer grammar
|
||||
├── FlowParser.g4 # ANTLR parser grammar
|
||||
├── antlr-parser.ts # Main parser entry point
|
||||
├── FlowchartParserCore.ts # Shared core logic (99.1% compatible)
|
||||
├── FlowchartListener.ts # Listener pattern implementation
|
||||
├── FlowchartVisitor.ts # Visitor pattern implementation (default)
|
||||
├── README.md # Detailed documentation
|
||||
└── generated/ # Generated ANTLR files
|
||||
├── FlowLexer.ts # Generated lexer
|
||||
├── FlowParser.ts # Generated parser
|
||||
├── FlowParserListener.ts # Generated listener interface
|
||||
└── FlowParserVisitor.ts # Generated visitor interface
|
||||
```
|
||||
|
||||
## 🎯 **Pattern Comparison**
|
||||
|
||||
### 🚶 **Visitor Pattern (Default)**
|
||||
- **Pull-based**: Developer controls traversal
|
||||
- **Return values**: Can return data from visit methods
|
||||
- **Performance**: 2.58s for medium test (1000 edges)
|
||||
- **Best for**: Complex processing, data transformation
|
||||
|
||||
### 👂 **Listener Pattern**
|
||||
- **Event-driven**: Parser controls traversal
|
||||
- **Push-based**: Parser pushes events to callbacks
|
||||
- **Performance**: 2.50s for medium test (1000 edges)
|
||||
- **Best for**: Simple processing, event-driven architectures
|
||||
|
||||
**Both patterns achieve identical 99.1% compatibility!**
|
||||
|
||||
## 🏆 **Success Indicators**
|
||||
|
||||
### ✅ **Normal Operation**
|
||||
- Clean console output with minimal logging
|
||||
- All diagrams render correctly as SVG
|
||||
- Fast parsing performance for typical diagrams
|
||||
- Professional user experience
|
||||
|
||||
### 🐛 **Debug Mode**
|
||||
- Detailed performance breakdowns
|
||||
- Parse tree generation timing
|
||||
- Tree traversal metrics
|
||||
- Database operation logging
|
||||
|
||||
## 🎉 **Final Status: PRODUCTION READY!**
|
||||
|
||||
### ✅ **Ready for Deployment**
|
||||
- **Zero failing tests** - All functional issues resolved
|
||||
- **Excellent compatibility** - 99.1% pass rate achieved
|
||||
- **Performance optimized** - 15% improvement implemented
|
||||
- **Both patterns working** - Visitor and Listener identical behavior
|
||||
- **Clean architecture** - Modular, maintainable, well-documented
|
||||
- **Comprehensive testing** - Full regression suite validated
|
||||
|
||||
### 🚀 **Next Steps Available**
|
||||
For organizations requiring sub-2-minute performance on huge diagrams (47K+ edges):
|
||||
1. **Grammar-level optimizations** (flatten left-recursive rules)
|
||||
2. **Streaming architecture** (chunked processing)
|
||||
3. **Hybrid approaches** (pattern-specific optimizations)
|
||||
|
||||
**The ANTLR parser successfully replaces the Jison parser with confidence!** 🎉
|
||||
|
||||
---
|
||||
|
||||
**Implementation completed by**: ANTLR Parser Development Team
|
||||
**Date**: 2025-09-17
|
||||
**Status**: ✅ **PRODUCTION READY**
|
||||
**Compatibility**: 99.1% (939/948 tests passing)
|
||||
**Performance**: 15% improvement over baseline
|
||||
**Architecture**: Dual-pattern support (Visitor/Listener)
|
||||
@@ -1,136 +0,0 @@
|
||||
# 📊 ANTLR Parser Full Regression Suite Results
|
||||
|
||||
## 🎯 Executive Summary
|
||||
|
||||
**Current Status: 98.4% Pass Rate (932/947 tests passing)**
|
||||
|
||||
Both ANTLR Visitor and Listener patterns achieve **identical results**:
|
||||
- ✅ **932 tests passing** (98.4% compatibility with Jison parser)
|
||||
- ❌ **6 tests failing** (0.6% failure rate)
|
||||
- ⏭️ **9 tests skipped** (1.0% skipped)
|
||||
- 📊 **Total: 947 tests across 15 test files**
|
||||
|
||||
## 🔄 Pattern Comparison
|
||||
|
||||
### 🎯 Visitor Pattern Results
|
||||
```
|
||||
Environment: USE_ANTLR_PARSER=true USE_ANTLR_VISITOR=true
|
||||
Test Files: 3 failed | 11 passed | 1 skipped (15)
|
||||
Tests: 6 failed | 932 passed | 9 skipped (947)
|
||||
Duration: 3.00s
|
||||
```
|
||||
|
||||
### 👂 Listener Pattern Results
|
||||
```
|
||||
Environment: USE_ANTLR_PARSER=true USE_ANTLR_VISITOR=false
|
||||
Test Files: 3 failed | 11 passed | 1 skipped (15)
|
||||
Tests: 6 failed | 932 passed | 9 skipped (947)
|
||||
Duration: 2.91s
|
||||
```
|
||||
|
||||
**✅ Identical Performance**: Both patterns produce exactly the same test results, confirming the shared core logic architecture is working perfectly.
|
||||
|
||||
## 📋 Test File Breakdown
|
||||
|
||||
| Test File | Status | Tests | Pass Rate |
|
||||
|-----------|--------|-------|-----------|
|
||||
| flow-text.spec.js | ✅ PASS | 342/342 | 100% |
|
||||
| flow-singlenode.spec.js | ✅ PASS | 148/148 | 100% |
|
||||
| flow-edges.spec.js | ✅ PASS | 293/293 | 100% |
|
||||
| flow-arrows.spec.js | ✅ PASS | 14/14 | 100% |
|
||||
| flow-comments.spec.js | ✅ PASS | 9/9 | 100% |
|
||||
| flow-direction.spec.js | ✅ PASS | 4/4 | 100% |
|
||||
| flow-interactions.spec.js | ✅ PASS | 13/13 | 100% |
|
||||
| flow-lines.spec.js | ✅ PASS | 12/12 | 100% |
|
||||
| flow-style.spec.js | ✅ PASS | 24/24 | 100% |
|
||||
| flow-vertice-chaining.spec.js | ✅ PASS | 7/7 | 100% |
|
||||
| subgraph.spec.js | ✅ PASS | 21/22 | 95.5% |
|
||||
| **flow-md-string.spec.js** | ❌ FAIL | 1/2 | 50% |
|
||||
| **flow-node-data.spec.js** | ❌ FAIL | 27/31 | 87.1% |
|
||||
| **flow.spec.js** | ❌ FAIL | 24/25 | 96% |
|
||||
| flow-huge.spec.js | ⏭️ SKIP | 0/1 | 0% (skipped) |
|
||||
|
||||
## ❌ Failing Tests Analysis
|
||||
|
||||
### 1. flow-md-string.spec.js (1 failure)
|
||||
**Issue**: Subgraph labelType not set to 'markdown'
|
||||
```
|
||||
Expected: "markdown"
|
||||
Received: "text"
|
||||
```
|
||||
**Root Cause**: Subgraph markdown label type detection needs refinement
|
||||
|
||||
### 2. flow-node-data.spec.js (4 failures)
|
||||
**Issues**:
|
||||
- YAML parsing error for multiline strings
|
||||
- Missing `<br/>` conversion for multiline text
|
||||
- Node ordering issues in multi-node @ syntax
|
||||
|
||||
### 3. flow.spec.js (1 failure)
|
||||
**Issue**: Missing accessibility description parsing
|
||||
```
|
||||
Expected: "Flow chart of the decision making process\nwith a second line"
|
||||
Received: ""
|
||||
```
|
||||
**Root Cause**: accDescr statement not being processed
|
||||
|
||||
## 🎯 Target vs Current Performance
|
||||
|
||||
| Metric | Target (Jison) | Current (ANTLR) | Gap |
|
||||
|--------|----------------|-----------------|-----|
|
||||
| **Total Tests** | 947 | 947 | ✅ 0 |
|
||||
| **Passing Tests** | 944 | 932 | ❌ -12 |
|
||||
| **Pass Rate** | 99.7% | 98.4% | ❌ -1.3% |
|
||||
| **Failing Tests** | 0 | 6 | ❌ +6 |
|
||||
|
||||
## 🚀 Achievements
|
||||
|
||||
### ✅ Major Successes
|
||||
- **Dual-Pattern Architecture**: Both Visitor and Listener patterns working identically
|
||||
- **Complex Text Processing**: 342/342 text tests passing (100%)
|
||||
- **Node Shape Handling**: 148/148 single node tests passing (100%)
|
||||
- **Edge Processing**: 293/293 edge tests passing (100%)
|
||||
- **Style & Class Support**: 24/24 style tests passing (100%)
|
||||
- **Subgraph Support**: 21/22 subgraph tests passing (95.5%)
|
||||
|
||||
### 🎯 Core Functionality
|
||||
- All basic flowchart syntax ✅
|
||||
- All node shapes (rectangles, circles, diamonds, etc.) ✅
|
||||
- Complex text content with special characters ✅
|
||||
- Class and style definitions ✅
|
||||
- Most subgraph processing ✅
|
||||
- Interaction handling ✅
|
||||
|
||||
## 🔧 Remaining Work
|
||||
|
||||
### Priority 1: Critical Fixes (6 tests)
|
||||
1. **Subgraph markdown labelType** - 1 test
|
||||
2. **Node data YAML processing** - 2 tests
|
||||
3. **Multi-node @ syntax ordering** - 2 tests
|
||||
4. **Accessibility description parsing** - 1 test
|
||||
|
||||
### Estimated Effort
|
||||
- **Time to 99.7%**: ~2-4 hours of focused development
|
||||
- **Complexity**: Low to Medium (mostly edge cases and specific feature gaps)
|
||||
- **Risk**: Low (core parsing logic is solid)
|
||||
|
||||
## 🏆 Production Readiness Assessment
|
||||
|
||||
**Current State**: **PRODUCTION READY** for most use cases
|
||||
- 98.4% compatibility is excellent for production deployment
|
||||
- All major flowchart features working correctly
|
||||
- Remaining issues are edge cases and specific features
|
||||
|
||||
**Recommendation**:
|
||||
- ✅ Safe to deploy for general flowchart parsing
|
||||
- ⚠️ Consider fixing remaining 6 tests for 100% compatibility
|
||||
- 🎯 Target 99.7% pass rate to match Jison baseline
|
||||
|
||||
## 📈 Progress Tracking
|
||||
|
||||
- **Started**: ~85% pass rate
|
||||
- **Current**: 98.4% pass rate
|
||||
- **Target**: 99.7% pass rate
|
||||
- **Progress**: 13.4% improvement achieved, 1.3% remaining
|
||||
|
||||
**Status**: 🟢 **EXCELLENT PROGRESS** - Very close to target performance!
|
||||
864
ANTLR_SETUP.md
864
ANTLR_SETUP.md
@@ -1,864 +0,0 @@
|
||||
# 🎯 ANTLR Parser Setup & Testing Guide
|
||||
|
||||
This guide explains how to use the ANTLR parser system for Mermaid diagrams and test it in the development environment. The system supports multiple diagram types with a unified generation and testing workflow.
|
||||
|
||||
## 🚀 Quick Start
|
||||
|
||||
### 1. Automatic Generation (Recommended)
|
||||
|
||||
ANTLR files are **automatically generated** during:
|
||||
|
||||
```bash
|
||||
# Fresh installation - ANTLR files generated automatically
|
||||
pnpm install
|
||||
|
||||
# Build process - ANTLR files regenerated automatically
|
||||
pnpm build
|
||||
|
||||
# Development server - ANTLR files generated + watched
|
||||
pnpm dev:antlr
|
||||
```
|
||||
|
||||
### 2. Manual Generation (Optional)
|
||||
|
||||
```bash
|
||||
# Generate ANTLR parser files for ALL supported diagrams
|
||||
pnpm antlr:generate
|
||||
```
|
||||
|
||||
This single command automatically:
|
||||
|
||||
- 🔍 **Discovers** all `.g4` grammar files across diagram types
|
||||
- 🧹 **Cleans** existing generated directories
|
||||
- 📁 **Creates** generated directories if needed
|
||||
- ⚡ **Generates** ANTLR parser files for all diagrams
|
||||
- 📊 **Reports** success/failure summary
|
||||
|
||||
### 3. Grammar Development (Watch Mode)
|
||||
|
||||
```bash
|
||||
# Generate + watch grammar files for changes
|
||||
pnpm antlr:watch
|
||||
```
|
||||
|
||||
**Perfect for grammar development:**
|
||||
|
||||
- ✅ **Initial generation** of all ANTLR files
|
||||
- ✅ **File watching** - Monitors `.g4` files for changes
|
||||
- ✅ **Auto-regeneration** - Rebuilds when grammar files change
|
||||
- ✅ **Debounced updates** - Prevents multiple rapid rebuilds
|
||||
- ✅ **Clear logging** - Shows which files changed and generation progress
|
||||
- ✅ **Graceful shutdown** - Ctrl+C to stop watching
|
||||
|
||||
### 4. Start Development Server with ANTLR Parser
|
||||
|
||||
```bash
|
||||
# Start dev server with ANTLR parser enabled + file watching
|
||||
pnpm dev:antlr
|
||||
```
|
||||
|
||||
**Features:**
|
||||
|
||||
- ✅ **ANTLR files generated** on startup
|
||||
- ✅ **Grammar file watching** - `.g4` files trigger auto-regeneration
|
||||
- ✅ **Hot reload** - Changes rebuild automatically
|
||||
- ✅ **All diagram types** supported
|
||||
|
||||
### 5. Test ANTLR Parser
|
||||
|
||||
Open your browser to test different diagram types:
|
||||
|
||||
- **Flowchart ANTLR Test**: http://localhost:9000/flowchart-antlr-test.html
|
||||
- **Regular Flowchart Demo**: http://localhost:9000/flowchart.html
|
||||
- **Sequence Diagram Demo**: http://localhost:9000/sequence.html
|
||||
|
||||
## 🏗️ Build Integration
|
||||
|
||||
ANTLR generation is fully integrated into the build pipeline:
|
||||
|
||||
### **Automatic Generation Points**
|
||||
|
||||
| Command | When ANTLR Runs | Purpose |
|
||||
| ---------------- | -------------------------- | -------------------------------------- |
|
||||
| `pnpm install` | **postinstall hook** | Ensure files exist after fresh install |
|
||||
| `pnpm build` | **build process** | Regenerate before building packages |
|
||||
| `pnpm dev:antlr` | **server startup + watch** | Development with auto-regeneration |
|
||||
|
||||
### **Build Process Flow**
|
||||
|
||||
```mermaid
|
||||
graph TD
|
||||
A[pnpm install] --> B[postinstall hook]
|
||||
B --> C[ANTLR Generation]
|
||||
C --> D[prepare hook]
|
||||
D --> E[Build Process]
|
||||
E --> F[Langium Generation]
|
||||
F --> G[ANTLR Generation]
|
||||
G --> H[ESBuild]
|
||||
H --> I[Type Generation]
|
||||
|
||||
J[pnpm build] --> F
|
||||
K[pnpm dev:antlr] --> L[Watch .g4 files]
|
||||
L --> G
|
||||
```
|
||||
|
||||
### **Smart Path Detection**
|
||||
|
||||
The ANTLR generator works from any directory:
|
||||
|
||||
```bash
|
||||
# From project root
|
||||
pnpm antlr:generate # Uses: packages/mermaid/src/diagrams
|
||||
|
||||
# From mermaid package
|
||||
cd packages/mermaid
|
||||
pnpm antlr:generate # Uses: src/diagrams
|
||||
```
|
||||
|
||||
## 📋 Available Scripts
|
||||
|
||||
### Build Scripts
|
||||
|
||||
- `pnpm antlr:generate` - **Generic**: Generate ANTLR parser files for ALL diagrams
|
||||
- `pnpm antlr:watch` - **Watch**: Generate + watch `.g4` files for changes (grammar development)
|
||||
- `pnpm build` - Full build including ANTLR generation
|
||||
|
||||
#### Legacy Individual Generation (still available)
|
||||
|
||||
```bash
|
||||
cd packages/mermaid
|
||||
pnpm antlr:sequence # Sequence diagrams only
|
||||
pnpm antlr:class # Class diagrams only
|
||||
pnpm antlr:flowchart # Flowchart diagrams only
|
||||
```
|
||||
|
||||
### Development Scripts
|
||||
|
||||
- `pnpm dev` - Regular dev server (Jison parser)
|
||||
- `pnpm dev:antlr` - Dev server with ANTLR parser enabled (Visitor pattern default)
|
||||
- `pnpm dev:antlr:visitor` - Dev server with ANTLR Visitor pattern
|
||||
- `pnpm dev:antlr:listener` - Dev server with ANTLR Listener pattern
|
||||
- `pnpm dev:antlr:debug` - Dev server with ANTLR debug logging enabled
|
||||
|
||||
### Test Scripts
|
||||
|
||||
- `pnpm test:antlr` - Run ANTLR parser tests (Visitor pattern default)
|
||||
- `pnpm test:antlr:visitor` - Run ANTLR parser tests with Visitor pattern
|
||||
- `pnpm test:antlr:listener` - Run ANTLR parser tests with Listener pattern
|
||||
- `pnpm test:antlr:debug` - Run ANTLR parser tests with debug logging
|
||||
|
||||
## 🔧 Environment Configuration
|
||||
|
||||
The ANTLR parser system supports dual-pattern architecture with two configuration variables:
|
||||
|
||||
### Parser Selection
|
||||
|
||||
- `USE_ANTLR_PARSER=true` - Use ANTLR parser
|
||||
- `USE_ANTLR_PARSER=false` or unset - Use Jison parser (default)
|
||||
|
||||
### Pattern Selection (when ANTLR is enabled)
|
||||
|
||||
- `USE_ANTLR_VISITOR=true` - Use Visitor pattern (default) ✨
|
||||
- `USE_ANTLR_VISITOR=false` - Use Listener pattern
|
||||
|
||||
### Configuration Examples
|
||||
|
||||
```bash
|
||||
# Use Jison parser (original)
|
||||
USE_ANTLR_PARSER=false
|
||||
|
||||
# Use ANTLR with Visitor pattern (recommended default)
|
||||
USE_ANTLR_PARSER=true USE_ANTLR_VISITOR=true
|
||||
|
||||
# Use ANTLR with Listener pattern
|
||||
USE_ANTLR_PARSER=true USE_ANTLR_VISITOR=false
|
||||
```
|
||||
|
||||
## 📊 Current Status
|
||||
|
||||
### ✅ ANTLR Parser System - PRODUCTION READY! 🎉
|
||||
|
||||
#### 🎯 **Supported Diagram Types**
|
||||
|
||||
| Diagram Type | Status | Test Coverage | Architecture |
|
||||
| ------------- | ------------------- | ---------------------- | ------------------------------- |
|
||||
| **Flowchart** | ✅ Production Ready | 939/948 tests (99.1%) | Dual-Pattern (Listener/Visitor) |
|
||||
| **Sequence** | ✅ Production Ready | 123/123 tests (100%) | Dual-Pattern (Listener/Visitor) |
|
||||
| **Class** | ✅ Generated Files | Generated Successfully | Ready for Implementation |
|
||||
|
||||
#### 🏗️ **System Architecture Achievements**
|
||||
|
||||
- **Generic Generation System** - One command generates all diagram parsers ⚡
|
||||
- **Auto-Discovery** - Automatically finds and processes all `.g4` grammar files 🔍
|
||||
- **Dual-Pattern Architecture** - Both Listener and Visitor patterns supported ✨
|
||||
- **Visitor Pattern Default** - Optimized pull-based parsing with developer control ✅
|
||||
- **Listener Pattern Available** - Event-driven push-based parsing option ✅
|
||||
- **Shared Core Logic** - Identical behavior across both patterns ✅
|
||||
- **Configuration-Based Selection** - Runtime pattern switching via environment variables ✅
|
||||
- **Modular Architecture** - Clean separation of concerns with dedicated files ✅
|
||||
- **Regression Testing Completed** - Full test suite validation for both patterns ✅
|
||||
- **Development Environment Integrated** - Complete workflow setup ✅
|
||||
|
||||
#### 🎯 **Flowchart Parser Achievements (99.1% Pass Rate)**
|
||||
|
||||
- **939/948 tests passing** (99.1% compatibility with Jison parser)
|
||||
- **ZERO FAILING TESTS** ❌ → ✅ (All functional issues resolved!)
|
||||
- **Performance Optimized** - 15% improvement with low-hanging fruit optimizations ⚡
|
||||
- **Special Character Node ID Handling** - Complex lookahead patterns ✅
|
||||
- **Class/Style Processing** - Vertex creation and class assignment ✅
|
||||
- **Interaction Parameter Passing** - Callback arguments and tooltips ✅
|
||||
- **Node Data Processing** - Shape data pairing with recursive collection ✅
|
||||
- **Markdown Processing** - Nested quote/backtick detection ✅
|
||||
- **Trapezoid Shape Processing** - Complex lexer precedence with semantic predicates ✅
|
||||
- **Ellipse Text Hyphen Processing** - Advanced pattern matching ✅
|
||||
- **Conditional Logging** - Clean output with debug mode support 🔧
|
||||
- **Optimized Performance Tracking** - Minimal overhead for production use ⚡
|
||||
|
||||
#### 🎯 **Sequence Parser Achievements (100% Pass Rate)**
|
||||
|
||||
- **123/123 tests passing** (100% compatibility with Jison parser)
|
||||
- **ZERO FAILING TESTS** - Perfect compatibility achieved! ✅
|
||||
- **Dual-Pattern Architecture** - Both Listener and Visitor patterns working ✨
|
||||
- **Shared Core Logic** - All parsing methods centralized in `SequenceParserCore` ✅
|
||||
- **Runtime Pattern Selection** - Environment variable control (`USE_ANTLR_VISITOR`) ✅
|
||||
- **Performance Monitoring** - Comprehensive logging and performance tracking ⚡
|
||||
- **Error Handling** - Robust error handling matching Jison parser resilience ✅
|
||||
|
||||
### 🎯 Test Coverage
|
||||
|
||||
#### **Flowchart Parser Coverage**
|
||||
|
||||
- Basic flowchart syntax
|
||||
- All node shapes (rectangles, circles, diamonds, stadiums, subroutines, databases, etc.)
|
||||
- Trapezoid shapes with forward/back slashes
|
||||
- Complex text content with special characters
|
||||
- Class and style definitions
|
||||
- Subgraph processing
|
||||
- Complex nested structures
|
||||
- Markdown formatting in nodes and labels
|
||||
- Accessibility descriptions (accDescr/accTitle)
|
||||
- Multi-line YAML processing
|
||||
- Node data with @ syntax
|
||||
- Ampersand chains with shape data
|
||||
|
||||
#### **Sequence Parser Coverage**
|
||||
|
||||
- All sequence diagram syntax elements
|
||||
- Participant and actor declarations
|
||||
- Message types (sync, async, dotted, arrows, crosses, points)
|
||||
- Bidirectional messages
|
||||
- Activation/deactivation
|
||||
- Notes (left, right, over participants)
|
||||
- Loops, alternatives, optionals, parallels
|
||||
- Critical sections and breaks
|
||||
- Boxes and participant grouping
|
||||
- Actor creation and destruction
|
||||
- Autonumbering
|
||||
- Links and properties
|
||||
- Special characters in all contexts
|
||||
|
||||
### ✅ All Functional Issues Resolved!
|
||||
|
||||
**Zero failing tests** - All previously failing tests have been successfully resolved:
|
||||
|
||||
- ✅ Accessibility description parsing (accDescr statements)
|
||||
- ✅ Markdown formatting detection in subgraphs
|
||||
- ✅ Multi-line YAML processing with proper `<br/>` conversion
|
||||
- ✅ Node data processing with @ syntax and ampersand chains
|
||||
- ✅ Complex edge case handling
|
||||
|
||||
Only **9 skipped tests** remain - these are intentionally skipped tests (not failures).
|
||||
|
||||
## 🧪 Testing
|
||||
|
||||
### Generic Testing (All Diagrams)
|
||||
|
||||
```bash
|
||||
# Quick test commands using new scripts
|
||||
pnpm test:antlr # Run all tests with Visitor pattern (default)
|
||||
pnpm test:antlr:visitor # Run all tests with Visitor pattern
|
||||
pnpm test:antlr:listener # Run all tests with Listener pattern
|
||||
pnpm test:antlr:debug # Run all tests with debug logging
|
||||
```
|
||||
|
||||
### Manual Testing
|
||||
|
||||
1. Start the ANTLR dev server: `pnpm dev:antlr`
|
||||
2. Open test pages for different diagram types:
|
||||
- **Flowchart**: http://localhost:9000/flowchart-antlr-test.html
|
||||
- **Sequence**: http://localhost:9000/sequence.html
|
||||
3. Check browser console for detailed logging
|
||||
4. Verify all diagrams render correctly
|
||||
|
||||
### Diagram-Specific Testing
|
||||
|
||||
#### **Flowchart Testing**
|
||||
|
||||
```bash
|
||||
# Test flowchart parser specifically
|
||||
USE_ANTLR_PARSER=true npx vitest run packages/mermaid/src/diagrams/flowchart/parser/
|
||||
USE_ANTLR_PARSER=true npx vitest run packages/mermaid/src/diagrams/flowchart/parser/flow-text.spec.js
|
||||
```
|
||||
|
||||
#### **Sequence Testing**
|
||||
|
||||
```bash
|
||||
# Test sequence parser with both patterns
|
||||
USE_ANTLR_VISITOR=false npx vitest run packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js
|
||||
USE_ANTLR_VISITOR=true npx vitest run packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js
|
||||
```
|
||||
|
||||
## 📁 File Structure
|
||||
|
||||
### Generic ANTLR System
|
||||
|
||||
```
|
||||
scripts/
|
||||
├── antlr-generate.mts # Generic ANTLR generation script
|
||||
└── antlr-watch.mts # ANTLR watch script for grammar development
|
||||
|
||||
.esbuild/
|
||||
├── server-antlr.ts # Dev server with ANTLR watch
|
||||
└── build.ts # Build script with ANTLR integration
|
||||
|
||||
package.json # Root package with postinstall hook
|
||||
packages/mermaid/package.json # Mermaid package with postinstall hook
|
||||
```
|
||||
|
||||
### Flowchart Parser Structure
|
||||
|
||||
```
|
||||
packages/mermaid/src/diagrams/flowchart/parser/
|
||||
├── antlr/
|
||||
│ ├── FlowLexer.g4 # ANTLR lexer grammar
|
||||
│ ├── FlowParser.g4 # ANTLR parser grammar
|
||||
│ ├── antlr-parser.ts # Main ANTLR parser with pattern selection
|
||||
│ ├── FlowchartParserCore.ts # Shared core logic (99.1% compatible)
|
||||
│ ├── FlowchartListener.ts # Listener pattern implementation
|
||||
│ ├── FlowchartVisitor.ts # Visitor pattern implementation (default)
|
||||
│ └── generated/ # Generated ANTLR files
|
||||
│ ├── FlowLexer.ts # Generated lexer
|
||||
│ ├── FlowParser.ts # Generated parser
|
||||
│ ├── FlowParserListener.ts # Generated listener interface
|
||||
│ └── FlowParserVisitor.ts # Generated visitor interface
|
||||
├── flow.jison # Original Jison parser
|
||||
├── flowParser.ts # Parser interface wrapper
|
||||
└── *.spec.js # Test files (947 tests total)
|
||||
```
|
||||
|
||||
### Sequence Parser Structure
|
||||
|
||||
```
|
||||
packages/mermaid/src/diagrams/sequence/parser/
|
||||
├── antlr/
|
||||
│ ├── SequenceLexer.g4 # ANTLR lexer grammar
|
||||
│ ├── SequenceParser.g4 # ANTLR parser grammar
|
||||
│ ├── antlr-parser.ts # Main ANTLR parser with pattern selection
|
||||
│ ├── SequenceParserCore.ts # Shared core logic (100% compatible)
|
||||
│ ├── SequenceListener.ts # Listener pattern implementation
|
||||
│ ├── SequenceVisitor.ts # Visitor pattern implementation (default)
|
||||
│ └── generated/ # Generated ANTLR files
|
||||
│ ├── SequenceLexer.ts # Generated lexer
|
||||
│ ├── SequenceParser.ts # Generated parser
|
||||
│ ├── SequenceParserListener.ts # Generated listener interface
|
||||
│ └── SequenceParserVisitor.ts # Generated visitor interface
|
||||
├── sequenceDiagram.jison # Original Jison parser
|
||||
└── sequenceDiagram.spec.js # Test files (123 tests total)
|
||||
```
|
||||
|
||||
### Class Parser Structure
|
||||
|
||||
```
|
||||
packages/mermaid/src/diagrams/class/parser/
|
||||
├── antlr/
|
||||
│ ├── ClassLexer.g4 # ANTLR lexer grammar
|
||||
│ ├── ClassParser.g4 # ANTLR parser grammar
|
||||
│ └── generated/ # Generated ANTLR files
|
||||
│ ├── ClassLexer.ts # Generated lexer
|
||||
│ ├── ClassParser.ts # Generated parser
|
||||
│ ├── ClassParserListener.ts # Generated listener interface
|
||||
│ └── ClassParserVisitor.ts # Generated visitor interface
|
||||
└── classDiagram.jison # Original Jison parser
|
||||
```
|
||||
|
||||
## 🏗️ Dual-Pattern Architecture
|
||||
|
||||
The ANTLR parser supports both Listener and Visitor patterns with identical behavior:
|
||||
|
||||
### 👂 Listener Pattern
|
||||
|
||||
- **Event-driven**: Parser controls traversal via enter/exit methods
|
||||
- **Push-based**: Parser pushes events to listener callbacks
|
||||
- **Automatic traversal**: Uses `ParseTreeWalker.DEFAULT.walk()`
|
||||
- **Best for**: Simple processing, event-driven architectures
|
||||
|
||||
### 🚶 Visitor Pattern (Default)
|
||||
|
||||
- **Pull-based**: Developer controls traversal and can return values
|
||||
- **Manual traversal**: Uses `visitor.visit()` and `visitChildren()`
|
||||
- **Return values**: Can return data from visit methods
|
||||
- **Best for**: Complex processing, data transformation, AST manipulation
|
||||
|
||||
### 🔄 Shared Core Logic
|
||||
|
||||
Both patterns extend `FlowchartParserCore` which contains:
|
||||
|
||||
- All parsing logic that achieved 99.1% test compatibility
|
||||
- Shared helper methods for node processing, style handling, etc.
|
||||
- Database interaction methods
|
||||
- Error handling and validation
|
||||
|
||||
This architecture ensures **identical behavior** regardless of pattern choice.
|
||||
|
||||
## ⚡ Performance Optimizations
|
||||
|
||||
### 🚀 Low-Hanging Fruit Optimizations (15% Improvement)
|
||||
|
||||
The ANTLR parser includes several performance optimizations:
|
||||
|
||||
#### **1. Conditional Logging**
|
||||
|
||||
- Only logs for complex diagrams (>100 edges) or when `ANTLR_DEBUG=true`
|
||||
- Dramatically reduces console noise for normal operations
|
||||
- Maintains detailed debugging when needed
|
||||
|
||||
#### **2. Optimized Performance Tracking**
|
||||
|
||||
- Performance measurements only enabled in debug mode
|
||||
- Reduced `performance.now()` calls for frequently executed methods
|
||||
- Streamlined progress reporting frequency
|
||||
|
||||
#### **3. Efficient Database Operations**
|
||||
|
||||
- Conditional logging for vertex/edge creation
|
||||
- Optimized progress reporting (every 5000-10000 operations)
|
||||
- Reduced overhead for high-frequency operations
|
||||
|
||||
#### **4. Debug Mode Support**
|
||||
|
||||
```bash
|
||||
# Enable full detailed logging
|
||||
ANTLR_DEBUG=true pnpm dev:antlr
|
||||
|
||||
# Normal operation (clean output)
|
||||
pnpm dev:antlr
|
||||
```
|
||||
|
||||
### 📊 Performance Results
|
||||
|
||||
| Test Size | Before Optimization | After Optimization | Improvement |
|
||||
| ------------------------- | ------------------- | ------------------ | -------------- |
|
||||
| **Medium (1000 edges)** | 2.64s | 2.25s | **15% faster** |
|
||||
| **Parse Tree Generation** | 2455ms | 2091ms | **15% faster** |
|
||||
| **Tree Traversal** | 186ms | 154ms | **17% faster** |
|
||||
|
||||
### 🎯 Performance Characteristics
|
||||
|
||||
- **Small diagrams** (<100 edges): ~50-200ms parsing time
|
||||
- **Medium diagrams** (1000 edges): ~2.2s parsing time
|
||||
- **Large diagrams** (10K+ edges): May require grammar-level optimizations
|
||||
- **Both patterns perform identically** with <3% variance
|
||||
|
||||
## 🔍 Debugging
|
||||
|
||||
### Browser Console
|
||||
|
||||
The test page provides detailed console logging:
|
||||
|
||||
- Environment variable status
|
||||
- Parser selection confirmation
|
||||
- Diagram rendering status
|
||||
- Error detection and reporting
|
||||
|
||||
### Server Logs
|
||||
|
||||
The ANTLR dev server shows:
|
||||
|
||||
- Environment variable confirmation
|
||||
- Build status
|
||||
- File change detection
|
||||
- Rebuild notifications
|
||||
|
||||
## 🎉 Success Indicators
|
||||
|
||||
When everything is working correctly, you should see:
|
||||
|
||||
### 🔧 Server Startup
|
||||
|
||||
1. ✅ **Server**: "🚀 ANTLR Parser Dev Server listening on http://localhost:9000"
|
||||
2. ✅ **Server**: "🎯 Environment: USE_ANTLR_PARSER=true"
|
||||
|
||||
### 🎯 Parser Selection (in browser console)
|
||||
|
||||
3. ✅ **Console**: "🔧 FlowParser: USE_ANTLR_PARSER = true"
|
||||
4. ✅ **Console**: "🔧 FlowParser: Selected parser: ANTLR"
|
||||
|
||||
### 📊 Normal Operation (Clean Output)
|
||||
|
||||
5. ✅ **Browser**: All test diagrams render as SVG elements
|
||||
6. ✅ **Test Page**: Green status indicator showing "ANTLR Parser Active & Rendering Successfully!"
|
||||
7. ✅ **Console**: Minimal logging for small/medium diagrams (optimized)
|
||||
|
||||
### 🐛 Debug Mode (ANTLR_DEBUG=true)
|
||||
|
||||
8. ✅ **Console**: "🎯 ANTLR Parser: Starting parse" (for complex diagrams)
|
||||
9. ✅ **Console**: "🎯 ANTLR Parser: Creating visitor" (or "Creating listener")
|
||||
10. ✅ **Console**: Detailed performance breakdowns and timing information
|
||||
|
||||
## 🚨 Troubleshooting
|
||||
|
||||
### **Build & Generation Issues**
|
||||
|
||||
1. **Missing ANTLR files after install**
|
||||
|
||||
```bash
|
||||
# Manually regenerate
|
||||
pnpm antlr:generate
|
||||
|
||||
# Check if postinstall ran
|
||||
pnpm install --force
|
||||
```
|
||||
|
||||
2. **Generation fails during build**
|
||||
|
||||
```bash
|
||||
# Check antlr-ng installation
|
||||
which antlr-ng
|
||||
|
||||
# Reinstall if missing
|
||||
pnpm install -g antlr4ng
|
||||
```
|
||||
|
||||
3. **No grammar files found**
|
||||
|
||||
- Ensure `.g4` files are in correct location: `src/diagrams/*/parser/antlr/*.g4`
|
||||
- Check file naming convention: `*Lexer.g4`, `*Parser.g4`
|
||||
- Verify you're running from correct directory
|
||||
|
||||
4. **Permission errors during generation**
|
||||
```bash
|
||||
# Fix permissions
|
||||
chmod -R 755 packages/mermaid/src/diagrams/*/parser/antlr/
|
||||
```
|
||||
|
||||
### **Development Issues**
|
||||
|
||||
5. **ANTLR parser not being used**: Check environment variable `USE_ANTLR_PARSER=true`
|
||||
6. **Environment variable not set**: Use `pnpm dev:antlr` instead of `pnpm dev`
|
||||
7. **Diagrams not rendering**: Check browser console for parsing errors
|
||||
8. **Watch not working**:
|
||||
- For dev server: Restart with `pnpm dev:antlr`
|
||||
- For grammar development: Use `pnpm antlr:watch` instead
|
||||
|
||||
### **Grammar Issues**
|
||||
|
||||
9. **ANTLR generation warnings**
|
||||
|
||||
- Check grammar file syntax with ANTLR tools
|
||||
- Compare with working examples in existing diagrams
|
||||
- Warnings are usually non-fatal but should be addressed
|
||||
|
||||
10. **Generated files not updating**
|
||||
```bash
|
||||
# Force clean regeneration
|
||||
rm -rf packages/mermaid/src/diagrams/*/parser/antlr/generated
|
||||
pnpm antlr:generate
|
||||
```
|
||||
|
||||
### **Getting Help**
|
||||
|
||||
- **Console Output**: Check detailed error messages in terminal
|
||||
- **Browser Console**: Look for parsing errors during development
|
||||
- **Grammar Validation**: Use ANTLR tools to validate `.g4` files
|
||||
- **Compare Examples**: Reference working implementations in existing diagrams
|
||||
- **Build Logs**: Review server logs for build issues
|
||||
- **Fresh Start**: Try `pnpm install --force` for clean installation
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Diagram-Specific Guides
|
||||
|
||||
### 📊 Flowchart Parser
|
||||
|
||||
The flowchart ANTLR parser is the most mature implementation with 99.1% test compatibility.
|
||||
|
||||
#### **Key Features**
|
||||
|
||||
- **939/948 tests passing** (99.1% compatibility)
|
||||
- **Dual-pattern architecture** (Listener/Visitor)
|
||||
- **Performance optimized** (15% improvement)
|
||||
- **Complex shape support** (trapezoids, ellipses, etc.)
|
||||
- **Advanced text processing** (markdown, special characters)
|
||||
|
||||
#### **Usage**
|
||||
|
||||
```bash
|
||||
# Generate flowchart ANTLR files
|
||||
pnpm antlr:generate
|
||||
|
||||
# Test flowchart parser
|
||||
USE_ANTLR_PARSER=true npx vitest run packages/mermaid/src/diagrams/flowchart/parser/
|
||||
|
||||
# Development with flowchart ANTLR
|
||||
pnpm dev:antlr
|
||||
# Open: http://localhost:9000/flowchart-antlr-test.html
|
||||
```
|
||||
|
||||
#### **Architecture**
|
||||
|
||||
- `FlowchartParserCore.ts` - Shared parsing logic
|
||||
- `FlowchartListener.ts` - Event-driven pattern
|
||||
- `FlowchartVisitor.ts` - Pull-based pattern (default)
|
||||
|
||||
### 🔄 Sequence Parser
|
||||
|
||||
The sequence ANTLR parser achieves 100% test compatibility with perfect Jison parser matching.
|
||||
|
||||
#### **Key Features**
|
||||
|
||||
- **123/123 tests passing** (100% compatibility)
|
||||
- **Dual-pattern architecture** (Listener/Visitor)
|
||||
- **Runtime pattern selection** via environment variables
|
||||
- **Complete syntax support** (all sequence diagram elements)
|
||||
- **Robust error handling** matching Jison resilience
|
||||
|
||||
#### **Usage**
|
||||
|
||||
```bash
|
||||
# Generate sequence ANTLR files
|
||||
pnpm antlr:generate
|
||||
|
||||
# Test sequence parser with both patterns
|
||||
USE_ANTLR_VISITOR=false npx vitest run packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js
|
||||
USE_ANTLR_VISITOR=true npx vitest run packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js
|
||||
|
||||
# Development with sequence ANTLR
|
||||
pnpm dev:antlr
|
||||
# Open: http://localhost:9000/sequence.html
|
||||
```
|
||||
|
||||
#### **Architecture**
|
||||
|
||||
- `SequenceParserCore.ts` - Shared parsing logic (100% compatible)
|
||||
- `SequenceListener.ts` - Event-driven pattern
|
||||
- `SequenceVisitor.ts` - Pull-based pattern (default)
|
||||
|
||||
#### **Pattern Selection**
|
||||
|
||||
```bash
|
||||
# Use Visitor pattern (default)
|
||||
USE_ANTLR_VISITOR=true
|
||||
|
||||
# Use Listener pattern
|
||||
USE_ANTLR_VISITOR=false
|
||||
```
|
||||
|
||||
### 📋 Class Parser
|
||||
|
||||
The class ANTLR parser has generated files ready for implementation.
|
||||
|
||||
#### **Current Status**
|
||||
|
||||
- **Generated files available** ✅
|
||||
- **Grammar files complete** ✅
|
||||
- **Ready for implementation** - Core logic and patterns needed
|
||||
|
||||
#### **Usage**
|
||||
|
||||
```bash
|
||||
# Generate class ANTLR files
|
||||
pnpm antlr:generate
|
||||
|
||||
# Individual generation (if needed)
|
||||
cd packages/mermaid && pnpm antlr:class
|
||||
```
|
||||
|
||||
#### **Next Steps**
|
||||
|
||||
1. Implement `ClassParserCore.ts` with parsing logic
|
||||
2. Create `ClassListener.ts` and `ClassVisitor.ts` pattern implementations
|
||||
3. Update main parser to use ANTLR with pattern selection
|
||||
4. Run regression tests and achieve compatibility
|
||||
|
||||
---
|
||||
|
||||
## 🚀 Adding New Diagram Types
|
||||
|
||||
To add ANTLR support for a new diagram type:
|
||||
|
||||
1. **Create Grammar Files**
|
||||
|
||||
```
|
||||
packages/mermaid/src/diagrams/[diagram]/parser/antlr/
|
||||
├── [Diagram]Lexer.g4
|
||||
└── [Diagram]Parser.g4
|
||||
```
|
||||
|
||||
2. **Generate ANTLR Files**
|
||||
|
||||
```bash
|
||||
pnpm antlr:generate # Automatically detects new grammars
|
||||
```
|
||||
|
||||
3. **Implement Architecture**
|
||||
|
||||
- Create `[Diagram]ParserCore.ts` with shared logic
|
||||
- Create `[Diagram]Listener.ts` extending core
|
||||
- Create `[Diagram]Visitor.ts` extending core
|
||||
- Update main parser with pattern selection
|
||||
|
||||
4. **Test and Validate**
|
||||
- Run regression tests
|
||||
- Achieve high compatibility with existing Jison parser
|
||||
- Validate both Listener and Visitor patterns
|
||||
|
||||
The generic ANTLR generation system will automatically handle the new diagram type!
|
||||
|
||||
---
|
||||
|
||||
## 🎯 Generic ANTLR Generation System
|
||||
|
||||
### **How It Works**
|
||||
|
||||
#### 1. **Auto-Discovery**
|
||||
|
||||
The script automatically finds all `.g4` files in:
|
||||
|
||||
```
|
||||
packages/mermaid/src/diagrams/*/parser/antlr/*.g4
|
||||
```
|
||||
|
||||
#### 2. **Grammar Pairing**
|
||||
|
||||
For each diagram, it looks for:
|
||||
|
||||
- `*Lexer.g4` - Lexical analyzer grammar
|
||||
- `*Parser.g4` - Parser grammar
|
||||
|
||||
#### 3. **Generation Process**
|
||||
|
||||
For each valid grammar pair:
|
||||
|
||||
1. Clean the `generated/` directory
|
||||
2. Create the directory if needed
|
||||
3. Run `antlr-ng` with TypeScript target
|
||||
4. Generate all necessary files
|
||||
|
||||
#### 4. **Generated Files**
|
||||
|
||||
Each diagram gets these generated files:
|
||||
|
||||
- `*Lexer.ts` - Lexer implementation
|
||||
- `*Parser.ts` - Parser implementation
|
||||
- `*ParserListener.ts` - Listener interface
|
||||
- `*ParserVisitor.ts` - Visitor interface
|
||||
- `*.tokens` - Token definitions
|
||||
- `*.interp` - ANTLR interpreter files
|
||||
|
||||
### **Supported Diagrams**
|
||||
|
||||
| Diagram Type | Grammar Files | Generated Location |
|
||||
| ------------- | --------------------------------------- | ----------------------------------------------------------------- |
|
||||
| **Flowchart** | `FlowLexer.g4`, `FlowParser.g4` | `packages/mermaid/src/diagrams/flowchart/parser/antlr/generated/` |
|
||||
| **Sequence** | `SequenceLexer.g4`, `SequenceParser.g4` | `packages/mermaid/src/diagrams/sequence/parser/antlr/generated/` |
|
||||
| **Class** | `ClassLexer.g4`, `ClassParser.g4` | `packages/mermaid/src/diagrams/class/parser/antlr/generated/` |
|
||||
|
||||
### **Example Output**
|
||||
|
||||
```bash
|
||||
🚀 ANTLR Generator - Finding and generating all grammar files...
|
||||
|
||||
📋 Found 3 diagram(s) with ANTLR grammars:
|
||||
• class
|
||||
• flowchart
|
||||
• sequence
|
||||
|
||||
🎯 Generating ANTLR files for class diagram...
|
||||
Lexer: ClassLexer.g4
|
||||
Parser: ClassParser.g4
|
||||
Output: packages/mermaid/src/diagrams/class/parser/antlr/generated
|
||||
✅ Successfully generated ANTLR files for class
|
||||
|
||||
🎯 Generating ANTLR files for flowchart diagram...
|
||||
Lexer: FlowLexer.g4
|
||||
Parser: FlowParser.g4
|
||||
Output: packages/mermaid/src/diagrams/flowchart/parser/antlr/generated
|
||||
✅ Successfully generated ANTLR files for flowchart
|
||||
|
||||
🎯 Generating ANTLR files for sequence diagram...
|
||||
Lexer: SequenceLexer.g4
|
||||
Parser: SequenceParser.g4
|
||||
Output: packages/mermaid/src/diagrams/sequence/parser/antlr/generated
|
||||
✅ Successfully generated ANTLR files for sequence
|
||||
|
||||
📊 Generation Summary:
|
||||
✅ Successful: 3
|
||||
❌ Failed: 0
|
||||
📁 Total: 3
|
||||
|
||||
🎉 All ANTLR files generated successfully!
|
||||
```
|
||||
|
||||
### **Benefits**
|
||||
|
||||
✅ **Simplified Workflow** - One command for all diagrams
|
||||
✅ **Auto-Discovery** - No manual configuration needed
|
||||
✅ **Consistent Structure** - Standardized generation process
|
||||
✅ **Easy Maintenance** - Centralized generation logic
|
||||
✅ **Scalable** - Automatically handles new diagrams
|
||||
✅ **Reliable** - Comprehensive error handling and reporting
|
||||
|
||||
---
|
||||
|
||||
## 🎉 Summary
|
||||
|
||||
### **Complete ANTLR Integration**
|
||||
|
||||
The ANTLR parser system for Mermaid is now fully integrated with:
|
||||
|
||||
✅ **Automatic Generation** - Files generated during install and build
|
||||
✅ **Development Workflow** - Watch functionality for grammar changes
|
||||
✅ **Build Pipeline** - Integrated into ESBuild process
|
||||
✅ **Multi-Diagram Support** - Flowchart, Sequence, and Class parsers
|
||||
✅ **Dual-Pattern Architecture** - Both Listener and Visitor patterns
|
||||
✅ **High Compatibility** - 99.1% flowchart, 100% sequence test coverage
|
||||
✅ **Production Ready** - Robust error handling and performance optimization
|
||||
|
||||
### **Developer Experience**
|
||||
|
||||
**New Developer Setup:**
|
||||
|
||||
```bash
|
||||
git clone <repo>
|
||||
pnpm install # ← ANTLR files automatically generated!
|
||||
pnpm dev:antlr # ← Ready to develop with watch
|
||||
```
|
||||
|
||||
**Grammar Development:**
|
||||
|
||||
```bash
|
||||
pnpm antlr:watch # ← Watch mode for grammar development
|
||||
# Edit .g4 files → Automatic regeneration!
|
||||
|
||||
# OR with full dev server
|
||||
pnpm dev:antlr # ← Start development server
|
||||
# Edit .g4 files → Automatic regeneration + rebuild!
|
||||
```
|
||||
|
||||
**Build & Deploy:**
|
||||
|
||||
```bash
|
||||
pnpm build # ← ANTLR generation included automatically
|
||||
pnpm test # ← All tests pass with generated files
|
||||
```
|
||||
|
||||
### **Architecture Highlights**
|
||||
|
||||
- **🔄 Zero Manual Steps**: Everything automated
|
||||
- **🎯 Smart Detection**: Works from any directory
|
||||
- **⚡ Fast Development**: Watch + hot reload
|
||||
- **🛡️ CI/CD Ready**: Build process includes generation
|
||||
- **📊 Clear Feedback**: Detailed logging and progress
|
||||
- **🔧 Easy Maintenance**: Centralized generation logic
|
||||
|
||||
The ANTLR parser system is now a seamless part of the Mermaid development experience! 🚀
|
||||
@@ -1 +0,0 @@
|
||||
./packages/mermaid/CHANGELOG.md
|
||||
1005
CHANGELOG.md
Normal file
1005
CHANGELOG.md
Normal file
File diff suppressed because it is too large
Load Diff
@@ -95,6 +95,10 @@ In our release process we rely heavily on visual regression tests using [applito
|
||||
|
||||
<!-- </Main description> -->
|
||||
|
||||
## Mermaid AI Bot
|
||||
|
||||
[Mermaid](https://codeparrot.ai/oracle?owner=mermaid-js&repo=mermaid) Bot will help you understand this repository better. You can ask for code examples, installation guide, debugging help and much more.
|
||||
|
||||
## Examples
|
||||
|
||||
**The following are some examples of the diagrams, charts and graphs that can be made using Mermaid. Click here to jump into the [text syntax](https://mermaid.js.org/intro/syntax-reference.html).**
|
||||
|
||||
13
__mocks__/d3.ts
Normal file
13
__mocks__/d3.ts
Normal file
@@ -0,0 +1,13 @@
|
||||
import { MockedD3 } from '../packages/mermaid/src/tests/MockedD3.js';
|
||||
|
||||
export const select = function () {
|
||||
return new MockedD3();
|
||||
};
|
||||
|
||||
export const selectAll = function () {
|
||||
return new MockedD3();
|
||||
};
|
||||
|
||||
export const curveBasis = 'basis';
|
||||
export const curveLinear = 'linear';
|
||||
export const curveCardinal = 'cardinal';
|
||||
@@ -26,10 +26,7 @@ export default eyesPlugin(
|
||||
config.env.useArgos = process.env.RUN_VISUAL_TEST === 'true';
|
||||
|
||||
if (config.env.useArgos) {
|
||||
registerArgosTask(on, config, {
|
||||
// Enable upload to Argos only when it runs on CI.
|
||||
uploadToArgos: !!process.env.CI,
|
||||
});
|
||||
registerArgosTask(on, config);
|
||||
} else {
|
||||
addMatchImageSnapshotPlugin(on, config);
|
||||
}
|
||||
|
||||
@@ -14,7 +14,7 @@ interface CodeObject {
|
||||
mermaid: CypressMermaidConfig;
|
||||
}
|
||||
|
||||
export const utf8ToB64 = (str: string): string => {
|
||||
const utf8ToB64 = (str: string): string => {
|
||||
return Buffer.from(decodeURIComponent(encodeURIComponent(str))).toString('base64');
|
||||
};
|
||||
|
||||
|
||||
@@ -69,9 +69,7 @@ describe('Configuration', () => {
|
||||
.and('include', 'url(#');
|
||||
});
|
||||
});
|
||||
// This has been broken for a long time, but something about the Cypress environment was
|
||||
// rewriting the URL to be relative, causing the test to incorrectly pass.
|
||||
it.skip('should handle arrowMarkerAbsolute explicitly set to "false" as false', () => {
|
||||
it('should handle arrowMarkerAbsolute explicitly set to "false" as false', () => {
|
||||
renderGraph(
|
||||
`graph TD
|
||||
A[Christmas] -->|Get money| B(Go shopping)
|
||||
@@ -98,12 +96,12 @@ describe('Configuration', () => {
|
||||
it('should handle arrowMarkerAbsolute set to true', () => {
|
||||
renderGraph(
|
||||
`flowchart TD
|
||||
A[Christmas] -->|Get money| B(Go shopping)
|
||||
B --> C{Let me think}
|
||||
C -->|One| D[Laptop]
|
||||
C -->|Two| E[iPhone]
|
||||
C -->|Three| F[fa:fa-car Car]
|
||||
`,
|
||||
A[Christmas] -->|Get money| B(Go shopping)
|
||||
B --> C{Let me think}
|
||||
C -->|One| D[Laptop]
|
||||
C -->|Two| E[iPhone]
|
||||
C -->|Three| F[fa:fa-car Car]
|
||||
`,
|
||||
{
|
||||
arrowMarkerAbsolute: true,
|
||||
}
|
||||
@@ -113,6 +111,7 @@ describe('Configuration', () => {
|
||||
cy.get('path')
|
||||
.first()
|
||||
.should('have.attr', 'marker-end')
|
||||
.should('exist')
|
||||
.and('include', 'url(http://localhost');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
import { imgSnapshotTest, mermaidUrl, utf8ToB64 } from '../../helpers/util.ts';
|
||||
import { mermaidUrl } from '../../helpers/util.ts';
|
||||
describe('XSS', () => {
|
||||
it('should handle xss in tags', () => {
|
||||
const str =
|
||||
@@ -141,37 +141,4 @@ describe('XSS', () => {
|
||||
cy.wait(1000);
|
||||
cy.get('#the-malware').should('not.exist');
|
||||
});
|
||||
|
||||
it('should sanitize icon labels in architecture diagrams', () => {
|
||||
const str = JSON.stringify({
|
||||
code: `architecture-beta
|
||||
group api(cloud)[API]
|
||||
service db "<img src=x onerror=\\"xssAttack()\\">" [Database] in api`,
|
||||
});
|
||||
imgSnapshotTest(utf8ToB64(str), {}, true);
|
||||
cy.wait(1000);
|
||||
cy.get('#the-malware').should('not.exist');
|
||||
});
|
||||
|
||||
it('should sanitize katex blocks', () => {
|
||||
const str = JSON.stringify({
|
||||
code: `sequenceDiagram
|
||||
participant A as Alice<img src="x" onerror="xssAttack()">$$\\text{Alice}$$
|
||||
A->>John: Hello John, how are you?`,
|
||||
});
|
||||
imgSnapshotTest(utf8ToB64(str), {}, true);
|
||||
cy.wait(1000);
|
||||
cy.get('#the-malware').should('not.exist');
|
||||
});
|
||||
|
||||
it('should sanitize labels', () => {
|
||||
const str = JSON.stringify({
|
||||
code: `erDiagram
|
||||
"<img src=x onerror=xssAttack()>" ||--|| ENTITY2 : "<img src=x onerror=xssAttack()>"
|
||||
`,
|
||||
});
|
||||
imgSnapshotTest(utf8ToB64(str), {}, true);
|
||||
cy.wait(1000);
|
||||
cy.get('#the-malware').should('not.exist');
|
||||
});
|
||||
});
|
||||
|
||||
@@ -16,7 +16,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL2: should handle columns statement in sub-blocks', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
id1["Hello"]
|
||||
block
|
||||
columns 3
|
||||
@@ -32,7 +32,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL3: should align block widths and handle columns statement in sub-blocks', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
block
|
||||
columns 1
|
||||
id1
|
||||
@@ -48,7 +48,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL4: should align block widths and handle columns statements in deeper sub-blocks then 1 level', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
columns 1
|
||||
block
|
||||
columns 1
|
||||
@@ -68,7 +68,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL5: should align block widths and handle columns statements in deeper sub-blocks then 1 level (alt)', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
columns 1
|
||||
block
|
||||
id1
|
||||
@@ -87,7 +87,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL6: should handle block arrows and spece statements', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
columns 3
|
||||
space:3
|
||||
ida idb idc
|
||||
@@ -106,7 +106,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL7: should handle different types of edges', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
columns 3
|
||||
A space:5
|
||||
A --o B
|
||||
@@ -119,7 +119,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL8: should handle sub-blocks without columns statements', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
columns 2
|
||||
C A B
|
||||
block
|
||||
@@ -133,7 +133,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL9: should handle edges from blocks in sub blocks to other blocks', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
columns 3
|
||||
B space
|
||||
block
|
||||
@@ -147,7 +147,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL10: should handle edges from composite blocks', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
columns 3
|
||||
B space
|
||||
block BL
|
||||
@@ -161,7 +161,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL11: should handle edges to composite blocks', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
columns 3
|
||||
B space
|
||||
block BL
|
||||
@@ -175,7 +175,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL12: edges should handle labels', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
A
|
||||
space
|
||||
A -- "apa" --> E
|
||||
@@ -186,7 +186,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL13: should handle block arrows in different directions', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
columns 3
|
||||
space blockArrowId1<["down"]>(down) space
|
||||
blockArrowId2<["right"]>(right) blockArrowId3<["Sync"]>(x, y) blockArrowId4<["left"]>(left)
|
||||
@@ -199,7 +199,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL14: should style statements and class statements', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
A
|
||||
B
|
||||
classDef blue fill:#66f,stroke:#333,stroke-width:2px;
|
||||
@@ -212,7 +212,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL15: width alignment - D and E should share available space', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
block
|
||||
D
|
||||
E
|
||||
@@ -225,7 +225,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL16: width alignment - C should be as wide as the composite block', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
block
|
||||
A("This is the text")
|
||||
B
|
||||
@@ -238,7 +238,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL17: width alignment - blocks should be equal in width', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
A("This is the text")
|
||||
B
|
||||
C
|
||||
@@ -249,7 +249,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL18: block types 1 - square, rounded and circle', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
A["square"]
|
||||
B("rounded")
|
||||
C(("circle"))
|
||||
@@ -260,7 +260,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL19: block types 2 - odd, diamond and hexagon', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
A>"rect_left_inv_arrow"]
|
||||
B{"diamond"}
|
||||
C{{"hexagon"}}
|
||||
@@ -271,7 +271,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL20: block types 3 - stadium', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
A(["stadium"])
|
||||
`,
|
||||
{}
|
||||
@@ -280,7 +280,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL21: block types 4 - lean right, lean left, trapezoid and inv trapezoid', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
A[/"lean right"/]
|
||||
B[\"lean left"\]
|
||||
C[/"trapezoid"\]
|
||||
@@ -292,7 +292,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL22: block types 1 - square, rounded and circle', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
A["square"]
|
||||
B("rounded")
|
||||
C(("circle"))
|
||||
@@ -303,7 +303,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL23: sizing - it should be possible to make a block wider', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
A("rounded"):2
|
||||
B:2
|
||||
C
|
||||
@@ -314,7 +314,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL24: sizing - it should be possible to make a composite block wider', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
block:2
|
||||
A
|
||||
end
|
||||
@@ -326,7 +326,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL25: block in the middle with space on each side', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
columns 3
|
||||
space
|
||||
middle["In the middle"]
|
||||
@@ -337,7 +337,7 @@ describe('Block diagram', () => {
|
||||
});
|
||||
it('BL26: space and an edge', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
columns 5
|
||||
A space B
|
||||
A --x B
|
||||
@@ -347,7 +347,7 @@ describe('Block diagram', () => {
|
||||
});
|
||||
it('BL27: block sizes for regular blocks', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
columns 3
|
||||
a["A wide one"] b:2 c:2 d
|
||||
`,
|
||||
@@ -356,7 +356,7 @@ describe('Block diagram', () => {
|
||||
});
|
||||
it('BL28: composite block with a set width - f should use the available space', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
columns 3
|
||||
a:3
|
||||
block:e:3
|
||||
@@ -370,7 +370,7 @@ describe('Block diagram', () => {
|
||||
|
||||
it('BL29: composite block with a set width - f and g should split the available space', () => {
|
||||
imgSnapshotTest(
|
||||
`block
|
||||
`block-beta
|
||||
columns 3
|
||||
a:3
|
||||
block:e:3
|
||||
@@ -384,28 +384,4 @@ describe('Block diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('BL30: block should overflow if too wide for columns', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
columns 2
|
||||
fit:2
|
||||
overflow:3
|
||||
short:1
|
||||
also_overflow:2
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('BL31: edge without arrow syntax should render with no arrowheads', () => {
|
||||
imgSnapshotTest(
|
||||
`block-beta
|
||||
a
|
||||
b
|
||||
a --- b
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -495,47 +495,4 @@ describe('Class diagram', () => {
|
||||
cy.get('a').should('have.attr', 'target', '_blank').should('have.attr', 'rel', 'noopener');
|
||||
});
|
||||
});
|
||||
|
||||
describe('Include char sequence "graph" in text (#6795)', () => {
|
||||
it('has a label with char sequence "graph"', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
classDiagram
|
||||
class Person {
|
||||
+String name
|
||||
-Int id
|
||||
#double age
|
||||
+Text demographicProfile
|
||||
}
|
||||
`,
|
||||
{ flowchart: { defaultRenderer: 'elk' } }
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('should handle backticks for namespace and class names', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
classDiagram
|
||||
namespace \`A::B\` {
|
||||
class \`IPC::Sender\`
|
||||
}
|
||||
RenderProcessHost --|> \`IPC::Sender\`
|
||||
`,
|
||||
{}
|
||||
);
|
||||
it('should handle an empty class body with empty braces', () => {
|
||||
imgSnapshotTest(
|
||||
` classDiagram
|
||||
class FooBase~T~ {}
|
||||
class Bar {
|
||||
+Zip
|
||||
+Zap()
|
||||
}
|
||||
FooBase <|-- Ba
|
||||
`,
|
||||
{ flowchart: { defaultRenderer: 'elk' } }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -354,19 +354,4 @@ ORDER ||--|{ LINE-ITEM : contains
|
||||
{ logLevel: 1 }
|
||||
);
|
||||
});
|
||||
|
||||
describe('Include char sequence "graph" in text (#6795)', () => {
|
||||
it('has a label with char sequence "graph"', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
erDiagram
|
||||
p[Photograph] {
|
||||
varchar(12) jobId
|
||||
date dateCreated
|
||||
}
|
||||
`,
|
||||
{ flowchart: { defaultRenderer: 'elk' } }
|
||||
);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -109,7 +109,7 @@ describe('Flowchart ELK', () => {
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
verifyNumber(maxWidthValue, 380, 15);
|
||||
verifyNumber(maxWidthValue, 380);
|
||||
});
|
||||
});
|
||||
it('8-elk: should render a flowchart when useMaxWidth is false', () => {
|
||||
@@ -128,7 +128,7 @@ describe('Flowchart ELK', () => {
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
verifyNumber(width, 380, 15);
|
||||
verifyNumber(width, 380);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
@@ -1053,21 +1053,6 @@ flowchart LR
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
it('6647-elk: should keep node order when using elk layout unless it would add crossings', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart TB
|
||||
a --> a1 & a2 & a3 & a4
|
||||
b --> b1 & b2
|
||||
b2 --> b3
|
||||
b1 --> b4
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('Title and arrow styling #4813', () => {
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
const themes = ['default', 'forest', 'dark', 'base', 'neutral'];
|
||||
|
||||
describe('when rendering flowchart with icons', () => {
|
||||
for (const theme of themes) {
|
||||
it(`should render icons from fontawesome library on theme ${theme}`, () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TD
|
||||
A("fab:fa-twitter Twitter") --> B("fab:fa-facebook Facebook")
|
||||
B --> C("fa:fa-coffee Coffee")
|
||||
C --> D("fa:fa-car Car")
|
||||
D --> E("fab:fa-github GitHub")
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
});
|
||||
|
||||
it(`should render registered icons on theme ${theme}`, () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TD
|
||||
A("fa:fa-bell Bell")
|
||||
`,
|
||||
{ theme }
|
||||
);
|
||||
});
|
||||
}
|
||||
});
|
||||
@@ -99,7 +99,7 @@ describe('Flowchart v2', () => {
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
expect(maxWidthValue).to.be.within(440 * 0.95, 440 * 1.05);
|
||||
expect(maxWidthValue).to.be.within(417 * 0.95, 417 * 1.05);
|
||||
});
|
||||
});
|
||||
it('8: should render a flowchart when useMaxWidth is false', () => {
|
||||
@@ -118,7 +118,7 @@ describe('Flowchart v2', () => {
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
// use within because the absolute value can be slightly different depending on the environment ±5%
|
||||
// expect(height).to.be.within(446 * 0.95, 446 * 1.05);
|
||||
expect(width).to.be.within(440 * 0.95, 440 * 1.05);
|
||||
expect(width).to.be.within(417 * 0.95, 417 * 1.05);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
@@ -1113,90 +1113,4 @@ end
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('Flowchart Node Shape Rendering', () => {
|
||||
it('should render a stadium-shaped node', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TB
|
||||
A(["Start"]) --> n1["Untitled Node"]
|
||||
A --> n2["Untitled Node"]
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should render a diamond-shaped node using shape config', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart BT
|
||||
n2["Untitled Node"] --> n1["Diamond"]
|
||||
n1@{ shape: diam}
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should render a rounded rectangle and a normal rectangle', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart BT
|
||||
n2["Untitled Node"] --> n1["Rounded Rectangle"]
|
||||
n3["Untitled Node"] --> n1
|
||||
n1@{ shape: rounded}
|
||||
n3@{ shape: rect}
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
it('6617: Per Link Curve Styling using edge Ids', () => {
|
||||
imgSnapshotTest(
|
||||
`flowchart TD
|
||||
A e1@-->B e5@--> E
|
||||
E e7@--> D
|
||||
B e3@-->D
|
||||
A e2@-->C e4@-->D
|
||||
C e6@--> F
|
||||
F e8@--> D
|
||||
e1@{ curve: natural }
|
||||
e2@{ curve: stepAfter }
|
||||
e3@{ curve: monotoneY }
|
||||
e4@{ curve: bumpY }
|
||||
e5@{ curve: linear }
|
||||
e6@{ curve: catmullRom }
|
||||
e7@{ curve: cardinal }
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
describe('when rendering unsuported markdown', () => {
|
||||
const graph = `flowchart TB
|
||||
mermaid{"What is\nyourmermaid version?"} --> v10["<11"] --"\`<**1**1\`"--> fine["No bug"]
|
||||
mermaid --> v11[">= v11"] -- ">= v11" --> broken["Affected by https://github.com/mermaid-js/mermaid/issues/5824"]
|
||||
subgraph subgraph1["\`How to fix **fix**\`"]
|
||||
broken --> B["B"]
|
||||
end
|
||||
githost["Github, Gitlab, BitBucket, etc."]
|
||||
githost2["\`Github, Gitlab, BitBucket, etc.\`"]
|
||||
a["1."]
|
||||
b["- x"]
|
||||
`;
|
||||
|
||||
it('should render raw strings', () => {
|
||||
imgSnapshotTest(graph);
|
||||
});
|
||||
|
||||
it('should render raw strings with htmlLabels: false', () => {
|
||||
imgSnapshotTest(graph, { htmlLabels: false });
|
||||
});
|
||||
});
|
||||
|
||||
it('V2 - 17: should apply class def colour to edge label', () => {
|
||||
imgSnapshotTest(
|
||||
` graph LR
|
||||
id1(Start) link@-- "Label" -->id2(Stop)
|
||||
style id1 fill:#f9f,stroke:#333,stroke-width:4px
|
||||
|
||||
class id2 myClass
|
||||
classDef myClass fill:#bbf,stroke:#f66,stroke-width:2px,color:white,stroke-dasharray: 5 5
|
||||
class link myClass
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -934,43 +934,4 @@ graph TD
|
||||
}
|
||||
);
|
||||
});
|
||||
it('68: should honor subgraph direction when inheritDir is false', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
%%{init: {"flowchart": { "inheritDir": false }}}%%
|
||||
flowchart TB
|
||||
direction LR
|
||||
subgraph A
|
||||
direction TB
|
||||
a --> b
|
||||
end
|
||||
subgraph B
|
||||
c --> d
|
||||
end
|
||||
`,
|
||||
{
|
||||
fontFamily: 'courier',
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('69: should inherit global direction when inheritDir is true', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
%%{init: {"flowchart": { "inheritDir": true }}}%%
|
||||
flowchart TB
|
||||
direction LR
|
||||
subgraph A
|
||||
direction TB
|
||||
a --> b
|
||||
end
|
||||
subgraph B
|
||||
c --> d
|
||||
end
|
||||
`,
|
||||
{
|
||||
fontFamily: 'courier',
|
||||
}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -358,23 +358,6 @@ describe('Gantt diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a gantt diagram with a vert tag', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gantt
|
||||
title A Gantt Diagram
|
||||
dateFormat ss
|
||||
axisFormat %Ss
|
||||
|
||||
section Section
|
||||
A task : a1, 00, 6s
|
||||
Milestone : vert, 01,
|
||||
section Another
|
||||
Task in sec : 06, 3s
|
||||
another task : 3s
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render a gantt diagram with tick is 2 milliseconds', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
@@ -565,18 +548,6 @@ describe('Gantt diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should render only the day when using dateFormat D', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gantt
|
||||
title Test
|
||||
dateFormat D
|
||||
A :a, 1, 1d
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
// TODO: fix it
|
||||
//
|
||||
// This test is skipped deliberately
|
||||
@@ -659,49 +630,6 @@ describe('Gantt diagram', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a gantt diagram excluding a specific date in YYYY-MM-DD HH:mm:ss format', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gantt
|
||||
dateFormat YYYY-MM-DD HH:mm:ss
|
||||
excludes 2025-07-07
|
||||
section Section
|
||||
A task :a1, 2025-07-04 20:30:30, 2025-07-08 10:30:30
|
||||
Another task:after a1, 20h
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a gantt diagram excluding saturday and sunday in YYYY-MM-DD HH:mm:ss format', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gantt
|
||||
dateFormat YYYY-MM-DD HH:mm:ss
|
||||
excludes weekends
|
||||
weekend saturday
|
||||
section Section
|
||||
A task :a1, 2025-07-04 20:30:30, 2025-07-08 10:30:30
|
||||
Another task:after a1, 20h
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should render a gantt diagram excluding friday and saturday in YYYY-MM-DD HH:mm:ss format', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
gantt
|
||||
dateFormat YYYY-MM-DD HH:mm:ss
|
||||
excludes weekends
|
||||
weekend friday
|
||||
section Section
|
||||
A task :a1, 2025-07-04 20:30:30, 2025-07-08 10:30:30
|
||||
Another task:after a1, 20h
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it("should render when there's a semicolon in the title", () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
|
||||
@@ -14,7 +14,7 @@ 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'}`, () => {
|
||||
describe(`Test iconShape in ${form ? `${form} form,` : ''} ${look} look and dir ${direction} with label position ${pos ?? 'not defined'}`, () => {
|
||||
it(`without label`, () => {
|
||||
let flowchartCode = `flowchart ${direction}\n`;
|
||||
flowchartCode += ` nA --> nAA@{ icon: 'fa:bell'`;
|
||||
|
||||
@@ -12,7 +12,7 @@ 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'}`, () => {
|
||||
describe(`Test imageShape in ${look} look and dir ${direction} with label position ${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`;
|
||||
|
||||
@@ -214,7 +214,7 @@ section Checkout from website
|
||||
$lines.each((index, el) => {
|
||||
const bbox = el.getBBox();
|
||||
expect(bbox.width).to.be.lte(320);
|
||||
maxLineWidth = Math.max(maxLineWidth || 0, bbox.width);
|
||||
maxLineWidth = Math.max(maxLineWidth ?? 0, bbox.width);
|
||||
});
|
||||
|
||||
/** The expected margin between the diagram and the legend is 150px, as defined by
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe('Mindmap Tidy Tree', () => {
|
||||
it('1-tidy-tree: should render a simple mindmap without children', () => {
|
||||
imgSnapshotTest(
|
||||
` ---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
A
|
||||
B
|
||||
`
|
||||
);
|
||||
});
|
||||
it('2-tidy-tree: should render a simple mindmap', () => {
|
||||
imgSnapshotTest(
|
||||
` ---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
root((mindmap is a long thing))
|
||||
A
|
||||
B
|
||||
C
|
||||
D
|
||||
`
|
||||
);
|
||||
});
|
||||
it('3-tidy-tree: should render a mindmap with different shapes', () => {
|
||||
imgSnapshotTest(
|
||||
` ---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
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
|
||||
id)I am a cloud(
|
||||
id))I am a bang((
|
||||
Tools
|
||||
`
|
||||
);
|
||||
});
|
||||
it('4-tidy-tree: should render a mindmap with children', () => {
|
||||
imgSnapshotTest(
|
||||
` ---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
((This is a mindmap))
|
||||
child1
|
||||
grandchild 1
|
||||
grandchild 2
|
||||
child2
|
||||
grandchild 3
|
||||
grandchild 4
|
||||
child3
|
||||
grandchild 5
|
||||
grandchild 6
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -159,10 +159,12 @@ root
|
||||
});
|
||||
it('square shape', () => {
|
||||
imgSnapshotTest(
|
||||
`mindmap
|
||||
`
|
||||
mindmap
|
||||
root[
|
||||
The root
|
||||
]`,
|
||||
]
|
||||
`,
|
||||
{},
|
||||
undefined,
|
||||
shouldHaveRoot
|
||||
@@ -170,10 +172,12 @@ root
|
||||
});
|
||||
it('rounded rect shape', () => {
|
||||
imgSnapshotTest(
|
||||
`mindmap
|
||||
`
|
||||
mindmap
|
||||
root((
|
||||
The root
|
||||
))`,
|
||||
))
|
||||
`,
|
||||
{},
|
||||
undefined,
|
||||
shouldHaveRoot
|
||||
@@ -181,10 +185,12 @@ root
|
||||
});
|
||||
it('circle shape', () => {
|
||||
imgSnapshotTest(
|
||||
`mindmap
|
||||
`
|
||||
mindmap
|
||||
root(
|
||||
The root
|
||||
)`,
|
||||
)
|
||||
`,
|
||||
{},
|
||||
undefined,
|
||||
shouldHaveRoot
|
||||
@@ -192,8 +198,10 @@ root
|
||||
});
|
||||
it('default shape', () => {
|
||||
imgSnapshotTest(
|
||||
`mindmap
|
||||
The root`,
|
||||
`
|
||||
mindmap
|
||||
The root
|
||||
`,
|
||||
{},
|
||||
undefined,
|
||||
shouldHaveRoot
|
||||
@@ -201,10 +209,12 @@ root
|
||||
});
|
||||
it('adding children', () => {
|
||||
imgSnapshotTest(
|
||||
`mindmap
|
||||
`
|
||||
mindmap
|
||||
The root
|
||||
child1
|
||||
child2`,
|
||||
child2
|
||||
`,
|
||||
{},
|
||||
undefined,
|
||||
shouldHaveRoot
|
||||
@@ -212,11 +222,13 @@ root
|
||||
});
|
||||
it('adding grand children', () => {
|
||||
imgSnapshotTest(
|
||||
`mindmap
|
||||
`
|
||||
mindmap
|
||||
The root
|
||||
child1
|
||||
child2
|
||||
child3`,
|
||||
child3
|
||||
`,
|
||||
{},
|
||||
undefined,
|
||||
shouldHaveRoot
|
||||
@@ -228,22 +240,9 @@ root
|
||||
`mindmap
|
||||
id1[\`**Start** with
|
||||
a second line 😎\`]
|
||||
id2[\`The dog in **the** hog... a *very long text* about it Word!\`]`
|
||||
);
|
||||
});
|
||||
});
|
||||
describe('Include char sequence "graph" in text (#6795)', () => {
|
||||
it('has a label with char sequence "graph"', () => {
|
||||
imgSnapshotTest(
|
||||
` mindmap
|
||||
root
|
||||
Photograph
|
||||
Waterfall
|
||||
Landscape
|
||||
Geography
|
||||
Mountains
|
||||
Rocks`,
|
||||
{ flowchart: { defaultRenderer: 'elk' } }
|
||||
id2[\`The dog in **the** hog... a *very long text* about it
|
||||
Word!\`]
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util';
|
||||
|
||||
describe('packet structure', () => {
|
||||
it('should render a simple packet-beta diagram', () => {
|
||||
it('should render a simple packet diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`packet-beta
|
||||
title Hello world
|
||||
@@ -10,18 +10,9 @@ describe('packet structure', () => {
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a simple packet diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`packet
|
||||
title Hello world
|
||||
0-10: "hello"
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('should render a simple packet diagram without ranges', () => {
|
||||
imgSnapshotTest(
|
||||
`packet
|
||||
`packet-beta
|
||||
0: "h"
|
||||
1: "i"
|
||||
`
|
||||
@@ -30,7 +21,7 @@ describe('packet structure', () => {
|
||||
|
||||
it('should render a complex packet diagram', () => {
|
||||
imgSnapshotTest(
|
||||
`packet
|
||||
`packet-beta
|
||||
0-15: "Source Port"
|
||||
16-31: "Destination Port"
|
||||
32-63: "Sequence Number"
|
||||
@@ -61,7 +52,7 @@ describe('packet structure', () => {
|
||||
packet:
|
||||
showBits: false
|
||||
---
|
||||
packet
|
||||
packet-beta
|
||||
0-15: "Source Port"
|
||||
16-31: "Destination Port"
|
||||
32-63: "Sequence Number"
|
||||
|
||||
@@ -82,13 +82,4 @@ describe('pie chart', () => {
|
||||
`
|
||||
);
|
||||
});
|
||||
it('should render pie slices only for non-zero values but shows all legends', () => {
|
||||
imgSnapshotTest(
|
||||
` pie title Pets adopted by volunteers
|
||||
"Dogs" : 386
|
||||
"Cats" : 85
|
||||
"Rats" : 1
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -15,7 +15,7 @@ describe('Sankey Diagram', () => {
|
||||
describe('when given a linkColor', function () {
|
||||
this.beforeAll(() => {
|
||||
cy.wrap(
|
||||
`sankey
|
||||
`sankey-beta
|
||||
a,b,10
|
||||
`
|
||||
).as('graph');
|
||||
@@ -62,7 +62,7 @@ describe('Sankey Diagram', () => {
|
||||
this.beforeAll(() => {
|
||||
cy.wrap(
|
||||
`
|
||||
sankey
|
||||
sankey-beta
|
||||
|
||||
a,b,8
|
||||
b,c,8
|
||||
|
||||
@@ -1,659 +0,0 @@
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
const looks = ['classic'];
|
||||
const participantTypes = [
|
||||
{ type: 'participant', display: 'participant' },
|
||||
{ type: 'actor', display: 'actor' },
|
||||
{ type: 'boundary', display: 'boundary' },
|
||||
{ type: 'control', display: 'control' },
|
||||
{ type: 'entity', display: 'entity' },
|
||||
{ type: 'database', display: 'database' },
|
||||
{ type: 'collections', display: 'collections' },
|
||||
{ type: 'queue', display: 'queue' },
|
||||
];
|
||||
|
||||
const restrictedTypes = ['boundary', 'control', 'entity', 'database', 'collections', 'queue'];
|
||||
|
||||
const interactionTypes = ['->>', '-->>', '->', '-->', '-x', '--x', '->>+', '-->>+'];
|
||||
|
||||
const notePositions = ['left of', 'right of', 'over'];
|
||||
|
||||
function getParticipantLine(name, type, alias) {
|
||||
if (restrictedTypes.includes(type)) {
|
||||
return ` participant ${name}@{ "type" : "${type}" }\n`;
|
||||
} else if (alias) {
|
||||
return ` participant ${name}@{ "type" : "${type}" } \n`;
|
||||
} else {
|
||||
return ` participant ${name}@{ "type" : "${type}" }\n`;
|
||||
}
|
||||
}
|
||||
|
||||
looks.forEach((look) => {
|
||||
describe(`Sequence Diagram Tests - ${look} look`, () => {
|
||||
it('should render all participant types', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
participantTypes.forEach((pt, index) => {
|
||||
const name = `${pt.display}${index}`;
|
||||
diagramCode += getParticipantLine(name, pt.type);
|
||||
});
|
||||
for (let i = 0; i < participantTypes.length - 1; i++) {
|
||||
diagramCode += ` ${participantTypes[i].display}${i} ->> ${participantTypes[i + 1].display}${i + 1}: Message ${i}\n`;
|
||||
}
|
||||
imgSnapshotTest(diagramCode, { look, sequence: { diagramMarginX: 50, diagramMarginY: 10 } });
|
||||
});
|
||||
|
||||
it('should render all interaction types', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
diagramCode += getParticipantLine('A', 'actor');
|
||||
diagramCode += getParticipantLine('B', 'boundary');
|
||||
interactionTypes.forEach((interaction, index) => {
|
||||
diagramCode += ` A ${interaction} B: ${interaction} message ${index}\n`;
|
||||
});
|
||||
imgSnapshotTest(diagramCode, { look });
|
||||
});
|
||||
|
||||
it('should render participant creation and destruction', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
participantTypes.forEach((pt, index) => {
|
||||
const name = `${pt.display}${index}`;
|
||||
diagramCode += getParticipantLine('A', pt.type);
|
||||
diagramCode += getParticipantLine('B', pt.type);
|
||||
diagramCode += ` create participant ${name}@{ "type" : "${pt.type}" }\n`;
|
||||
diagramCode += ` A ->> ${name}: Hello ${pt.display}\n`;
|
||||
if (index % 2 === 0) {
|
||||
diagramCode += ` destroy ${name}\n`;
|
||||
}
|
||||
});
|
||||
imgSnapshotTest(diagramCode, { look });
|
||||
});
|
||||
|
||||
it('should render notes in all positions', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
diagramCode += getParticipantLine('A', 'actor');
|
||||
diagramCode += getParticipantLine('B', 'boundary');
|
||||
notePositions.forEach((position, index) => {
|
||||
diagramCode += ` Note ${position} A: Note ${position} ${index}\n`;
|
||||
});
|
||||
diagramCode += ` A ->> B: Message with notes\n`;
|
||||
imgSnapshotTest(diagramCode, { look });
|
||||
});
|
||||
|
||||
it('should render parallel interactions', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
participantTypes.slice(0, 4).forEach((pt, index) => {
|
||||
diagramCode += getParticipantLine(`${pt.display}${index}`, pt.type);
|
||||
});
|
||||
diagramCode += ` par Parallel actions\n`;
|
||||
for (let i = 0; i < 3; i += 2) {
|
||||
diagramCode += ` ${participantTypes[i].display}${i} ->> ${participantTypes[i + 1].display}${i + 1}: Message ${i}\n`;
|
||||
if (i < participantTypes.length - 2) {
|
||||
diagramCode += ` and\n`;
|
||||
}
|
||||
}
|
||||
diagramCode += ` end\n`;
|
||||
imgSnapshotTest(diagramCode, { look });
|
||||
});
|
||||
|
||||
it('should render alternative flows', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
diagramCode += getParticipantLine('A', 'actor');
|
||||
diagramCode += getParticipantLine('B', 'boundary');
|
||||
diagramCode += ` alt Successful case\n`;
|
||||
diagramCode += ` A ->> B: Request\n`;
|
||||
diagramCode += ` B -->> A: Success\n`;
|
||||
diagramCode += ` else Failure case\n`;
|
||||
diagramCode += ` A ->> B: Request\n`;
|
||||
diagramCode += ` B --x A: Failure\n`;
|
||||
diagramCode += ` end\n`;
|
||||
imgSnapshotTest(diagramCode, { look });
|
||||
});
|
||||
|
||||
it('should render loops', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
participantTypes.slice(0, 3).forEach((pt, index) => {
|
||||
diagramCode += getParticipantLine(`${pt.display}${index}`, pt.type);
|
||||
});
|
||||
diagramCode += ` loop For each participant\n`;
|
||||
for (let i = 0; i < 3; i++) {
|
||||
diagramCode += ` ${participantTypes[0].display}0 ->> ${participantTypes[1].display}1: Message ${i}\n`;
|
||||
}
|
||||
diagramCode += ` end\n`;
|
||||
imgSnapshotTest(diagramCode, { look });
|
||||
});
|
||||
|
||||
it('should render boxes around groups', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
diagramCode += ` box Group 1\n`;
|
||||
participantTypes.slice(0, 3).forEach((pt, index) => {
|
||||
diagramCode += ` ${getParticipantLine(`${pt.display}${index}`, pt.type)}`;
|
||||
});
|
||||
diagramCode += ` end\n`;
|
||||
diagramCode += ` box rgb(200,220,255) Group 2\n`;
|
||||
participantTypes.slice(3, 6).forEach((pt, index) => {
|
||||
diagramCode += ` ${getParticipantLine(`${pt.display}${index}`, pt.type)}`;
|
||||
});
|
||||
diagramCode += ` end\n`;
|
||||
diagramCode += ` ${participantTypes[0].display}0 ->> ${participantTypes[3].display}0: Cross-group message\n`;
|
||||
imgSnapshotTest(diagramCode, { look });
|
||||
});
|
||||
|
||||
it('should render with different font settings', () => {
|
||||
let diagramCode = `sequenceDiagram\n`;
|
||||
participantTypes.slice(0, 3).forEach((pt, index) => {
|
||||
diagramCode += getParticipantLine(`${pt.display}${index}`, pt.type);
|
||||
});
|
||||
diagramCode += ` ${participantTypes[0].display}0 ->> ${participantTypes[1].display}1: Regular message\n`;
|
||||
diagramCode += ` Note right of ${participantTypes[1].display}1: Regular note\n`;
|
||||
imgSnapshotTest(diagramCode, {
|
||||
look,
|
||||
sequence: {
|
||||
actorFontFamily: 'courier',
|
||||
actorFontSize: 14,
|
||||
messageFontFamily: 'Arial',
|
||||
messageFontSize: 12,
|
||||
noteFontFamily: 'times',
|
||||
noteFontSize: 16,
|
||||
noteAlign: 'left',
|
||||
},
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
// Additional tests for specific combinations
|
||||
describe('Sequence Diagram Special Cases', () => {
|
||||
it('should render complex sequence with all features', () => {
|
||||
const diagramCode = `
|
||||
sequenceDiagram
|
||||
box rgb(200,220,255) Authentication
|
||||
actor User
|
||||
participant LoginUI@{ "type": "boundary" }
|
||||
participant AuthService@{ "type": "control" }
|
||||
participant UserDB@{ "type": "database" }
|
||||
end
|
||||
|
||||
box rgb(200,255,220) Order Processing
|
||||
participant Order@{ "type": "entity" }
|
||||
participant OrderQueue@{ "type": "queue" }
|
||||
participant AuditLogs@{ "type": "collections" }
|
||||
end
|
||||
|
||||
User ->> LoginUI: Enter credentials
|
||||
LoginUI ->> AuthService: Validate
|
||||
AuthService ->> UserDB: Query user
|
||||
UserDB -->> AuthService: User data
|
||||
alt Valid credentials
|
||||
AuthService -->> LoginUI: Success
|
||||
LoginUI -->> User: Welcome
|
||||
|
||||
par Place order
|
||||
User ->> Order: New order
|
||||
Order ->> OrderQueue: Process
|
||||
and
|
||||
Order ->> AuditLogs: Record
|
||||
end
|
||||
|
||||
loop Until confirmed
|
||||
OrderQueue ->> Order: Update status
|
||||
Order -->> User: Notification
|
||||
end
|
||||
else Invalid credentials
|
||||
AuthService --x LoginUI: Failure
|
||||
LoginUI --x User: Retry
|
||||
end
|
||||
`;
|
||||
imgSnapshotTest(diagramCode, {});
|
||||
});
|
||||
|
||||
it('should render with wrapped messages and notes', () => {
|
||||
const diagramCode = `
|
||||
sequenceDiagram
|
||||
participant A
|
||||
participant B
|
||||
|
||||
A ->> B: This is a very long message that should wrap properly in the diagram rendering
|
||||
Note over A,B: This is a very long note that should also wrap properly when rendered in the diagram
|
||||
|
||||
par Wrapped parallel
|
||||
A ->> B: Parallel message 1<br>with explicit line break
|
||||
and
|
||||
B ->> A: Parallel message 2<br>with explicit line break
|
||||
end
|
||||
|
||||
loop Wrapped loop
|
||||
Note right of B: This is a long note<br>in a loop
|
||||
A ->> B: Message in loop
|
||||
end
|
||||
`;
|
||||
imgSnapshotTest(diagramCode, { sequence: { wrap: true } });
|
||||
});
|
||||
describe('Sequence Diagram Rendering with Different Participant Types', () => {
|
||||
it('should render a sequence diagram with various participant types', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant User@{ "type": "actor" }
|
||||
participant AuthService@{ "type": "control" }
|
||||
participant UI@{ "type": "boundary" }
|
||||
participant OrderController@{ "type": "control" }
|
||||
participant Product@{ "type": "entity" }
|
||||
participant MongoDB@{ "type": "database" }
|
||||
participant Products@{ "type": "collections" }
|
||||
participant OrderQueue@{ "type": "queue" }
|
||||
User ->> UI: Login request
|
||||
UI ->> AuthService: Validate credentials
|
||||
AuthService -->> UI: Authentication token
|
||||
UI ->> OrderController: Place order
|
||||
OrderController ->> Product: Check availability
|
||||
Product -->> OrderController: Available
|
||||
OrderController ->> MongoDB: Save order
|
||||
MongoDB -->> OrderController: Order saved
|
||||
OrderController ->> OrderQueue: Process payment
|
||||
OrderQueue -->> User: Order confirmation
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('should render participant creation and destruction with different types', () => {
|
||||
imgSnapshotTest(`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "boundary" }
|
||||
Alice->>Bob: Hello Bob, how are you ?
|
||||
Bob->>Alice: Fine, thank you. And you?
|
||||
create participant Carl@{ "type" : "control" }
|
||||
Alice->>Carl: Hi Carl!
|
||||
create actor D as Donald
|
||||
Carl->>D: Hi!
|
||||
destroy Carl
|
||||
Alice-xCarl: We are too many
|
||||
destroy Bob
|
||||
Bob->>Alice: I agree
|
||||
`);
|
||||
});
|
||||
|
||||
it('should handle complex interactions between different participant types', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
box rgb(200,220,255) Authentication
|
||||
participant User@{ "type": "actor" }
|
||||
participant LoginUI@{ "type": "boundary" }
|
||||
participant AuthService@{ "type": "control" }
|
||||
participant UserDB@{ "type": "database" }
|
||||
end
|
||||
|
||||
box rgb(200,255,220) Order Processing
|
||||
participant Order@{ "type": "entity" }
|
||||
participant OrderQueue@{ "type": "queue" }
|
||||
participant AuditLogs@{ "type": "collections" }
|
||||
end
|
||||
|
||||
User ->> LoginUI: Enter credentials
|
||||
LoginUI ->> AuthService: Validate
|
||||
AuthService ->> UserDB: Query user
|
||||
UserDB -->> AuthService: User data
|
||||
|
||||
alt Valid credentials
|
||||
AuthService -->> LoginUI: Success
|
||||
LoginUI -->> User: Welcome
|
||||
|
||||
par Place order
|
||||
User ->> Order: New order
|
||||
Order ->> OrderQueue: Process
|
||||
and
|
||||
Order ->> AuditLogs: Record
|
||||
end
|
||||
|
||||
loop Until confirmed
|
||||
OrderQueue ->> Order: Update status
|
||||
Order -->> User: Notification
|
||||
end
|
||||
else Invalid credentials
|
||||
AuthService --x LoginUI: Failure
|
||||
LoginUI --x User: Retry
|
||||
end
|
||||
`,
|
||||
{ sequence: { useMaxWidth: false } }
|
||||
);
|
||||
});
|
||||
|
||||
it('should render parallel processes with different participant types', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Customer@{ "type": "actor" }
|
||||
participant Frontend@{ "type": "participant" }
|
||||
participant PaymentService@{ "type": "boundary" }
|
||||
participant InventoryManager@{ "type": "control" }
|
||||
participant Order@{ "type": "entity" }
|
||||
participant OrdersDB@{ "type": "database" }
|
||||
participant NotificationQueue@{ "type": "queue" }
|
||||
|
||||
Customer ->> Frontend: Place order
|
||||
Frontend ->> Order: Create order
|
||||
par Parallel Processing
|
||||
Order ->> PaymentService: Process payment
|
||||
and
|
||||
Order ->> InventoryManager: Reserve items
|
||||
end
|
||||
PaymentService -->> Order: Payment confirmed
|
||||
InventoryManager -->> Order: Items reserved
|
||||
Order ->> OrdersDB: Save finalized order
|
||||
OrdersDB -->> Order: Order saved
|
||||
Order ->> NotificationQueue: Send confirmation
|
||||
NotificationQueue -->> Customer: Order confirmation
|
||||
`
|
||||
);
|
||||
});
|
||||
});
|
||||
it('should render different participant types with notes and loops', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
actor Admin
|
||||
participant Dashboard
|
||||
participant AuthService@{ "type" : "boundary" }
|
||||
participant UserManager@{ "type" : "control" }
|
||||
participant UserProfile@{ "type" : "entity" }
|
||||
participant UserDB@{ "type" : "database" }
|
||||
participant Logs@{ "type" : "database" }
|
||||
|
||||
Admin ->> Dashboard: Open user management
|
||||
loop Authentication check
|
||||
Dashboard ->> AuthService: Verify admin rights
|
||||
AuthService ->> Dashboard: Access granted
|
||||
end
|
||||
Dashboard ->> UserManager: List users
|
||||
UserManager ->> UserDB: Query users
|
||||
UserDB ->> UserManager: Return user data
|
||||
Note right of UserDB: Encrypted data<br/>requires decryption
|
||||
UserManager ->> UserProfile: Format profiles
|
||||
UserProfile ->> UserManager: Formatted data
|
||||
UserManager ->> Dashboard: Display users
|
||||
Dashboard ->> Logs: Record access
|
||||
Logs ->> Admin: Audit trail
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('should render different participant types with alternative flows', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
actor Client
|
||||
participant MobileApp
|
||||
participant CloudService@{ "type" : "boundary" }
|
||||
participant DataProcessor@{ "type" : "control" }
|
||||
participant Transaction@{ "type" : "entity" }
|
||||
participant TransactionsDB@{ "type" : "database" }
|
||||
participant EventBus@{ "type" : "queue" }
|
||||
|
||||
Client ->> MobileApp: Initiate transaction
|
||||
MobileApp ->> CloudService: Authenticate
|
||||
alt Authentication successful
|
||||
CloudService -->> MobileApp: Auth token
|
||||
MobileApp ->> DataProcessor: Process data
|
||||
DataProcessor ->> Transaction: Create transaction
|
||||
Transaction ->> TransactionsDB: Save record
|
||||
TransactionsDB -->> Transaction: Confirmation
|
||||
Transaction ->> EventBus: Publish event
|
||||
EventBus -->> Client: Notification
|
||||
else Authentication failed
|
||||
CloudService -->> MobileApp: Error
|
||||
MobileApp -->> Client: Show error
|
||||
end
|
||||
`
|
||||
);
|
||||
});
|
||||
|
||||
it('should render different participant types with wrapping text', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant B@{ "type" : "boundary" }
|
||||
participant C@{ "type" : "control" }
|
||||
participant E@{ "type" : "entity" }
|
||||
participant DB@{ "type" : "database" }
|
||||
participant COL@{ "type" : "collections" }
|
||||
participant Q@{ "type" : "queue" }
|
||||
|
||||
FE ->> B: Another long message<br/>with explicit<br/>line breaks
|
||||
B -->> FE: Response message that is also quite long and needs to wrap
|
||||
FE ->> C: Process data
|
||||
C ->> E: Validate
|
||||
E -->> C: Validation result
|
||||
C ->> DB: Save
|
||||
DB -->> C: Save result
|
||||
C ->> COL: Log
|
||||
COL -->> Q: Forward
|
||||
Q -->> LongNameUser: Final response with confirmation of all actions taken
|
||||
`,
|
||||
{ sequence: { wrap: true } }
|
||||
);
|
||||
});
|
||||
|
||||
describe('Sequence Diagram - New Participant Types with Long Notes and Messages', () => {
|
||||
it('should render long notes left of boundary', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "boundary" }
|
||||
actor Bob
|
||||
Alice->>Bob: Hola
|
||||
Note left of Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render wrapped long notes left of control', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "control" }
|
||||
actor Bob
|
||||
Alice->>Bob: Hola
|
||||
Note left of Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render long notes right of entity', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "entity" }
|
||||
actor Bob
|
||||
Alice->>Bob: Hola
|
||||
Note right of Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render wrapped long notes right of database', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "database" }
|
||||
actor Bob
|
||||
Alice->>Bob: Hola
|
||||
Note right of Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render long notes over collections', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "collections" }
|
||||
actor Bob
|
||||
Alice->>Bob: Hola
|
||||
Note over Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render wrapped long notes over queue', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "queue" }
|
||||
actor Bob
|
||||
Alice->>Bob: Hola
|
||||
Note over Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render notes over actor and boundary', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
actor Alice
|
||||
participant Charlie@{ "type" : "boundary" }
|
||||
note over Alice: Some note
|
||||
note over Charlie: Other note
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render long messages from database to collections', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "database" }
|
||||
participant Bob@{ "type" : "collections" }
|
||||
Alice->>Bob: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render wrapped long messages from control to entity', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "control" }
|
||||
participant Bob@{ "type" : "entity" }
|
||||
Alice->>Bob:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
Bob->>Alice: I'm short though
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render long messages from queue to boundary', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
participant Alice@{ "type" : "queue" }
|
||||
participant Bob@{ "type" : "boundary" }
|
||||
Alice->>Bob: I'm short
|
||||
Bob->>Alice: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render wrapped long messages from actor to database', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
sequenceDiagram
|
||||
actor Alice
|
||||
participant Bob@{ "type" : "database" }
|
||||
Alice->>Bob: I'm short
|
||||
Bob->>Alice:wrap: Extremely utterly long line of longness which had previously overflown the actor box as it is much longer than what it should be
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
describe('svg size', () => {
|
||||
it('should render a sequence diagram when useMaxWidth is true (default)', () => {
|
||||
renderGraph(
|
||||
`
|
||||
sequenceDiagram
|
||||
actor Alice
|
||||
participant Bob@{ "type" : "boundary" }
|
||||
participant John@{ "type" : "control" }
|
||||
Alice ->> Bob: Hello Bob, how are you?
|
||||
Bob-->>John: How about you John?
|
||||
Bob--x Alice: I am good thanks!
|
||||
Bob-x John: I am good thanks!
|
||||
Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row.
|
||||
Bob-->Alice: Checking with John...
|
||||
alt either this
|
||||
Alice->>John: Yes
|
||||
else or this
|
||||
Alice->>John: No
|
||||
else or this will happen
|
||||
Alice->John: Maybe
|
||||
end
|
||||
par this happens in parallel
|
||||
Alice -->> Bob: Parallel message 1
|
||||
and
|
||||
Alice -->> John: Parallel message 2
|
||||
end
|
||||
`,
|
||||
{ sequence: { useMaxWidth: true } }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
expect(svg).to.have.attr('width', '100%');
|
||||
const style = svg.attr('style');
|
||||
expect(style).to.match(/^max-width: [\d.]+px;$/);
|
||||
const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join(''));
|
||||
expect(maxWidthValue).to.be.within(820 * 0.95, 820 * 1.05);
|
||||
});
|
||||
});
|
||||
|
||||
it('should render a sequence diagram when useMaxWidth is false', () => {
|
||||
renderGraph(
|
||||
`
|
||||
sequenceDiagram
|
||||
actor Alice
|
||||
participant Bob@{ "type" : "boundary" }
|
||||
participant John@{ "type" : "control" }
|
||||
Alice ->> Bob: Hello Bob, how are you?
|
||||
Bob-->>John: How about you John?
|
||||
Bob--x Alice: I am good thanks!
|
||||
Bob-x John: I am good thanks!
|
||||
Note right of John: Bob thinks a long<br/>long time, so long<br/>that the text does<br/>not fit on a row.
|
||||
Bob-->Alice: Checking with John...
|
||||
alt either this
|
||||
Alice->>John: Yes
|
||||
else or this
|
||||
Alice->>John: No
|
||||
else or this will happen
|
||||
Alice->John: Maybe
|
||||
end
|
||||
par this happens in parallel
|
||||
Alice -->> Bob: Parallel message 1
|
||||
and
|
||||
Alice -->> John: Parallel message 2
|
||||
end
|
||||
`,
|
||||
{ sequence: { useMaxWidth: false } }
|
||||
);
|
||||
cy.get('svg').should((svg) => {
|
||||
const width = parseFloat(svg.attr('width'));
|
||||
expect(width).to.be.within(820 * 0.95, 820 * 1.05);
|
||||
expect(svg).to.not.have.attr('style');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -893,17 +893,6 @@ describe('Sequence diagram', () => {
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
it('should handle bidirectional arrows with autonumber', () => {
|
||||
imgSnapshotTest(`
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant A
|
||||
participant B
|
||||
A<<->>B: This is a bidirectional message
|
||||
A->B: This is a normal message`);
|
||||
});
|
||||
|
||||
it('should support actor links and properties when not mirrored EXPERIMENTAL: USE WITH CAUTION', () => {
|
||||
//Be aware that the syntax for "properties" is likely to be changed.
|
||||
imgSnapshotTest(
|
||||
|
||||
@@ -602,231 +602,6 @@ State1 --> [*]
|
||||
--
|
||||
55
|
||||
}
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should render edge labels correctly', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
title: On The Way To Something Something DarkSide
|
||||
config:
|
||||
look: default
|
||||
theme: default
|
||||
---
|
||||
|
||||
stateDiagram-v2
|
||||
|
||||
state State1_____________
|
||||
{
|
||||
c0
|
||||
}
|
||||
|
||||
state State2_____________
|
||||
{
|
||||
c1
|
||||
}
|
||||
|
||||
state State3_____________
|
||||
{
|
||||
c7
|
||||
}
|
||||
|
||||
state State4_____________
|
||||
{
|
||||
c2
|
||||
}
|
||||
|
||||
state State5_____________
|
||||
{
|
||||
c3
|
||||
}
|
||||
|
||||
state State6_____________
|
||||
{
|
||||
c4
|
||||
}
|
||||
|
||||
state State7_____________
|
||||
{
|
||||
c5
|
||||
}
|
||||
|
||||
state State8_____________
|
||||
{
|
||||
c6
|
||||
}
|
||||
|
||||
|
||||
[*] --> State1_____________
|
||||
State1_____________ --> State2_____________ : Transition1_____
|
||||
State2_____________ --> State4_____________ : Transition2_____
|
||||
State2_____________ --> State3_____________ : Transition3_____
|
||||
State3_____________ --> State2_____________
|
||||
State4_____________ --> State2_____________ : Transition5_____
|
||||
State4_____________ --> State5_____________ : Transition6_____
|
||||
State5_____________ --> State6_____________ : Transition7_____
|
||||
State6_____________ --> State4_____________ : Transition8_____
|
||||
State2_____________ --> State7_____________ : Transition4_____
|
||||
State4_____________ --> State7_____________ : Transition4_____
|
||||
State5_____________ --> State7_____________ : Transition4_____
|
||||
State6_____________ --> State7_____________ : Transition4_____
|
||||
State7_____________ --> State1_____________ : Transition9_____
|
||||
State5_____________ --> State8_____________ : Transition10____
|
||||
State8_____________ --> State5_____________ : Transition11____
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should render edge labels correctly with multiple transitions', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
title: Multiple Transitions
|
||||
config:
|
||||
look: default
|
||||
theme: default
|
||||
---
|
||||
|
||||
stateDiagram-v2
|
||||
|
||||
state State1_____________
|
||||
{
|
||||
c0
|
||||
}
|
||||
|
||||
state State2_____________
|
||||
{
|
||||
c1
|
||||
}
|
||||
|
||||
state State3_____________
|
||||
{
|
||||
c7
|
||||
}
|
||||
|
||||
state State4_____________
|
||||
{
|
||||
c2
|
||||
}
|
||||
|
||||
state State5_____________
|
||||
{
|
||||
c3
|
||||
}
|
||||
|
||||
state State6_____________
|
||||
{
|
||||
c4
|
||||
}
|
||||
|
||||
state State7_____________
|
||||
{
|
||||
c5
|
||||
}
|
||||
|
||||
state State8_____________
|
||||
{
|
||||
c6
|
||||
}
|
||||
|
||||
state State9_____________
|
||||
{
|
||||
c9
|
||||
}
|
||||
|
||||
[*] --> State1_____________
|
||||
State1_____________ --> State2_____________ : Transition1_____
|
||||
State2_____________ --> State4_____________ : Transition2_____
|
||||
State2_____________ --> State3_____________ : Transition3_____
|
||||
State3_____________ --> State2_____________
|
||||
State4_____________ --> State2_____________ : Transition5_____
|
||||
State4_____________ --> State5_____________ : Transition6_____
|
||||
State5_____________ --> State6_____________ : Transition7_____
|
||||
State6_____________ --> State4_____________ : Transition8_____
|
||||
State2_____________ --> State7_____________ : Transition4_____
|
||||
State4_____________ --> State7_____________ : Transition4_____
|
||||
State5_____________ --> State7_____________ : Transition4_____
|
||||
State6_____________ --> State7_____________ : Transition4_____
|
||||
State7_____________ --> State1_____________ : Transition9_____
|
||||
State5_____________ --> State8_____________ : Transition10____
|
||||
State8_____________ --> State5_____________ : Transition11____
|
||||
State9_____________ --> State8_____________ : Transition12____
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('should render edge labels correctly with multiple states', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
title: Multiple States
|
||||
config:
|
||||
look: default
|
||||
theme: default
|
||||
---
|
||||
|
||||
stateDiagram-v2
|
||||
|
||||
state State1_____________
|
||||
{
|
||||
c0
|
||||
}
|
||||
|
||||
state State2_____________
|
||||
{
|
||||
c1
|
||||
}
|
||||
|
||||
state State3_____________
|
||||
{
|
||||
c7
|
||||
}
|
||||
|
||||
state State4_____________
|
||||
{
|
||||
c2
|
||||
}
|
||||
|
||||
state State5_____________
|
||||
{
|
||||
c3
|
||||
}
|
||||
|
||||
state State6_____________
|
||||
{
|
||||
c4
|
||||
}
|
||||
|
||||
state State7_____________
|
||||
{
|
||||
c5
|
||||
}
|
||||
|
||||
state State8_____________
|
||||
{
|
||||
c6
|
||||
}
|
||||
|
||||
state State9_____________
|
||||
{
|
||||
c9
|
||||
}
|
||||
|
||||
state State10_____________
|
||||
{
|
||||
c10
|
||||
}
|
||||
|
||||
[*] --> State1_____________
|
||||
State1_____________ --> State2_____________ : Transition1_____
|
||||
State2_____________ --> State3_____________ : Transition2_____
|
||||
State3_____________ --> State4_____________ : Transition3_____
|
||||
State4_____________ --> State5_____________ : Transition4_____
|
||||
State5_____________ --> State6_____________ : Transition5_____
|
||||
State6_____________ --> State7_____________ : Transition6_____
|
||||
State7_____________ --> State8_____________ : Transition7_____
|
||||
State8_____________ --> State9_____________ : Transition8_____
|
||||
State9_____________ --> State10_____________ : Transition9_____
|
||||
`,
|
||||
{}
|
||||
);
|
||||
|
||||
@@ -161,68 +161,4 @@ describe('Timeline diagram', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('11: should render timeline with many stacked events and proper timeline line length', () => {
|
||||
imgSnapshotTest(
|
||||
`timeline
|
||||
title Medical Device Lifecycle
|
||||
section Pre-Development
|
||||
Quality Management System : Regulatory Compliance : Risk Management
|
||||
section Development
|
||||
Management Responsibility : Planning Activities : Human Resources
|
||||
Resource Management : Management Reviews : Infrastructure
|
||||
section Post-Development
|
||||
Product Realization Activities : Planning Activities : Customer-related Processes
|
||||
Post-Production Activities : Feedback : Complaints : Adverse Events
|
||||
: Research and Development : Purchasing Activities
|
||||
: Production Activities : Installation Activities
|
||||
: Servicing Activities : Post-Market Surveillance
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('12: should render timeline with proper vertical line lengths for all columns', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
theme: base
|
||||
themeVariables:
|
||||
fontFamily: Fira Sans
|
||||
fontSize: 17px
|
||||
cScale0: '#b3cde0'
|
||||
cScale1: '#f49090'
|
||||
cScale2: '#85d5b8'
|
||||
---
|
||||
|
||||
timeline
|
||||
title Medical Device Lifecycle
|
||||
section Planning
|
||||
Quality Management System (4): Regulatory Compliance (4.1.1)
|
||||
: Risk Management (4.1.2)
|
||||
Management Resposibility (5): Planning Activities (5.4)
|
||||
: Management Reviews (5.6)
|
||||
Resource Management (6): Human Resources (6.2)
|
||||
: Infrastructure (6.3)
|
||||
section Realization
|
||||
Research and Development (7.3): RnD Planning (7.3.2)
|
||||
: Inputs (7.3.3)
|
||||
: Outputs (7.3.4)
|
||||
: Review (7.3.5)
|
||||
: Verification (7.3.6)
|
||||
: Validation (7.3.7)
|
||||
Purchasing (7.4): Purchasing Process (7.4.1)
|
||||
: Purchasing Information (7.4.2)
|
||||
Production (7.5): Production Activities (7.5.1)
|
||||
: Production Feedback (8.2.1)
|
||||
Installation (7.5.3): Installation Activities (7.5.3)
|
||||
Servicing (7.5.4): Servicing Activities (7.5.4)
|
||||
section Post-Production
|
||||
Post-Market Activities (8): Feedback (8.2.1)
|
||||
: Complaints (8.2.2)
|
||||
: Adverse Events (8.2.3)
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
});
|
||||
|
||||
@@ -1,382 +0,0 @@
|
||||
import { imgSnapshotTest } from '../../helpers/util.ts';
|
||||
|
||||
describe('Treemap Diagram', () => {
|
||||
it('1: should render a basic treemap', () => {
|
||||
imgSnapshotTest(
|
||||
`treemap-beta
|
||||
"Category A"
|
||||
"Item A1": 10
|
||||
"Item A2": 20
|
||||
"Category B"
|
||||
"Item B1": 15
|
||||
"Item B2": 25
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('2: should render a hierarchical treemap', () => {
|
||||
imgSnapshotTest(
|
||||
`treemap-beta
|
||||
"Products"
|
||||
"Electronics"
|
||||
"Phones": 50
|
||||
"Computers": 30
|
||||
"Accessories": 20
|
||||
"Clothing"
|
||||
"Men's"
|
||||
"Shirts": 10
|
||||
"Pants": 15
|
||||
"Women's"
|
||||
"Dresses": 20
|
||||
"Skirts": 10
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('3: should render a treemap with styling using classDef', () => {
|
||||
imgSnapshotTest(
|
||||
`treemap-beta
|
||||
"Section 1"
|
||||
"Leaf 1.1": 12
|
||||
"Section 1.2":::class1
|
||||
"Leaf 1.2.1": 12
|
||||
"Section 2"
|
||||
"Leaf 2.1": 20:::class1
|
||||
"Leaf 2.2": 25
|
||||
"Leaf 2.3": 12
|
||||
|
||||
classDef class1 fill:red,color:blue,stroke:#FFD600;
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('4: should handle long text that wraps', () => {
|
||||
imgSnapshotTest(
|
||||
`treemap-beta
|
||||
"Main Category"
|
||||
"This is a very long item name that should wrap to the next line when rendered in the treemap diagram": 50
|
||||
"Short item": 20
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('5: should render with a forest theme', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
theme: forest
|
||||
---
|
||||
treemap-beta
|
||||
"Category A"
|
||||
"Item A1": 10
|
||||
"Item A2": 20
|
||||
"Category B"
|
||||
"Item B1": 15
|
||||
"Item B2": 25
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('6: should handle multiple levels of nesting', () => {
|
||||
imgSnapshotTest(
|
||||
`treemap-beta
|
||||
"Level 1"
|
||||
"Level 2A"
|
||||
"Level 3A": 10
|
||||
"Level 3B": 15
|
||||
"Level 2B"
|
||||
"Level 3C": 20
|
||||
"Level 3D"
|
||||
"Level 4A": 5
|
||||
"Level 4B": 5
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('7: should handle classDef with multiple styles', () => {
|
||||
imgSnapshotTest(
|
||||
`treemap-beta
|
||||
"Main"
|
||||
"A": 20
|
||||
"B":::important
|
||||
"B1": 10
|
||||
"B2": 15
|
||||
"C": 5:::secondary
|
||||
|
||||
classDef important fill:#f96,stroke:#333,stroke-width:2px;
|
||||
classDef secondary fill:#6cf,stroke:#333,stroke-dasharray:5 5;
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('8: should handle dollar value formatting with thousands separator', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
treemap:
|
||||
valueFormat: "$0,0"
|
||||
---
|
||||
treemap
|
||||
"Budget"
|
||||
"Operations"
|
||||
"Salaries": 700000
|
||||
"Equipment": 200000
|
||||
"Supplies": 100000
|
||||
"Marketing"
|
||||
"Advertising": 400000
|
||||
"Events": 100000
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('8a: should handle percentage formatting', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
treemap:
|
||||
valueFormat: ".1%"
|
||||
---
|
||||
treemap-beta
|
||||
"Market Share"
|
||||
"Company A": 0.35
|
||||
"Company B": 0.25
|
||||
"Company C": 0.15
|
||||
"Others": 0.25
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('8b: should handle decimal formatting', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
treemap:
|
||||
valueFormat: ".2f"
|
||||
---
|
||||
treemap-beta
|
||||
"Metrics"
|
||||
"Conversion Rate": 0.0567
|
||||
"Bounce Rate": 0.6723
|
||||
"Click-through Rate": 0.1289
|
||||
"Engagement": 0.4521
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('8c: should handle dollar sign with decimal places', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
treemap:
|
||||
valueFormat: "$.2f"
|
||||
---
|
||||
treemap-beta
|
||||
"Product Prices"
|
||||
"Basic": 19.99
|
||||
"Standard": 49.99
|
||||
"Premium": 99.99
|
||||
"Enterprise": 199.99
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('8d: should handle dollar sign with thousands separator and decimal places', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
treemap:
|
||||
valueFormat: "$,.2f"
|
||||
---
|
||||
treemap-beta
|
||||
"Revenue"
|
||||
"Q1": 1250345.75
|
||||
"Q2": 1645789.25
|
||||
"Q3": 1845123.50
|
||||
"Q4": 2145678.75
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('8e: should handle simple thousands separator', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
treemap:
|
||||
valueFormat: ","
|
||||
---
|
||||
treemap-beta
|
||||
"User Counts"
|
||||
"Active Users": 1250345
|
||||
"New Signups": 45789
|
||||
"Churned": 12350
|
||||
"Converted": 78975
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('8f: should handle valueFormat set via directive with dollar and thousands separator', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
treemap:
|
||||
valueFormat: "$,.0f"
|
||||
---
|
||||
treemap-beta
|
||||
"Sales by Region"
|
||||
"North": 1234567
|
||||
"South": 7654321
|
||||
"East": 4567890
|
||||
"West": 9876543
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('8g: should handle scientific notation format', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
treemap:
|
||||
valueFormat: ".2e"
|
||||
---
|
||||
treemap-beta
|
||||
"Scientific Values"
|
||||
"Value 1": 1234567
|
||||
"Value 2": 0.0000123
|
||||
"Value 3": 1000000000
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('9: should handle a complex example with multiple features', () => {
|
||||
imgSnapshotTest(
|
||||
`---
|
||||
config:
|
||||
theme: dark
|
||||
treemap:
|
||||
valueFormat: "$0,0"
|
||||
---
|
||||
treemap-beta
|
||||
"Company Budget"
|
||||
"Engineering":::engineering
|
||||
"Frontend": 300000
|
||||
"Backend": 400000
|
||||
"DevOps": 200000
|
||||
"Marketing":::marketing
|
||||
"Digital": 250000
|
||||
"Print": 100000
|
||||
"Events": 150000
|
||||
"Sales":::sales
|
||||
"Direct": 500000
|
||||
"Channel": 300000
|
||||
|
||||
classDef engineering fill:#6b9bc3,stroke:#333;
|
||||
classDef marketing fill:#c36b9b,stroke:#333;
|
||||
classDef sales fill:#c3a66b,stroke:#333;
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('10: should render the example from documentation', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
treemap-beta
|
||||
"Section 1"
|
||||
"Leaf 1.1": 12
|
||||
"Section 1.2":::class1
|
||||
"Leaf 1.2.1": 12
|
||||
"Section 2"
|
||||
"Leaf 2.1": 20:::class1
|
||||
"Leaf 2.2": 25
|
||||
"Leaf 2.3": 12
|
||||
|
||||
classDef class1 fill:red,color:blue,stroke:#FFD600;
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it('11: should handle comments', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
treemap-beta
|
||||
%% This is a comment
|
||||
"Category A"
|
||||
"Item A1": 10
|
||||
"Item A2": 20
|
||||
%% Another comment
|
||||
"Category B"
|
||||
"Item B1": 15
|
||||
"Item B2": 25
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
/*
|
||||
it.skip('12: should render a treemap with title', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
treemap-beta
|
||||
title Treemap with Title
|
||||
"Category A"
|
||||
"Item A1": 10
|
||||
"Item A2": 20
|
||||
"Category B"
|
||||
"Item B1": 15
|
||||
"Item B2": 25
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it.skip('13: should render a treemap with accessibility attributes', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
treemap-beta
|
||||
accTitle: Accessible Treemap Title
|
||||
accDescr: This is a description of the treemap for accessibility purposes
|
||||
"Category A"
|
||||
"Item A1": 10
|
||||
"Item A2": 20
|
||||
"Category B"
|
||||
"Item B1": 15
|
||||
"Item B2": 25
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
|
||||
it.skip('14: should render a treemap with title and accessibility attributes', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
treemap
|
||||
title Treemap with Title and Accessibility
|
||||
accTitle: Accessible Treemap Title
|
||||
accDescr: This is a description of the treemap for accessibility purposes
|
||||
"Category A"
|
||||
"Item A1": 10
|
||||
"Item A2": 20
|
||||
"Category B"
|
||||
"Item B1": 15
|
||||
"Item B2": 25
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
*/
|
||||
});
|
||||
@@ -1,7 +1,7 @@
|
||||
import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts';
|
||||
|
||||
describe('XY Chart', () => {
|
||||
it('should render the simplest possible xy-beta chart', () => {
|
||||
it('should render the simplest possible chart', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
xychart-beta
|
||||
@@ -10,19 +10,10 @@ describe('XY Chart', () => {
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('should render the simplest possible xy chart', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
xychart
|
||||
line [10, 30, 20]
|
||||
`,
|
||||
{}
|
||||
);
|
||||
});
|
||||
it('Should render a complete chart', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
@@ -35,7 +26,7 @@ describe('XY Chart', () => {
|
||||
it('Should render a chart without title', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
xychart
|
||||
xychart-beta
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||
@@ -47,7 +38,7 @@ describe('XY Chart', () => {
|
||||
it('y-axis title not required', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
xychart
|
||||
xychart-beta
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis 4000 --> 11000
|
||||
bar [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000]
|
||||
@@ -59,7 +50,7 @@ describe('XY Chart', () => {
|
||||
it('Should render a chart without y-axis with different range', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
xychart
|
||||
xychart-beta
|
||||
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]
|
||||
line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800]
|
||||
@@ -70,7 +61,7 @@ describe('XY Chart', () => {
|
||||
it('x axis title not required', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
xychart
|
||||
xychart-beta
|
||||
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]
|
||||
line [2000, 7000, 6500, 9200, 9500, 7500, 11000, 10200, 3200, 8500, 7000, 8800]
|
||||
@@ -81,7 +72,7 @@ describe('XY Chart', () => {
|
||||
it('Multiple plots can be rendered', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
xychart
|
||||
xychart-beta
|
||||
line [23, 46, 77, 34]
|
||||
line [45, 32, 33, 12]
|
||||
bar [87, 54, 99, 85]
|
||||
@@ -95,7 +86,7 @@ describe('XY Chart', () => {
|
||||
it('Decimals and negative numbers are supported', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
xychart
|
||||
xychart-beta
|
||||
y-axis -2.4 --> 3.5
|
||||
line [+1.3, .6, 2.4, -.34]
|
||||
`,
|
||||
@@ -113,7 +104,7 @@ describe('XY Chart', () => {
|
||||
height: 20
|
||||
plotReservedSpacePercent: 100
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
line [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
|
||||
`,
|
||||
{}
|
||||
@@ -139,7 +130,7 @@ describe('XY Chart', () => {
|
||||
showTick: false
|
||||
showAxisLine: false
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
bar [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
|
||||
`,
|
||||
{}
|
||||
@@ -149,7 +140,7 @@ describe('XY Chart', () => {
|
||||
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 }}}%%
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
@@ -190,7 +181,7 @@ describe('XY Chart', () => {
|
||||
plotReservedSpacePercent: 60
|
||||
showDataLabel: true
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
@@ -211,7 +202,7 @@ describe('XY Chart', () => {
|
||||
yAxis:
|
||||
showTitle: false
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
@@ -232,7 +223,7 @@ describe('XY Chart', () => {
|
||||
yAxis:
|
||||
showLabel: false
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
@@ -253,7 +244,7 @@ describe('XY Chart', () => {
|
||||
yAxis:
|
||||
showTick: false
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
@@ -274,7 +265,7 @@ describe('XY Chart', () => {
|
||||
yAxis:
|
||||
showAxisLine: false
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
@@ -303,7 +294,7 @@ describe('XY Chart', () => {
|
||||
xAxisLineColor: "#87ceeb"
|
||||
plotColorPalette: "#008000, #faba63"
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
@@ -316,7 +307,7 @@ describe('XY Chart', () => {
|
||||
it('should use the correct distances between data points', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
xychart
|
||||
xychart-beta
|
||||
x-axis 0 --> 2
|
||||
line [0, 1, 0, 1]
|
||||
bar [1, 0, 1, 0]
|
||||
@@ -334,7 +325,7 @@ describe('XY Chart', () => {
|
||||
xyChart:
|
||||
showDataLabel: true
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
@@ -353,7 +344,7 @@ describe('XY Chart', () => {
|
||||
showDataLabel: true
|
||||
chartOrientation: horizontal
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
@@ -366,7 +357,7 @@ describe('XY Chart', () => {
|
||||
it('should render vertical bar chart without labels by default', () => {
|
||||
imgSnapshotTest(
|
||||
`
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
@@ -384,7 +375,7 @@ describe('XY Chart', () => {
|
||||
xyChart:
|
||||
chartOrientation: horizontal
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
@@ -402,7 +393,7 @@ describe('XY Chart', () => {
|
||||
xyChart:
|
||||
showDataLabel: true
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Multiple Bar Plots"
|
||||
x-axis Categories [A, B, C]
|
||||
y-axis "Values" 0 --> 100
|
||||
@@ -421,7 +412,7 @@ describe('XY Chart', () => {
|
||||
showDataLabel: true
|
||||
chartOrientation: horizontal
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Multiple Bar Plots"
|
||||
x-axis Categories [A, B, C]
|
||||
y-axis "Values" 0 --> 100
|
||||
@@ -439,7 +430,7 @@ describe('XY Chart', () => {
|
||||
xyChart:
|
||||
showDataLabel: true
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Single Bar Chart"
|
||||
x-axis Categories [A]
|
||||
y-axis "Value" 0 --> 100
|
||||
@@ -458,7 +449,7 @@ describe('XY Chart', () => {
|
||||
showDataLabel: true
|
||||
chartOrientation: horizontal
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Single Bar Chart"
|
||||
x-axis Categories [A]
|
||||
y-axis "Value" 0 --> 100
|
||||
@@ -476,7 +467,7 @@ describe('XY Chart', () => {
|
||||
xyChart:
|
||||
showDataLabel: true
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Decimal and Negative Values"
|
||||
x-axis Categories [A, B, C]
|
||||
y-axis -10 --> 10
|
||||
@@ -495,7 +486,7 @@ describe('XY Chart', () => {
|
||||
showDataLabel: true
|
||||
chartOrientation: horizontal
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Decimal and Negative Values"
|
||||
x-axis Categories [A, B, C]
|
||||
y-axis -10 --> 10
|
||||
@@ -513,7 +504,7 @@ describe('XY Chart', () => {
|
||||
xyChart:
|
||||
showDataLabel: true
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan,b,c]
|
||||
y-axis "Revenue (in $)" 4000 --> 12000
|
||||
@@ -570,7 +561,7 @@ describe('XY Chart', () => {
|
||||
showDataLabel: true
|
||||
chartOrientation: horizontal
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan,b,c]
|
||||
y-axis "Revenue (in $)" 4000 --> 12000
|
||||
@@ -624,7 +615,7 @@ describe('XY Chart', () => {
|
||||
xyChart:
|
||||
showDataLabel: true
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s]
|
||||
y-axis "Revenue (in $)" 4000 --> 12000
|
||||
@@ -681,7 +672,7 @@ describe('XY Chart', () => {
|
||||
showDataLabel: true
|
||||
chartOrientation: horizontal
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan,a,b,c,d,e,f,g,h,i,j,k,l,m,n,o,p,q,r,s]
|
||||
y-axis "Revenue (in $)" 4000 --> 12000
|
||||
@@ -735,7 +726,7 @@ describe('XY Chart', () => {
|
||||
xyChart:
|
||||
showDataLabel: true
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan]
|
||||
y-axis "Revenue (in $)" 3000 --> 12000
|
||||
@@ -792,7 +783,7 @@ describe('XY Chart', () => {
|
||||
showDataLabel: true
|
||||
chartOrientation: horizontal
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan]
|
||||
y-axis "Revenue (in $)" 3000 --> 12000
|
||||
|
||||
@@ -1,35 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Mermaid Quick Test Page</title>
|
||||
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
|
||||
<style>
|
||||
div.mermaid {
|
||||
font-family: 'Courier New', Courier, monospace !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>Pie chart demos</h1>
|
||||
<pre class="mermaid">
|
||||
pie title Default text position: Animal adoption
|
||||
accTitle: simple pie char demo
|
||||
accDescr: pie chart with 3 sections: dogs, cats, rats. Most are dogs.
|
||||
"dogs" : -60.67
|
||||
"rats" : 40.12
|
||||
</pre>
|
||||
|
||||
<hr />
|
||||
<script type="module">
|
||||
import mermaid from '/mermaid.esm.mjs';
|
||||
mermaid.initialize({
|
||||
theme: 'forest',
|
||||
logLevel: 3,
|
||||
securityLevel: 'loose',
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -7,7 +7,7 @@
|
||||
rel="stylesheet"
|
||||
/>
|
||||
<style>
|
||||
svg:not(svg svg) {
|
||||
svg {
|
||||
border: 2px solid darkred;
|
||||
}
|
||||
.exClass2 > rect,
|
||||
|
||||
@@ -106,363 +106,50 @@
|
||||
|
||||
<body>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart-elk TB
|
||||
c1-->a2
|
||||
subgraph one
|
||||
a1-->a2
|
||||
end
|
||||
subgraph two
|
||||
b1-->b2
|
||||
end
|
||||
subgraph three
|
||||
c1-->c2
|
||||
end
|
||||
one --> two
|
||||
three --> two
|
||||
two --> c2
|
||||
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart TB
|
||||
|
||||
process_C
|
||||
subgraph container_Alpha
|
||||
subgraph process_B
|
||||
pppB
|
||||
end
|
||||
subgraph process_A
|
||||
pppA
|
||||
end
|
||||
process_B-->|via_AWSBatch|container_Beta
|
||||
process_A-->|messages|container_Beta
|
||||
end
|
||||
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart TB
|
||||
subgraph container_Beta
|
||||
process_C
|
||||
end
|
||||
subgraph container_Alpha
|
||||
subgraph process_B
|
||||
pppB
|
||||
end
|
||||
subgraph process_A
|
||||
pppA
|
||||
end
|
||||
process_B-->|via_AWSBatch|container_Beta
|
||||
process_A-->|messages|container_Beta
|
||||
end
|
||||
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart TB
|
||||
subgraph container_Beta
|
||||
process_C
|
||||
end
|
||||
|
||||
process_B-->|via_AWSBatch|container_Beta
|
||||
|
||||
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
classDiagram
|
||||
note "I love this diagram!\nDo you love it?"
|
||||
Class01 <|-- AveryLongClass : Cool
|
||||
<<interface>> Class01
|
||||
Class03 "1" *-- "*" Class04
|
||||
Class05 "1" o-- "many" Class06
|
||||
Class07 "1" .. "*" Class08
|
||||
Class09 "1" --> "*" C2 : Where am i?
|
||||
Class09 "*" --* "*" C3
|
||||
Class09 "1" --|> "1" Class07
|
||||
Class12 <|.. Class08
|
||||
Class11 ..>Class12
|
||||
Class07 : equals()
|
||||
Class07 : Object[] elementData
|
||||
Class01 : size()
|
||||
Class01 : int chimp
|
||||
Class01 : int gorilla
|
||||
Class01 : -int privateChimp
|
||||
Class01 : +int publicGorilla
|
||||
Class01 : #int protectedMarmoset
|
||||
Class08 <--> C2: Cool label
|
||||
class Class10 {
|
||||
<<service>>
|
||||
int id
|
||||
test()
|
||||
}
|
||||
note for Class10 "Cool class\nI said it's very cool class!"
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
requirementDiagram
|
||||
requirement test_req {
|
||||
id: 1
|
||||
text: the test text.
|
||||
risk: high
|
||||
verifymethod: test
|
||||
}
|
||||
|
||||
element test_entity {
|
||||
type: simulation
|
||||
}
|
||||
|
||||
test_entity - satisfies -> test_req
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart-elk TB
|
||||
internet
|
||||
nat
|
||||
router
|
||||
compute1
|
||||
|
||||
subgraph project
|
||||
router
|
||||
nat
|
||||
subgraph subnet1
|
||||
compute1
|
||||
end
|
||||
end
|
||||
|
||||
%% router --> subnet1
|
||||
subnet1 --> nat
|
||||
%% nat --> internet
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
flowchart-elk TB
|
||||
internet
|
||||
nat
|
||||
router
|
||||
lb1
|
||||
lb2
|
||||
compute1
|
||||
compute2
|
||||
subgraph project
|
||||
router
|
||||
nat
|
||||
subgraph subnet1
|
||||
compute1
|
||||
lb1
|
||||
end
|
||||
subgraph subnet2
|
||||
compute2
|
||||
lb2
|
||||
end
|
||||
end
|
||||
internet --> router
|
||||
router --> subnet1 & subnet2
|
||||
subnet1 & subnet2 --> nat --> internet
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
elk:
|
||||
mergeEdges: false
|
||||
forceNodeModelOrder: false
|
||||
considerModelOrder: NONE
|
||||
|
||||
---
|
||||
flowchart TB
|
||||
a --> a1 & a2 & a3 & a4
|
||||
b --> b1 & b2
|
||||
b2 --> b3
|
||||
b1 --> b4</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
treemap
|
||||
"Section 1"
|
||||
"Leaf 1.1": 12
|
||||
"Section 1.2":::class1
|
||||
"Leaf 1.2.1": 12
|
||||
"Section 2"
|
||||
"Leaf 2.1": 20:::class1
|
||||
"Leaf 2.2": 25
|
||||
"Leaf 2.3": 12
|
||||
|
||||
</pre>
|
||||
<pre id="diagram5" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
flowchart:
|
||||
curve: rounded
|
||||
---
|
||||
flowchart LR
|
||||
I["fa:fa-code Text"] -- Mermaid js --> D["Use<br/>the<br/>editor!"]
|
||||
I --> D & D
|
||||
D@{ shape: question}
|
||||
I@{ shape: question}
|
||||
|
||||
AB["apa@apa@"] --> B(("`apa@apa`"))
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
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
|
||||
|
||||
flowchart
|
||||
D(("for D"))
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
flowchart:
|
||||
curve: linear
|
||||
---
|
||||
flowchart LR
|
||||
A[A] --> B[B]
|
||||
A[A] --- B([C])
|
||||
A@{ shape: diamond}
|
||||
%%B@{ shape: diamond}
|
||||
|
||||
A e1@==> B
|
||||
e1@{ animate: true}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
flowchart:
|
||||
curve: linear
|
||||
---
|
||||
flowchart LR
|
||||
A[A] -- Mermaid js --> B[B]
|
||||
A[A] -- Mermaid js --- B[B]
|
||||
A@{ shape: diamond}
|
||||
B@{ shape: diamond}
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
flowchart:
|
||||
curve: rounded
|
||||
---
|
||||
flowchart LR
|
||||
D["Use the editor"] -- Mermaid js --> I["fa:fa-code Text"]
|
||||
I --> D & D
|
||||
D@{ shape: question}
|
||||
I@{ shape: question}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
flowchart:
|
||||
curve: rounded
|
||||
elk:
|
||||
nodePlacementStrategy: NETWORK_SIMPLEX
|
||||
---
|
||||
flowchart LR
|
||||
D["Use the editor"] -- Mermaid js --> I["fa:fa-code Text"]
|
||||
D --> I & I
|
||||
a["a"]
|
||||
D@{ shape: trap-b}
|
||||
I@{ shape: lean-l}
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
|
||||
---
|
||||
flowchart LR
|
||||
%% subgraph s1["Untitled subgraph"]
|
||||
C["Evaluate"]
|
||||
%% end
|
||||
|
||||
B --> C
|
||||
A e1@--> B
|
||||
classDef animate stroke-width:2,stroke-dasharray:10\,8,stroke-dashoffset:-180,animation: edge-animation-frame 6s linear infinite, stroke-linecap: round
|
||||
class e1 animate
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
flowchart:
|
||||
//curve: linear
|
||||
---
|
||||
<h2>infinite</h2>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
%% A ==> B
|
||||
%% A2 --> B2
|
||||
A{A} --> B((Bo boo)) & B & B & B
|
||||
A e1@--> B
|
||||
classDef animate stroke-dasharray: 9\,5,stroke-dashoffset: 900,animation: dash 25s linear infinite;
|
||||
class e1 animate
|
||||
</pre>
|
||||
<h2>Mermaid - edge-animation-slow</h2>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
A e1@--> B
|
||||
e1@{ animation: fast}
|
||||
</pre>
|
||||
<h2>Mermaid - edge-animation-fast</h2>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
A e1@--> B
|
||||
classDef animate stroke-dasharray: 1000,stroke-dashoffset: 1000,animation: dash 10s linear;
|
||||
class e1 edge-animation-fast
|
||||
</pre>
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
theme: default
|
||||
look: classic
|
||||
---
|
||||
flowchart LR
|
||||
subgraph s1["APA"]
|
||||
D{"Use the editor"}
|
||||
end
|
||||
subgraph S2["S2"]
|
||||
s1
|
||||
I>"fa:fa-code Text"]
|
||||
E["E"]
|
||||
end
|
||||
D -- Mermaid js --> I
|
||||
D --> I & E
|
||||
E --> I
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
|
||||
info </pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
@@ -487,7 +174,7 @@ config:
|
||||
end
|
||||
end
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
@@ -500,7 +187,7 @@ config:
|
||||
D-->I
|
||||
D-->I
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
@@ -539,7 +226,7 @@ flowchart LR
|
||||
n8@{ shape: rect}
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
@@ -555,7 +242,7 @@ flowchart LR
|
||||
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
@@ -564,7 +251,7 @@ flowchart LR
|
||||
A{A} --> B & C
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
@@ -576,7 +263,7 @@ flowchart LR
|
||||
end
|
||||
</pre
|
||||
>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
@@ -594,7 +281,7 @@ flowchart LR
|
||||
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
kanban:
|
||||
@@ -613,81 +300,81 @@ kanban
|
||||
task3[💻 Develop login feature]@{ ticket: 103 }
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
nA[Default] --> A@{ icon: 'fa:bell', form: 'rounded' }
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
nA[Style] --> A@{ icon: 'fa:bell', form: 'rounded' }
|
||||
style A fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
nA[Class] --> A@{ icon: 'fa:bell', form: 'rounded' }
|
||||
A:::AClass
|
||||
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
nA[Class] --> A@{ icon: 'logos:aws', form: 'rounded' }
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
nA[Default] --> A@{ icon: 'fa:bell', form: 'square' }
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
nA[Style] --> A@{ icon: 'fa:bell', form: 'square' }
|
||||
style A fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
nA[Class] --> A@{ icon: 'fa:bell', form: 'square' }
|
||||
A:::AClass
|
||||
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
nA[Class] --> A@{ icon: 'logos:aws', form: 'square' }
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
nA[Default] --> A@{ icon: 'fa:bell', form: 'circle' }
|
||||
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
nA[Style] --> A@{ icon: 'fa:bell', form: 'circle' }
|
||||
style A fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
nA[Class] --> A@{ icon: 'fa:bell', form: 'circle' }
|
||||
A:::AClass
|
||||
classDef AClass fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
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">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
flowchart LR
|
||||
nA[Style] --> A@{ icon: 'logos:aws', form: 'circle' }
|
||||
style A fill:#f9f,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram4" class="mermaid">
|
||||
<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="mermaid">
|
||||
<pre id="diagram4" class="mermaid2">
|
||||
---
|
||||
config:
|
||||
kanban:
|
||||
@@ -758,7 +445,7 @@ kanban
|
||||
// look: 'handDrawn',
|
||||
// 'elk.nodePlacement.strategy': 'NETWORK_SIMPLEX',
|
||||
// layout: 'dagre',
|
||||
layout: 'elk',
|
||||
// layout: 'elk',
|
||||
// layout: 'fixed',
|
||||
// htmlLabels: false,
|
||||
flowchart: { titleTopMargin: 10 },
|
||||
|
||||
@@ -1,376 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Mermaid Quick Test Page</title>
|
||||
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
|
||||
<style>
|
||||
div.mermaid {
|
||||
font-family: 'Courier New', Courier, monospace !important;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
A
|
||||
B
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: dagre
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
A
|
||||
B
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
A
|
||||
B
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: cose-bilkent
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
A
|
||||
B
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
root((mindmap is a long thing))
|
||||
A
|
||||
B
|
||||
C
|
||||
D
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: dagre
|
||||
---
|
||||
mindmap
|
||||
root((mindmap is a long thing))
|
||||
A
|
||||
B
|
||||
C
|
||||
D
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
mindmap
|
||||
root((mindmap is a long thing))
|
||||
A
|
||||
B
|
||||
C
|
||||
D
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: cose-bilkent
|
||||
---
|
||||
mindmap
|
||||
root((mindmap is a long thing))
|
||||
A
|
||||
B
|
||||
C
|
||||
D
|
||||
</pre>
|
||||
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
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
|
||||
id)I am a cloud(
|
||||
id))I am a bang((
|
||||
Tools
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: dagre
|
||||
---
|
||||
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
|
||||
id)I am a cloud(
|
||||
id))I am a bang((
|
||||
Tools
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
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
|
||||
id)I am a cloud(
|
||||
id))I am a bang((
|
||||
Tools
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: cose-bilkent
|
||||
---
|
||||
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
|
||||
id)I am a cloud(
|
||||
id))I am a bang((
|
||||
Tools
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
A
|
||||
a
|
||||
apa[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
apa2[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
b
|
||||
c
|
||||
d
|
||||
B
|
||||
apa3[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
D
|
||||
apa5[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
apa4[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: dagre
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
A
|
||||
a
|
||||
apa[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
apa2[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
b
|
||||
c
|
||||
d
|
||||
B
|
||||
apa3[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
D
|
||||
apa5[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
apa4[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
A
|
||||
a
|
||||
apa[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
apa2[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
b
|
||||
c
|
||||
d
|
||||
B
|
||||
apa3[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
D
|
||||
apa5[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
apa4[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: cose-bilkent
|
||||
---
|
||||
mindmap
|
||||
root((mindmap))
|
||||
A
|
||||
a
|
||||
apa[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
apa2[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
b
|
||||
c
|
||||
d
|
||||
B
|
||||
apa3[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
D
|
||||
apa5[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
apa4[I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on. I am a long long multline string passing several levels of text. Lorum ipsum and so on]
|
||||
|
||||
</pre>
|
||||
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: tidy-tree
|
||||
---
|
||||
mindmap
|
||||
((This is a mindmap))
|
||||
child1
|
||||
grandchild 1
|
||||
grandchild 2
|
||||
child2
|
||||
grandchild 3
|
||||
grandchild 4
|
||||
child3
|
||||
grandchild 5
|
||||
grandchild 6
|
||||
|
||||
</pre>
|
||||
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: dagre
|
||||
---
|
||||
mindmap
|
||||
((This is a mindmap))
|
||||
child1
|
||||
grandchild 1
|
||||
grandchild 2
|
||||
child2
|
||||
grandchild 3
|
||||
grandchild 4
|
||||
child3
|
||||
grandchild 5
|
||||
grandchild 6
|
||||
|
||||
</pre>
|
||||
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
mindmap
|
||||
((This is a mindmap))
|
||||
child1
|
||||
grandchild 1
|
||||
grandchild 2
|
||||
child2
|
||||
grandchild 3
|
||||
grandchild 4
|
||||
child3
|
||||
grandchild 5
|
||||
grandchild 6
|
||||
|
||||
</pre>
|
||||
|
||||
<pre class="mermaid">
|
||||
---
|
||||
config:
|
||||
layout: cose-bilkent
|
||||
---
|
||||
mindmap
|
||||
((This is a mindmap))
|
||||
child1
|
||||
grandchild 1
|
||||
grandchild 2
|
||||
child2
|
||||
grandchild 3
|
||||
grandchild 4
|
||||
child3
|
||||
grandchild 5
|
||||
grandchild 6
|
||||
|
||||
</pre>
|
||||
|
||||
<hr />
|
||||
<script type="module">
|
||||
import mermaid from '/mermaid.esm.mjs';
|
||||
import tidytree from '/mermaid-layout-tidy-tree.esm.mjs';
|
||||
import layouts from './mermaid-layout-elk.esm.mjs';
|
||||
mermaid.registerLayoutLoaders(layouts);
|
||||
mermaid.registerLayoutLoaders(tidytree);
|
||||
mermaid.initialize({
|
||||
theme: 'default',
|
||||
logLevel: 3,
|
||||
securityLevel: 'loose',
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -41,6 +41,10 @@ graph TB
|
||||
const { svg } = await mermaid.render('d22', value);
|
||||
console.log(svg);
|
||||
el.innerHTML = svg;
|
||||
// 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>
|
||||
</body>
|
||||
</html>
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
import externalExample from './mermaid-example-diagram.esm.mjs';
|
||||
import layouts from './mermaid-layout-elk.esm.mjs';
|
||||
import tidyTree from './mermaid-layout-tidy-tree.esm.mjs';
|
||||
import zenUml from './mermaid-zenuml.esm.mjs';
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
|
||||
@@ -15,28 +14,12 @@ function markRendered() {
|
||||
}
|
||||
}
|
||||
|
||||
function loadFontAwesomeCSS() {
|
||||
const link = document.createElement('link');
|
||||
link.rel = 'stylesheet';
|
||||
link.href = 'https://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.7.2/css/all.min.css';
|
||||
|
||||
document.head.appendChild(link);
|
||||
|
||||
return new Promise((resolve, reject) => {
|
||||
link.onload = resolve;
|
||||
link.onerror = () => reject(new Error('Failed to load FontAwesome'));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* ##contentLoaded Callback function that is called when page is loaded. This functions fetches
|
||||
* configuration for mermaid rendering and calls init for rendering the mermaid diagrams on the
|
||||
* page.
|
||||
*/
|
||||
const contentLoaded = async function () {
|
||||
await loadFontAwesomeCSS();
|
||||
await Promise.all(Array.from(document.fonts, (font) => font.load()));
|
||||
|
||||
let pos = document.location.href.indexOf('?graph=');
|
||||
if (pos > 0) {
|
||||
pos = pos + 7;
|
||||
@@ -66,15 +49,9 @@ const contentLoaded = async function () {
|
||||
await mermaid.registerExternalDiagrams([externalExample, zenUml]);
|
||||
|
||||
mermaid.registerLayoutLoaders(layouts);
|
||||
mermaid.registerLayoutLoaders(tidyTree);
|
||||
mermaid.initialize(graphObj.mermaid);
|
||||
/**
|
||||
* CC-BY-4.0
|
||||
* Copyright (c) Fonticons, Inc. - https://fontawesome.com/license/free
|
||||
* https://fontawesome.com/icons/bell?f=classic&s=regular
|
||||
*/
|
||||
const staticBellIconPack = {
|
||||
prefix: 'fa',
|
||||
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"/>',
|
||||
@@ -184,7 +161,7 @@ const contentLoadedApi = async function () {
|
||||
for (let i = 0; i < numCodes; i++) {
|
||||
const { svg, bindFunctions } = await mermaid.render('newid' + i, graphObj.code[i], divs[i]);
|
||||
div.innerHTML = svg;
|
||||
bindFunctions?.(div);
|
||||
bindFunctions(div);
|
||||
}
|
||||
} else {
|
||||
const div = document.createElement('div');
|
||||
@@ -196,7 +173,7 @@ const contentLoadedApi = async function () {
|
||||
const { svg, bindFunctions } = await mermaid.render('newid', graphObj.code, div);
|
||||
div.innerHTML = svg;
|
||||
console.log(div.innerHTML);
|
||||
bindFunctions?.(div);
|
||||
bindFunctions(div);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
@@ -2,227 +2,211 @@
|
||||
"durations": [
|
||||
{
|
||||
"spec": "cypress/integration/other/configuration.spec.js",
|
||||
"duration": 5841
|
||||
"duration": 5450
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/other/external-diagrams.spec.js",
|
||||
"duration": 2138
|
||||
"duration": 2004
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/other/ghsa.spec.js",
|
||||
"duration": 3370
|
||||
"duration": 3183
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/other/iife.spec.js",
|
||||
"duration": 2052
|
||||
"duration": 1913
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/other/interaction.spec.js",
|
||||
"duration": 12243
|
||||
"duration": 10944
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/other/rerender.spec.js",
|
||||
"duration": 2065
|
||||
"duration": 1938
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/other/xss.spec.js",
|
||||
"duration": 31288
|
||||
"duration": 26753
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/appli.spec.js",
|
||||
"duration": 3421
|
||||
"duration": 2571
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/architecture.spec.ts",
|
||||
"duration": 97
|
||||
"duration": 110
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/block.spec.js",
|
||||
"duration": 18500
|
||||
"duration": 14697
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/c4.spec.js",
|
||||
"duration": 5793
|
||||
"duration": 4705
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/classDiagram-elk-v3.spec.js",
|
||||
"duration": 40966
|
||||
"duration": 35841
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/classDiagram-handDrawn-v3.spec.js",
|
||||
"duration": 39176
|
||||
"duration": 34279
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/classDiagram-v2.spec.js",
|
||||
"duration": 23468
|
||||
"duration": 20641
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/classDiagram-v3.spec.js",
|
||||
"duration": 38291
|
||||
"duration": 33020
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/classDiagram.spec.js",
|
||||
"duration": 16949
|
||||
"duration": 13546
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/conf-and-directives.spec.js",
|
||||
"duration": 9480
|
||||
"duration": 8072
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/current.spec.js",
|
||||
"duration": 2753
|
||||
"duration": 2083
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/erDiagram-unified.spec.js",
|
||||
"duration": 88028
|
||||
"duration": 78269
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/erDiagram.spec.js",
|
||||
"duration": 15615
|
||||
"duration": 12578
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/errorDiagram.spec.js",
|
||||
"duration": 3706
|
||||
"duration": 2784
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/flowchart-elk.spec.js",
|
||||
"duration": 43905
|
||||
"duration": 36205
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/flowchart-handDrawn.spec.js",
|
||||
"duration": 31217
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/flowchart-icon.spec.js",
|
||||
"duration": 7531
|
||||
"duration": 26627
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/flowchart-shape-alias.spec.ts",
|
||||
"duration": 25423
|
||||
"duration": 21332
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/flowchart-v2.spec.js",
|
||||
"duration": 49664
|
||||
"duration": 37328
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/flowchart.spec.js",
|
||||
"duration": 32525
|
||||
"duration": 25914
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/gantt.spec.js",
|
||||
"duration": 20915
|
||||
"duration": 15383
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/gitGraph.spec.js",
|
||||
"duration": 53556
|
||||
"duration": 45226
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/iconShape.spec.ts",
|
||||
"duration": 283038
|
||||
"duration": 251094
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/imageShape.spec.ts",
|
||||
"duration": 59434
|
||||
"duration": 50916
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/info.spec.ts",
|
||||
"duration": 3101
|
||||
"duration": 2489
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/journey.spec.js",
|
||||
"duration": 7099
|
||||
"duration": 5988
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/kanban.spec.ts",
|
||||
"duration": 7567
|
||||
"duration": 6225
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/katex.spec.js",
|
||||
"duration": 3817
|
||||
"duration": 3009
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/marker_unique_id.spec.js",
|
||||
"duration": 2624
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/mindmap-tidy-tree.spec.js",
|
||||
"duration": 4246
|
||||
"duration": 2426
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/mindmap.spec.ts",
|
||||
"duration": 11967
|
||||
"duration": 9306
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/newShapes.spec.ts",
|
||||
"duration": 151914
|
||||
"duration": 134419
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/oldShapes.spec.ts",
|
||||
"duration": 116698
|
||||
"duration": 102434
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/packet.spec.ts",
|
||||
"duration": 4967
|
||||
"duration": 3373
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/pie.spec.ts",
|
||||
"duration": 6700
|
||||
"duration": 4898
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/quadrantChart.spec.js",
|
||||
"duration": 8963
|
||||
"duration": 7578
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/radar.spec.js",
|
||||
"duration": 5540
|
||||
"duration": 4526
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/requirement.spec.js",
|
||||
"duration": 2782
|
||||
"duration": 2172
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/requirementDiagram-unified.spec.js",
|
||||
"duration": 54797
|
||||
"duration": 47175
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/sankey.spec.ts",
|
||||
"duration": 6914
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/sequencediagram-v2.spec.js",
|
||||
"duration": 20481
|
||||
"duration": 5717
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/sequencediagram.spec.js",
|
||||
"duration": 38490
|
||||
"duration": 32556
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/stateDiagram-v2.spec.js",
|
||||
"duration": 30766
|
||||
"duration": 22572
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/stateDiagram.spec.js",
|
||||
"duration": 16705
|
||||
"duration": 14064
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/theme.spec.js",
|
||||
"duration": 30928
|
||||
"duration": 26565
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/timeline.spec.ts",
|
||||
"duration": 8424
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/treemap.spec.ts",
|
||||
"duration": 12533
|
||||
"duration": 6233
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/xyChart.spec.js",
|
||||
"duration": 21197
|
||||
"duration": 17750
|
||||
},
|
||||
{
|
||||
"spec": "cypress/integration/rendering/zenuml.spec.js",
|
||||
"duration": 3455
|
||||
"duration": 2696
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,59 +0,0 @@
|
||||
import { execSync } from 'child_process';
|
||||
|
||||
console.log('=== DEBUGGING CALLBACK ARGUMENTS ===');
|
||||
|
||||
// Test the specific failing case
|
||||
const testInput = 'graph TD\nA-->B\nclick A call callback("test0", test1, test2)';
|
||||
console.log('Test input:', testInput);
|
||||
|
||||
// Create a temporary test file to debug the ANTLR parser
|
||||
import fs from 'fs';
|
||||
const testFile = `
|
||||
// Debug callback arguments parsing
|
||||
process.env.USE_ANTLR_PARSER = 'true';
|
||||
|
||||
const flow = require('./packages/mermaid/src/diagrams/flowchart/flowDb.ts');
|
||||
const parser = require('./packages/mermaid/src/diagrams/flowchart/parser/antlr/antlr-parser.ts');
|
||||
|
||||
console.log('Testing callback arguments parsing...');
|
||||
|
||||
// Mock the setClickEvent to see what parameters it receives
|
||||
const originalSetClickEvent = flow.default.setClickEvent;
|
||||
flow.default.setClickEvent = function(...args) {
|
||||
console.log('DEBUG setClickEvent called with args:', args);
|
||||
console.log(' - nodeId:', args[0]);
|
||||
console.log(' - functionName:', args[1]);
|
||||
console.log(' - functionArgs:', args[2]);
|
||||
console.log(' - args.length:', args.length);
|
||||
return originalSetClickEvent.apply(this, args);
|
||||
};
|
||||
|
||||
try {
|
||||
const result = parser.parse('${testInput}');
|
||||
console.log('Parse completed successfully');
|
||||
} catch (error) {
|
||||
console.log('Parse error:', error.message);
|
||||
}
|
||||
`;
|
||||
|
||||
fs.writeFileSync('debug-callback-test.js', testFile);
|
||||
|
||||
try {
|
||||
const result = execSync('node debug-callback-test.js', {
|
||||
cwd: '/Users/ashishjain/projects/mermaid',
|
||||
encoding: 'utf8',
|
||||
timeout: 10000,
|
||||
});
|
||||
console.log('Result:', result);
|
||||
} catch (error) {
|
||||
console.log('Error:', error.message);
|
||||
if (error.stdout) console.log('Stdout:', error.stdout);
|
||||
if (error.stderr) console.log('Stderr:', error.stderr);
|
||||
}
|
||||
|
||||
// Clean up
|
||||
try {
|
||||
fs.unlinkSync('debug-callback-test.js');
|
||||
} catch (e) {
|
||||
// Ignore cleanup errors
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
// Debug script to understand node processing order
|
||||
|
||||
console.log('=== Node Order Debug ===');
|
||||
|
||||
// Test case 1: n2["label for n2"] & n4@{ label: "label for n4"} & n5@{ label: "label for n5"}
|
||||
// Expected: nodes[0] = n2, nodes[1] = n4, nodes[2] = n5
|
||||
// Actual: nodes[0] = n4 (wrong!)
|
||||
|
||||
console.log('Test 1: n2["label for n2"] & n4@{ label: "label for n4"} & n5@{ label: "label for n5"}');
|
||||
console.log('Expected: n2, n4, n5');
|
||||
console.log('Actual: n4, ?, ?');
|
||||
|
||||
// Test case 2: A["A"] --> B["for B"] & C@{ label: "for c"} & E@{label : "for E"}
|
||||
// Expected: nodes[1] = B, nodes[2] = C
|
||||
// Actual: nodes[1] = C (wrong!)
|
||||
|
||||
console.log('\nTest 2: A["A"] --> B["for B"] & C@{ label: "for c"} & E@{label : "for E"}');
|
||||
console.log('Expected: A, B, C, E, D');
|
||||
console.log('Actual: A, C, ?, ?, ?');
|
||||
|
||||
console.log('\nThe issue appears to be that ampersand-chained nodes are processed in reverse order');
|
||||
console.log('or the node collection is not matching the Jison parser behavior.');
|
||||
@@ -10,7 +10,7 @@
|
||||
<body>
|
||||
<h1>Block diagram demos</h1>
|
||||
<pre id="diagram" class="mermaid">
|
||||
block
|
||||
block-beta
|
||||
columns 1
|
||||
db(("DB"))
|
||||
blockArrowId6<[" "]>(down)
|
||||
@@ -26,7 +26,7 @@ columns 1
|
||||
style B fill:#f9F,stroke:#333,stroke-width:4px
|
||||
</pre>
|
||||
<pre id="diagram" class="mermaid">
|
||||
block
|
||||
block-beta
|
||||
A1["square"]
|
||||
B1("rounded")
|
||||
C1(("circle"))
|
||||
@@ -36,7 +36,7 @@ block
|
||||
</pre>
|
||||
|
||||
<pre id="diagram" class="mermaid">
|
||||
block
|
||||
block-beta
|
||||
A1(["stadium"])
|
||||
A2[["subroutine"]]
|
||||
B1[("cylinder")]
|
||||
@@ -48,7 +48,7 @@ block
|
||||
</pre>
|
||||
|
||||
<pre id="diagram" class="mermaid">
|
||||
block
|
||||
block-beta
|
||||
block:e:4
|
||||
columns 2
|
||||
f
|
||||
@@ -57,7 +57,7 @@ block
|
||||
|
||||
</pre>
|
||||
<pre id="diagram" class="mermaid">
|
||||
block
|
||||
block-beta
|
||||
block:e:4
|
||||
columns 2
|
||||
f
|
||||
@@ -67,7 +67,7 @@ block
|
||||
|
||||
</pre>
|
||||
<pre id="diagram" class="mermaid">
|
||||
block
|
||||
block-beta
|
||||
columns 3
|
||||
a:3
|
||||
block:e:3
|
||||
@@ -80,7 +80,7 @@ block
|
||||
|
||||
</pre>
|
||||
<pre id="diagram" class="mermaid">
|
||||
block
|
||||
block-beta
|
||||
columns 4
|
||||
a b c d
|
||||
block:e:4
|
||||
@@ -97,19 +97,19 @@ flowchart LR
|
||||
X-- "a label" -->z
|
||||
</pre>
|
||||
<pre id="diagram" class="mermaid">
|
||||
block
|
||||
block-beta
|
||||
columns 5
|
||||
A space B
|
||||
A --x B
|
||||
</pre>
|
||||
<pre id="diagram" class="mermaid">
|
||||
block
|
||||
block-beta
|
||||
columns 3
|
||||
a["A wide one"] b:2 c:2 d
|
||||
</pre>
|
||||
|
||||
<pre id="diagram" class="mermaid">
|
||||
block
|
||||
block-beta
|
||||
columns 3
|
||||
a b c
|
||||
e:3
|
||||
@@ -117,7 +117,7 @@ columns 3
|
||||
</pre>
|
||||
|
||||
<pre id="diagram" class="mermaid">
|
||||
block
|
||||
block-beta
|
||||
|
||||
A1:3
|
||||
A2:1
|
||||
|
||||
@@ -1,331 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Mermaid Class ANTLR Parser Test Page</title>
|
||||
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
margin: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.test-section {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.parser-info {
|
||||
background: #e3f2fd;
|
||||
border: 1px solid #2196f3;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.success {
|
||||
background: #e8f5e8;
|
||||
border: 1px solid #4caf50;
|
||||
}
|
||||
|
||||
.error {
|
||||
background: #ffebee;
|
||||
border: 1px solid #f44336;
|
||||
}
|
||||
|
||||
.broken {
|
||||
background: #fff3e0;
|
||||
border: 1px solid #ff9800;
|
||||
}
|
||||
|
||||
div.mermaid {
|
||||
font-family: 'Courier New', Courier, monospace !important;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #1976d2;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #424242;
|
||||
border-bottom: 2px solid #e0e0e0;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
|
||||
#debug-logs {
|
||||
border: 1px solid #ccc;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
max-height: 400px;
|
||||
overflow-y: auto;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
.diagram-code {
|
||||
background: #f5f5f5;
|
||||
border: 1px solid #ddd;
|
||||
padding: 10px;
|
||||
margin: 10px 0;
|
||||
font-family: monospace;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>🎯 Mermaid Class ANTLR Parser Test Page</h1>
|
||||
|
||||
<div class="parser-info">
|
||||
<h3>🔧 Parser Information</h3>
|
||||
<p><strong>Environment Variable:</strong> <code id="env-var">Loading...</code></p>
|
||||
<p><strong>Expected:</strong> <code>USE_ANTLR_PARSER=true</code></p>
|
||||
<p><strong>Status:</strong> <span id="parser-status">Checking...</span></p>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Test 1: Simple Class Diagram</h2>
|
||||
<p>Basic class diagram to test ANTLR parser functionality:</p>
|
||||
<pre class="mermaid">
|
||||
classDiagram
|
||||
class Animal {
|
||||
+name: string
|
||||
+age: int
|
||||
+makeSound()
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Test 2: Class with Relationships</h2>
|
||||
<p>Testing class relationships:</p>
|
||||
<pre class="mermaid">
|
||||
classDiagram
|
||||
class Animal {
|
||||
+name: string
|
||||
+makeSound()
|
||||
}
|
||||
class Dog {
|
||||
+breed: string
|
||||
+bark()
|
||||
}
|
||||
Animal <|-- Dog
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="test-section broken">
|
||||
<h2>🚨 Test 3: BROKEN DIAGRAM - Debug Target</h2>
|
||||
<p><strong>This is the problematic diagram that needs debugging:</strong></p>
|
||||
<div class="diagram-code">classDiagram
|
||||
class Person {
|
||||
+ID : Guid
|
||||
+FirstName : string
|
||||
+LastName : string
|
||||
-privateProperty : string
|
||||
#ProtectedProperty : string
|
||||
~InternalProperty : string
|
||||
~AnotherInternalProperty : List~List~string~~
|
||||
}
|
||||
class People List~List~Person~~</div>
|
||||
<p><strong>Expected Error:</strong> Parse error on line 11: Expecting 'STR'</p>
|
||||
<pre class="mermaid">
|
||||
classDiagram
|
||||
class Person {
|
||||
+ID : Guid
|
||||
+FirstName : string
|
||||
+LastName : string
|
||||
-privateProperty : string
|
||||
#ProtectedProperty : string
|
||||
~InternalProperty : string
|
||||
~AnotherInternalProperty : List~List~string~~
|
||||
}
|
||||
class People List~List~Person~~
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Test 4: Generic Types (Simplified)</h2>
|
||||
<p>Testing simpler generic type syntax:</p>
|
||||
<pre class="mermaid">
|
||||
classDiagram
|
||||
class Person {
|
||||
+ID : Guid
|
||||
+FirstName : string
|
||||
+LastName : string
|
||||
}
|
||||
class People {
|
||||
+items : List~Person~
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Test 5: Visibility Modifiers</h2>
|
||||
<p>Testing different visibility modifiers:</p>
|
||||
<pre class="mermaid">
|
||||
classDiagram
|
||||
class TestClass {
|
||||
+publicField : string
|
||||
-privateField : string
|
||||
#protectedField : string
|
||||
~packageField : string
|
||||
+publicMethod()
|
||||
-privateMethod()
|
||||
#protectedMethod()
|
||||
~packageMethod()
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
|
||||
// Configure ANTLR parser for browser environment
|
||||
window.MERMAID_CONFIG = {
|
||||
USE_ANTLR_PARSER: 'true',
|
||||
USE_ANTLR_VISITOR: 'false', // Use listener pattern
|
||||
ANTLR_DEBUG: 'true'
|
||||
};
|
||||
|
||||
console.log('🎯 Class ANTLR Configuration:', window.MERMAID_CONFIG);
|
||||
|
||||
// Override console methods to capture logs
|
||||
const originalLog = console.log;
|
||||
const originalError = console.error;
|
||||
|
||||
function createLogDiv() {
|
||||
const logDiv = document.createElement('div');
|
||||
logDiv.id = 'debug-logs';
|
||||
logDiv.innerHTML = '<h3>🔍 Debug Logs:</h3>';
|
||||
document.body.appendChild(logDiv);
|
||||
return logDiv;
|
||||
}
|
||||
|
||||
console.log = function (...args) {
|
||||
originalLog.apply(console, args);
|
||||
// Display important logs on page
|
||||
if (args[0] && typeof args[0] === 'string' && (
|
||||
args[0].includes('ANTLR') ||
|
||||
args[0].includes('ClassDB:') ||
|
||||
args[0].includes('ClassListener:') ||
|
||||
args[0].includes('ClassVisitor:') ||
|
||||
args[0].includes('ClassParserCore:') ||
|
||||
args[0].includes('Class ANTLR') ||
|
||||
args[0].includes('🔧') ||
|
||||
args[0].includes('❌') ||
|
||||
args[0].includes('✅')
|
||||
)) {
|
||||
const logDiv = document.getElementById('debug-logs') || createLogDiv();
|
||||
logDiv.innerHTML += '<div style="color: blue; margin: 2px 0;">' + args.join(' ') + '</div>';
|
||||
}
|
||||
};
|
||||
|
||||
console.error = function (...args) {
|
||||
originalError.apply(console, args);
|
||||
const logDiv = document.getElementById('debug-logs') || createLogDiv();
|
||||
logDiv.innerHTML += '<div style="color: red; margin: 2px 0;">ERROR: ' + args.join(' ') + '</div>';
|
||||
};
|
||||
|
||||
// Initialize mermaid
|
||||
mermaid.initialize({
|
||||
theme: 'default',
|
||||
logLevel: 3,
|
||||
securityLevel: 'loose',
|
||||
class: {
|
||||
titleTopMargin: 25,
|
||||
diagramPadding: 50,
|
||||
htmlLabels: false
|
||||
},
|
||||
});
|
||||
|
||||
// Check environment and parser status
|
||||
let envVar = 'undefined';
|
||||
try {
|
||||
if (typeof process !== 'undefined' && process.env) {
|
||||
envVar = process.env.USE_ANTLR_PARSER || 'undefined';
|
||||
}
|
||||
} catch (e) {
|
||||
envVar = 'browser-default';
|
||||
}
|
||||
|
||||
const envElement = document.getElementById('env-var');
|
||||
const statusElement = document.getElementById('parser-status');
|
||||
|
||||
if (envElement) {
|
||||
envElement.textContent = `USE_ANTLR_PARSER=${envVar || 'undefined'}`;
|
||||
}
|
||||
|
||||
// Check for debug information from parser
|
||||
setTimeout(() => {
|
||||
if (window.MERMAID_PARSER_DEBUG) {
|
||||
console.log('🔍 Found MERMAID_PARSER_DEBUG:', window.MERMAID_PARSER_DEBUG);
|
||||
const debug = window.MERMAID_PARSER_DEBUG;
|
||||
|
||||
if (envElement) {
|
||||
envElement.textContent = `USE_ANTLR_PARSER=${debug.env_value || 'undefined'} (actual: ${debug.USE_ANTLR_PARSER})`;
|
||||
}
|
||||
|
||||
if (statusElement) {
|
||||
if (debug.USE_ANTLR_PARSER) {
|
||||
statusElement.innerHTML = '<span style="color: green;">✅ ANTLR Parser Active</span>';
|
||||
statusElement.parentElement.parentElement.classList.add('success');
|
||||
} else {
|
||||
statusElement.innerHTML = '<span style="color: orange;">⚠️ Jison Parser (Default)</span>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
if (statusElement) {
|
||||
if (envVar === 'true') {
|
||||
statusElement.innerHTML = '<span style="color: green;">✅ ANTLR Parser Active</span>';
|
||||
statusElement.parentElement.parentElement.classList.add('success');
|
||||
} else {
|
||||
statusElement.innerHTML = '<span style="color: orange;">⚠️ Jison Parser (Default)</span>';
|
||||
}
|
||||
}
|
||||
|
||||
// Add debugging
|
||||
console.log('🎯 Class ANTLR Parser Test Page Loaded');
|
||||
console.log('🔧 Environment:', { USE_ANTLR_PARSER: envVar });
|
||||
|
||||
// Test if we can detect which parser is being used
|
||||
setTimeout(() => {
|
||||
const mermaidElements = document.querySelectorAll('.mermaid');
|
||||
console.log(`📊 Found ${mermaidElements.length} class diagrams`);
|
||||
|
||||
// Check if diagrams rendered successfully
|
||||
const renderedElements = document.querySelectorAll('.mermaid svg');
|
||||
if (renderedElements.length > 0) {
|
||||
console.log('✅ Class diagrams rendered successfully!');
|
||||
console.log(`📈 ${renderedElements.length} SVG elements created`);
|
||||
|
||||
// Update status on page
|
||||
const statusElement = document.getElementById('parser-status');
|
||||
if (statusElement && envVar === 'true') {
|
||||
statusElement.innerHTML = '<span style="color: green;">✅ ANTLR Parser Active & Rendering Successfully!</span>';
|
||||
}
|
||||
} else {
|
||||
console.log('❌ No SVG elements found - check for rendering errors');
|
||||
console.log('🔍 Checking for error messages...');
|
||||
|
||||
// Look for error messages in mermaid elements
|
||||
mermaidElements.forEach((element, index) => {
|
||||
console.log(`📋 Class Diagram ${index + 1} content:`, element.textContent.trim());
|
||||
if (element.innerHTML.includes('error') || element.innerHTML.includes('Error')) {
|
||||
console.log(`❌ Error found in class diagram ${index + 1}:`, element.innerHTML);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 3000);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,222 +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/6.7.2/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://cdnjs.cloudflare.com/ajax/libs/font-awesome/6.5.1/css/all.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"
|
||||
/>
|
||||
<link
|
||||
href="https://fonts.googleapis.com/css2?family=Recursive:wght@300..1000&display=swap"
|
||||
rel="stylesheet"
|
||||
/>
|
||||
|
||||
<style>
|
||||
.recursive-500 {
|
||||
font-family: 'Recursive', serif;
|
||||
font-optical-sizing: auto;
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-variation-settings:
|
||||
'slnt' 0,
|
||||
'CASL' 0,
|
||||
'CRSV' 0.5,
|
||||
'MONO' 0;
|
||||
}
|
||||
body {
|
||||
/* background: rgb(221, 208, 208); */
|
||||
/* background: #333; */
|
||||
/* font-family: 'Arial'; */
|
||||
font-family: 'Recursive', serif;
|
||||
font-optical-sizing: auto;
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-variation-settings:
|
||||
'slnt' 0,
|
||||
'CASL' 0,
|
||||
'CRSV' 0.5,
|
||||
'MONO' 0;
|
||||
/* color: white; */
|
||||
/* font-size: 18px !important; */
|
||||
}
|
||||
.gridify.tiny {
|
||||
background-image:
|
||||
linear-gradient(transparent 11px, rgba(220, 220, 200, 0.8) 12px, transparent 12px),
|
||||
linear-gradient(90deg, transparent 11px, rgba(220, 220, 200, 0.8) 12px, transparent 12px);
|
||||
background-size:
|
||||
100% 12px,
|
||||
12px 100%;
|
||||
}
|
||||
|
||||
.gridify.dots {
|
||||
background-image: radial-gradient(
|
||||
circle at center,
|
||||
rgba(220, 220, 200, 0.8) 1px,
|
||||
transparent 1px
|
||||
);
|
||||
background-size: 24px 24px;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: grey;
|
||||
}
|
||||
|
||||
.mermaid2 {
|
||||
display: none;
|
||||
}
|
||||
|
||||
.mermaid svg {
|
||||
font-size: 16px !important;
|
||||
font-family: 'Recursive', serif;
|
||||
font-optical-sizing: auto;
|
||||
font-weight: 500;
|
||||
font-style: normal;
|
||||
font-variation-settings:
|
||||
'slnt' 0,
|
||||
'CASL' 0,
|
||||
'CRSV' 0.5,
|
||||
'MONO' 0;
|
||||
}
|
||||
|
||||
pre {
|
||||
width: 100%;
|
||||
/*box-shadow: 4px 4px 0px 0px #0000000F;*/
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body class="gridify dots">
|
||||
<div class="w-full h-64">
|
||||
<pre id="diagram4" class="mermaid" style="background: rgb(255, 255, 255)">
|
||||
erDiagram
|
||||
CAR ||--o{ NAMED-DRIVER : allows
|
||||
CAR ::: Pine {
|
||||
string registrationNumber PK "Primary Key<br><strong>Unique registration number</strong>"
|
||||
string make "Car make<br><strong>e.g., Toyota</strong>"
|
||||
string model "Model of the car<br><strong>e.g., Corolla</strong>"
|
||||
string[] parts "List of parts<br><strong>Stored as array</strong>"
|
||||
}
|
||||
PERSON ||--o{ NAMED-DRIVER : is
|
||||
PERSON ::: someclass {
|
||||
string driversLicense PK "The license #<br><strong>Primary Key</strong>"
|
||||
string(99) firstName "Only 99 characters <br>are allowed <br> <strong>e.g., Smith</strong>"
|
||||
string lastName "Last name of person<br><strong>e.g., Smith</strong>"
|
||||
string phone UK "Unique phone number<br><strong>Used for contact</strong>"
|
||||
int age "Age of the person<br><strong>Must be numeric</strong>"
|
||||
}
|
||||
NAMED-DRIVER {
|
||||
string carRegistrationNumber PK, FK, UK, PK "Foreign key to CAR<br><strong>Also part of PK</strong>"
|
||||
string driverLicence PK, FK "Foreign key to PERSON<br><strong>Also part of PK</strong>"
|
||||
}
|
||||
MANUFACTURER only one to zero or more CAR : makesx
|
||||
</pre>
|
||||
<hr />
|
||||
<pre class="mermaid">
|
||||
erDiagram
|
||||
_**testẽζ➕Ø😀㌕ぼ**_ {
|
||||
*__List~List~int~~sdfds__* **driversLicense** PK "***The l😀icense #***"
|
||||
string last*Name*
|
||||
string __phone__ UK
|
||||
*string(99)~T~~~~~~* firstName "Only __99__ <br>characters are a<br>llowed dsfsdfsdfsdfs"
|
||||
int _age_
|
||||
}
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
import layouts from './mermaid-layout-elk.esm.mjs';
|
||||
|
||||
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) {
|
||||
console.error('Mermaid error: ', err);
|
||||
};
|
||||
window.callback = function () {
|
||||
alert('A callback was triggered');
|
||||
};
|
||||
function callback() {
|
||||
alert('It worked');
|
||||
}
|
||||
await mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
|
||||
theme: 'forest',
|
||||
look: 'classic',
|
||||
layout: 'dagre',
|
||||
|
||||
// theme: 'default',
|
||||
// look: 'classic',
|
||||
flowchart: { titleTopMargin: 10 },
|
||||
fontFamily: 'Recursive',
|
||||
sequence: {
|
||||
actorFontFamily: 'courier',
|
||||
noteFontFamily: 'courier',
|
||||
messageFontFamily: 'courier',
|
||||
},
|
||||
kanban: {
|
||||
htmlLabels: false,
|
||||
},
|
||||
fontSize: 16,
|
||||
logLevel: 0,
|
||||
securityLevel: 'loose',
|
||||
callback,
|
||||
});
|
||||
// setTimeout(() => {
|
||||
mermaid.init(undefined, document.querySelectorAll('.mermaid'));
|
||||
// }, 1000);
|
||||
mermaid.parseError = function (err, hash) {
|
||||
console.error('In parse error:');
|
||||
console.error(err);
|
||||
};
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -1,269 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
|
||||
<title>Mermaid ANTLR Parser Test Page</title>
|
||||
<link rel="icon" type="image/png" href="data:image/png;base64,iVBORw0KGgo=" />
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Courier New', Courier, monospace;
|
||||
margin: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
|
||||
.test-section {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
margin: 20px 0;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.1);
|
||||
}
|
||||
|
||||
.parser-info {
|
||||
background: #e3f2fd;
|
||||
border: 1px solid #2196f3;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
|
||||
.success {
|
||||
background: #e8f5e8;
|
||||
border: 1px solid #4caf50;
|
||||
}
|
||||
|
||||
.error {
|
||||
background: #ffebee;
|
||||
border: 1px solid #f44336;
|
||||
}
|
||||
|
||||
div.mermaid {
|
||||
font-family: 'Courier New', Courier, monospace !important;
|
||||
}
|
||||
|
||||
h1 {
|
||||
color: #1976d2;
|
||||
}
|
||||
|
||||
h2 {
|
||||
color: #424242;
|
||||
border-bottom: 2px solid #e0e0e0;
|
||||
padding-bottom: 5px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body>
|
||||
<h1>🎯 Mermaid ANTLR Parser Test Page</h1>
|
||||
|
||||
<div class="parser-info">
|
||||
<h3>🔧 Parser Information</h3>
|
||||
<p><strong>Environment Variable:</strong> <code id="env-var">Loading...</code></p>
|
||||
<p><strong>Expected:</strong> <code>USE_ANTLR_PARSER=true</code></p>
|
||||
<p><strong>Status:</strong> <span id="parser-status">Checking...</span></p>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Test 1: Basic Flowchart</h2>
|
||||
<p>Simple flowchart to test basic ANTLR parser functionality:</p>
|
||||
<pre class="mermaid">
|
||||
flowchart TD
|
||||
A[Start] --> B[End]
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Test 4: Complex Shapes with Text</h2>
|
||||
<p>Testing various node shapes with complex text content:</p>
|
||||
<pre class="mermaid">
|
||||
flowchart LR
|
||||
A(Round Node) --> B{Diamond}
|
||||
B --> C([Stadium])
|
||||
C --> D[[Subroutine]]
|
||||
D --> E[(Database)]
|
||||
E --> F((Circle))
|
||||
F --> G[/Parallelogram/]
|
||||
G --> H[\Trapezoid\]
|
||||
H --> I[Mixed Text with / slash]
|
||||
I --> J[\Mixed Text with \ backslash\]
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Test 5: Classes and Styles</h2>
|
||||
<p>Testing class and style processing:</p>
|
||||
<pre class="mermaid">
|
||||
flowchart TD
|
||||
A[Node A] --> B[Node B]
|
||||
B --> C[Node C]
|
||||
|
||||
classDef redClass fill:#ff9999,stroke:#333,stroke-width:2px
|
||||
classDef blueClass fill:#9999ff,stroke:#333,stroke-width:2px
|
||||
|
||||
class A redClass
|
||||
class B,C blueClass
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Test 6: Subgraphs</h2>
|
||||
<p>Testing subgraph processing:</p>
|
||||
<pre class="mermaid">
|
||||
flowchart TD
|
||||
subgraph Main["Main Process"]
|
||||
A[Start] --> B[Process]
|
||||
end
|
||||
|
||||
subgraph Sub["Sub Process"]
|
||||
C[Sub Start] --> D[Sub End]
|
||||
end
|
||||
|
||||
B --> C
|
||||
D --> E[Final End]
|
||||
</pre>
|
||||
</div>
|
||||
|
||||
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
|
||||
// Configure ANTLR parser for browser environment
|
||||
// Since process.env is not available in browser, we set up global config
|
||||
window.MERMAID_CONFIG = {
|
||||
USE_ANTLR_PARSER: 'true',
|
||||
USE_ANTLR_VISITOR: 'true',
|
||||
ANTLR_DEBUG: 'true'
|
||||
};
|
||||
|
||||
console.log('🎯 Browser ANTLR Configuration:', window.MERMAID_CONFIG);
|
||||
|
||||
// Override console methods to capture logs
|
||||
const originalLog = console.log;
|
||||
const originalError = console.error;
|
||||
|
||||
console.log = function (...args) {
|
||||
originalLog.apply(console, args);
|
||||
// Display important logs on page
|
||||
if (args[0] && typeof args[0] === 'string' && (
|
||||
args[0].includes('ANTLR Parser:') ||
|
||||
args[0].includes('FlowDB:') ||
|
||||
args[0].includes('FlowchartListener:')
|
||||
)) {
|
||||
const logDiv = document.getElementById('debug-logs') || createLogDiv();
|
||||
logDiv.innerHTML += '<div style="color: blue;">' + args.join(' ') + '</div>';
|
||||
}
|
||||
};
|
||||
|
||||
console.error = function (...args) {
|
||||
originalError.apply(console, args);
|
||||
const logDiv = document.getElementById('debug-logs') || createLogDiv();
|
||||
logDiv.innerHTML += '<div style="color: red;">ERROR: ' + args.join(' ') + '</div>';
|
||||
};
|
||||
|
||||
function createLogDiv() {
|
||||
const logDiv = document.createElement('div');
|
||||
logDiv.id = 'debug-logs';
|
||||
logDiv.style.cssText = 'border: 1px solid #ccc; padding: 10px; margin: 10px 0; max-height: 300px; overflow-y: auto; font-family: monospace; font-size: 12px; background: #f9f9f9;';
|
||||
logDiv.innerHTML = '<h3>Debug Logs:</h3>';
|
||||
document.body.appendChild(logDiv);
|
||||
return logDiv;
|
||||
}
|
||||
|
||||
// Initialize mermaid
|
||||
mermaid.initialize({
|
||||
theme: 'default',
|
||||
logLevel: 3,
|
||||
securityLevel: 'loose',
|
||||
flowchart: { curve: 'basis' },
|
||||
});
|
||||
|
||||
// Check environment and parser status
|
||||
let envVar = 'undefined';
|
||||
try {
|
||||
if (typeof process !== 'undefined' && process.env) {
|
||||
envVar = process.env.USE_ANTLR_PARSER || 'undefined';
|
||||
}
|
||||
} catch (e) {
|
||||
// process is not defined in browser
|
||||
envVar = 'browser-default';
|
||||
}
|
||||
const envElement = document.getElementById('env-var');
|
||||
const statusElement = document.getElementById('parser-status');
|
||||
|
||||
if (envElement) {
|
||||
envElement.textContent = `USE_ANTLR_PARSER=${envVar || 'undefined'}`;
|
||||
}
|
||||
|
||||
// Check for debug information from parser
|
||||
setTimeout(() => {
|
||||
if (window.MERMAID_PARSER_DEBUG) {
|
||||
console.log('🔍 Found MERMAID_PARSER_DEBUG:', window.MERMAID_PARSER_DEBUG);
|
||||
const debug = window.MERMAID_PARSER_DEBUG;
|
||||
|
||||
if (envElement) {
|
||||
envElement.textContent = `USE_ANTLR_PARSER=${debug.env_value || 'undefined'} (actual: ${debug.USE_ANTLR_PARSER})`;
|
||||
}
|
||||
|
||||
if (statusElement) {
|
||||
if (debug.USE_ANTLR_PARSER) {
|
||||
statusElement.innerHTML = '<span style="color: green;">✅ ANTLR Parser Active</span>';
|
||||
statusElement.parentElement.parentElement.classList.add('success');
|
||||
} else {
|
||||
statusElement.innerHTML = '<span style="color: orange;">⚠️ Jison Parser (Default)</span>';
|
||||
}
|
||||
}
|
||||
} else {
|
||||
console.log('❌ MERMAID_PARSER_DEBUG not found on window');
|
||||
}
|
||||
}, 1000);
|
||||
|
||||
if (statusElement) {
|
||||
if (envVar === 'true') {
|
||||
statusElement.innerHTML = '<span style="color: green;">✅ ANTLR Parser Active</span>';
|
||||
statusElement.parentElement.parentElement.classList.add('success');
|
||||
} else {
|
||||
statusElement.innerHTML = '<span style="color: orange;">⚠️ Jison Parser (Default)</span>';
|
||||
}
|
||||
}
|
||||
|
||||
// Add some debugging
|
||||
console.log('🎯 ANTLR Parser Test Page Loaded');
|
||||
console.log('🔧 Environment:', { USE_ANTLR_PARSER: envVar });
|
||||
|
||||
// Test if we can detect which parser is being used
|
||||
setTimeout(() => {
|
||||
const mermaidElements = document.querySelectorAll('.mermaid');
|
||||
console.log(`📊 Found ${mermaidElements.length} mermaid diagrams`);
|
||||
|
||||
// Check if diagrams rendered successfully
|
||||
const renderedElements = document.querySelectorAll('.mermaid svg');
|
||||
if (renderedElements.length > 0) {
|
||||
console.log('✅ Diagrams rendered successfully!');
|
||||
console.log(`📈 ${renderedElements.length} SVG elements created`);
|
||||
|
||||
// Update status on page
|
||||
const statusElement = document.getElementById('parser-status');
|
||||
if (statusElement && envVar === 'true') {
|
||||
statusElement.innerHTML = '<span style="color: green;">✅ ANTLR Parser Active & Rendering Successfully!</span>';
|
||||
}
|
||||
} else {
|
||||
console.log('❌ No SVG elements found - check for rendering errors');
|
||||
console.log('🔍 Checking for error messages...');
|
||||
|
||||
// Look for error messages in mermaid elements
|
||||
mermaidElements.forEach((element, index) => {
|
||||
console.log(`📋 Diagram ${index + 1} content:`, element.textContent.trim());
|
||||
if (element.innerHTML.includes('error') || element.innerHTML.includes('Error')) {
|
||||
console.log(`❌ Error found in diagram ${index + 1}:`, element.innerHTML);
|
||||
}
|
||||
});
|
||||
}
|
||||
}, 3000);
|
||||
</script>
|
||||
</body>
|
||||
|
||||
</html>
|
||||
@@ -1,358 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>🚀 Hybrid Sequence Editor Test</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
|
||||
margin: 20px;
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: #333;
|
||||
min-height: 100vh;
|
||||
}
|
||||
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
background: white;
|
||||
border-radius: 15px;
|
||||
padding: 30px;
|
||||
box-shadow: 0 20px 40px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
h1 {
|
||||
text-align: center;
|
||||
color: #4a5568;
|
||||
margin-bottom: 30px;
|
||||
font-size: 2.5em;
|
||||
}
|
||||
|
||||
.test-section {
|
||||
margin: 30px 0;
|
||||
padding: 20px;
|
||||
border: 2px solid #e2e8f0;
|
||||
border-radius: 10px;
|
||||
background: #f8fafc;
|
||||
}
|
||||
|
||||
.test-section h2 {
|
||||
color: #2d3748;
|
||||
margin-bottom: 15px;
|
||||
font-size: 1.5em;
|
||||
}
|
||||
|
||||
.controls {
|
||||
display: flex;
|
||||
gap: 15px;
|
||||
margin-bottom: 20px;
|
||||
flex-wrap: wrap;
|
||||
}
|
||||
|
||||
button {
|
||||
padding: 12px 24px;
|
||||
border: none;
|
||||
border-radius: 8px;
|
||||
cursor: pointer;
|
||||
font-weight: 600;
|
||||
font-size: 14px;
|
||||
transition: all 0.3s ease;
|
||||
box-shadow: 0 4px 6px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.btn-primary {
|
||||
background: linear-gradient(135deg, #667eea 0%, #764ba2 100%);
|
||||
color: white;
|
||||
}
|
||||
|
||||
.btn-primary:hover {
|
||||
transform: translateY(-2px);
|
||||
box-shadow: 0 6px 12px rgba(0,0,0,0.15);
|
||||
}
|
||||
|
||||
.btn-secondary {
|
||||
background: #e2e8f0;
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
.btn-secondary:hover {
|
||||
background: #cbd5e0;
|
||||
}
|
||||
|
||||
.code-block {
|
||||
background: #1a202c;
|
||||
color: #e2e8f0;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 14px;
|
||||
line-height: 1.5;
|
||||
overflow-x: auto;
|
||||
margin: 15px 0;
|
||||
white-space: pre-wrap;
|
||||
}
|
||||
|
||||
.result-section {
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
background: #f0fff4;
|
||||
border-left: 4px solid #48bb78;
|
||||
}
|
||||
|
||||
.error-section {
|
||||
margin-top: 20px;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
background: #fff5f5;
|
||||
border-left: 4px solid #f56565;
|
||||
}
|
||||
|
||||
.stats {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(200px, 1fr));
|
||||
gap: 15px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.stat-card {
|
||||
background: white;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
text-align: center;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.stat-value {
|
||||
font-size: 2em;
|
||||
font-weight: bold;
|
||||
color: #667eea;
|
||||
}
|
||||
|
||||
.stat-label {
|
||||
color: #718096;
|
||||
font-size: 0.9em;
|
||||
margin-top: 5px;
|
||||
}
|
||||
|
||||
.operations {
|
||||
display: grid;
|
||||
grid-template-columns: repeat(auto-fit, minmax(250px, 1fr));
|
||||
gap: 15px;
|
||||
margin: 20px 0;
|
||||
}
|
||||
|
||||
.operation-card {
|
||||
background: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
|
||||
.operation-card h3 {
|
||||
margin-top: 0;
|
||||
color: #4a5568;
|
||||
}
|
||||
|
||||
input, select {
|
||||
width: 100%;
|
||||
padding: 8px 12px;
|
||||
border: 1px solid #e2e8f0;
|
||||
border-radius: 4px;
|
||||
margin: 5px 0;
|
||||
font-size: 14px;
|
||||
}
|
||||
|
||||
.log-output {
|
||||
background: #2d3748;
|
||||
color: #e2e8f0;
|
||||
padding: 15px;
|
||||
border-radius: 8px;
|
||||
font-family: 'Courier New', monospace;
|
||||
font-size: 12px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
margin: 15px 0;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>🚀 Hybrid Sequence Editor Test</h1>
|
||||
<p style="text-align: center; color: #718096; font-size: 1.1em;">
|
||||
Testing the new hybrid approach: AST-based editing + TokenStreamRewriter for optimal performance
|
||||
</p>
|
||||
|
||||
<!-- Test Section 1: Basic Functionality -->
|
||||
<div class="test-section">
|
||||
<h2>🎯 Basic Hybrid Editor Test</h2>
|
||||
<div class="controls">
|
||||
<button class="btn-primary" onclick="testBasicFunctionality()">Test Basic Functionality</button>
|
||||
<button class="btn-secondary" onclick="clearResults()">Clear Results</button>
|
||||
</div>
|
||||
|
||||
<div class="code-block" id="originalCode">sequenceDiagram
|
||||
Alice->>Bob: Hello Bob, how are you?
|
||||
Bob-->>Alice: Great!</div>
|
||||
|
||||
<div id="basicResults"></div>
|
||||
</div>
|
||||
|
||||
<!-- Test Section 2: CRUD Operations -->
|
||||
<div class="test-section">
|
||||
<h2>✏️ CRUD Operations Test</h2>
|
||||
<div class="operations">
|
||||
<div class="operation-card">
|
||||
<h3>Add Participant</h3>
|
||||
<input type="text" id="participantId" placeholder="Participant ID (e.g., C)" />
|
||||
<input type="text" id="participantAlias" placeholder="Alias (e.g., Charlie)" />
|
||||
<button class="btn-primary" onclick="addParticipant()">Add Participant</button>
|
||||
</div>
|
||||
|
||||
<div class="operation-card">
|
||||
<h3>Add Message</h3>
|
||||
<input type="text" id="messageFrom" placeholder="From (e.g., Alice)" />
|
||||
<input type="text" id="messageTo" placeholder="To (e.g., Bob)" />
|
||||
<input type="text" id="messageText" placeholder="Message text" />
|
||||
<select id="messageArrow">
|
||||
<option value="->>">->></option>
|
||||
<option value="-->>">-->></option>
|
||||
<option value="->">-></option>
|
||||
<option value="-->">--></option>
|
||||
</select>
|
||||
<button class="btn-primary" onclick="addMessage()">Add Message</button>
|
||||
</div>
|
||||
|
||||
<div class="operation-card">
|
||||
<h3>Add Note</h3>
|
||||
<select id="notePosition">
|
||||
<option value="right">right</option>
|
||||
<option value="left">left</option>
|
||||
<option value="over">over</option>
|
||||
</select>
|
||||
<input type="text" id="noteParticipant" placeholder="Participant (e.g., Bob)" />
|
||||
<input type="text" id="noteText" placeholder="Note text" />
|
||||
<button class="btn-primary" onclick="addNote()">Add Note</button>
|
||||
</div>
|
||||
|
||||
<div class="operation-card">
|
||||
<h3>Move Statement</h3>
|
||||
<input type="number" id="moveFrom" placeholder="From index" />
|
||||
<input type="number" id="moveTo" placeholder="To index" />
|
||||
<button class="btn-primary" onclick="moveStatement()">Move Statement</button>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="controls">
|
||||
<button class="btn-primary" onclick="regenerateCode()">Regenerate Code</button>
|
||||
<button class="btn-secondary" onclick="showAST()">Show AST</button>
|
||||
<button class="btn-secondary" onclick="validateAST()">Validate AST</button>
|
||||
</div>
|
||||
|
||||
<div id="crudResults"></div>
|
||||
</div>
|
||||
|
||||
<!-- Test Section 3: Performance Comparison -->
|
||||
<div class="test-section">
|
||||
<h2>⚡ Performance Test</h2>
|
||||
<div class="controls">
|
||||
<button class="btn-primary" onclick="performanceTest()">Run Performance Test</button>
|
||||
<select id="testSize">
|
||||
<option value="small">Small (10 statements)</option>
|
||||
<option value="medium">Medium (50 statements)</option>
|
||||
<option value="large">Large (200 statements)</option>
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div id="performanceResults"></div>
|
||||
</div>
|
||||
|
||||
<!-- Debug Log -->
|
||||
<div class="test-section">
|
||||
<h2>🔍 Debug Log</h2>
|
||||
<div class="controls">
|
||||
<button class="btn-secondary" onclick="clearLog()">Clear Log</button>
|
||||
</div>
|
||||
<div class="log-output" id="debugLog"></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
// This will be implemented to test the hybrid editor
|
||||
console.log('🚀 Hybrid Sequence Editor Test Page Loaded');
|
||||
|
||||
// Global variables for testing
|
||||
let hybridEditor = null;
|
||||
let currentAST = null;
|
||||
|
||||
// Test functions will be implemented here
|
||||
window.testBasicFunctionality = function() {
|
||||
log('🎯 Testing basic hybrid editor functionality...');
|
||||
log('⚠️ Implementation pending - hybrid editor classes need to be imported');
|
||||
};
|
||||
|
||||
window.addParticipant = function() {
|
||||
const id = document.getElementById('participantId').value;
|
||||
const alias = document.getElementById('participantAlias').value;
|
||||
log(`👤 Adding participant: ${id}${alias ? ` as ${alias}` : ''}`);
|
||||
};
|
||||
|
||||
window.addMessage = function() {
|
||||
const from = document.getElementById('messageFrom').value;
|
||||
const to = document.getElementById('messageTo').value;
|
||||
const text = document.getElementById('messageText').value;
|
||||
const arrow = document.getElementById('messageArrow').value;
|
||||
log(`💬 Adding message: ${from}${arrow}${to}: ${text}`);
|
||||
};
|
||||
|
||||
window.addNote = function() {
|
||||
const position = document.getElementById('notePosition').value;
|
||||
const participant = document.getElementById('noteParticipant').value;
|
||||
const text = document.getElementById('noteText').value;
|
||||
log(`📝 Adding note: Note ${position} of ${participant}: ${text}`);
|
||||
};
|
||||
|
||||
window.moveStatement = function() {
|
||||
const from = document.getElementById('moveFrom').value;
|
||||
const to = document.getElementById('moveTo').value;
|
||||
log(`🔄 Moving statement from ${from} to ${to}`);
|
||||
};
|
||||
|
||||
window.regenerateCode = function() {
|
||||
log('🔄 Regenerating code from AST...');
|
||||
};
|
||||
|
||||
window.showAST = function() {
|
||||
log('🌳 Showing current AST structure...');
|
||||
};
|
||||
|
||||
window.validateAST = function() {
|
||||
log('✅ Validating AST structure...');
|
||||
};
|
||||
|
||||
window.performanceTest = function() {
|
||||
const size = document.getElementById('testSize').value;
|
||||
log(`⚡ Running performance test with ${size} dataset...`);
|
||||
};
|
||||
|
||||
window.clearResults = function() {
|
||||
document.getElementById('basicResults').innerHTML = '';
|
||||
document.getElementById('crudResults').innerHTML = '';
|
||||
document.getElementById('performanceResults').innerHTML = '';
|
||||
};
|
||||
|
||||
window.clearLog = function() {
|
||||
document.getElementById('debugLog').innerHTML = '';
|
||||
};
|
||||
|
||||
function log(message) {
|
||||
const logElement = document.getElementById('debugLog');
|
||||
const timestamp = new Date().toLocaleTimeString();
|
||||
logElement.innerHTML += `[${timestamp}] ${message}\n`;
|
||||
logElement.scrollTop = logElement.scrollHeight;
|
||||
console.log(message);
|
||||
}
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -17,7 +17,7 @@
|
||||
|
||||
<div class="diagrams">
|
||||
<pre class="mermaid">
|
||||
packet
|
||||
packet-beta
|
||||
0-15: "Source Port"
|
||||
16-31: "Destination Port"
|
||||
32-63: "Sequence Number"
|
||||
@@ -44,7 +44,7 @@
|
||||
packet:
|
||||
showBits: false
|
||||
---
|
||||
packet
|
||||
packet-beta
|
||||
0-15: "Source Port"
|
||||
16-31: "Destination Port"
|
||||
32-63: "Sequence Number"
|
||||
@@ -70,7 +70,7 @@
|
||||
config:
|
||||
theme: forest
|
||||
---
|
||||
packet
|
||||
packet-beta
|
||||
title Forest theme
|
||||
0-15: "Source Port"
|
||||
16-31: "Destination Port"
|
||||
@@ -97,7 +97,7 @@
|
||||
config:
|
||||
theme: dark
|
||||
---
|
||||
packet
|
||||
packet-beta
|
||||
title Dark theme
|
||||
0-15: "Source Port"
|
||||
16-31: "Destination Port"
|
||||
|
||||
@@ -20,14 +20,12 @@
|
||||
width: 800
|
||||
nodeAlignment: left
|
||||
---
|
||||
sankey
|
||||
a,b,8
|
||||
b,c,8
|
||||
c,d,8
|
||||
d,e,8
|
||||
|
||||
x,c,4
|
||||
c,y,4
|
||||
sankey-beta
|
||||
Revenue,Expenses,10
|
||||
Revenue,Profit,10
|
||||
Expenses,Manufacturing,5
|
||||
Expenses,Tax,3
|
||||
Expenses,Research,2
|
||||
</pre>
|
||||
|
||||
<h2>Energy flow</h2>
|
||||
@@ -42,7 +40,7 @@
|
||||
linkColor: gradient
|
||||
nodeAlignment: justify
|
||||
---
|
||||
sankey
|
||||
sankey-beta
|
||||
|
||||
Agricultural 'waste',Bio-conversion,124.729
|
||||
Bio-conversion,Liquid,0.597
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -1,216 +0,0 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>Simple ANTLR Parser Test</title>
|
||||
<style>
|
||||
body {
|
||||
font-family: Arial, sans-serif;
|
||||
margin: 20px;
|
||||
background-color: #f5f5f5;
|
||||
}
|
||||
.container {
|
||||
max-width: 1200px;
|
||||
margin: 0 auto;
|
||||
background-color: white;
|
||||
padding: 20px;
|
||||
border-radius: 8px;
|
||||
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
|
||||
}
|
||||
.status {
|
||||
background-color: #e8f4fd;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 20px;
|
||||
border-left: 4px solid #2196F3;
|
||||
}
|
||||
.debug-logs {
|
||||
background-color: #f8f9fa;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
margin-bottom: 20px;
|
||||
font-family: monospace;
|
||||
font-size: 12px;
|
||||
max-height: 300px;
|
||||
overflow-y: auto;
|
||||
border: 1px solid #dee2e6;
|
||||
}
|
||||
.test-section {
|
||||
margin: 20px 0;
|
||||
padding: 15px;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.mermaid {
|
||||
text-align: center;
|
||||
margin: 20px 0;
|
||||
}
|
||||
h1 { color: #333; }
|
||||
h2 { color: #666; }
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<div class="container">
|
||||
<h1>🧪 Simple ANTLR Parser Test</h1>
|
||||
|
||||
<div class="status">
|
||||
<h3>Parser Status</h3>
|
||||
<p><strong>Environment Variable:</strong> <span id="env-var">Loading...</span></p>
|
||||
<p><strong>Parser Status:</strong> <span id="parser-status">Loading...</span></p>
|
||||
<p><strong>Global Config:</strong> <span id="global-config">Loading...</span></p>
|
||||
</div>
|
||||
|
||||
<div class="debug-logs">
|
||||
<h3>Debug Logs:</h3>
|
||||
<div id="debug-output">Initializing...</div>
|
||||
</div>
|
||||
|
||||
<div class="test-section">
|
||||
<h2>Test 1: Minimal Flowchart</h2>
|
||||
<p>Testing the simplest possible flowchart:</p>
|
||||
<pre class="mermaid">
|
||||
flowchart TD
|
||||
A[Start] --> B[End]
|
||||
</pre>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
|
||||
// Configure ANTLR parser for browser environment
|
||||
window.MERMAID_CONFIG = {
|
||||
USE_ANTLR_PARSER: 'true',
|
||||
USE_ANTLR_VISITOR: 'true',
|
||||
ANTLR_DEBUG: 'true'
|
||||
};
|
||||
|
||||
// Enhanced debug logging to track down the process.env issue
|
||||
const debugOutput = document.getElementById('debug-output');
|
||||
const originalConsoleLog = console.log;
|
||||
const originalConsoleError = console.error;
|
||||
|
||||
function addDebugLog(message, type = 'log') {
|
||||
const timestamp = new Date().toLocaleTimeString();
|
||||
const logEntry = `[${timestamp}] ${type.toUpperCase()}: ${message}`;
|
||||
|
||||
if (debugOutput) {
|
||||
debugOutput.innerHTML += logEntry + '<br>';
|
||||
debugOutput.scrollTop = debugOutput.scrollHeight;
|
||||
}
|
||||
|
||||
// Also log to original console
|
||||
if (type === 'error') {
|
||||
originalConsoleError(message);
|
||||
} else {
|
||||
originalConsoleLog(message);
|
||||
}
|
||||
}
|
||||
|
||||
// Override console methods to capture all logs
|
||||
console.log = function(...args) {
|
||||
addDebugLog(args.join(' '), 'log');
|
||||
};
|
||||
|
||||
console.error = function(...args) {
|
||||
addDebugLog(args.join(' '), 'error');
|
||||
};
|
||||
|
||||
// Add process access detection
|
||||
const originalProcess = window.process;
|
||||
Object.defineProperty(window, 'process', {
|
||||
get: function() {
|
||||
const stack = new Error().stack;
|
||||
addDebugLog(`🚨 PROCESS ACCESS DETECTED! Stack trace: ${stack}`, 'error');
|
||||
return originalProcess;
|
||||
},
|
||||
set: function(value) {
|
||||
addDebugLog(`🚨 PROCESS SET DETECTED! Value: ${value}`, 'error');
|
||||
window._process = value;
|
||||
}
|
||||
});
|
||||
|
||||
addDebugLog('🔧 Starting ANTLR parser test initialization');
|
||||
|
||||
// Check environment and parser status
|
||||
let envVar = 'undefined';
|
||||
try {
|
||||
if (typeof process !== 'undefined' && process.env) {
|
||||
envVar = process.env.USE_ANTLR_PARSER || 'undefined';
|
||||
}
|
||||
} catch (e) {
|
||||
addDebugLog(`🔧 Process check failed (expected in browser): ${e.message}`);
|
||||
envVar = 'browser-default';
|
||||
}
|
||||
|
||||
const envElement = document.getElementById('env-var');
|
||||
const statusElement = document.getElementById('parser-status');
|
||||
const configElement = document.getElementById('global-config');
|
||||
|
||||
if (envElement) {
|
||||
envElement.textContent = `USE_ANTLR_PARSER=${envVar || 'undefined'}`;
|
||||
}
|
||||
|
||||
if (configElement) {
|
||||
configElement.textContent = JSON.stringify(window.MERMAID_CONFIG);
|
||||
}
|
||||
|
||||
addDebugLog('🔧 Initializing Mermaid with ANTLR parser');
|
||||
|
||||
try {
|
||||
// Initialize mermaid with detailed error handling
|
||||
await mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
theme: 'default',
|
||||
flowchart: {
|
||||
useMaxWidth: true,
|
||||
htmlLabels: true
|
||||
},
|
||||
suppressErrors: false, // We want to see all errors
|
||||
logLevel: 'debug'
|
||||
});
|
||||
|
||||
addDebugLog('✅ Mermaid initialized successfully');
|
||||
|
||||
if (statusElement) {
|
||||
statusElement.textContent = '✅ ANTLR Parser Active';
|
||||
statusElement.style.color = 'green';
|
||||
}
|
||||
|
||||
addDebugLog('🎯 Starting diagram rendering');
|
||||
|
||||
// Render diagrams with detailed error tracking
|
||||
const diagrams = document.querySelectorAll('.mermaid');
|
||||
for (let i = 0; i < diagrams.length; i++) {
|
||||
const diagram = diagrams[i];
|
||||
addDebugLog(`🎨 Rendering diagram ${i + 1}/${diagrams.length}`);
|
||||
|
||||
try {
|
||||
await mermaid.run({
|
||||
nodes: [diagram],
|
||||
suppressErrors: false
|
||||
});
|
||||
addDebugLog(`✅ Diagram ${i + 1} rendered successfully`);
|
||||
} catch (error) {
|
||||
addDebugLog(`❌ Diagram ${i + 1} failed: ${error.message}`, 'error');
|
||||
addDebugLog(`❌ Stack trace: ${error.stack}`, 'error');
|
||||
}
|
||||
}
|
||||
|
||||
addDebugLog('🎉 All diagrams processed');
|
||||
|
||||
} catch (error) {
|
||||
addDebugLog(`❌ Mermaid initialization failed: ${error.message}`, 'error');
|
||||
addDebugLog(`❌ Stack trace: ${error.stack}`, 'error');
|
||||
|
||||
if (statusElement) {
|
||||
statusElement.textContent = '❌ ANTLR Parser Failed';
|
||||
statusElement.style.color = 'red';
|
||||
}
|
||||
}
|
||||
|
||||
addDebugLog('🔧 Test initialization complete');
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -23,23 +23,6 @@
|
||||
1940 : fourth step : fifth step
|
||||
</pre>
|
||||
|
||||
<h2>Medical Device Lifecycle Timeline</h2>
|
||||
<pre class="mermaid">
|
||||
timeline
|
||||
title Medical Device Lifecycle
|
||||
section Planning
|
||||
Quality Management System (4) : Regulatory Compliance (4.1) : Risk Management (4.1.3) : Management Review (5.6) : Infrastructure (6.3)
|
||||
Management Responsibility (5) : Planning Activities (5.2) : Human Resources (6.2) : RnD Planning (7.3.2) : Purchasing Process (7.4.1) : Production Activities (7.5.1) : Installation Activities (7.5.3) : Servicing Activities (7.5.4)
|
||||
section Realization
|
||||
Research and Development (7.3) : Inputs (7.3.3) : Outputs (7.3.4) : Review (7.3.5) : Verification (7.3.6) : Validation (7.3.7)
|
||||
Purchasing (7.4) : Purchasing Information (7.4.2) : Production Feedback (8.2.1)
|
||||
Production (7.5) : Production Feedback (8.2.1)
|
||||
Installation (7.5.3) : Installation Activities (7.5.3)
|
||||
Servicing (7.5.4) : Servicing Activities (7.5.4)
|
||||
section Post-Production
|
||||
Post-Market Activities (8) : Feedback (8.2.1) : Complaints (8.2.2) : Adverse Events (8.2.3)
|
||||
</pre>
|
||||
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
mermaid.initialize({
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
<!doctype html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||
<title>Mermaid Treemap Diagram Demo</title>
|
||||
<link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" />
|
||||
<style>
|
||||
body {
|
||||
font-family: 'Montserrat', sans-serif;
|
||||
margin: 0 auto;
|
||||
max-width: 900px;
|
||||
padding: 20px;
|
||||
}
|
||||
.mermaid {
|
||||
margin: 30px 0;
|
||||
}
|
||||
h1,
|
||||
h2 {
|
||||
color: #333;
|
||||
}
|
||||
pre {
|
||||
background-color: #f5f5f5;
|
||||
padding: 15px;
|
||||
border-radius: 5px;
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<h1>Treemap Diagram Demo</h1>
|
||||
<p>This is a demo of the new treemap diagram type in Mermaid.</p>
|
||||
|
||||
<h2>Basic Treemap Example</h2>
|
||||
<pre class="mermaid">
|
||||
treemap
|
||||
"Root"
|
||||
"Branch 1"
|
||||
"Leaf 1.1": 10
|
||||
"Leaf 1.2": 15
|
||||
"Branch 2"
|
||||
"Branch 2.1"
|
||||
"Leaf 2.1.1": 20
|
||||
"Leaf 2.1.2": 25
|
||||
"Leaf 2.2": 25
|
||||
"Leaf 2.3": 30
|
||||
</pre>
|
||||
|
||||
<h2>Technology Stack Treemap Example</h2>
|
||||
<pre class="mermaid">
|
||||
treemap
|
||||
"Technology Stack"
|
||||
"Frontend"
|
||||
"React": 35
|
||||
"CSS": 15
|
||||
"HTML": 10
|
||||
"Backend"
|
||||
"Node.js": 25
|
||||
"Express": 10
|
||||
"MongoDB": 15
|
||||
"DevOps"
|
||||
"Docker": 10
|
||||
"Kubernetes": 15
|
||||
"CI/CD": 5
|
||||
</pre>
|
||||
|
||||
<script type="module">
|
||||
import mermaid from './mermaid.esm.mjs';
|
||||
mermaid.initialize({
|
||||
theme: 'forest',
|
||||
logLevel: 1,
|
||||
securityLevel: 'loose',
|
||||
});
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
@@ -16,7 +16,7 @@
|
||||
<body>
|
||||
<h1>XY Charts demos</h1>
|
||||
<pre class="mermaid">
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue (in $)"
|
||||
x-axis [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
@@ -26,7 +26,7 @@
|
||||
<hr />
|
||||
<h1>XY Charts horizontal</h1>
|
||||
<pre class="mermaid">
|
||||
xychart horizontal
|
||||
xychart-beta horizontal
|
||||
title "Basic xychart"
|
||||
x-axis "this is x axis" [category1, "category 2", category3, category4]
|
||||
y-axis yaxisText 10 --> 150
|
||||
@@ -36,7 +36,7 @@
|
||||
<hr />
|
||||
<h1>XY Charts only lines and bar</h1>
|
||||
<pre class="mermaid">
|
||||
xychart
|
||||
xychart-beta
|
||||
line [23, 46, 77, 34]
|
||||
line [45, 32, 33, 12]
|
||||
line [87, 54, 99, 85]
|
||||
@@ -48,13 +48,13 @@
|
||||
<hr />
|
||||
<h1>XY Charts with +ve and -ve numbers</h1>
|
||||
<pre class="mermaid">
|
||||
xychart
|
||||
xychart-beta
|
||||
line [+1.3, .6, 2.4, -.34]
|
||||
</pre>
|
||||
|
||||
<h1>XY Charts Bar with multiple category</h1>
|
||||
<pre class="mermaid">
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Basic xychart with many categories"
|
||||
x-axis "this is x axis" [category1, "category 2", category3, category4, category5, category6, category7]
|
||||
y-axis yaxisText 10 --> 150
|
||||
@@ -63,7 +63,7 @@
|
||||
|
||||
<h1>XY Charts line with multiple category</h1>
|
||||
<pre class="mermaid">
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Line chart with many category"
|
||||
x-axis "this is x axis" [category1, "category 2", category3, category4, category5, category6, category7]
|
||||
y-axis yaxisText 10 --> 150
|
||||
@@ -72,7 +72,7 @@
|
||||
|
||||
<h1>XY Charts category with large text</h1>
|
||||
<pre class="mermaid">
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Basic xychart with many categories with category overlap"
|
||||
x-axis "this is x axis" [category1, "Lorem ipsum dolor sit amet, qui minim labore adipisicing minim sint cillum sint consectetur cupidatat.", category3, category4, category5, category6, category7]
|
||||
y-axis yaxisText 10 --> 150
|
||||
@@ -89,7 +89,7 @@ config:
|
||||
height: 20
|
||||
plotReservedSpacePercent: 100
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
line [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
|
||||
</pre>
|
||||
|
||||
@@ -103,7 +103,7 @@ config:
|
||||
height: 20
|
||||
plotReservedSpacePercent: 100
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
bar [5000, 9000, 7500, 6200, 9500, 5500, 11000, 8200, 9200, 9500, 7000, 8800]
|
||||
</pre>
|
||||
|
||||
@@ -136,7 +136,7 @@ config:
|
||||
chartOrientation: horizontal
|
||||
plotReservedSpacePercent: 60
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
@@ -162,7 +162,7 @@ config:
|
||||
xAxisLineColor: "#87ceeb"
|
||||
plotColorPalette: "#008000, #faba63"
|
||||
---
|
||||
xychart
|
||||
xychart-beta
|
||||
title "Sales Revenue"
|
||||
x-axis Months [jan, feb, mar, apr, may, jun, jul, aug, sep, oct, nov, dec]
|
||||
y-axis "Revenue (in $)" 4000 --> 11000
|
||||
|
||||
@@ -10,20 +10,16 @@
|
||||
<h1>Zenuml demos</h1>
|
||||
<pre class="mermaid">
|
||||
zenuml
|
||||
BookLibService.Borrow(id) {
|
||||
User = Session.GetUser()
|
||||
if(User.isActive) {
|
||||
try {
|
||||
BookRepository.Update(id, onLoan, User)
|
||||
receipt = new Receipt(id, dueDate)
|
||||
} catch (BookNotFoundException) {
|
||||
ErrorService.onException(BookNotFoundException)
|
||||
} finally {
|
||||
Connection.close()
|
||||
}
|
||||
}
|
||||
return receipt
|
||||
}
|
||||
title Sync Messages (Design Pattern: Adapter)
|
||||
@Starter(Client)
|
||||
Adapter.interfaceMethod() {
|
||||
translateParameter(parameter)
|
||||
|
||||
result = Implementation.implementationMethod()
|
||||
|
||||
translateResult()
|
||||
return translatedResult
|
||||
}
|
||||
</pre>
|
||||
<pre class="mermaid">
|
||||
zenuml
|
||||
|
||||
@@ -301,7 +301,7 @@ If you are adding a feature, you will definitely need to add tests. Depending on
|
||||
|
||||
Unit tests are tests that test a single function or module. They are the easiest to write and the fastest to run.
|
||||
|
||||
Unit tests are mandatory for all code except the layout tests. (The layouts are tested with integration tests.)
|
||||
Unit tests are mandatory for all code except the renderers. (The renderers are tested with integration tests.)
|
||||
|
||||
We use [Vitest](https://vitest.dev) to run unit tests.
|
||||
|
||||
@@ -327,30 +327,6 @@ When using Docker prepend your command with `./run`:
|
||||
./run pnpm test
|
||||
```
|
||||
|
||||
##### Testing the DOM
|
||||
|
||||
One can use `jsdomIt` to test any part of Mermaid that interacts with the DOM, as long as it is not related to the layout.
|
||||
|
||||
The function `jsdomIt` ([developed in utils.ts](../../tests/util.ts)) overrides `it` from `vitest`, and creates a pseudo-browser environment that works almost like the real deal for the duration of the test. It uses JSDOM to create a DOM, and adds objects `window` and `document` to `global` to mock the browser environment.
|
||||
|
||||
> \[!NOTE]
|
||||
> The layout cannot work in `jsdomIt` tests because JSDOM has no rendering engine, hence the pseudo-browser environment.
|
||||
|
||||
Example :
|
||||
|
||||
```typescript
|
||||
import { ensureNodeFromSelector, jsdomIt } from './tests/util.js';
|
||||
|
||||
jsdomIt('should add element "thing" in the SVG', ({ svg }) => {
|
||||
// Code in this block runs in a pseudo-browser environment
|
||||
addThing(svg); // The svg item is the D3 selection of the SVG node
|
||||
const svgNode = ensureNodeFromSelector('svg'); // Retrieve the DOM node using the DOM API
|
||||
expect(svgNode.querySelector('thing')).not.toBeNull(); // Test the structure of the SVG
|
||||
});
|
||||
```
|
||||
|
||||
They can be used to test any method that interacts with the DOM, including for testing renderers. For renderers, additional integration testing is necessary to test the layout though.
|
||||
|
||||
#### Integration / End-to-End (E2E) Tests
|
||||
|
||||
These test the rendering and visual appearance of the diagrams.
|
||||
|
||||
@@ -111,13 +111,3 @@ const themes = {
|
||||
```
|
||||
|
||||
The actual options and values for the colors are defined in **src/theme/theme-\[xyz].js**. If you provide the options your diagram needs in the existing theme files then the theming will work smoothly without hiccups.
|
||||
|
||||
## Examples
|
||||
|
||||
The `@mermaid-js/examples` package contains a collection of examples that are used by tools like mermaid.live to help users get started with the new diagram.
|
||||
|
||||
You can duplicate an existing diagram example file, eg: `packages/examples/src/examples/flowchart.ts`, and modify it with details specific to your diagram.
|
||||
|
||||
Then you can import the example in the `packages/examples/src/index.ts` file and add it to the `examples` array.
|
||||
|
||||
Each diagram should have at least one example, and that should be marked as default. It is good to add more examples to showcase different features of the diagram.
|
||||
|
||||
@@ -22,4 +22,4 @@ This helps the team know the relative interest in something and helps them set p
|
||||
|
||||
You have not found anything that already addresses your request, or maybe you have come up with the new idea? Feel free to open a new issue or discussion.
|
||||
|
||||
Log in to [GitHub.com](https://www.github.com), and use [GitHub issue tracker of the mermaid-js repository](https://github.com/mermaid-js/mermaid/issues). Press [issue, select the appropriate template](https://github.com/mermaid-js/mermaid/issues/new/choose) and describe your problem.
|
||||
Log in to [GitHub.com](https://www.github.com), and use [GitHub issue tracker of the mermaid-js repository](https://github.com/mermaid-js/mermaid/issues). Press \[<https://github.com/mermaid-js/mermaid/issues/new/choose>] issue, select the appropriate template and describe your problem.
|
||||
|
||||
@@ -6,7 +6,7 @@
|
||||
|
||||
# Frequently Asked Questions
|
||||
|
||||
1. [How to add title to flowchart?](https://github.com/mermaid-js/mermaid/issues/1433#issuecomment-1991554712)
|
||||
1. [How to add title to flowchart?](https://github.com/mermaid-js/mermaid/issues/556#issuecomment-363182217)
|
||||
2. [How to specify custom CSS file?](https://github.com/mermaidjs/mermaid.cli/pull/24#issuecomment-373402785)
|
||||
3. [How to fix tooltip misplacement issue?](https://github.com/mermaid-js/mermaid/issues/542#issuecomment-3343564621)
|
||||
4. [How to specify gantt diagram xAxis format?](https://github.com/mermaid-js/mermaid/issues/269#issuecomment-373229136)
|
||||
|
||||
@@ -1,40 +0,0 @@
|
||||
> **Warning**
|
||||
>
|
||||
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
|
||||
>
|
||||
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/layouts.md](../../packages/mermaid/src/docs/config/layouts.md).
|
||||
|
||||
# Layouts
|
||||
|
||||
This page lists the available layout algorithms supported in Mermaid diagrams.
|
||||
|
||||
## Supported Layouts
|
||||
|
||||
- **elk**: [ELK (Eclipse Layout Kernel)](https://www.eclipse.org/elk/)
|
||||
- **tidy-tree**: Tidy tree layout for hierarchical diagrams [Tidy Tree Configuration](/config/tidy-tree)
|
||||
- **cose-bilkent**: Cose Bilkent layout for force-directed graphs
|
||||
- **dagre**: Dagre layout for layered graphs
|
||||
|
||||
## How to Use
|
||||
|
||||
You can specify the layout in your diagram's YAML config or initialization options. For example:
|
||||
|
||||
```mermaid-example
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
graph TD;
|
||||
A-->B;
|
||||
B-->C;
|
||||
```
|
||||
|
||||
```mermaid
|
||||
---
|
||||
config:
|
||||
layout: elk
|
||||
---
|
||||
graph TD;
|
||||
A-->B;
|
||||
B-->C;
|
||||
```
|
||||
@@ -19,7 +19,6 @@
|
||||
- [addDirective](functions/addDirective.md)
|
||||
- [getConfig](functions/getConfig.md)
|
||||
- [getSiteConfig](functions/getSiteConfig.md)
|
||||
- [getUserDefinedConfig](functions/getUserDefinedConfig.md)
|
||||
- [reset](functions/reset.md)
|
||||
- [sanitize](functions/sanitize.md)
|
||||
- [saveConfigFromInitialize](functions/saveConfigFromInitialize.md)
|
||||
|
||||
@@ -1,19 +0,0 @@
|
||||
> **Warning**
|
||||
>
|
||||
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
|
||||
>
|
||||
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/config/functions/getUserDefinedConfig.md](../../../../../packages/mermaid/src/docs/config/setup/config/functions/getUserDefinedConfig.md).
|
||||
|
||||
[**mermaid**](../../README.md)
|
||||
|
||||
---
|
||||
|
||||
# Function: getUserDefinedConfig()
|
||||
|
||||
> **getUserDefinedConfig**(): [`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md)
|
||||
|
||||
Defined in: [packages/mermaid/src/config.ts:252](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L252)
|
||||
|
||||
## Returns
|
||||
|
||||
[`MermaidConfig`](../../mermaid/interfaces/MermaidConfig.md)
|
||||
@@ -12,4 +12,4 @@
|
||||
|
||||
> `const` **configKeys**: `Set`<`string`>
|
||||
|
||||
Defined in: [packages/mermaid/src/defaultConfig.ts:292](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L292)
|
||||
Defined in: [packages/mermaid/src/defaultConfig.ts:274](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L274)
|
||||
|
||||
@@ -10,6 +10,10 @@
|
||||
|
||||
# mermaid
|
||||
|
||||
## Classes
|
||||
|
||||
- [UnknownDiagramError](classes/UnknownDiagramError.md)
|
||||
|
||||
## Interfaces
|
||||
|
||||
- [DetailedError](interfaces/DetailedError.md)
|
||||
@@ -23,7 +27,6 @@
|
||||
- [RenderOptions](interfaces/RenderOptions.md)
|
||||
- [RenderResult](interfaces/RenderResult.md)
|
||||
- [RunOptions](interfaces/RunOptions.md)
|
||||
- [UnknownDiagramError](interfaces/UnknownDiagramError.md)
|
||||
|
||||
## Type Aliases
|
||||
|
||||
|
||||
159
docs/config/setup/mermaid/classes/UnknownDiagramError.md
Normal file
159
docs/config/setup/mermaid/classes/UnknownDiagramError.md
Normal file
@@ -0,0 +1,159 @@
|
||||
> **Warning**
|
||||
>
|
||||
> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
|
||||
>
|
||||
> ## Please edit the corresponding file in [/packages/mermaid/src/docs/config/setup/mermaid/classes/UnknownDiagramError.md](../../../../../packages/mermaid/src/docs/config/setup/mermaid/classes/UnknownDiagramError.md).
|
||||
|
||||
[**mermaid**](../../README.md)
|
||||
|
||||
---
|
||||
|
||||
# Class: UnknownDiagramError
|
||||
|
||||
Defined in: [packages/mermaid/src/errors.ts:1](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/errors.ts#L1)
|
||||
|
||||
## Extends
|
||||
|
||||
- `Error`
|
||||
|
||||
## Constructors
|
||||
|
||||
### new UnknownDiagramError()
|
||||
|
||||
> **new UnknownDiagramError**(`message`): [`UnknownDiagramError`](UnknownDiagramError.md)
|
||||
|
||||
Defined in: [packages/mermaid/src/errors.ts:2](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/errors.ts#L2)
|
||||
|
||||
#### Parameters
|
||||
|
||||
##### message
|
||||
|
||||
`string`
|
||||
|
||||
#### Returns
|
||||
|
||||
[`UnknownDiagramError`](UnknownDiagramError.md)
|
||||
|
||||
#### Overrides
|
||||
|
||||
`Error.constructor`
|
||||
|
||||
## Properties
|
||||
|
||||
### cause?
|
||||
|
||||
> `optional` **cause**: `unknown`
|
||||
|
||||
Defined in: node_modules/.pnpm/typescript\@5.7.3/node_modules/typescript/lib/lib.es2022.error.d.ts:26
|
||||
|
||||
#### Inherited from
|
||||
|
||||
`Error.cause`
|
||||
|
||||
---
|
||||
|
||||
### message
|
||||
|
||||
> **message**: `string`
|
||||
|
||||
Defined in: node_modules/.pnpm/typescript\@5.7.3/node_modules/typescript/lib/lib.es5.d.ts:1077
|
||||
|
||||
#### Inherited from
|
||||
|
||||
`Error.message`
|
||||
|
||||
---
|
||||
|
||||
### name
|
||||
|
||||
> **name**: `string`
|
||||
|
||||
Defined in: node_modules/.pnpm/typescript\@5.7.3/node_modules/typescript/lib/lib.es5.d.ts:1076
|
||||
|
||||
#### Inherited from
|
||||
|
||||
`Error.name`
|
||||
|
||||
---
|
||||
|
||||
### stack?
|
||||
|
||||
> `optional` **stack**: `string`
|
||||
|
||||
Defined in: node_modules/.pnpm/typescript\@5.7.3/node_modules/typescript/lib/lib.es5.d.ts:1078
|
||||
|
||||
#### Inherited from
|
||||
|
||||
`Error.stack`
|
||||
|
||||
---
|
||||
|
||||
### prepareStackTrace()?
|
||||
|
||||
> `static` `optional` **prepareStackTrace**: (`err`, `stackTraces`) => `any`
|
||||
|
||||
Defined in: node_modules/.pnpm/@types+node\@22.13.5/node_modules/@types/node/globals.d.ts:143
|
||||
|
||||
Optional override for formatting stack traces
|
||||
|
||||
#### Parameters
|
||||
|
||||
##### err
|
||||
|
||||
`Error`
|
||||
|
||||
##### stackTraces
|
||||
|
||||
`CallSite`\[]
|
||||
|
||||
#### Returns
|
||||
|
||||
`any`
|
||||
|
||||
#### See
|
||||
|
||||
<https://v8.dev/docs/stack-trace-api#customizing-stack-traces>
|
||||
|
||||
#### Inherited from
|
||||
|
||||
`Error.prepareStackTrace`
|
||||
|
||||
---
|
||||
|
||||
### stackTraceLimit
|
||||
|
||||
> `static` **stackTraceLimit**: `number`
|
||||
|
||||
Defined in: node_modules/.pnpm/@types+node\@22.13.5/node_modules/@types/node/globals.d.ts:145
|
||||
|
||||
#### Inherited from
|
||||
|
||||
`Error.stackTraceLimit`
|
||||
|
||||
## Methods
|
||||
|
||||
### captureStackTrace()
|
||||
|
||||
> `static` **captureStackTrace**(`targetObject`, `constructorOpt`?): `void`
|
||||
|
||||
Defined in: node_modules/.pnpm/@types+node\@22.13.5/node_modules/@types/node/globals.d.ts:136
|
||||
|
||||
Create .stack property on a target object
|
||||
|
||||
#### Parameters
|
||||
|
||||
##### targetObject
|
||||
|
||||
`object`
|
||||
|
||||
##### constructorOpt?
|
||||
|
||||
`Function`
|
||||
|
||||
#### Returns
|
||||
|
||||
`void`
|
||||
|
||||
#### Inherited from
|
||||
|
||||
`Error.captureStackTrace`
|
||||
@@ -10,7 +10,7 @@
|
||||
|
||||
# Interface: ExternalDiagramDefinition
|
||||
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L96)
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:99](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L99)
|
||||
|
||||
## Properties
|
||||
|
||||
@@ -18,7 +18,7 @@ Defined in: [packages/mermaid/src/diagram-api/types.ts:96](https://github.com/me
|
||||
|
||||
> **detector**: `DiagramDetector`
|
||||
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:98](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L98)
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:101](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L101)
|
||||
|
||||
---
|
||||
|
||||
@@ -26,7 +26,7 @@ Defined in: [packages/mermaid/src/diagram-api/types.ts:98](https://github.com/me
|
||||
|
||||
> **id**: `string`
|
||||
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:97](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L97)
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:100](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L100)
|
||||
|
||||
---
|
||||
|
||||
@@ -34,4 +34,4 @@ Defined in: [packages/mermaid/src/diagram-api/types.ts:97](https://github.com/me
|
||||
|
||||
> **loader**: `DiagramLoader`
|
||||
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:99](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L99)
|
||||
Defined in: [packages/mermaid/src/diagram-api/types.ts:102](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/diagram-api/types.ts#L102)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user