From 86e1bb38eecfd4179fe9b296f111d8e53d586fb6 Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Wed, 5 Jul 2023 12:01:37 +0200 Subject: [PATCH 01/97] #3358 First commit with basic grammar and 1st test --- packages/mermaid/src/config.type.ts | 4 + .../src/diagrams/blockDiagram/blockDB.ts | 35 ++++ .../src/diagrams/blockDiagram/blockDiagram.ts | 15 ++ .../blockDiagram/blockDiagramDetector.ts | 20 ++ .../blockDiagram/blockDiagramRenderer.ts | 63 ++++++ .../blockDiagram/blockDiagramUtils.ts | 8 + .../blockDiagram/parser/blockDiagram.jison | 195 ++++++++++++++++++ .../blockDiagram/parser/blockDiagram.spec.ts | 85 ++++++++ .../mermaid/src/docs/.vitepress/block.mmd | 33 +++ 9 files changed, 458 insertions(+) create mode 100644 packages/mermaid/src/diagrams/blockDiagram/blockDB.ts create mode 100644 packages/mermaid/src/diagrams/blockDiagram/blockDiagram.ts create mode 100644 packages/mermaid/src/diagrams/blockDiagram/blockDiagramDetector.ts create mode 100644 packages/mermaid/src/diagrams/blockDiagram/blockDiagramRenderer.ts create mode 100644 packages/mermaid/src/diagrams/blockDiagram/blockDiagramUtils.ts create mode 100644 packages/mermaid/src/diagrams/blockDiagram/parser/blockDiagram.jison create mode 100644 packages/mermaid/src/diagrams/blockDiagram/parser/blockDiagram.spec.ts create mode 100644 packages/mermaid/src/docs/.vitepress/block.mmd diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index 138eee44f3..a784b9d300 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -33,6 +33,7 @@ export interface MermaidConfig { gitGraph?: GitGraphDiagramConfig; c4?: C4DiagramConfig; sankey?: SankeyDiagramConfig; + blockDiagram?: BlockDiagramConfig; dompurifyConfig?: DOMPurify.Config; wrap?: boolean; fontSize?: number; @@ -421,6 +422,9 @@ export interface SankeyDiagramConfig extends BaseDiagramConfig { linkColor?: SankeyLinkColor | string; nodeAlignment?: SankeyNodeAlignment; } +export interface BlockDiagramConfig extends BaseDiagramConfig { + padding?: number; +} export interface FontConfig { fontSize?: string | number; diff --git a/packages/mermaid/src/diagrams/blockDiagram/blockDB.ts b/packages/mermaid/src/diagrams/blockDiagram/blockDB.ts new file mode 100644 index 0000000000..265835cd7d --- /dev/null +++ b/packages/mermaid/src/diagrams/blockDiagram/blockDB.ts @@ -0,0 +1,35 @@ +import * as configApi from '../../config.js'; +import common from '../common/common.js'; +import { + setAccTitle, + getAccTitle, + getAccDescription, + setAccDescription, + setDiagramTitle, + getDiagramTitle, + clear as commonClear, +} from '../../commonDb.js'; + +type Block = { + ID: string; +}; + +// Array of nodes guarantees their order +let blocks: Block[] = []; + +const clear = (): void => { + blocks = []; + commonClear(); +}; + +export default { + getConfig: () => configApi.getConfig().blockDiagram, + + getAccTitle, + setAccTitle, + getAccDescription, + setAccDescription, + getDiagramTitle, + setDiagramTitle, + clear, +}; diff --git a/packages/mermaid/src/diagrams/blockDiagram/blockDiagram.ts b/packages/mermaid/src/diagrams/blockDiagram/blockDiagram.ts new file mode 100644 index 0000000000..c3913a7f29 --- /dev/null +++ b/packages/mermaid/src/diagrams/blockDiagram/blockDiagram.ts @@ -0,0 +1,15 @@ +import { DiagramDefinition } from '../../diagram-api/types.js'; +// @ts-ignore: jison doesn't export types +import parser from './parser/sankey.jison'; +import db from './blockDB.js'; +import renderer from './blockDiagramRenderer.js'; +import { prepareTextForParsing } from './blockDiagramUtils.js'; + +const originalParse = parser.parse.bind(parser); +parser.parse = (text: string) => originalParse(prepareTextForParsing(text)); + +export const diagram: DiagramDefinition = { + parser, + db, + renderer, +}; diff --git a/packages/mermaid/src/diagrams/blockDiagram/blockDiagramDetector.ts b/packages/mermaid/src/diagrams/blockDiagram/blockDiagramDetector.ts new file mode 100644 index 0000000000..41dc911275 --- /dev/null +++ b/packages/mermaid/src/diagrams/blockDiagram/blockDiagramDetector.ts @@ -0,0 +1,20 @@ +import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js'; + +const id = 'sankey'; + +const detector: DiagramDetector = (txt) => { + return /^\s*blockDiagram-beta/.test(txt); +}; + +const loader = async () => { + const { diagram } = await import('./blockDiagram.js'); + return { id, diagram }; +}; + +const plugin: ExternalDiagramDefinition = { + id, + detector, + loader, +}; + +export default plugin; diff --git a/packages/mermaid/src/diagrams/blockDiagram/blockDiagramRenderer.ts b/packages/mermaid/src/diagrams/blockDiagram/blockDiagramRenderer.ts new file mode 100644 index 0000000000..5a2f595bcf --- /dev/null +++ b/packages/mermaid/src/diagrams/blockDiagram/blockDiagramRenderer.ts @@ -0,0 +1,63 @@ +import { Diagram } from '../../Diagram.js'; +import * as configApi from '../../config.js'; + +import { + select as d3select, + scaleOrdinal as d3scaleOrdinal, + schemeTableau10 as d3schemeTableau10, +} from 'd3'; + +import { configureSvgSize } from '../../setupGraphViewbox.js'; +import { Uid } from '../../rendering-util/uid.js'; +import type { SankeyLinkColor, SankeyNodeAlignment } from '../../config.type.js'; + +export const draw = function (text: string, id: string, _version: string, diagObj: Diagram): void { + // Get the config + const { securityLevel, sankey: conf } = configApi.getConfig(); + const defaultSankeyConfig = configApi!.defaultConfig!.blockDiagram!; + + // TODO: + // This code repeats for every diagram + // Figure out what is happening there, probably it should be separated + // The main thing is svg object that is a d3 wrapper for svg operations + // + let sandboxElement: any; + if (securityLevel === 'sandbox') { + sandboxElement = d3select('#i' + id); + } + const root = + securityLevel === 'sandbox' + ? d3select(sandboxElement.nodes()[0].contentDocument.body) + : d3select('body'); + // @ts-ignore TODO root.select is not callable + const svg = securityLevel === 'sandbox' ? root.select(`[id="${id}"]`) : d3select(`[id="${id}"]`); + + // Establish svg dimensions and get width and height + // + + // FIX: using max width prevents height from being set, is it intended? + // to add height directly one can use `svg.attr('height', height)` + // + // @ts-ignore TODO: svg type vs selection mismatch + configureSvgSize(svg, height, width, useMaxWidth); + + // Prepare data for construction based on diagObj.db + // This must be a mutable object with `nodes` and `links` properties: + // + // { + // "nodes": [ { "id": "Alice" }, { "id": "Bob" }, { "id": "Carol" } ], + // "links": [ { "source": "Alice", "target": "Bob", "value": 23 }, { "source": "Bob", "target": "Carol", "value": 43 } ] + // } + // + // @ts-ignore TODO: db type + const graph = diagObj.db.getGraph(); + + const nodeWidth = 10; + + // Get color scheme for the graph + const colorScheme = d3scaleOrdinal(d3schemeTableau10); +}; + +export default { + draw, +}; diff --git a/packages/mermaid/src/diagrams/blockDiagram/blockDiagramUtils.ts b/packages/mermaid/src/diagrams/blockDiagram/blockDiagramUtils.ts new file mode 100644 index 0000000000..45ecf21dda --- /dev/null +++ b/packages/mermaid/src/diagrams/blockDiagram/blockDiagramUtils.ts @@ -0,0 +1,8 @@ +export const prepareTextForParsing = (text: string): string => { + const textToParse = text + .replaceAll(/^[^\S\n\r]+|[^\S\n\r]+$/g, '') // remove all trailing spaces for each row + .replaceAll(/([\n\r])+/g, '\n') // remove empty lines duplicated + .trim(); + + return textToParse; +}; diff --git a/packages/mermaid/src/diagrams/blockDiagram/parser/blockDiagram.jison b/packages/mermaid/src/diagrams/blockDiagram/parser/blockDiagram.jison new file mode 100644 index 0000000000..aced2c0237 --- /dev/null +++ b/packages/mermaid/src/diagrams/blockDiagram/parser/blockDiagram.jison @@ -0,0 +1,195 @@ +/** mermaid */ + +//--------------------------------------------------------- +// We support csv format as defined here: +// https://www.ietf.org/rfc/rfc4180.txt +// There are some minor changes for compliance with jison +// We also parse only 3 columns: source,target,value +// And allow blank lines for visual purposes +//--------------------------------------------------------- + +%lex +%x acc_title +%x acc_descr +%x acc_descr_multiline +%x string +%x md_string +%x NODE +%options easy_keword_rules + + +// as per section 6.1 of RFC 2234 [2] +COMMA \u002C +CR \u000D +LF \u000A +CRLF \u000D\u000A + + +%% + +"blockDiagram-beta" { return 'BLOCK_DIAGRAM_KEY'; } +// \s*\%\%.* { yy.getLogger().info('Found comment',yytext); } +[\s]+ { yy.getLogger().info('.', yytext); /* skip all whitespace */ } +[\n]+ {yy.getLogger().info('_', yytext); /* skip all whitespace */ } +// [\n] return 'NL'; +({CRLF}|{LF}) { return 'NL' } +["][`] { this.begin("md_string");} +[^`"]+ { return "MD_STR";} +[`]["] { this.popState();} +["] this.begin("string"); +["] this.popState(); +[^"]* return "STR"; +"style" return 'STYLE'; +"default" return 'DEFAULT'; +"linkStyle" return 'LINKSTYLE'; +"interpolate" return 'INTERPOLATE'; +"classDef" return 'CLASSDEF'; +"class" return 'CLASS'; +accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; } +(?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; } +accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; } +(?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; } +accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} +[\}] { this.popState(); } +[^\}]* return "acc_descr_multiline_value"; +"subgraph" return 'subgraph'; +"end"\b\s* return 'end'; +.*direction\s+TB[^\n]* return 'direction_tb'; +.*direction\s+BT[^\n]* return 'direction_bt'; +.*direction\s+RL[^\n]* return 'direction_rl'; +.*direction\s+LR[^\n]* return 'direction_lr'; + +// Start of nodes with shapes and description +"-)" { yy.getLogger().info('Lex: -)'); this.begin('NODE');return 'NODE_D START'; } +"(-" { yy.getLogger().info('Lex: (-'); this.begin('NODE');return 'NODE_DSTART'; } +"))" { yy.getLogger().info('Lex: ))'); this.begin('NODE');return 'NODE_DSTART'; } +")" { yy.getLogger().info('Lex: )'); this.begin('NODE');return 'NODE_DSTART'; } +"((" { yy.getLogger().info('Lex: )'); this.begin('NODE');return 'NODE_DSTART'; } +"{{" { yy.getLogger().info('Lex: )'); this.begin('NODE');return 'NODE_DSTART'; } +"(" { yy.getLogger().info('Lex: )'); this.begin('NODE');return 'NODE_DSTART'; } +"[" { yy.getLogger().info('Lex: ['); this.begin('NODE');return 'NODE_DSTART'; } +"([" { yy.getLogger().info('Lex: )'); this.begin('NODE');return 'NODE_DSTART'; } +"[[" { this.begin('NODE');return 'NODE_DSTART'; } +"[|" { this.begin('NODE');return 'NODE_DSTART'; } +"[(" { this.begin('NODE');return 'NODE_DSTART'; } +"(((" { this.begin('NODE');return 'NODE_DSTART'; } +")))" { this.begin('NODE');return 'NODE_DSTART'; } +"[/" { this.begin('NODE');return 'NODE_DSTART'; } +"[\\" { this.begin('NODE');return 'NODE_DSTART'; } + + +[^\(\[\n\-\)\{\}]+ { yy.getLogger().info('Lex: NODE_ID', yytext);return 'NODE_ID'; } +<> { yy.getLogger().info('Lex: EOF', yytext);return 'EOF'; } + +// Handling of strings in node +["][`] { this.begin("md_string");} +[^`"]+ { return "NODE_DESCR";} +[`]["] { this.popState();} +["] { yy.getLogger().info('Lex: Starting string');this.begin("string");} +[^"]+ { yy.getLogger().info('Lex: NODE_DESCR:', yytext); return "NODE_DESCR";} +["] {this.popState();} + +// Node end of shape +[\)]\) { this.popState();yy.getLogger().info('Lex: ))'); return "NODE_DEND"; } +[\)] { this.popState();yy.getLogger().info('Lex: )'); return "NODE_DEND"; } +[\]] { this.popState();yy.getLogger().info('Lex: ]'); return "NODE_DEND"; } +"}}" { this.popState();yy.getLogger().info('Lex: (('); return "NODE_DEND"; } +"(-" { this.popState();yy.getLogger().info('Lex: (-'); return "NODE_DEND"; } +"-)" { this.popState();yy.getLogger().info('Lex: -)'); return "NODE_DEND"; } +"((" { this.popState();yy.getLogger().info('Lex: (('); return "NODE_DEND"; } +"(" { this.popState();yy.getLogger().info('Lex: ('); return "NODE_DEND"; } +"])" { this.popState();yy.getLogger().info('Lex: ])'); return "NODE_DEND"; } +"]]" { this.popState();yy.getLogger().info('Lex: ]]'); return "NODE_DEND"; } +"/]" { this.popState();yy.getLogger().info('Lex: /]'); return "NODE_DEND"; } +")]" { this.popState();yy.getLogger().info('Lex: )]'); return "NODE_DEND"; } + +// Edges +\s*[xo<]?\-\-+[-xo>]\s* { yy.getLogger().info('Lex: LINK', '#'+yytext+'#'); return 'LINK'; } +\s*[xo<]?\=\=+[=xo>]\s* { yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; } +\s*[xo<]?\-?\.+\-[xo>]?\s* { yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; } +\s*\~\~[\~]+\s* { yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; } +\s*[xo<]?\-\-\s* { yy.getLogger().info('Lex: START_LINK', yytext); return 'START_LINK'; } +\s*[xo<]?\=\=\s* { yy.getLogger().info('Lex: START_LINK', yytext); return 'START_LINK'; } +\s*[xo<]?\-\.\s* { yy.getLogger().info('Lex: START_LINK', yytext); return 'START_LINK'; } + +/lex + +%start start + +%% // language grammar + +spaceLines + : SPACELINE + | spaceLines SPACELINE + | spaceLines NL + ; + +seperator + : NL + {yy.getLogger().info('Rule: seperator (NL) ');} + | SPACE + {yy.getLogger().info('Rule: seperator (Space) ');} + | EOF + {yy.getLogger().info('Rule: seperator (EOF) ');} + ; + +start: BLOCK_DIAGRAM_KEY document; + +blockDiagram + : blockDiagram document { return yy; } + | blockDiagram NL document { return yy; } + ; + +stop + : NL {yy.getLogger().info('Stop NL ');} + | EOF {yy.getLogger().info('Stop EOF ');} + // | SPACELINE + | stop NL {yy.getLogger().info('Stop NL2 ');} + | stop EOF {yy.getLogger().info('Stop EOF2 ');} + ; + +document + : document statement + | statement + ; + +link + : LINK + { yy.getLogger().info("Rule: link: ", $1); } + | START_LINK + { yy.getLogger().info("Rule: link: ", $1); } + ; + +statement + : nodeStatement +// SPACELIST node { yy.getLogger().info('Node: ',$2.id);yy.addNode($1.length, $2.id, $2.descr, $2.type); } +// | SPACELIST ICON { yy.getLogger().info('Icon: ',$2);yy.decorateNode({icon: $2}); } +// | SPACELIST CLASS { yy.decorateNode({class: $2}); } +// | SPACELINE { yy.getLogger().info('SPACELIST');} +// | +// node { yy.getLogger().info('Node: ',$1.id);yy.addNode(0, $1.id, $1.descr, $1.type); } +// | ICON { yy.decorateNode({icon: $1}); } +// | CLASS { yy.decorateNode({class: $1}); } +// // | SPACELIST + | EOF + ; + +nodeStatement: nodeStatement link node { yy.getLogger().info('Rule: nodeStatement (nodeStatement link node) ');} + |node { yy.getLogger().info('Rule: nodeStatement (node) ');} + ; + +node + : NODE_ID + { yy.getLogger().info("Rule: node (NODE_ID seperator): ", $1); } + |NODE_ID nodeShapeNLabel + { yy.getLogger().info("Rule: node (NODE_ID nodeShapeNLabel seperator): ", $1, $2); } + // |nodeShapeNLabel seperator + // { yy.getLogger().info("Rule: node (nodeShapeNLabel seperator): ", $1, $2, $3); } + ; + +nodeShapeNLabel + : NODE_DSTART STR NODE_DEND + { yy.getLogger().info("Rule: nodeShapeNLabel: ", $1, $2, $3); $$ = { type: $1 + $3, descr: $2 }; } + ; + +%% diff --git a/packages/mermaid/src/diagrams/blockDiagram/parser/blockDiagram.spec.ts b/packages/mermaid/src/diagrams/blockDiagram/parser/blockDiagram.spec.ts new file mode 100644 index 0000000000..3c076c04fd --- /dev/null +++ b/packages/mermaid/src/diagrams/blockDiagram/parser/blockDiagram.spec.ts @@ -0,0 +1,85 @@ +// @ts-ignore: jison doesn't export types +import blockDiagram from './blockDiagram.jison'; +import db from '../blockDB.js'; +import { cleanupComments } from '../../../diagram-api/comments.js'; +import { prepareTextForParsing } from '../blockDiagramUtils.js'; +import * as fs from 'fs'; +import * as path from 'path'; + +describe('Sankey diagram', function () { + describe('when parsing an block diagram graph it should handle > ', function () { + beforeEach(function () { + blockDiagram.parser.yy = db; + blockDiagram.parser.yy.clear(); + blockDiagram.parser.yy.getLogger = () => console; + }); + + it('a diagram with a node', async () => { + const str = `blockDiagram-beta + id + `; + + blockDiagram.parse(str); + }); + it('a diagram with multiple nodes', async () => { + const str = `blockDiagram-beta + id1 + id2 + `; + + blockDiagram.parse(str); + }); + it('a node with a square shape and a label', async () => { + const str = `blockDiagram-beta + id["A label"] + id2`; + + blockDiagram.parse(str); + }); + it('a diagram with multiple nodes with edges', async () => { + const str = `blockDiagram-beta + id1["first"] --> id2["second"] + `; + + blockDiagram.parse(str); + }); + // it('a diagram with column statements', async () => { + // const str = `blockDiagram-beta + // columns 1 + // block1["Block 1"] + // `; + + // blockDiagram.parse(str); + // }); + // it('a diagram with block hierarchies', async () => { + // const str = `blockDiagram-beta + // columns 1 + // block1[Block 1] + + // block + // columns 2 + // block2[Block 2] + // block3[Block 3] + // end %% End the compound block + // `; + + // blockDiagram.parse(str); + // }); + // it('a diagram with differernt column values in different blocks', async () => { + // const str = `blockDiagram-beta + // columns 1 + // block1[Block 1] + + // block + // columns 2 + // block2[Block 2] + // block3[Block 3] + // end %% End the compound block + // `; + + // blockDiagram.parse(str); + + // // Todo check that the different blocks have different column values + // }); + }); +}); diff --git a/packages/mermaid/src/docs/.vitepress/block.mmd b/packages/mermaid/src/docs/.vitepress/block.mmd new file mode 100644 index 0000000000..7ce628f446 --- /dev/null +++ b/packages/mermaid/src/docs/.vitepress/block.mmd @@ -0,0 +1,33 @@ +block + columns 3 + Block1 + Block2["Block 2"] + block + columns 2 + Block2.1 + Block2.2 + end + Block3 + + +---- + +block + columns 2 + Block[Frontend]:vertical + + block "Document management System" + columns 3 + MO[Manager Operation]:vertical + block + columns 2 + block "Security and User Manager" + end + + +---- +block frontend:vertical +move right +block "Document Management System" +move down + From 791e67641eafe845b243ace394749f9fc2b2602c Mon Sep 17 00:00:00 2001 From: Nikolay Rozhkov Date: Fri, 7 Jul 2023 13:58:30 +0300 Subject: [PATCH 02/97] Rename BlockDiagram to Block --- packages/mermaid/src/config.type.ts | 2 +- .../src/diagram-api/diagram-orchestration.ts | 4 +- .../{blockDiagram => block}/blockDB.ts | 2 +- .../blockDetector.ts} | 4 +- .../{blockDiagram => block}/blockDiagram.ts | 6 +-- .../blockRenderer.ts} | 0 .../mermaid/src/diagrams/block/blockTypes.ts | 5 +++ .../blockUtils.ts} | 0 .../parser/block.jison} | 2 +- .../parser/block.spec.ts} | 38 +++++++++---------- 10 files changed, 35 insertions(+), 28 deletions(-) rename packages/mermaid/src/diagrams/{blockDiagram => block}/blockDB.ts (91%) rename packages/mermaid/src/diagrams/{blockDiagram/blockDiagramDetector.ts => block/blockDetector.ts} (84%) rename packages/mermaid/src/diagrams/{blockDiagram => block}/blockDiagram.ts (68%) rename packages/mermaid/src/diagrams/{blockDiagram/blockDiagramRenderer.ts => block/blockRenderer.ts} (100%) create mode 100644 packages/mermaid/src/diagrams/block/blockTypes.ts rename packages/mermaid/src/diagrams/{blockDiagram/blockDiagramUtils.ts => block/blockUtils.ts} (100%) rename packages/mermaid/src/diagrams/{blockDiagram/parser/blockDiagram.jison => block/parser/block.jison} (98%) rename packages/mermaid/src/diagrams/{blockDiagram/parser/blockDiagram.spec.ts => block/parser/block.spec.ts} (68%) diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index a784b9d300..fdb2450ba0 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -33,7 +33,7 @@ export interface MermaidConfig { gitGraph?: GitGraphDiagramConfig; c4?: C4DiagramConfig; sankey?: SankeyDiagramConfig; - blockDiagram?: BlockDiagramConfig; + block?: BlockDiagramConfig; dompurifyConfig?: DOMPurify.Config; wrap?: boolean; fontSize?: number; diff --git a/packages/mermaid/src/diagram-api/diagram-orchestration.ts b/packages/mermaid/src/diagram-api/diagram-orchestration.ts index 9c03e27f31..470a13fa0a 100644 --- a/packages/mermaid/src/diagram-api/diagram-orchestration.ts +++ b/packages/mermaid/src/diagram-api/diagram-orchestration.ts @@ -19,6 +19,7 @@ import flowchartElk from '../diagrams/flowchart/elk/detector.js'; import timeline from '../diagrams/timeline/detector.js'; import mindmap from '../diagrams/mindmap/detector.js'; import sankey from '../diagrams/sankey/sankeyDetector.js'; +import block from '../diagrams/block/blockDetector.js'; import { registerLazyLoadedDiagrams } from './detectType.js'; import { registerDiagram } from './diagramAPI.js'; @@ -81,6 +82,7 @@ export const addDiagrams = () => { state, journey, quadrantChart, - sankey + sankey, + block ); }; diff --git a/packages/mermaid/src/diagrams/blockDiagram/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts similarity index 91% rename from packages/mermaid/src/diagrams/blockDiagram/blockDB.ts rename to packages/mermaid/src/diagrams/block/blockDB.ts index 265835cd7d..4cb611b177 100644 --- a/packages/mermaid/src/diagrams/blockDiagram/blockDB.ts +++ b/packages/mermaid/src/diagrams/block/blockDB.ts @@ -23,7 +23,7 @@ const clear = (): void => { }; export default { - getConfig: () => configApi.getConfig().blockDiagram, + getConfig: () => configApi.getConfig().block, getAccTitle, setAccTitle, diff --git a/packages/mermaid/src/diagrams/blockDiagram/blockDiagramDetector.ts b/packages/mermaid/src/diagrams/block/blockDetector.ts similarity index 84% rename from packages/mermaid/src/diagrams/blockDiagram/blockDiagramDetector.ts rename to packages/mermaid/src/diagrams/block/blockDetector.ts index 41dc911275..c4da643f03 100644 --- a/packages/mermaid/src/diagrams/blockDiagram/blockDiagramDetector.ts +++ b/packages/mermaid/src/diagrams/block/blockDetector.ts @@ -1,9 +1,9 @@ import type { DiagramDetector, ExternalDiagramDefinition } from '../../diagram-api/types.js'; -const id = 'sankey'; +const id = 'block'; const detector: DiagramDetector = (txt) => { - return /^\s*blockDiagram-beta/.test(txt); + return /^\s*block-beta/.test(txt); }; const loader = async () => { diff --git a/packages/mermaid/src/diagrams/blockDiagram/blockDiagram.ts b/packages/mermaid/src/diagrams/block/blockDiagram.ts similarity index 68% rename from packages/mermaid/src/diagrams/blockDiagram/blockDiagram.ts rename to packages/mermaid/src/diagrams/block/blockDiagram.ts index c3913a7f29..1cd619749e 100644 --- a/packages/mermaid/src/diagrams/blockDiagram/blockDiagram.ts +++ b/packages/mermaid/src/diagrams/block/blockDiagram.ts @@ -1,9 +1,9 @@ import { DiagramDefinition } from '../../diagram-api/types.js'; // @ts-ignore: jison doesn't export types -import parser from './parser/sankey.jison'; +import parser from './parser/blockDiagram.jison'; import db from './blockDB.js'; -import renderer from './blockDiagramRenderer.js'; -import { prepareTextForParsing } from './blockDiagramUtils.js'; +import renderer from './blockRenderer.js'; +import { prepareTextForParsing } from './blockUtils.js'; const originalParse = parser.parse.bind(parser); parser.parse = (text: string) => originalParse(prepareTextForParsing(text)); diff --git a/packages/mermaid/src/diagrams/blockDiagram/blockDiagramRenderer.ts b/packages/mermaid/src/diagrams/block/blockRenderer.ts similarity index 100% rename from packages/mermaid/src/diagrams/blockDiagram/blockDiagramRenderer.ts rename to packages/mermaid/src/diagrams/block/blockRenderer.ts diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts new file mode 100644 index 0000000000..28e5cd1679 --- /dev/null +++ b/packages/mermaid/src/diagrams/block/blockTypes.ts @@ -0,0 +1,5 @@ +import type { DiagramDB } from '../../diagram-api/types.js'; + +export interface BlockDB extends DiagramDB { + clear: () => void; +} diff --git a/packages/mermaid/src/diagrams/blockDiagram/blockDiagramUtils.ts b/packages/mermaid/src/diagrams/block/blockUtils.ts similarity index 100% rename from packages/mermaid/src/diagrams/blockDiagram/blockDiagramUtils.ts rename to packages/mermaid/src/diagrams/block/blockUtils.ts diff --git a/packages/mermaid/src/diagrams/blockDiagram/parser/blockDiagram.jison b/packages/mermaid/src/diagrams/block/parser/block.jison similarity index 98% rename from packages/mermaid/src/diagrams/blockDiagram/parser/blockDiagram.jison rename to packages/mermaid/src/diagrams/block/parser/block.jison index aced2c0237..ba58a60971 100644 --- a/packages/mermaid/src/diagrams/blockDiagram/parser/blockDiagram.jison +++ b/packages/mermaid/src/diagrams/block/parser/block.jison @@ -27,7 +27,7 @@ CRLF \u000D\u000A %% -"blockDiagram-beta" { return 'BLOCK_DIAGRAM_KEY'; } +"block-beta" { return 'BLOCK_DIAGRAM_KEY'; } // \s*\%\%.* { yy.getLogger().info('Found comment',yytext); } [\s]+ { yy.getLogger().info('.', yytext); /* skip all whitespace */ } [\n]+ {yy.getLogger().info('_', yytext); /* skip all whitespace */ } diff --git a/packages/mermaid/src/diagrams/blockDiagram/parser/blockDiagram.spec.ts b/packages/mermaid/src/diagrams/block/parser/block.spec.ts similarity index 68% rename from packages/mermaid/src/diagrams/blockDiagram/parser/blockDiagram.spec.ts rename to packages/mermaid/src/diagrams/block/parser/block.spec.ts index 3c076c04fd..08b36c7449 100644 --- a/packages/mermaid/src/diagrams/blockDiagram/parser/blockDiagram.spec.ts +++ b/packages/mermaid/src/diagrams/block/parser/block.spec.ts @@ -1,58 +1,58 @@ // @ts-ignore: jison doesn't export types -import blockDiagram from './blockDiagram.jison'; +import block from './block.jison'; import db from '../blockDB.js'; import { cleanupComments } from '../../../diagram-api/comments.js'; -import { prepareTextForParsing } from '../blockDiagramUtils.js'; +import { prepareTextForParsing } from '../blockUtils.js'; import * as fs from 'fs'; import * as path from 'path'; describe('Sankey diagram', function () { describe('when parsing an block diagram graph it should handle > ', function () { beforeEach(function () { - blockDiagram.parser.yy = db; - blockDiagram.parser.yy.clear(); - blockDiagram.parser.yy.getLogger = () => console; + block.parser.yy = db; + block.parser.yy.clear(); + block.parser.yy.getLogger = () => console; }); it('a diagram with a node', async () => { - const str = `blockDiagram-beta + const str = `block-beta id `; - blockDiagram.parse(str); + block.parse(str); }); it('a diagram with multiple nodes', async () => { - const str = `blockDiagram-beta + const str = `block-beta id1 id2 `; - blockDiagram.parse(str); + block.parse(str); }); it('a node with a square shape and a label', async () => { - const str = `blockDiagram-beta + const str = `block-beta id["A label"] id2`; - blockDiagram.parse(str); + block.parse(str); }); it('a diagram with multiple nodes with edges', async () => { - const str = `blockDiagram-beta + const str = `block-beta id1["first"] --> id2["second"] `; - blockDiagram.parse(str); + block.parse(str); }); // it('a diagram with column statements', async () => { - // const str = `blockDiagram-beta + // const str = `block-beta // columns 1 // block1["Block 1"] // `; - // blockDiagram.parse(str); + // block.parse(str); // }); // it('a diagram with block hierarchies', async () => { - // const str = `blockDiagram-beta + // const str = `block-beta // columns 1 // block1[Block 1] @@ -63,10 +63,10 @@ describe('Sankey diagram', function () { // end %% End the compound block // `; - // blockDiagram.parse(str); + // block.parse(str); // }); // it('a diagram with differernt column values in different blocks', async () => { - // const str = `blockDiagram-beta + // const str = `block-beta // columns 1 // block1[Block 1] @@ -77,7 +77,7 @@ describe('Sankey diagram', function () { // end %% End the compound block // `; - // blockDiagram.parse(str); + // block.parse(str); // // Todo check that the different blocks have different column values // }); From fee2b244a1796bbcb07661062830160d6cc06821 Mon Sep 17 00:00:00 2001 From: Nikolay Rozhkov Date: Fri, 7 Jul 2023 14:12:18 +0300 Subject: [PATCH 03/97] Small cleanup --- packages/mermaid/src/config.type.ts | 6 ++-- .../mermaid/src/diagrams/block/blockDB.ts | 33 ++++++++++--------- .../src/diagrams/block/blockRenderer.ts | 11 +------ .../mermaid/src/diagrams/block/blockTypes.ts | 6 ++++ 4 files changed, 27 insertions(+), 29 deletions(-) diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index fdb2450ba0..becfc90e63 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -1,6 +1,7 @@ // TODO: This was auto generated from defaultConfig. Needs to be verified. import DOMPurify from 'dompurify'; +import { BlockConfig } from './diagrams/block/blockTypes.js'; export interface MermaidConfig { theme?: string; @@ -33,7 +34,7 @@ export interface MermaidConfig { gitGraph?: GitGraphDiagramConfig; c4?: C4DiagramConfig; sankey?: SankeyDiagramConfig; - block?: BlockDiagramConfig; + block?: BlockConfig; dompurifyConfig?: DOMPurify.Config; wrap?: boolean; fontSize?: number; @@ -422,9 +423,6 @@ export interface SankeyDiagramConfig extends BaseDiagramConfig { linkColor?: SankeyLinkColor | string; nodeAlignment?: SankeyNodeAlignment; } -export interface BlockDiagramConfig extends BaseDiagramConfig { - padding?: number; -} export interface FontConfig { fontSize?: string | number; diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts index 4cb611b177..db216160af 100644 --- a/packages/mermaid/src/diagrams/block/blockDB.ts +++ b/packages/mermaid/src/diagrams/block/blockDB.ts @@ -1,12 +1,14 @@ +import type { BlockDB } from './blockTypes.js'; + import * as configApi from '../../config.js'; -import common from '../common/common.js'; +// import common from '../common/common.js'; import { - setAccTitle, - getAccTitle, - getAccDescription, - setAccDescription, - setDiagramTitle, - getDiagramTitle, + // setAccTitle, + // getAccTitle, + // getAccDescription, + // setAccDescription, + // setDiagramTitle, + // getDiagramTitle, clear as commonClear, } from '../../commonDb.js'; @@ -14,7 +16,6 @@ type Block = { ID: string; }; -// Array of nodes guarantees their order let blocks: Block[] = []; const clear = (): void => { @@ -22,14 +23,16 @@ const clear = (): void => { commonClear(); }; -export default { +const db: BlockDB = { getConfig: () => configApi.getConfig().block, - getAccTitle, - setAccTitle, - getAccDescription, - setAccDescription, - getDiagramTitle, - setDiagramTitle, + // getAccTitle, + // setAccTitle, + // getAccDescription, + // setAccDescription, + // getDiagramTitle, + // setDiagramTitle, clear, }; + +export default db; \ No newline at end of file diff --git a/packages/mermaid/src/diagrams/block/blockRenderer.ts b/packages/mermaid/src/diagrams/block/blockRenderer.ts index 5a2f595bcf..cfa9cc522d 100644 --- a/packages/mermaid/src/diagrams/block/blockRenderer.ts +++ b/packages/mermaid/src/diagrams/block/blockRenderer.ts @@ -9,18 +9,14 @@ import { import { configureSvgSize } from '../../setupGraphViewbox.js'; import { Uid } from '../../rendering-util/uid.js'; -import type { SankeyLinkColor, SankeyNodeAlignment } from '../../config.type.js'; export const draw = function (text: string, id: string, _version: string, diagObj: Diagram): void { - // Get the config - const { securityLevel, sankey: conf } = configApi.getConfig(); - const defaultSankeyConfig = configApi!.defaultConfig!.blockDiagram!; - // TODO: // This code repeats for every diagram // Figure out what is happening there, probably it should be separated // The main thing is svg object that is a d3 wrapper for svg operations // + const { securityLevel } = configApi.getConfig(); let sandboxElement: any; if (securityLevel === 'sandbox') { sandboxElement = d3select('#i' + id); @@ -44,11 +40,6 @@ export const draw = function (text: string, id: string, _version: string, diagOb // Prepare data for construction based on diagObj.db // This must be a mutable object with `nodes` and `links` properties: // - // { - // "nodes": [ { "id": "Alice" }, { "id": "Bob" }, { "id": "Carol" } ], - // "links": [ { "source": "Alice", "target": "Bob", "value": 23 }, { "source": "Bob", "target": "Carol", "value": 43 } ] - // } - // // @ts-ignore TODO: db type const graph = diagObj.db.getGraph(); diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts index 28e5cd1679..014e6b7cb8 100644 --- a/packages/mermaid/src/diagrams/block/blockTypes.ts +++ b/packages/mermaid/src/diagrams/block/blockTypes.ts @@ -1,5 +1,11 @@ import type { DiagramDB } from '../../diagram-api/types.js'; +import type { BaseDiagramConfig } from '../../config.type.js'; + +export interface BlockConfig extends BaseDiagramConfig { + padding?: number; +} export interface BlockDB extends DiagramDB { clear: () => void; + getConfig: () => BlockConfig | undefined; } From 975f36c7db44d859e873c9349f6282dc367befdc Mon Sep 17 00:00:00 2001 From: Nikolay Rozhkov Date: Fri, 7 Jul 2023 14:14:30 +0300 Subject: [PATCH 04/97] Fixed block diagram parser import --- packages/mermaid/src/diagrams/block/blockDiagram.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/mermaid/src/diagrams/block/blockDiagram.ts b/packages/mermaid/src/diagrams/block/blockDiagram.ts index 1cd619749e..667783f492 100644 --- a/packages/mermaid/src/diagrams/block/blockDiagram.ts +++ b/packages/mermaid/src/diagrams/block/blockDiagram.ts @@ -1,6 +1,6 @@ import { DiagramDefinition } from '../../diagram-api/types.js'; // @ts-ignore: jison doesn't export types -import parser from './parser/blockDiagram.jison'; +import parser from './parser/block.jison'; import db from './blockDB.js'; import renderer from './blockRenderer.js'; import { prepareTextForParsing } from './blockUtils.js'; From c10f76580fa7919a5f259b4c8a3587697ecf124d Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Sun, 9 Jul 2023 12:28:14 +0200 Subject: [PATCH 05/97] Adding some more tests --- .../src/diagrams/block/parser/block.spec.ts | 200 ++++++++++++++---- 1 file changed, 162 insertions(+), 38 deletions(-) diff --git a/packages/mermaid/src/diagrams/block/parser/block.spec.ts b/packages/mermaid/src/diagrams/block/parser/block.spec.ts index 08b36c7449..4713b57c07 100644 --- a/packages/mermaid/src/diagrams/block/parser/block.spec.ts +++ b/packages/mermaid/src/diagrams/block/parser/block.spec.ts @@ -28,7 +28,19 @@ describe('Sankey diagram', function () { `; block.parse(str); + // Todo: DB check that the we have two nodes and that the root block has two columns }); + it('a diagram with multiple nodes', async () => { + const str = `block-beta + id1 + id2 + id3 + `; + + block.parse(str); + // Todo: DB check that the we have two nodes and that the root block has three columns + }); + it('a node with a square shape and a label', async () => { const str = `block-beta id["A label"] @@ -43,43 +55,155 @@ describe('Sankey diagram', function () { block.parse(str); }); - // it('a diagram with column statements', async () => { - // const str = `block-beta - // columns 1 - // block1["Block 1"] - // `; - - // block.parse(str); - // }); - // it('a diagram with block hierarchies', async () => { - // const str = `block-beta - // columns 1 - // block1[Block 1] - - // block - // columns 2 - // block2[Block 2] - // block3[Block 3] - // end %% End the compound block - // `; - - // block.parse(str); - // }); - // it('a diagram with differernt column values in different blocks', async () => { - // const str = `block-beta - // columns 1 - // block1[Block 1] - - // block - // columns 2 - // block2[Block 2] - // block3[Block 3] - // end %% End the compound block - // `; - - // block.parse(str); - - // // Todo check that the different blocks have different column values - // }); + it.skip('a diagram with column statements', async () => { + const str = `block-beta + columns 1 + block1["Block 1"] + `; + + block.parse(str); + // Todo: DB check that the we have one block and that the root block has one column + }); + + it.skip('blocks next to each other', async () => { + const str = `block-beta + block + columns 2 + block1["Block 1"] + block2["Block 2"] + `; + + block.parse(str); + + // Todo: DB check that the we have two blocks and that the root block has two columns + }); + + it.skip('blocks on top of each other', async () => { + const str = `block-beta + block + columns 1 + block1["Block 1"] + block2["Block 2"] + `; + + block.parse(str); + + // Todo: DB check that the we have two blocks and that the root block has one column + }); + + it.skip('compound blocks', async () => { + const str = `block + block + columns 2 + block2["Block 2"] + block3["Block 3"] + end %% End the compound block + `; + + block.parse(str); + }); + it.skip('compound blocks with title', async () => { + const str = `block + block compoundBlock["Compound block"] + columns 1 + block2["Block 1"] + end + `; + + block.parse(str); + }); + it.skip('blocks mixed with compound blocks', async () => { + const str = `block + columns 1 + block1["Block 1"] + + block + columns 2 + block2["Block 2"] + block3["Block 3"] + end %% End the compound block + `; + + block.parse(str); + }); + + it.skip('Arrow blocks', async () => { + const str = `block + columns 3 + block1["Block 1"] + blockArrow + block2["Block 2"]`; + + block.parse(str); + }); + it.skip('Arrow blocks with multiple points', async () => { + const str = `block-beta + columns 1 + A + blockArrow(1,3) + block + columns 3 + B + C + D + end`; + + block.parse(str); + }); + it.skip('blocks with different widths', async () => { + const str = `block-beta + columns 3 + one["One Slot"] + two["Two slots"]:2 + `; + + block.parse(str); + }); + it.skip('empty blocks', async () => { + const str = `block-beta + columns 3 + space + middle["In the middle"] + `; + + block.parse(str); + }); + it.skip('classDef statements applied to a block', async () => { + const str = `block-beta + classDef black color:#ffffff, fill:#000000; + + mc["Memcache"]:::black + `; + + block.parse(str); + }); + it.skip('classDef statements applied to a block with a width', async () => { + const str = `block-beta + classDef black color:#ffffff, fill:#000000; + columns 2 + mc["Memcache"]:2::black + `; + + block.parse(str); + }); + + it.skip('classDef statements', async () => { + const str = `block-beta + classDef black color:#ffffff, fill:#000000; + + block DataServices["Data Services"] + columns H + block Relational + mssql["Microsoft SQL
Server"] + end + block Tabular + columns 3 + gds["Google Data Store"]:1 + mc["Memcache"]:2:::black + end + end`; + + block.parse(str); + }); }); }); From d165e8a642bf11426f99adaab20a770d2dcca62f Mon Sep 17 00:00:00 2001 From: Nikolay Rozhkov Date: Mon, 10 Jul 2023 23:33:11 +0300 Subject: [PATCH 06/97] Started block diag db development --- demos/block.html | 93 +++++++++++++++++++ demos/index.html | 3 + .../mermaid/src/diagrams/block/blockDB.ts | 46 ++++++++- .../src/diagrams/block/blockDiagram.ts | 8 +- .../src/diagrams/block/blockRenderer.ts | 22 ++--- .../mermaid/src/diagrams/block/blockTypes.ts | 6 -- .../src/diagrams/block/parser/block.jison | 46 ++++----- .../src/diagrams/block/parser/block.spec.ts | 2 +- 8 files changed, 174 insertions(+), 52 deletions(-) create mode 100644 demos/block.html diff --git a/demos/block.html b/demos/block.html new file mode 100644 index 0000000000..141d139700 --- /dev/null +++ b/demos/block.html @@ -0,0 +1,93 @@ + + + + + + States Mermaid Quick Test Page + + + + + +

Block diagram demos

+

TCI IP

+
+      block-beta
+
+      block TCP_IP["TCP/IP"]
+    
+ + + + + + diff --git a/demos/index.html b/demos/index.html index 24c4fbf3b0..113d674337 100644 --- a/demos/index.html +++ b/demos/index.html @@ -78,6 +78,9 @@

ZenUML

  • Sankey

  • +
  • +

    Layered Blocks

    +
  • diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts index db216160af..de332e19b1 100644 --- a/packages/mermaid/src/diagrams/block/blockDB.ts +++ b/packages/mermaid/src/diagrams/block/blockDB.ts @@ -1,4 +1,6 @@ -import type { BlockDB } from './blockTypes.js'; +// import type { BlockDB } from './blockTypes.js'; +import type { DiagramDB } from '../../diagram-api/types.js'; +import { BlockConfig } from './blockTypes.js'; import * as configApi from '../../config.js'; // import common from '../common/common.js'; @@ -12,20 +14,54 @@ import { clear as commonClear, } from '../../commonDb.js'; -type Block = { +export type TBlockColumnsDefaultValue = 'H'; // Do we support something else, like 'auto' | 0? + +interface Block { ID: string; -}; + label?: string; + parent?: Block; + children?: Block[]; + columns: number | TBlockColumnsDefaultValue; +} + +interface Link { + source: Block; + target: Block; +} let blocks: Block[] = []; +let links: Link[] = []; const clear = (): void => { blocks = []; commonClear(); }; +type IAddBlock = (block: Block) => Block; +const addBlock: IAddBlock = (block: Block): Block => { + blocks.push(block); + return block; +}; + +type IAddLink = (link: Link) => Link; +const addLink: IAddLink = (link: Link): Link => { + links.push(link); + return link; +}; + +export interface BlockDB extends DiagramDB { + clear: () => void; + getConfig: () => BlockConfig | undefined; + addBlock: IAddBlock; + addLink: IAddLink; + getLogger: () => Console; +} + const db: BlockDB = { getConfig: () => configApi.getConfig().block, - + addBlock: addBlock, + addLink: addLink, + getLogger: () => console, // TODO: remove // getAccTitle, // setAccTitle, // getAccDescription, @@ -35,4 +71,4 @@ const db: BlockDB = { clear, }; -export default db; \ No newline at end of file +export default db; diff --git a/packages/mermaid/src/diagrams/block/blockDiagram.ts b/packages/mermaid/src/diagrams/block/blockDiagram.ts index 667783f492..e098360f43 100644 --- a/packages/mermaid/src/diagrams/block/blockDiagram.ts +++ b/packages/mermaid/src/diagrams/block/blockDiagram.ts @@ -3,10 +3,12 @@ import { DiagramDefinition } from '../../diagram-api/types.js'; import parser from './parser/block.jison'; import db from './blockDB.js'; import renderer from './blockRenderer.js'; -import { prepareTextForParsing } from './blockUtils.js'; -const originalParse = parser.parse.bind(parser); -parser.parse = (text: string) => originalParse(prepareTextForParsing(text)); +// TODO: do we need this? +// import { prepareTextForParsing } from './blockUtils.js'; +// const originalParse = parser.parse.bind(parser); +// parser.parse = (text: string) => originalParse(prepareTextForParsing(text)); +// parser.yy.getLogger = () => console; export const diagram: DiagramDefinition = { parser, diff --git a/packages/mermaid/src/diagrams/block/blockRenderer.ts b/packages/mermaid/src/diagrams/block/blockRenderer.ts index cfa9cc522d..8896b272db 100644 --- a/packages/mermaid/src/diagrams/block/blockRenderer.ts +++ b/packages/mermaid/src/diagrams/block/blockRenderer.ts @@ -11,11 +11,6 @@ import { configureSvgSize } from '../../setupGraphViewbox.js'; import { Uid } from '../../rendering-util/uid.js'; export const draw = function (text: string, id: string, _version: string, diagObj: Diagram): void { - // TODO: - // This code repeats for every diagram - // Figure out what is happening there, probably it should be separated - // The main thing is svg object that is a d3 wrapper for svg operations - // const { securityLevel } = configApi.getConfig(); let sandboxElement: any; if (securityLevel === 'sandbox') { @@ -25,28 +20,27 @@ export const draw = function (text: string, id: string, _version: string, diagOb securityLevel === 'sandbox' ? d3select(sandboxElement.nodes()[0].contentDocument.body) : d3select('body'); + // @ts-ignore TODO root.select is not callable const svg = securityLevel === 'sandbox' ? root.select(`[id="${id}"]`) : d3select(`[id="${id}"]`); // Establish svg dimensions and get width and height - // - - // FIX: using max width prevents height from being set, is it intended? - // to add height directly one can use `svg.attr('height', height)` - // - // @ts-ignore TODO: svg type vs selection mismatch + // + const height = 400; + const width = 600; + const useMaxWidth = false; configureSvgSize(svg, height, width, useMaxWidth); // Prepare data for construction based on diagObj.db // This must be a mutable object with `nodes` and `links` properties: // // @ts-ignore TODO: db type - const graph = diagObj.db.getGraph(); + // const graph = diagObj.db.getGraph(); - const nodeWidth = 10; + // const nodeWidth = 10; // Get color scheme for the graph - const colorScheme = d3scaleOrdinal(d3schemeTableau10); + // const colorScheme = d3scaleOrdinal(d3schemeTableau10); }; export default { diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts index 014e6b7cb8..c190c5779c 100644 --- a/packages/mermaid/src/diagrams/block/blockTypes.ts +++ b/packages/mermaid/src/diagrams/block/blockTypes.ts @@ -1,11 +1,5 @@ -import type { DiagramDB } from '../../diagram-api/types.js'; import type { BaseDiagramConfig } from '../../config.type.js'; export interface BlockConfig extends BaseDiagramConfig { padding?: number; } - -export interface BlockDB extends DiagramDB { - clear: () => void; - getConfig: () => BlockConfig | undefined; -} diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison index ba58a60971..6870859391 100644 --- a/packages/mermaid/src/diagrams/block/parser/block.jison +++ b/packages/mermaid/src/diagrams/block/parser/block.jison @@ -33,10 +33,10 @@ CRLF \u000D\u000A [\n]+ {yy.getLogger().info('_', yytext); /* skip all whitespace */ } // [\n] return 'NL'; ({CRLF}|{LF}) { return 'NL' } -["][`] { this.begin("md_string");} +["][`] { this.pushState("md_string");} [^`"]+ { return "MD_STR";} [`]["] { this.popState();} -["] this.begin("string"); +["] this.pushState("string"); ["] this.popState(); [^"]* return "STR"; "style" return 'STYLE'; @@ -45,11 +45,11 @@ CRLF \u000D\u000A "interpolate" return 'INTERPOLATE'; "classDef" return 'CLASSDEF'; "class" return 'CLASS'; -accTitle\s*":"\s* { this.begin("acc_title");return 'acc_title'; } +accTitle\s*":"\s* { this.pushState("acc_title");return 'acc_title'; } (?!\n|;|#)*[^\n]* { this.popState(); return "acc_title_value"; } -accDescr\s*":"\s* { this.begin("acc_descr");return 'acc_descr'; } +accDescr\s*":"\s* { this.pushState("acc_descr");return 'acc_descr'; } (?!\n|;|#)*[^\n]* { this.popState(); return "acc_descr_value"; } -accDescr\s*"{"\s* { this.begin("acc_descr_multiline");} +accDescr\s*"{"\s* { this.pushState("acc_descr_multiline");} [\}] { this.popState(); } [^\}]* return "acc_descr_multiline_value"; "subgraph" return 'subgraph'; @@ -60,32 +60,32 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili .*direction\s+LR[^\n]* return 'direction_lr'; // Start of nodes with shapes and description -"-)" { yy.getLogger().info('Lex: -)'); this.begin('NODE');return 'NODE_D START'; } -"(-" { yy.getLogger().info('Lex: (-'); this.begin('NODE');return 'NODE_DSTART'; } -"))" { yy.getLogger().info('Lex: ))'); this.begin('NODE');return 'NODE_DSTART'; } -")" { yy.getLogger().info('Lex: )'); this.begin('NODE');return 'NODE_DSTART'; } -"((" { yy.getLogger().info('Lex: )'); this.begin('NODE');return 'NODE_DSTART'; } -"{{" { yy.getLogger().info('Lex: )'); this.begin('NODE');return 'NODE_DSTART'; } -"(" { yy.getLogger().info('Lex: )'); this.begin('NODE');return 'NODE_DSTART'; } -"[" { yy.getLogger().info('Lex: ['); this.begin('NODE');return 'NODE_DSTART'; } -"([" { yy.getLogger().info('Lex: )'); this.begin('NODE');return 'NODE_DSTART'; } -"[[" { this.begin('NODE');return 'NODE_DSTART'; } -"[|" { this.begin('NODE');return 'NODE_DSTART'; } -"[(" { this.begin('NODE');return 'NODE_DSTART'; } -"(((" { this.begin('NODE');return 'NODE_DSTART'; } -")))" { this.begin('NODE');return 'NODE_DSTART'; } -"[/" { this.begin('NODE');return 'NODE_DSTART'; } -"[\\" { this.begin('NODE');return 'NODE_DSTART'; } +"-)" { yy.getLogger().info('Lex: -)'); this.pushState('NODE');return 'NODE_D START'; } +"(-" { yy.getLogger().info('Lex: (-'); this.pushState('NODE');return 'NODE_DSTART'; } +"))" { yy.getLogger().info('Lex: ))'); this.pushState('NODE');return 'NODE_DSTART'; } +")" { yy.getLogger().info('Lex: )'); this.pushState('NODE');return 'NODE_DSTART'; } +"((" { yy.getLogger().info('Lex: )'); this.pushState('NODE');return 'NODE_DSTART'; } +"{{" { yy.getLogger().info('Lex: )'); this.pushState('NODE');return 'NODE_DSTART'; } +"(" { yy.getLogger().info('Lex: )'); this.pushState('NODE');return 'NODE_DSTART'; } +"[" { yy.getLogger().info('Lex: ['); this.pushState('NODE');return 'NODE_DSTART'; } +"([" { yy.getLogger().info('Lex: )'); this.pushState('NODE');return 'NODE_DSTART'; } +"[[" { this.pushState('NODE');return 'NODE_DSTART'; } +"[|" { this.pushState('NODE');return 'NODE_DSTART'; } +"[(" { this.pushState('NODE');return 'NODE_DSTART'; } +"(((" { this.pushState('NODE');return 'NODE_DSTART'; } +")))" { this.pushState('NODE');return 'NODE_DSTART'; } +"[/" { this.pushState('NODE');return 'NODE_DSTART'; } +"[\\" { this.pushState('NODE');return 'NODE_DSTART'; } [^\(\[\n\-\)\{\}]+ { yy.getLogger().info('Lex: NODE_ID', yytext);return 'NODE_ID'; } <> { yy.getLogger().info('Lex: EOF', yytext);return 'EOF'; } // Handling of strings in node -["][`] { this.begin("md_string");} +["][`] { this.pushState("md_string");} [^`"]+ { return "NODE_DESCR";} [`]["] { this.popState();} -["] { yy.getLogger().info('Lex: Starting string');this.begin("string");} +["] { yy.getLogger().info('Lex: Starting string');this.pushState("string");} [^"]+ { yy.getLogger().info('Lex: NODE_DESCR:', yytext); return "NODE_DESCR";} ["] {this.popState();} diff --git a/packages/mermaid/src/diagrams/block/parser/block.spec.ts b/packages/mermaid/src/diagrams/block/parser/block.spec.ts index 4713b57c07..2c575aeba3 100644 --- a/packages/mermaid/src/diagrams/block/parser/block.spec.ts +++ b/packages/mermaid/src/diagrams/block/parser/block.spec.ts @@ -6,7 +6,7 @@ import { prepareTextForParsing } from '../blockUtils.js'; import * as fs from 'fs'; import * as path from 'path'; -describe('Sankey diagram', function () { +describe('Block diagram', function () { describe('when parsing an block diagram graph it should handle > ', function () { beforeEach(function () { block.parser.yy = db; From e251baa61c50d429f1a2d17ba67f04f8bfebf5f0 Mon Sep 17 00:00:00 2001 From: Nikolay Rozhkov Date: Tue, 11 Jul 2023 02:51:10 +0300 Subject: [PATCH 07/97] Started layout and rendering --- demos/block.html | 10 +- .../mermaid/src/diagrams/block/blockDB.ts | 37 ++++-- .../src/diagrams/block/blockRenderer.ts | 115 +++++++++++++++++- 3 files changed, 150 insertions(+), 12 deletions(-) diff --git a/demos/block.html b/demos/block.html index 141d139700..3e8769ecc4 100644 --- a/demos/block.html +++ b/demos/block.html @@ -18,14 +18,18 @@

    TCI IP

           block-beta
     
    -      block TCP_IP["TCP/IP"]
         
    - Still - Still --> [*] - Still --> Moving - Moving --> Still - Moving --> Crash - Crash --> [*]
     flowchart RL
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index a0c97fc0fa..bec5c33c3f 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -1,6 +1,6 @@
     // import type { BlockDB } from './blockTypes.js';
     import type { DiagramDB } from '../../diagram-api/types.js';
    -import { BlockConfig } from './blockTypes.js';
    +import { BlockConfig, BlockType, Block, Link } from './blockTypes.js';
     
     import * as configApi from '../../config.js';
     // import common from '../common/common.js';
    @@ -13,47 +13,78 @@ import {
       // getDiagramTitle,
       clear as commonClear,
     } from '../../commonDb.js';
    +import { log } from '../../logger.js';
     
     // export type TBlockColumnsDefaultValue = 'H'; // Do we support something else, like 'auto' | 0?
     
    -// TODO: Convert to generic TreeNode type? Convert to class?
    -export interface Block {
    -  ID: string;
    -  label?: string;
    -  parent?: Block;
    -  children?: Block[];
    -  columns?: number; // | TBlockColumnsDefaultValue;
    -}
    +// Initialize the node database for simple lookups
    +let nodeDatabase: Record = {};
    +const blockDatabase: Record = {};
     
    -export interface Link {
    -  source: Block;
    -  target: Block;
    -}
    +// Function to get a node by its ID
    +export const getNodeById = (id: string): Node | undefined => {
    +  return nodeDatabase[id];
    +};
    +
    +// TODO: Convert to generic TreeNode type? Convert to class?
     
    -let rootBlocks: Block[] = [];
    +let rootBlock = { ID: 'root', children: [] as Block[], columns: -1 };
     let blocks: Block[] = [];
     const links: Link[] = [];
    -let rootBlock = { ID: 'root', children: [], columns: -1 } as Block;
    -let currentBlock: Block | undefined;
    +// let rootBlock = { ID: 'root', children: [], columns: -1 } as Block;
    +let currentBlock = rootBlock;
     
     const clear = (): void => {
    -  rootBlocks = [];
    -  blocks = [];
    +  log.info('Clear called');
    +  // rootBlocks = [];
    +  blocks = [] as Block[];
       commonClear();
       rootBlock = { ID: 'root', children: [], columns: -1 };
       currentBlock = rootBlock;
    +  nodeDatabase = {};
    +  blockDatabase[rootBlock.ID] = rootBlock;
     };
     
    -type IAddBlock = (block: Block) => Block;
    -const addBlock: IAddBlock = (block: Block, parent?: Block): Block => {
    -  if (parent) {
    -    parent.children ??= [];
    -    parent.children.push(block);
    -  } else {
    -    rootBlocks.push(block);
    +// type IAddBlock = (block: Block) => Block;
    +// const addBlock: IAddBlock = (block: Block, parent?: Block): Block => {
    +//   log.info('addBlock', block, parent);
    +//   if (parent) {
    +//     parent.children ??= [];
    +//     parent.children.push(block);
    +//   } else {
    +//     rootBlock.children.push(block);
    +//   }
    +//   blocks.push(block);
    +//   return block;
    +// };
    +
    +type ITypeStr2Type = (typeStr: string) => BlockType;
    +export function typeStr2Type(typeStr: string) {
    +  // TODO: add all types
    +  switch (typeStr) {
    +    case '[]':
    +      return 'square';
    +    case '()':
    +      return 'round';
    +    default:
    +      return 'square';
       }
    -  blocks.push(block);
    -  return block;
    +}
    +
    +type IAddBlock = (id: string, label: string, type: BlockType) => Block;
    +// Function to add a node to the database
    +export const addBlock = (id: string, _label?: string, type?: BlockType) => {
    +  log.info('addNode called:', id, _label, type);
    +  const label = _label || id;
    +  const node: Block = {
    +    ID: id,
    +    label,
    +    type: type || 'square',
    +  };
    +  blockDatabase[node.ID] = node;
    +  currentBlock.children ??= [];
    +  currentBlock.children.push(node);
    +  return node;
     };
     
     type IAddLink = (link: Link) => Link;
    @@ -84,16 +115,21 @@ const getBlock = (id: string, blocks: Block[]): Block | undefined => {
     
     type IGetColumns = (blockID: string) => number;
     const getColumns = (blockID: string): number => {
    -  const blocks = [rootBlock];
    -  const block = getBlock(blockID, blocks);
    +  const block = blockDatabase[blockID];
       if (!block) {
         return -1;
       }
    -  return block.columns || -1;
    +  if (block.columns) {
    +    return block.columns;
    +  }
    +  if (!block.children) {
    +    return -1;
    +  }
    +  return block.children.length;
     };
     
     type IGetBlocks = () => Block[];
    -const getBlocks: IGetBlocks = () => blocks;
    +const getBlocks: IGetBlocks = () => rootBlock.children || [];
     
     type IGetLinks = () => Link[];
     const getLinks: IGetLinks = () => links;
    @@ -111,12 +147,14 @@ export interface BlockDB extends DiagramDB {
       getLinks: IGetLinks;
       setColumns: ISetColumns;
       getColumns: IGetColumns;
    +  typeStr2Type: ITypeStr2Type;
     }
     
     const db: BlockDB = {
       getConfig: () => configApi.getConfig().block,
       addBlock: addBlock,
       addLink: addLink,
    +  typeStr2Type: typeStr2Type,
       getLogger, // TODO: remove
       getBlocks,
       getLinks,
    diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts
    index c190c5779c..b373d6b9cc 100644
    --- a/packages/mermaid/src/diagrams/block/blockTypes.ts
    +++ b/packages/mermaid/src/diagrams/block/blockTypes.ts
    @@ -3,3 +3,36 @@ import type { BaseDiagramConfig } from '../../config.type.js';
     export interface BlockConfig extends BaseDiagramConfig {
       padding?: number;
     }
    +
    +export type BlockType =
    +  | 'round'
    +  | 'square'
    +  | 'diamond'
    +  | 'hexagon'
    +  | 'odd'
    +  | 'lean_right'
    +  | 'lean_left'
    +  | 'trapezoid'
    +  | 'inv_trapezoid'
    +  | 'odd_right'
    +  | 'circle'
    +  | 'ellipse'
    +  | 'stadium'
    +  | 'subroutine'
    +  | 'cylinder'
    +  | 'group'
    +  | 'doublecircle';
    +
    +export interface Block {
    +  ID: string;
    +  label?: string;
    +  parent?: Block;
    +  type?: BlockType;
    +  children?: Block[];
    +  columns?: number; // | TBlockColumnsDefaultValue;
    +}
    +
    +export interface Link {
    +  source: Block;
    +  target: Block;
    +}
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index afd645d96f..9422d8ee3a 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -64,7 +64,7 @@ accDescr\s*"{"\s*                                { this.pushState("acc_descr_mul
     
     // Start of nodes with shapes and description
     "-)"                   { yy.getLogger().info('Lex: -)'); this.pushState('NODE');return 'NODE_D START'; }
    -"(-"                   { yy.getLogger().info('Lex: (-'); this.pushState('NODE');return 'NODE_DSTART';           }
    +"(-"                   { yy.getLogger().info('Lex: (-'); this.pushState('NODE');return 'NODE_DSTART'; }
     "))"                   { yy.getLogger().info('Lex: ))'); this.pushState('NODE');return 'NODE_DSTART';  }
     ")"                    { yy.getLogger().info('Lex: )'); this.pushState('NODE');return 'NODE_DSTART';      }
     "(("                   { yy.getLogger().info('Lex: )'); this.pushState('NODE');return 'NODE_DSTART'; }
    @@ -177,8 +177,8 @@ statement
     	;
     
     nodeStatement
    -  : nodeStatement link node { yy.getLogger().info('Rule: nodeStatement (nodeStatement link node) ');}
    -  | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1);}
    +  : nodeStatement link node { yy.getLogger().info('Rule: nodeStatement (nodeStatement link node) '); yy.addBlock($1.id);}
    +  | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); yy.addBlock($1.id, $1.label, yy.typeStr2Type($1)); }
       ;
     
     columnsStatement
    @@ -192,16 +192,16 @@ blockStatement
     
     node
       : NODE_ID
    -  { yy.getLogger().info("Rule: node (NODE_ID seperator): ", $1); }
    +  { yy.getLogger().info("Rule: node (NODE_ID seperator): ", $1); $$ = { id: $1 }; }
       |NODE_ID nodeShapeNLabel
    -    { yy.getLogger().info("Rule: node (NODE_ID nodeShapeNLabel seperator): ", $1, $2); }
    +    { yy.getLogger().info("Rule: node (NODE_ID nodeShapeNLabel seperator): ", $1, $2); $$ = { id: $1, label: $2.label, typeStr: $2.typeStr };}
       // |nodeShapeNLabel seperator
       // { yy.getLogger().info("Rule: node (nodeShapeNLabel seperator): ", $1, $2, $3); }
       ;
     
     nodeShapeNLabel
       :   NODE_DSTART STR NODE_DEND
    -	      { yy.getLogger().info("Rule: nodeShapeNLabel: ", $1, $2, $3); $$ = { type: $1 + $3, descr: $2 }; }
    +	      { yy.getLogger().info("Rule: nodeShapeNLabel: ", $1, $2, $3); $$ = { typeStr: $1 + $3, label: $2 }; }
       ;
     
     %%
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.spec.ts b/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    index 75cd76b82a..ded6db4684 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    +++ b/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    @@ -3,8 +3,7 @@ import block from './block.jison';
     import db from '../blockDB.js';
     import { cleanupComments } from '../../../diagram-api/comments.js';
     import { prepareTextForParsing } from '../blockUtils.js';
    -import * as fs from 'fs';
    -import * as path from 'path';
    +import { setConfig } from '../../../config.js';
     
     describe('Block diagram', function () {
       describe('when parsing an block diagram graph it should handle > ', function () {
    @@ -20,6 +19,22 @@ describe('Block diagram', function () {
           `;
     
           block.parse(str);
    +      const blocks = db.getBlocks();
    +      expect(blocks.length).toBe(1);
    +      expect(blocks[0].ID).toBe('id');
    +      expect(blocks[0].label).toBe('id');
    +    });
    +    it('a node with a square shape and a label', async () => {
    +      const str = `block-beta
    +          id["A label"]
    +          `;
    +
    +      block.parse(str);
    +      const blocks = db.getBlocks();
    +      expect(blocks.length).toBe(1);
    +      expect(blocks[0].ID).toBe('id');
    +      expect(blocks[0].label).toBe('A label');
    +      expect(blocks[0].type).toBe('square');
         });
         it('a diagram with multiple nodes', async () => {
           const str = `block-beta
    diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js b/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js
    index 3852c4f92c..8d0aec789e 100644
    --- a/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js
    +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow.spec.js
    @@ -1,7 +1,7 @@
     import flowDb from '../flowDb.js';
     import flow from './flow.jison';
    -import { setConfig } from '../../../config.js';
     import { cleanupComments } from '../../../diagram-api/comments.js';
    +import { setConfig } from '../../../config.js';
     
     setConfig({
       securityLevel: 'strict',
    
    From aa7f5a83879df60ff2316149ae80f179cac20d97 Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Fri, 1 Sep 2023 14:06:13 +0200
    Subject: [PATCH 10/97] before refactoring
    
    ---
     .../mermaid/src/diagrams/block/blockDB.ts     | 65 +++++++++++-----
     .../mermaid/src/diagrams/block/blockTypes.ts  |  7 +-
     .../src/diagrams/block/parser/block.jison     | 15 ++--
     .../src/diagrams/block/parser/block.spec.ts   | 76 ++++++++++++++++++-
     4 files changed, 132 insertions(+), 31 deletions(-)
    
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index bec5c33c3f..2ef2044306 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -21,17 +21,19 @@ import { log } from '../../logger.js';
     let nodeDatabase: Record = {};
     const blockDatabase: Record = {};
     
    -// Function to get a node by its ID
    -export const getNodeById = (id: string): Node | undefined => {
    -  return nodeDatabase[id];
    +// Function to get a node by its id
    +type IGetNodeById = (id: string) => Block | undefined;
    +export const getNodeById = (id: string): Block | undefined => {
    +  console.log(id, nodeDatabase);
    +  return blockDatabase[id];
     };
     
     // TODO: Convert to generic TreeNode type? Convert to class?
     
    -let rootBlock = { ID: 'root', children: [] as Block[], columns: -1 };
    +let rootBlock = { id: 'root', children: [] as Block[], columns: -1 };
     let blocks: Block[] = [];
     const links: Link[] = [];
    -// let rootBlock = { ID: 'root', children: [], columns: -1 } as Block;
    +// let rootBlock = { id: 'root', children: [], columns: -1 } as Block;
     let currentBlock = rootBlock;
     
     const clear = (): void => {
    @@ -39,10 +41,10 @@ const clear = (): void => {
       // rootBlocks = [];
       blocks = [] as Block[];
       commonClear();
    -  rootBlock = { ID: 'root', children: [], columns: -1 };
    +  rootBlock = { id: 'root', children: [], columns: -1 };
       currentBlock = rootBlock;
       nodeDatabase = {};
    -  blockDatabase[rootBlock.ID] = rootBlock;
    +  blockDatabase[rootBlock.id] = rootBlock;
     };
     
     // type IAddBlock = (block: Block) => Block;
    @@ -71,22 +73,39 @@ export function typeStr2Type(typeStr: string) {
       }
     }
     
    -type IAddBlock = (id: string, label: string, type: BlockType) => Block;
    +let cnt = 0;
    +export const generateId = () => {
    +  cnt++;
    +  return 'id-' + Math.random().toString(36).substr(2, 12) + '-' + cnt;
    +};
    +
    +type IAddBlock = (_id: string, label: string, type: BlockType) => Block;
     // Function to add a node to the database
    -export const addBlock = (id: string, _label?: string, type?: BlockType) => {
    -  log.info('addNode called:', id, _label, type);
    +export const addBlock = (_id: string, _label?: string, type?: BlockType) => {
    +  let id = _id;
    +  if (!_id) {
    +    id = generateId();
    +  }
       const label = _label || id;
       const node: Block = {
    -    ID: id,
    +    id: id,
         label,
         type: type || 'square',
    +    children: [],
       };
    -  blockDatabase[node.ID] = node;
    -  currentBlock.children ??= [];
    -  currentBlock.children.push(node);
    +  blockDatabase[node.id] = node;
    +  // currentBlock.children ??= [];
    +  // currentBlock.children.push(node);
    +  // console.log('currentBlock', currentBlock.children, nodeDatabase);
    +  console.log('addNode called:', id, label, type, node);
       return node;
     };
     
    +type ISetHierarchy = (block: Block[]) => void;
    +const setHierarchy = (block: Block[]): void => {
    +  blocks = block;
    +};
    +
     type IAddLink = (link: Link) => Link;
     const addLink: IAddLink = (link: Link): Link => {
       links.push(link);
    @@ -101,7 +120,7 @@ const setColumns = (columnsStr: string): void => {
     
     const getBlock = (id: string, blocks: Block[]): Block | undefined => {
       for (const block of blocks) {
    -    if (block.ID === id) {
    +    if (block.id === id) {
           return block;
         }
         if (block.children) {
    @@ -113,9 +132,9 @@ const getBlock = (id: string, blocks: Block[]): Block | undefined => {
       }
     };
     
    -type IGetColumns = (blockID: string) => number;
    -const getColumns = (blockID: string): number => {
    -  const block = blockDatabase[blockID];
    +type IGetColumns = (blockid: string) => number;
    +const getColumns = (blockid: string): number => {
    +  const block = blockDatabase[blockid];
       if (!block) {
         return -1;
       }
    @@ -129,7 +148,11 @@ const getColumns = (blockID: string): number => {
     };
     
     type IGetBlocks = () => Block[];
    -const getBlocks: IGetBlocks = () => rootBlock.children || [];
    +const getBlocks: IGetBlocks = () => {
    +  // console.log('Block in test', rootBlock.children || []);
    +  console.log('Block in test', blocks, blocks[0].id);
    +  return blocks || [];
    +};
     
     type IGetLinks = () => Link[];
     const getLinks: IGetLinks = () => links;
    @@ -148,6 +171,8 @@ export interface BlockDB extends DiagramDB {
       setColumns: ISetColumns;
       getColumns: IGetColumns;
       typeStr2Type: ITypeStr2Type;
    +  setHierarchy: ISetHierarchy;
    +  getNodeById: IGetNodeById;
     }
     
     const db: BlockDB = {
    @@ -158,6 +183,8 @@ const db: BlockDB = {
       getLogger, // TODO: remove
       getBlocks,
       getLinks,
    +  setHierarchy,
    +  getNodeById,
       // getAccTitle,
       // setAccTitle,
       // getAccDescription,
    diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts
    index b373d6b9cc..4afbe43519 100644
    --- a/packages/mermaid/src/diagrams/block/blockTypes.ts
    +++ b/packages/mermaid/src/diagrams/block/blockTypes.ts
    @@ -21,14 +21,15 @@ export type BlockType =
       | 'subroutine'
       | 'cylinder'
       | 'group'
    -  | 'doublecircle';
    +  | 'doublecircle'
    +  | 'composite';
     
     export interface Block {
    -  ID: string;
    +  id: string;
       label?: string;
       parent?: Block;
       type?: BlockType;
    -  children?: Block[];
    +  children: Block[];
       columns?: number; // | TBlockColumnsDefaultValue;
     }
     
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index 9422d8ee3a..309dbfdeaf 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -137,7 +137,9 @@ seperator
         {yy.getLogger().info('Rule: seperator (EOF) ');}
       ;
     
    -start: BLOCK_DIAGRAM_KEY document EOF;
    +start: BLOCK_DIAGRAM_KEY document EOF
    +  {console.log('This is the hierarchy ', JSON.stringify($2, null, 2)); yy.setHierarchy($2); }
    +  ;
     
     
     stop
    @@ -148,9 +150,10 @@ stop
       | stop EOF {yy.getLogger().info('Stop EOF2 ');}
       ;
     
    +//array of statements
     document
    -	: statement { yy.getLogger().info("Rule: statement: ", $1);}
    -	| statement document { yy.getLogger().info("Rule: document statement: ", $1);}
    +	: statement { yy.getLogger().info("Rule: statement: ", $1); $$ = [$1]; }
    +	| statement document { yy.getLogger().info("Rule: document statement: ", $1, $2); $$ = [$1].concat($2); }
     	;
     
     link
    @@ -177,8 +180,8 @@ statement
     	;
     
     nodeStatement
    -  : nodeStatement link node { yy.getLogger().info('Rule: nodeStatement (nodeStatement link node) '); yy.addBlock($1.id);}
    -  | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); yy.addBlock($1.id, $1.label, yy.typeStr2Type($1)); }
    +  : nodeStatement link node { yy.getLogger().info('Rule: nodeStatement (nodeStatement link node) '); yy.addBlock($1.id); $$ = {id: $1.id}; }
    +  | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); yy.addBlock($1.id, $1.label, yy.typeStr2Type($1)); $$ = {id: $1.id}; }
       ;
     
     columnsStatement
    @@ -186,7 +189,7 @@ columnsStatement
       ;
     
     blockStatement
    -  : block document end { yy.getLogger().info('Rule: blockStatement : ', $1); }
    +  : block document end { console.log('Rule: blockStatement : ', $1, $2, $3); const block = yy.addBlock(undefined, undefined, 'composite'); $$ = { id: block.id, children: $2 }; }
       ;
     
     
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.spec.ts b/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    index ded6db4684..584a817b55 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    +++ b/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    @@ -43,7 +43,14 @@ describe('Block diagram', function () {
           `;
     
           block.parse(str);
    -      // Todo: DB check that the we have two nodes and that the root block has two columns
    +      const blocks = db.getBlocks();
    +      expect(blocks.length).toBe(2);
    +      expect(blocks[0].ID).toBe('id1');
    +      expect(blocks[0].label).toBe('id1');
    +      expect(blocks[0].type).toBe('square');
    +      expect(blocks[1].ID).toBe('id2');
    +      expect(blocks[1].label).toBe('id2');
    +      expect(blocks[1].type).toBe('square');
         });
         it('a diagram with multiple nodes', async () => {
           const str = `block-beta
    @@ -53,7 +60,17 @@ describe('Block diagram', function () {
           `;
     
           block.parse(str);
    -      // Todo: DB check that the we have two nodes and that the root block has three columns
    +      const blocks = db.getBlocks();
    +      expect(blocks.length).toBe(3);
    +      expect(blocks[0].ID).toBe('id1');
    +      expect(blocks[0].label).toBe('id1');
    +      expect(blocks[0].type).toBe('square');
    +      expect(blocks[1].ID).toBe('id2');
    +      expect(blocks[1].label).toBe('id2');
    +      expect(blocks[1].type).toBe('square');
    +      expect(blocks[2].ID).toBe('id3');
    +      expect(blocks[2].label).toBe('id3');
    +      expect(blocks[2].type).toBe('square');
         });
     
         it('a node with a square shape and a label', async () => {
    @@ -62,6 +79,14 @@ describe('Block diagram', function () {
               id2`;
     
           block.parse(str);
    +      const blocks = db.getBlocks();
    +      expect(blocks.length).toBe(2);
    +      expect(blocks[0].ID).toBe('id');
    +      expect(blocks[0].label).toBe('A label');
    +      expect(blocks[0].type).toBe('square');
    +      expect(blocks[1].ID).toBe('id2');
    +      expect(blocks[1].label).toBe('id2');
    +      expect(blocks[1].type).toBe('square');
         });
         it('a diagram with multiple nodes with edges', async () => {
           const str = `block-beta
    @@ -124,14 +149,59 @@ describe('Block diagram', function () {
           // Todo: DB check that the we have two blocks and that the root block has one column
         });
     
    -    it('compound blocks', async () => {
    +    it('compound blocks 2', async () => {
           const str = `block-beta
               block
                 aBlock["Block"]
    +            bBlock["Block"]
    +          end
    +        `;
    +
    +      block.parse(str);
    +      const blocks = db.getBlocks();
    +      console.log('blocks', blocks);
    +      expect(blocks.length).toBe(1);
    +      expect(blocks[0].children.length).toBe(2);
    +      expect(blocks[0].id).toBe('id');
    +      expect(blocks[0].label).toBe('A label');
    +      expect(blocks[0].type).toBe('square');
    +      // expect(blocks[1].ID).toBe('id2');
    +      // expect(blocks[1].label).toBe('id2');
    +      // expect(blocks[1].type).toBe('square');
    +    });
    +    it.only('compound blocks', async () => {
    +      const str = `block-beta
    +          block
    +            aBlock["ABlock"]
    +            block
    +              bBlock["BBlock"]
    +            end
               end
             `;
     
           block.parse(str);
    +      const blocks = db.getBlocks();
    +
    +      const aBlockPos = blocks[0].children[0];
    +      const bBlockPos = blocks[0].children[1].children[0];
    +
    +      const root = db.getNodeById(blocks[0].id);
    +      expect(blocks.length).toBe(1);
    +      expect(blocks[0].id).not.toBe(undefined);
    +      expect(root?.label).toBe(blocks[0].id);
    +      expect(blocks[0].children.length).toBe(2);
    +      expect(root?.type).toBe('composite');
    +
    +      const aBlock = db.getNodeById(aBlockPos.id);
    +      console.log('aBlock', aBlock);
    +      expect(aBlock?.label).toBe('ABlock');
    +      expect(aBlock?.type).toBe('square');
    +
    +      const bBlock = db.getNodeById(bBlockPos.id);
    +
    +      expect(bBlock.id).toBe('bBlock');
    +      expect(bBlock.label).toBe('BBlock');
    +      expect(bBlock.type).toBe('square');
         });
         it.skip('compound blocks with title', async () => {
           const str = `block
    
    From 8a55b212a227c970fda4030d5e94e668dc9d17ad Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Fri, 1 Sep 2023 15:33:38 +0200
    Subject: [PATCH 11/97] Saving data from compound blocks
    
    ---
     .../mermaid/src/diagrams/block/blockDB.ts     | 68 ++++++++--------
     .../mermaid/src/diagrams/block/blockTypes.ts  |  3 +-
     .../src/diagrams/block/parser/block.jison     | 10 +--
     .../src/diagrams/block/parser/block.spec.ts   | 77 +++++++++++--------
     4 files changed, 85 insertions(+), 73 deletions(-)
    
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index 2ef2044306..9717bc348b 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -18,48 +18,46 @@ import { log } from '../../logger.js';
     // export type TBlockColumnsDefaultValue = 'H'; // Do we support something else, like 'auto' | 0?
     
     // Initialize the node database for simple lookups
    -let nodeDatabase: Record = {};
    -const blockDatabase: Record = {};
    +let blockDatabase: Record = {};
    +
    +const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
    +  for (const block of blockList) {
    +    if (block.type === 'column-setting') {
    +      const columns = block.columns || -1;
    +      parent.columns = columns;
    +    } else {
    +      if (!block.label) {
    +        block.label = block.id;
    +      }
    +      blockDatabase[block.id] = block;
    +
    +      if (block.children) {
    +        populateBlockDatabase(block.children, block);
    +      }
    +    }
    +  }
    +};
     
     // Function to get a node by its id
     type IGetNodeById = (id: string) => Block | undefined;
    -export const getNodeById = (id: string): Block | undefined => {
    -  console.log(id, nodeDatabase);
    +export const getBlockById = (id: string): Block | undefined => {
       return blockDatabase[id];
     };
     
     // TODO: Convert to generic TreeNode type? Convert to class?
     
    -let rootBlock = { id: 'root', children: [] as Block[], columns: -1 };
     let blocks: Block[] = [];
     const links: Link[] = [];
    -// let rootBlock = { id: 'root', children: [], columns: -1 } as Block;
    -let currentBlock = rootBlock;
    +let rootBlock = { id: 'root', type: 'composite', children: [], columns: -1 } as Block;
     
     const clear = (): void => {
       log.info('Clear called');
    -  // rootBlocks = [];
    -  blocks = [] as Block[];
       commonClear();
    -  rootBlock = { id: 'root', children: [], columns: -1 };
    -  currentBlock = rootBlock;
    -  nodeDatabase = {};
    -  blockDatabase[rootBlock.id] = rootBlock;
    +  rootBlock = { id: 'root', type: 'composite', children: [], columns: -1 } as Block;
    +  blockDatabase = { root: rootBlock };
    +  blocks = [] as Block[];
     };
     
    -// type IAddBlock = (block: Block) => Block;
    -// const addBlock: IAddBlock = (block: Block, parent?: Block): Block => {
    -//   log.info('addBlock', block, parent);
    -//   if (parent) {
    -//     parent.children ??= [];
    -//     parent.children.push(block);
    -//   } else {
    -//     rootBlock.children.push(block);
    -//   }
    -//   blocks.push(block);
    -//   return block;
    -// };
    -
     type ITypeStr2Type = (typeStr: string) => BlockType;
     export function typeStr2Type(typeStr: string) {
       // TODO: add all types
    @@ -74,6 +72,7 @@ export function typeStr2Type(typeStr: string) {
     }
     
     let cnt = 0;
    +type IGenerateId = () => string;
     export const generateId = () => {
       cnt++;
       return 'id-' + Math.random().toString(36).substr(2, 12) + '-' + cnt;
    @@ -96,13 +95,15 @@ export const addBlock = (_id: string, _label?: string, type?: BlockType) => {
       blockDatabase[node.id] = node;
       // currentBlock.children ??= [];
       // currentBlock.children.push(node);
    -  // console.log('currentBlock', currentBlock.children, nodeDatabase);
    -  console.log('addNode called:', id, label, type, node);
    +  // log.info('currentBlock', currentBlock.children, nodeDatabase);
    +  log.info('addNode called:', id, label, type, node);
       return node;
     };
     
     type ISetHierarchy = (block: Block[]) => void;
     const setHierarchy = (block: Block[]): void => {
    +  populateBlockDatabase(block, rootBlock);
    +  log.info('blockdb', JSON.stringify(blockDatabase, null, 2));
       blocks = block;
     };
     
    @@ -115,7 +116,6 @@ const addLink: IAddLink = (link: Link): Link => {
     type ISetColumns = (columnsStr: string) => void;
     const setColumns = (columnsStr: string): void => {
       const columns = columnsStr === 'auto' ? -1 : parseInt(columnsStr);
    -  currentBlock!.columns = columns;
     };
     
     const getBlock = (id: string, blocks: Block[]): Block | undefined => {
    @@ -149,8 +149,8 @@ const getColumns = (blockid: string): number => {
     
     type IGetBlocks = () => Block[];
     const getBlocks: IGetBlocks = () => {
    -  // console.log('Block in test', rootBlock.children || []);
    -  console.log('Block in test', blocks, blocks[0].id);
    +  // log.info('Block in test', rootBlock.children || []);
    +  log.info('Block in test', blocks, blocks[0].id);
       return blocks || [];
     };
     
    @@ -172,7 +172,8 @@ export interface BlockDB extends DiagramDB {
       getColumns: IGetColumns;
       typeStr2Type: ITypeStr2Type;
       setHierarchy: ISetHierarchy;
    -  getNodeById: IGetNodeById;
    +  getBlockById: IGetNodeById;
    +  generateId: IGenerateId;
     }
     
     const db: BlockDB = {
    @@ -184,7 +185,7 @@ const db: BlockDB = {
       getBlocks,
       getLinks,
       setHierarchy,
    -  getNodeById,
    +  getBlockById,
       // getAccTitle,
       // setAccTitle,
       // getAccDescription,
    @@ -194,6 +195,7 @@ const db: BlockDB = {
       setColumns,
       getColumns,
       clear,
    +  generateId,
     };
     
     export default db;
    diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts
    index 4afbe43519..a695b4ec78 100644
    --- a/packages/mermaid/src/diagrams/block/blockTypes.ts
    +++ b/packages/mermaid/src/diagrams/block/blockTypes.ts
    @@ -22,7 +22,8 @@ export type BlockType =
       | 'cylinder'
       | 'group'
       | 'doublecircle'
    -  | 'composite';
    +  | 'composite'
    +  | 'column-setting';
     
     export interface Block {
       id: string;
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index 309dbfdeaf..829ccd300c 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -138,7 +138,7 @@ seperator
       ;
     
     start: BLOCK_DIAGRAM_KEY document EOF
    -  {console.log('This is the hierarchy ', JSON.stringify($2, null, 2)); yy.setHierarchy($2); }
    +  {yy.getLogger().info('This is the hierarchy ', JSON.stringify($2, null, 2)); yy.setHierarchy($2); }
       ;
     
     
    @@ -180,16 +180,16 @@ statement
     	;
     
     nodeStatement
    -  : nodeStatement link node { yy.getLogger().info('Rule: nodeStatement (nodeStatement link node) '); yy.addBlock($1.id); $$ = {id: $1.id}; }
    -  | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); yy.addBlock($1.id, $1.label, yy.typeStr2Type($1)); $$ = {id: $1.id}; }
    +  : nodeStatement link node { yy.getLogger().info('Rule: nodeStatement (nodeStatement link node) '); $$ = {id: $1.id}; }
    +  | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); $$ = {id: $1.id, label: $1.label, type: yy.typeStr2Type($1)}; }
       ;
     
     columnsStatement
    -  : COLUMNS { yy.getLogger().info("COLUMNS: ", $1);yy.setColumns($1); }
    +  : COLUMNS { yy.getLogger().info("COLUMNS: ", $1); $$ = {type: 'column-setting', columns: $1 === 'auto'?-1:parseInt($1) } }
       ;
     
     blockStatement
    -  : block document end { console.log('Rule: blockStatement : ', $1, $2, $3); const block = yy.addBlock(undefined, undefined, 'composite'); $$ = { id: block.id, children: $2 }; }
    +  : block document end { yy.getLogger().info('Rule: blockStatement : ', $1, $2, $3); const id = yy.generateId(); $$ = { id, type:'composite', label:id, children: $2 }; }
       ;
     
     
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.spec.ts b/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    index 584a817b55..eea9bb65bb 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    +++ b/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    @@ -21,7 +21,7 @@ describe('Block diagram', function () {
           block.parse(str);
           const blocks = db.getBlocks();
           expect(blocks.length).toBe(1);
    -      expect(blocks[0].ID).toBe('id');
    +      expect(blocks[0].id).toBe('id');
           expect(blocks[0].label).toBe('id');
         });
         it('a node with a square shape and a label', async () => {
    @@ -32,7 +32,7 @@ describe('Block diagram', function () {
           block.parse(str);
           const blocks = db.getBlocks();
           expect(blocks.length).toBe(1);
    -      expect(blocks[0].ID).toBe('id');
    +      expect(blocks[0].id).toBe('id');
           expect(blocks[0].label).toBe('A label');
           expect(blocks[0].type).toBe('square');
         });
    @@ -45,10 +45,10 @@ describe('Block diagram', function () {
           block.parse(str);
           const blocks = db.getBlocks();
           expect(blocks.length).toBe(2);
    -      expect(blocks[0].ID).toBe('id1');
    +      expect(blocks[0].id).toBe('id1');
           expect(blocks[0].label).toBe('id1');
           expect(blocks[0].type).toBe('square');
    -      expect(blocks[1].ID).toBe('id2');
    +      expect(blocks[1].id).toBe('id2');
           expect(blocks[1].label).toBe('id2');
           expect(blocks[1].type).toBe('square');
         });
    @@ -62,13 +62,13 @@ describe('Block diagram', function () {
           block.parse(str);
           const blocks = db.getBlocks();
           expect(blocks.length).toBe(3);
    -      expect(blocks[0].ID).toBe('id1');
    +      expect(blocks[0].id).toBe('id1');
           expect(blocks[0].label).toBe('id1');
           expect(blocks[0].type).toBe('square');
    -      expect(blocks[1].ID).toBe('id2');
    +      expect(blocks[1].id).toBe('id2');
           expect(blocks[1].label).toBe('id2');
           expect(blocks[1].type).toBe('square');
    -      expect(blocks[2].ID).toBe('id3');
    +      expect(blocks[2].id).toBe('id3');
           expect(blocks[2].label).toBe('id3');
           expect(blocks[2].type).toBe('square');
         });
    @@ -81,10 +81,10 @@ describe('Block diagram', function () {
           block.parse(str);
           const blocks = db.getBlocks();
           expect(blocks.length).toBe(2);
    -      expect(blocks[0].ID).toBe('id');
    +      expect(blocks[0].id).toBe('id');
           expect(blocks[0].label).toBe('A label');
           expect(blocks[0].type).toBe('square');
    -      expect(blocks[1].ID).toBe('id2');
    +      expect(blocks[1].id).toBe('id2');
           expect(blocks[1].label).toBe('id2');
           expect(blocks[1].type).toBe('square');
         });
    @@ -152,24 +152,32 @@ describe('Block diagram', function () {
         it('compound blocks 2', async () => {
           const str = `block-beta
               block
    -            aBlock["Block"]
    -            bBlock["Block"]
    +            aBlock["ABlock"]
    +            bBlock["BBlock"]
               end
             `;
     
           block.parse(str);
           const blocks = db.getBlocks();
    -      console.log('blocks', blocks);
           expect(blocks.length).toBe(1);
    +
           expect(blocks[0].children.length).toBe(2);
    -      expect(blocks[0].id).toBe('id');
    -      expect(blocks[0].label).toBe('A label');
    -      expect(blocks[0].type).toBe('square');
    -      // expect(blocks[1].ID).toBe('id2');
    -      // expect(blocks[1].label).toBe('id2');
    -      // expect(blocks[1].type).toBe('square');
    +      expect(blocks[0].id).not.toBe(undefined);
    +      expect(blocks[0].label).toBe(blocks[0].id);
    +      expect(blocks[0].type).toBe('composite');
    +
    +      const aBlock = blocks[0].children[0];
    +
    +      expect(aBlock.id).not.toBe(aBlock);
    +      expect(aBlock.label).toBe('ABlock');
    +      expect(aBlock.type).toBe('square');
    +
    +      const bBlock = blocks[0].children[1];
    +      expect(bBlock.id).not.toBe(bBlock);
    +      expect(bBlock.label).toBe('BBlock');
    +      expect(bBlock.type).toBe('square');
         });
    -    it.only('compound blocks', async () => {
    +    it('compound blocks of compound blocks', async () => {
           const str = `block-beta
               block
                 aBlock["ABlock"]
    @@ -182,29 +190,30 @@ describe('Block diagram', function () {
           block.parse(str);
           const blocks = db.getBlocks();
     
    -      const aBlockPos = blocks[0].children[0];
    -      const bBlockPos = blocks[0].children[1].children[0];
    +      const aBlock = blocks[0].children[0];
    +      const secondComposite = blocks[0].children[1];
    +      const bBlock = blocks[0].children[1].children[0];
     
    -      const root = db.getNodeById(blocks[0].id);
    -      expect(blocks.length).toBe(1);
    -      expect(blocks[0].id).not.toBe(undefined);
    -      expect(root?.label).toBe(blocks[0].id);
           expect(blocks[0].children.length).toBe(2);
    -      expect(root?.type).toBe('composite');
    +      expect(blocks[0].id).not.toBe(undefined);
    +      expect(blocks[0].label).toBe(blocks[0].id);
    +      expect(blocks[0].type).toBe('composite');
     
    -      const aBlock = db.getNodeById(aBlockPos.id);
    -      console.log('aBlock', aBlock);
    -      expect(aBlock?.label).toBe('ABlock');
    -      expect(aBlock?.type).toBe('square');
    +      expect(secondComposite.children.length).toBe(1);
    +      expect(secondComposite.id).not.toBe(undefined);
    +      expect(secondComposite.label).toBe(secondComposite.id);
    +      expect(secondComposite.type).toBe('composite');
     
    -      const bBlock = db.getNodeById(bBlockPos.id);
    +      expect(aBlock.id).not.toBe(aBlock);
    +      expect(aBlock.label).toBe('ABlock');
    +      expect(aBlock.type).toBe('square');
     
    -      expect(bBlock.id).toBe('bBlock');
    +      expect(bBlock.id).not.toBe(bBlock);
           expect(bBlock.label).toBe('BBlock');
           expect(bBlock.type).toBe('square');
         });
    -    it.skip('compound blocks with title', async () => {
    -      const str = `block
    +    it('compound blocks with title', async () => {
    +      const str = `block-beta
               block compoundBlock["Compound block"]
                 columns 1
                 block2["Block 1"]
    
    From e52de6c27982fd8b1cedb8e2c00fb137e0081ed9 Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Fri, 1 Sep 2023 15:40:49 +0200
    Subject: [PATCH 12/97] Some cleanup
    
    ---
     .../mermaid/src/diagrams/block/blockDB.ts     | 58 -------------------
     1 file changed, 58 deletions(-)
    
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index 9717bc348b..b0a7c20c16 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -15,8 +15,6 @@ import {
     } from '../../commonDb.js';
     import { log } from '../../logger.js';
     
    -// export type TBlockColumnsDefaultValue = 'H'; // Do we support something else, like 'auto' | 0?
    -
     // Initialize the node database for simple lookups
     let blockDatabase: Record = {};
     
    @@ -38,14 +36,6 @@ const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
       }
     };
     
    -// Function to get a node by its id
    -type IGetNodeById = (id: string) => Block | undefined;
    -export const getBlockById = (id: string): Block | undefined => {
    -  return blockDatabase[id];
    -};
    -
    -// TODO: Convert to generic TreeNode type? Convert to class?
    -
     let blocks: Block[] = [];
     const links: Link[] = [];
     let rootBlock = { id: 'root', type: 'composite', children: [], columns: -1 } as Block;
    @@ -78,28 +68,6 @@ export const generateId = () => {
       return 'id-' + Math.random().toString(36).substr(2, 12) + '-' + cnt;
     };
     
    -type IAddBlock = (_id: string, label: string, type: BlockType) => Block;
    -// Function to add a node to the database
    -export const addBlock = (_id: string, _label?: string, type?: BlockType) => {
    -  let id = _id;
    -  if (!_id) {
    -    id = generateId();
    -  }
    -  const label = _label || id;
    -  const node: Block = {
    -    id: id,
    -    label,
    -    type: type || 'square',
    -    children: [],
    -  };
    -  blockDatabase[node.id] = node;
    -  // currentBlock.children ??= [];
    -  // currentBlock.children.push(node);
    -  // log.info('currentBlock', currentBlock.children, nodeDatabase);
    -  log.info('addNode called:', id, label, type, node);
    -  return node;
    -};
    -
     type ISetHierarchy = (block: Block[]) => void;
     const setHierarchy = (block: Block[]): void => {
       populateBlockDatabase(block, rootBlock);
    @@ -113,25 +81,6 @@ const addLink: IAddLink = (link: Link): Link => {
       return link;
     };
     
    -type ISetColumns = (columnsStr: string) => void;
    -const setColumns = (columnsStr: string): void => {
    -  const columns = columnsStr === 'auto' ? -1 : parseInt(columnsStr);
    -};
    -
    -const getBlock = (id: string, blocks: Block[]): Block | undefined => {
    -  for (const block of blocks) {
    -    if (block.id === id) {
    -      return block;
    -    }
    -    if (block.children) {
    -      const foundBlock = getBlock(id, block.children);
    -      if (foundBlock) {
    -        return foundBlock;
    -      }
    -    }
    -  }
    -};
    -
     type IGetColumns = (blockid: string) => number;
     const getColumns = (blockid: string): number => {
       const block = blockDatabase[blockid];
    @@ -149,7 +98,6 @@ const getColumns = (blockid: string): number => {
     
     type IGetBlocks = () => Block[];
     const getBlocks: IGetBlocks = () => {
    -  // log.info('Block in test', rootBlock.children || []);
       log.info('Block in test', blocks, blocks[0].id);
       return blocks || [];
     };
    @@ -163,36 +111,30 @@ const getLogger: IGetLogger = () => console;
     export interface BlockDB extends DiagramDB {
       clear: () => void;
       getConfig: () => BlockConfig | undefined;
    -  addBlock: IAddBlock;
       addLink: IAddLink;
       getLogger: IGetLogger;
       getBlocks: IGetBlocks;
       getLinks: IGetLinks;
    -  setColumns: ISetColumns;
       getColumns: IGetColumns;
       typeStr2Type: ITypeStr2Type;
       setHierarchy: ISetHierarchy;
    -  getBlockById: IGetNodeById;
       generateId: IGenerateId;
     }
     
     const db: BlockDB = {
       getConfig: () => configApi.getConfig().block,
    -  addBlock: addBlock,
       addLink: addLink,
       typeStr2Type: typeStr2Type,
       getLogger, // TODO: remove
       getBlocks,
       getLinks,
       setHierarchy,
    -  getBlockById,
       // getAccTitle,
       // setAccTitle,
       // getAccDescription,
       // setAccDescription,
       // getDiagramTitle,
       // setDiagramTitle,
    -  setColumns,
       getColumns,
       clear,
       generateId,
    
    From 5f1cfc7519031f92ccdbca3dde85736a979a08bc Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Fri, 1 Sep 2023 16:22:23 +0200
    Subject: [PATCH 13/97] Support for compound blocks with id, title and type
    
    ---
     .../mermaid/src/diagrams/block/blockDB.ts     |  7 ++++++-
     .../mermaid/src/diagrams/block/blockTypes.ts  |  4 ++--
     .../src/diagrams/block/parser/block.jison     |  6 ++++--
     .../src/diagrams/block/parser/block.spec.ts   | 19 +++++++++++++++++--
     4 files changed, 29 insertions(+), 7 deletions(-)
    
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index b0a7c20c16..7c90ad2dbc 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -19,6 +19,7 @@ import { log } from '../../logger.js';
     let blockDatabase: Record = {};
     
     const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
    +  const children = [];
       for (const block of blockList) {
         if (block.type === 'column-setting') {
           const columns = block.columns || -1;
    @@ -32,8 +33,12 @@ const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
           if (block.children) {
             populateBlockDatabase(block.children, block);
           }
    +      if (block.type !== 'column-setting') {
    +        children.push(block);
    +      }
         }
       }
    +  parent.children = children;
     };
     
     let blocks: Block[] = [];
    @@ -71,7 +76,7 @@ export const generateId = () => {
     type ISetHierarchy = (block: Block[]) => void;
     const setHierarchy = (block: Block[]): void => {
       populateBlockDatabase(block, rootBlock);
    -  log.info('blockdb', JSON.stringify(blockDatabase, null, 2));
    +  log.debug('The hierarchy', JSON.stringify(block, null, 2));
       blocks = block;
     };
     
    diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts
    index a695b4ec78..aca83f4212 100644
    --- a/packages/mermaid/src/diagrams/block/blockTypes.ts
    +++ b/packages/mermaid/src/diagrams/block/blockTypes.ts
    @@ -5,6 +5,7 @@ export interface BlockConfig extends BaseDiagramConfig {
     }
     
     export type BlockType =
    +  | 'column-setting'
       | 'round'
       | 'square'
       | 'diamond'
    @@ -22,8 +23,7 @@ export type BlockType =
       | 'cylinder'
       | 'group'
       | 'doublecircle'
    -  | 'composite'
    -  | 'column-setting';
    +  | 'composite';
     
     export interface Block {
       id: string;
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index 829ccd300c..9cc220ff40 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -29,6 +29,7 @@ CRLF \u000D\u000A
     "block-beta"                                             { return 'BLOCK_DIAGRAM_KEY'; }
     "block"\s+            { yy.getLogger().info('Found space-block'); return 'block';}
     "block"\n+            { yy.getLogger().info('Found nl-block'); return 'block';}
    +"block:"            { yy.getLogger().info('Found space-block'); return 'id-block';}
     // \s*\%\%.*                                                       { yy.getLogger().info('Found comment',yytext); }
     [\s]+                                                           { yy.getLogger().info('.', yytext); /* skip all whitespace */  }
     [\n]+ {yy.getLogger().info('_', yytext);                 /* skip all whitespace */   }
    @@ -138,7 +139,7 @@ seperator
       ;
     
     start: BLOCK_DIAGRAM_KEY document EOF
    -  {yy.getLogger().info('This is the hierarchy ', JSON.stringify($2, null, 2)); yy.setHierarchy($2); }
    +  { yy.setHierarchy($2); }
       ;
     
     
    @@ -189,7 +190,8 @@ columnsStatement
       ;
     
     blockStatement
    -  : block document end { yy.getLogger().info('Rule: blockStatement : ', $1, $2, $3); const id = yy.generateId(); $$ = { id, type:'composite', label:id, children: $2 }; }
    +  : id-block nodeStatement document end { yy.getLogger().info('Rule: id-block statement : ', $2, $3); const id2 = yy.generateId(); $$ = { ...$2, children: $3 }; }
    +  | block document end { yy.getLogger().info('Rule: blockStatement : ', $1, $2, $3); const id = yy.generateId(); $$ = { id, type:'composite', label:id, children: $2 }; }
       ;
     
     
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.spec.ts b/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    index eea9bb65bb..adb814be22 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    +++ b/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    @@ -214,13 +214,28 @@ describe('Block diagram', function () {
         });
         it('compound blocks with title', async () => {
           const str = `block-beta
    -          block compoundBlock["Compound block"]
    +          block:compoundBlock["Compound block"]
                 columns 1
    -            block2["Block 1"]
    +            block2["Block 2"]
               end
             `;
     
           block.parse(str);
    +
    +      const blocks = db.getBlocks();
    +      expect(blocks.length).toBe(1);
    +
    +      const compoundBlock = blocks[0];
    +      const block2 = compoundBlock.children[0];
    +
    +      expect(compoundBlock.children.length).toBe(1);
    +      expect(compoundBlock.id).toBe('compoundBlock');
    +      expect(compoundBlock.label).toBe('Compound block');
    +      expect(compoundBlock.type).toBe('square');
    +
    +      expect(block2.id).toBe('block2');
    +      expect(block2.label).toBe('Block 2');
    +      expect(block2.type).toBe('square');
         });
         it.skip('blocks mixed with compound blocks', async () => {
           const str = `block
    
    From 1e864a508d7f030b79e9bf58667354057694b1fc Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Tue, 5 Sep 2023 11:13:27 +0200
    Subject: [PATCH 14/97] Rendering, tmp commit before refactoring
    
    ---
     cypress/platform/knsv2.html                   |  24 +-
     packages/mermaid/src/dagre-wrapper/nodes.js   |  16 +-
     .../mermaid/src/diagrams/block/blockDB.ts     |  14 +
     .../src/diagrams/block/blockDiagram.ts        |   2 +
     .../src/diagrams/block/blockRenderer.ts       | 126 +++---
     .../mermaid/src/diagrams/block/blockTypes.ts  |   7 +
     packages/mermaid/src/diagrams/block/layout.ts | 108 +++++
     .../src/diagrams/block/renderHelpers.ts       | 270 ++++++++++++
     packages/mermaid/src/diagrams/block/styles.ts | 144 +++++++
     .../flowchart/swimlane/swimlaneRenderer.js    | 400 ++++++++++++++++++
     10 files changed, 1033 insertions(+), 78 deletions(-)
     create mode 100644 packages/mermaid/src/diagrams/block/layout.ts
     create mode 100644 packages/mermaid/src/diagrams/block/renderHelpers.ts
     create mode 100644 packages/mermaid/src/diagrams/block/styles.ts
     create mode 100644 packages/mermaid/src/diagrams/flowchart/swimlane/swimlaneRenderer.js
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index e19d53ae47..4609331dd5 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -24,6 +24,9 @@
           h1 {
             color: grey;
           }
    +      .mermaid {
    +        border: 1px solid #ddd;
    +      }
           .mermaid2 {
             display: none;
           }
    @@ -59,16 +62,17 @@
       
         
     block-beta
    -          id
    + id1("Wide 1") + id2("2") + id3("3") + id4("A final one") + +
     flowchart RL
    -    subgraph "`one`"
    -      a1 -- l1 --> a2
    -      a1 -- l2 --> a2
    -    end
    +    id
         
    -
    +    
     flowchart RL
         subgraph "`one`"
           a1 -- l1 --> a2
    @@ -93,11 +97,11 @@
             way`"]
       
    -
    +    
           classDiagram-v2
             note "I love this diagram!\nDo you love it?"
         
    -
    +    
         stateDiagram-v2
         State1: The state with a note with minus - and plus + in it
         note left of State1
    @@ -142,7 +146,7 @@
           शान्तिः سلام  和平 `"]
     
         
    -
    +    
     %%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
     flowchart TB
       %% I could not figure out how to use double quotes in labels in Mermaid
    diff --git a/packages/mermaid/src/dagre-wrapper/nodes.js b/packages/mermaid/src/dagre-wrapper/nodes.js
    index 6c67333585..e6a9d982a2 100644
    --- a/packages/mermaid/src/dagre-wrapper/nodes.js
    +++ b/packages/mermaid/src/dagre-wrapper/nodes.js
    @@ -1037,14 +1037,14 @@ export const positionNode = (node) => {
       const padding = 8;
       const diff = node.diff || 0;
       if (node.clusterNode) {
    -    el.attr(
    -      'transform',
    -      'translate(' +
    -        (node.x + diff - node.width / 2) +
    -        ', ' +
    -        (node.y - node.height / 2 - padding) +
    -        ')'
    -    );
    +      el.attr(
    +        'transform',
    +        'translate(' +
    +          (node.x + diff - node.width / 2) +
    +          ', ' +
    +          (node.y - node.height / 2 - padding) +
    +          ')'
    +      );
       } else {
         el.attr('transform', 'translate(' + node.x + ', ' + node.y + ')');
       }
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index 7c90ad2dbc..039353830e 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -106,6 +106,16 @@ const getBlocks: IGetBlocks = () => {
       log.info('Block in test', blocks, blocks[0].id);
       return blocks || [];
     };
    +type IGetBlock = (id: string) => Block | undefined;
    +const getBlock: IGetBlock = (id: string) => {
    +  log.info('Block in test', blocks, blocks[0].id);
    +  return blockDatabase[id];
    +};
    +type ISetBlock = (block: Block) => void;
    +const setBlock: ISetBlock = (block: Block) => {
    +  log.info('Block in test', blocks, blocks[0].id);
    +  blockDatabase[block.id] = block;
    +};
     
     type IGetLinks = () => Link[];
     const getLinks: IGetLinks = () => links;
    @@ -119,6 +129,8 @@ export interface BlockDB extends DiagramDB {
       addLink: IAddLink;
       getLogger: IGetLogger;
       getBlocks: IGetBlocks;
    +  getBlock: IGetBlock;
    +  setBlock: ISetBlock;
       getLinks: IGetLinks;
       getColumns: IGetColumns;
       typeStr2Type: ITypeStr2Type;
    @@ -134,6 +146,8 @@ const db: BlockDB = {
       getBlocks,
       getLinks,
       setHierarchy,
    +  getBlock,
    +  setBlock,
       // getAccTitle,
       // setAccTitle,
       // getAccDescription,
    diff --git a/packages/mermaid/src/diagrams/block/blockDiagram.ts b/packages/mermaid/src/diagrams/block/blockDiagram.ts
    index e098360f43..b3071cb0b3 100644
    --- a/packages/mermaid/src/diagrams/block/blockDiagram.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDiagram.ts
    @@ -2,6 +2,7 @@ import { DiagramDefinition } from '../../diagram-api/types.js';
     // @ts-ignore: jison doesn't export types
     import parser from './parser/block.jison';
     import db from './blockDB.js';
    +import flowStyles from './styles.js';
     import renderer from './blockRenderer.js';
     
     // TODO: do we need this?
    @@ -14,4 +15,5 @@ export const diagram: DiagramDefinition = {
       parser,
       db,
       renderer,
    +  styles: flowStyles,
     };
    diff --git a/packages/mermaid/src/diagrams/block/blockRenderer.ts b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    index 84acdaf3f9..0dac714d42 100644
    --- a/packages/mermaid/src/diagrams/block/blockRenderer.ts
    +++ b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    @@ -1,20 +1,30 @@
     import { Diagram } from '../../Diagram.js';
     import * as configApi from '../../config.js';
    -
    +import { calculateBlockSizes } from './renderHelpers.js';
    +import { layout } from './layout.js';
    +import { setupGraphViewbox } from '../../setupGraphViewbox.js';
     import {
       select as d3select,
       scaleOrdinal as d3scaleOrdinal,
       schemeTableau10 as d3schemeTableau10,
    +  ContainerElement,
     } from 'd3';
     
    -import { BlockDB, Block } from './blockDB.js';
    +import { BlockDB } from './blockDB.js';
    +import type { Block } from './blockTypes.js';
     
     // import { diagram as BlockDiagram } from './blockDiagram.js';
     import { configureSvgSize } from '../../setupGraphViewbox.js';
     import { Uid } from '../../rendering-util/uid.js';
     
    -export const draw = function (text: string, id: string, _version: string, diagObj: Diagram): void {
    -  const { securityLevel } = configApi.getConfig();
    +export const draw = async function (
    +  text: string,
    +  id: string,
    +  _version: string,
    +  diagObj: Diagram
    +): Promise {
    +  const { securityLevel, flowchart: conf } = configApi.getConfig();
    +  const db = diagObj.db as BlockDB;
       let sandboxElement: any;
       if (securityLevel === 'sandbox') {
         sandboxElement = d3select('#i' + id);
    @@ -27,12 +37,23 @@ export const draw = function (text: string, id: string, _version: string, diagOb
       // @ts-ignore TODO root.select is not callable
       const svg = securityLevel === 'sandbox' ? root.select(`[id="${id}"]`) : d3select(`[id="${id}"]`);
     
    +  const bl = db.getBlocks();
    +
    +  const nodes = svg.insert('g').attr('class', 'block');
    +  await calculateBlockSizes(nodes, bl, db);
    +  const bounds = layout(db);
    +
    +  console.log('Here', bl);
    +
       // Establish svg dimensions and get width and height
    -  //  
    -  const height = 400;
    -  const width = 600;
    +  //
    +  // const bounds = nodes.node().getBoundingClientRect();
    +  const height = bounds.height;
    +  const width = bounds.width;
       const useMaxWidth = false;
       configureSvgSize(svg, height, width, useMaxWidth);
    +  console.log('Here Bounds', bounds);
    +  svg.attr('viewBox', `${bounds.x} ${bounds.y} ${bounds.width} ${bounds.height}`);
     
       // Prepare data for construction based on diagObj.db
       // This must be a mutable object with `nodes` and `links` properties:
    @@ -53,107 +74,92 @@ export const draw = function (text: string, id: string, _version: string, diagOb
     
       const blocks: LayedBlock[] = [
         {
    -      ID: "ApplicationLayer",
    -      label: "Application Layer",
    +      ID: 'ApplicationLayer',
    +      label: 'Application Layer',
           x: 0,
           y: 0,
           children: [
             {
    -          ID: "UserInterface",
    -          label: "User Interface (WPF, HTML5/CSS3, Swing)",
    +          ID: 'UserInterface',
    +          label: 'User Interface (WPF, HTML5/CSS3, Swing)',
               x: 0,
    -          y: 50,    
    -        }
    +          y: 50,
    +        },
           ],
         },
         {
    -      ID: "PresentationLayer",
    -      label: "Presentation Layer",
    +      ID: 'PresentationLayer',
    +      label: 'Presentation Layer',
           x: 0,
           y: 50,
           children: [
             {
    -          ID: "Smack",
    -          label: "J2SE Mobil App (Smack)"
    +          ID: 'Smack',
    +          label: 'J2SE Mobil App (Smack)',
             },
             {
    -          ID: "JsJAC",
    -          label: "Java Script Browser App (JsJAC)",
    +          ID: 'JsJAC',
    +          label: 'Java Script Browser App (JsJAC)',
             },
             {
    -          ID: "babelim",
    -          label: ".NET Windows App (Babel-im)",
    +          ID: 'babelim',
    +          label: '.NET Windows App (Babel-im)',
             },
    -      ]
    +      ],
         },
         {
    -      ID: "SessionLayer",
    -      label: "Session Layer",
    +      ID: 'SessionLayer',
    +      label: 'Session Layer',
           x: 0,
           y: 100,
           children: [
             {
    -          ID: "XMPP",
    -          label: "XMPP Component"
    +          ID: 'XMPP',
    +          label: 'XMPP Component',
             },
             {
               children: [
                 {
    -              ID: "Authentication",
    -              label: "Authentication",
    +              ID: 'Authentication',
    +              label: 'Authentication',
                 },
                 {
    -              ID: "Authorization",
    -              label: "Authorization",
    +              ID: 'Authorization',
    +              label: 'Authorization',
                 },
    -          ]
    +          ],
             },
             {
    -          ID: "LDAP",
    -          label: "LDAP, DB, POP",
    +          ID: 'LDAP',
    +          label: 'LDAP, DB, POP',
             },
    -      ]
    +      ],
         },
         {
    -      ID: "NetworkLayer",
    -      label: "Network Layer",
    +      ID: 'NetworkLayer',
    +      label: 'Network Layer',
           x: 0,
           y: 150,
           children: [
    -        { ID: "HTTP", label: "HTTP" },
    -        { ID: "SOCK", label: "SOCK" },
    -      ]
    +        { ID: 'HTTP', label: 'HTTP' },
    +        { ID: 'SOCK', label: 'SOCK' },
    +      ],
         },
         {
    -      ID: "DataLayer",
    -      label: "Data Layer",
    +      ID: 'DataLayer',
    +      label: 'Data Layer',
           x: 0,
           y: 200,
           children: [
    -        { ID: "XMPP", label: "XMPP" },
    -        { ID: "BDB", label: "Business DB" },
    -        { ID: "AD", label: "Active Directory" },
    -      ]
    +        { ID: 'XMPP', label: 'XMPP' },
    +        { ID: 'BDB', label: 'Business DB' },
    +        { ID: 'AD', label: 'Active Directory' },
    +      ],
         },
       ];
     
       // Get color scheme for the graph
       const colorScheme = d3scaleOrdinal(d3schemeTableau10);
    -
    -  svg
    -    .append('g')
    -    .attr('class', 'block')
    -    .selectAll('.block')
    -    .data(blocks)
    -    .join('rect')
    -    .attr('x', (d: any) => d.x || 0)
    -    .attr('y', (d: any) => d.y || 0)
    -    .attr('class', 'block')
    -    .attr('stroke', 'black')
    -    .attr('height', (d: any) => 50)
    -    .attr('width', (d: any) => 100)
    -    .attr('fill', (d: any) => colorScheme(d.ID));
    -
     };
     
     export default {
    diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts
    index aca83f4212..5a4431c0ae 100644
    --- a/packages/mermaid/src/diagrams/block/blockTypes.ts
    +++ b/packages/mermaid/src/diagrams/block/blockTypes.ts
    @@ -31,6 +31,13 @@ export interface Block {
       parent?: Block;
       type?: BlockType;
       children: Block[];
    +  size?: {
    +    width: number;
    +    height: number;
    +    x: number;
    +    y: number;
    +  };
    +  node?: any;
       columns?: number; // | TBlockColumnsDefaultValue;
     }
     
    diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts
    new file mode 100644
    index 0000000000..65b99c1543
    --- /dev/null
    +++ b/packages/mermaid/src/diagrams/block/layout.ts
    @@ -0,0 +1,108 @@
    +import { BlockDB } from './blockDB.js';
    +import type { Block } from './blockTypes.js';
    +
    +function layoutBLock(block: Block, db: BlockDB) {
    +  if (block.children) {
    +    for (const child of block.children) {
    +      layoutBLock(child, db);
    +    }
    +    // find max width of children
    +    let maxWidth = 0;
    +    let maxHeight = 0;
    +    for (const child of block.children) {
    +      const { width, height, x, y } = child.size || { width: 0, height: 0, x: 0, y: 0 };
    +      if (width > maxWidth) {
    +        maxWidth = width;
    +      }
    +      if (height > maxHeight) {
    +        maxHeight = height;
    +      }
    +    }
    +
    +    // set width of block to max width of children
    +    for (const child of block.children) {
    +      if (child.size) {
    +        child.size.width = maxWidth;
    +        child.size.height = maxHeight;
    +      }
    +    }
    +
    +    // Position items
    +    let x = 0;
    +    let y = 0;
    +    const padding = 10;
    +    for (const child of block.children) {
    +      if (child.size) {
    +        child.size.x = x;
    +        child.size.y = y;
    +        x += maxWidth + padding;
    +      }
    +    }
    +  }
    +}
    +
    +function positionBlock(block: Block, db: BlockDB) {
    +  console.log('Here Positioning', block?.size?.node);
    +  // const o = db.getBlock(block.id);
    +  // const node;
    +  if (block?.size?.node) {
    +    const node = block?.size?.node;
    +    const size = block?.size;
    +    console.log('Here as well', node);
    +    if (node) {
    +      node.attr(
    +        'transform',
    +        'translate(' + (size.x - size.width / 2) + ', ' + (size.y - size.height / 2) + ')'
    +      );
    +    }
    +  }
    +  if (block.children) {
    +    for (const child of block.children) {
    +      positionBlock(child, db);
    +    }
    +  }
    +}
    +let minX = 0;
    +let minY = 0;
    +let maxX = 0;
    +let maxY = 0;
    +
    +function findBounds(block: Block) {
    +  if (block.size) {
    +    const { x, y, width, height } = block.size;
    +    console.log('Here', minX, minY, x, y, width, height);
    +    if (x - width < minX) {
    +      minX = x - width;
    +    }
    +    if (y - height < minY) {
    +      minY = y - height;
    +    }
    +    if (x > maxX) {
    +      maxX = x;
    +    }
    +    if (y > maxY) {
    +      maxY = y;
    +    }
    +  }
    +  if (block.children) {
    +    for (const child of block.children) {
    +      findBounds(child);
    +    }
    +  }
    +}
    +
    +export function layout(db: BlockDB) {
    +  const blocks = db.getBlocks();
    +  const root = { id: 'root', type: 'composite', children: blocks } as Block;
    +  layoutBLock(root, db);
    +  positionBlock(root, db);
    +
    +  minX = 0;
    +  minY = 0;
    +  maxX = 0;
    +  maxY = 0;
    +  findBounds(root);
    +  const height = maxY - minY;
    +  const width = maxX - minX;
    +  return { x: minX, y: minY, width, height };
    +}
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    new file mode 100644
    index 0000000000..34d8baa054
    --- /dev/null
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -0,0 +1,270 @@
    +import { getStylesFromArray } from '../../utils.js';
    +import { insertNode } from '../../dagre-wrapper/nodes.js';
    +import { getConfig } from '../../config.js';
    +import { ContainerElement } from 'd3';
    +import type { Block } from './blockTypes.js';
    +import { BlockDB } from './blockDB.js';
    +
    +function getNodeFromBlock(block: Block, db: BlockDB) {
    +  const vertex = block;
    +
    +  /**
    +   * Variable for storing the classes for the vertex
    +   *
    +   * @type {string}
    +   */
    +  let classStr = 'default';
    +  if ((vertex?.classes?.length || []) > 0) {
    +    classStr = vertex.classes.join(' ');
    +  }
    +  classStr = classStr + ' flowchart-label';
    +
    +  // We create a SVG label, either by delegating to addHtmlLabel or manually
    +  let vertexNode;
    +  const labelData = { width: 0, height: 0 };
    +
    +  let radious = 0;
    +  let _shape = '';
    +  let layoutOptions = {};
    +  // Set the shape based parameters
    +  switch (vertex.type) {
    +    case 'round':
    +      radious = 5;
    +      _shape = 'rect';
    +      break;
    +    case 'square':
    +      _shape = 'rect';
    +      break;
    +    case 'diamond':
    +      _shape = 'question';
    +      layoutOptions = {
    +        portConstraints: 'FIXED_SIDE',
    +      };
    +      break;
    +    case 'hexagon':
    +      _shape = 'hexagon';
    +      break;
    +    case 'odd':
    +      _shape = 'rect_left_inv_arrow';
    +      break;
    +    case 'lean_right':
    +      _shape = 'lean_right';
    +      break;
    +    case 'lean_left':
    +      _shape = 'lean_left';
    +      break;
    +    case 'trapezoid':
    +      _shape = 'trapezoid';
    +      break;
    +    case 'inv_trapezoid':
    +      _shape = 'inv_trapezoid';
    +      break;
    +    case 'odd_right':
    +      _shape = 'rect_left_inv_arrow';
    +      break;
    +    case 'circle':
    +      _shape = 'circle';
    +      break;
    +    case 'ellipse':
    +      _shape = 'ellipse';
    +      break;
    +    case 'stadium':
    +      _shape = 'stadium';
    +      break;
    +    case 'subroutine':
    +      _shape = 'subroutine';
    +      break;
    +    case 'cylinder':
    +      _shape = 'cylinder';
    +      break;
    +    case 'group':
    +      _shape = 'rect';
    +      break;
    +    case 'doublecircle':
    +      _shape = 'doublecircle';
    +      break;
    +    default:
    +      _shape = 'rect';
    +  }
    +
    +  // const styles = getStylesFromArray(vertex.styles);
    +  const styles = getStylesFromArray([]);
    +
    +  // Use vertex id as text in the box if no text is provided by the graph definition
    +  const vertexText = vertex.label;
    +
    +  // Add the node
    +  const node = {
    +    labelStyle: styles.labelStyle,
    +    shape: _shape,
    +    labelText: vertexText,
    +    // labelType: vertex.labelType,
    +    rx: radious,
    +    ry: radious,
    +    class: classStr,
    +    style: styles.style,
    +    id: vertex.id,
    +    // link: vertex.link,
    +    // linkTarget: vertex.linkTarget,
    +    // tooltip: diagObj.db.getTooltip(vertex.id) || '',
    +    // domId: diagObj.db.lookUpDomId(vertex.id),
    +    // haveCallback: vertex.haveCallback,
    +    // width: vertex.type === 'group' ? 500 : undefined,
    +    // dir: vertex.dir,
    +    type: vertex.type,
    +    // props: vertex.props,
    +    padding: getConfig()?.flowchart?.padding || 0,
    +  };
    +  return node;
    +}
    +
    +async function calculateBlockSize(elem: any, block: any, db: any) {
    +  console.log('Here befoire 3');
    +  const node = getNodeFromBlock(block, db);
    +  if (node.type === 'group') return;
    +
    +  // Add the element to the DOM to size it
    +  const nodeEl = await insertNode(elem, node);
    +  const boundingBox = nodeEl.node().getBBox();
    +  const obj = db.getBlock(node.id);
    +  console.log('Here el', nodeEl);
    +  obj.size = { width: boundingBox.width, height: boundingBox.height, x: 0, y: 0, node: nodeEl };
    +  db.setBlock(obj);
    +  // nodeEl.remove();
    +}
    +
    +export async function calculateBlockSizes(elem: ContainerElement, blocks: Block[], db: BlockDB) {
    +  console.log('Here before 2');
    +  for (const block of blocks) {
    +    await calculateBlockSize(elem, block, db);
    +    if (block.children) {
    +      await calculateBlockSizes(elem, block.children, db);
    +    }
    +  }
    +}
    +export async function insertBlockPositioned(elem: any, block: any, db: any) {
    +  const vertex = block;
    +
    +  /**
    +   * Variable for storing the classes for the vertex
    +   *
    +   * @type {string}
    +   */
    +  let classStr = 'default';
    +  if ((vertex?.classes?.length || []) > 0) {
    +    classStr = vertex.classes.join(' ');
    +  }
    +  classStr = classStr + ' flowchart-label';
    +
    +  // We create a SVG label, either by delegating to addHtmlLabel or manually
    +  let vertexNode;
    +  const labelData = { width: 0, height: 0 };
    +
    +  let radious = 0;
    +  let _shape = '';
    +  let layoutOptions = {};
    +  // Set the shape based parameters
    +  switch (vertex.type) {
    +    case 'round':
    +      radious = 5;
    +      _shape = 'rect';
    +      break;
    +    case 'square':
    +      _shape = 'rect';
    +      break;
    +    case 'diamond':
    +      _shape = 'question';
    +      layoutOptions = {
    +        portConstraints: 'FIXED_SIDE',
    +      };
    +      break;
    +    case 'hexagon':
    +      _shape = 'hexagon';
    +      break;
    +    case 'odd':
    +      _shape = 'rect_left_inv_arrow';
    +      break;
    +    case 'lean_right':
    +      _shape = 'lean_right';
    +      break;
    +    case 'lean_left':
    +      _shape = 'lean_left';
    +      break;
    +    case 'trapezoid':
    +      _shape = 'trapezoid';
    +      break;
    +    case 'inv_trapezoid':
    +      _shape = 'inv_trapezoid';
    +      break;
    +    case 'odd_right':
    +      _shape = 'rect_left_inv_arrow';
    +      break;
    +    case 'circle':
    +      _shape = 'circle';
    +      break;
    +    case 'ellipse':
    +      _shape = 'ellipse';
    +      break;
    +    case 'stadium':
    +      _shape = 'stadium';
    +      break;
    +    case 'subroutine':
    +      _shape = 'subroutine';
    +      break;
    +    case 'cylinder':
    +      _shape = 'cylinder';
    +      break;
    +    case 'group':
    +      _shape = 'rect';
    +      break;
    +    case 'doublecircle':
    +      _shape = 'doublecircle';
    +      break;
    +    default:
    +      _shape = 'rect';
    +  }
    +
    +  // const styles = getStylesFromArray(vertex.styles);
    +  const styles = getStylesFromArray([]);
    +
    +  // Use vertex id as text in the box if no text is provided by the graph definition
    +  const vertexText = vertex.label;
    +
    +  // Add the node
    +  const node = {
    +    labelStyle: styles.labelStyle,
    +    shape: _shape,
    +    labelText: vertexText,
    +    labelType: vertex.labelType,
    +    rx: radious,
    +    ry: radious,
    +    class: classStr,
    +    style: styles.style,
    +    id: vertex.id,
    +    link: vertex.link,
    +    linkTarget: vertex.linkTarget,
    +    // tooltip: diagObj.db.getTooltip(vertex.id) || '',
    +    // domId: diagObj.db.lookUpDomId(vertex.id),
    +    haveCallback: vertex.haveCallback,
    +    width: vertex.width,
    +    height: vertex.height,
    +    dir: vertex.dir,
    +    type: vertex.type,
    +    props: vertex.props,
    +    padding: getConfig()?.flowchart?.padding || 0,
    +  };
    +  let boundingBox;
    +  let nodeEl;
    +
    +  // Add the element to the DOM
    +  if (node.type !== 'group') {
    +    nodeEl = await insertNode(elem, node, vertex.dir);
    +    // nodeEl.remove();
    +    boundingBox = nodeEl.node().getBBox();
    +    if (node.id) {
    +      const obj = db.getBlock(node.id);
    +      obj.size = { width: boundingBox.width, height: boundingBox.height, x: 0, y: 0, node: nodeEl };
    +      db.setBlock(obj);
    +    }
    +  }
    +}
    diff --git a/packages/mermaid/src/diagrams/block/styles.ts b/packages/mermaid/src/diagrams/block/styles.ts
    new file mode 100644
    index 0000000000..a4af4f1283
    --- /dev/null
    +++ b/packages/mermaid/src/diagrams/block/styles.ts
    @@ -0,0 +1,144 @@
    +// import khroma from 'khroma';
    +import * as khroma from 'khroma';
    +
    +/** Returns the styles given options */
    +export interface FlowChartStyleOptions {
    +  arrowheadColor: string;
    +  border2: string;
    +  clusterBkg: string;
    +  clusterBorder: string;
    +  edgeLabelBackground: string;
    +  fontFamily: string;
    +  lineColor: string;
    +  mainBkg: string;
    +  nodeBorder: string;
    +  nodeTextColor: string;
    +  tertiaryColor: string;
    +  textColor: string;
    +  titleColor: string;
    +}
    +
    +const fade = (color: string, opacity: number) => {
    +  // @ts-ignore TODO: incorrect types from khroma
    +  const channel = khroma.channel;
    +
    +  const r = channel(color, 'r');
    +  const g = channel(color, 'g');
    +  const b = channel(color, 'b');
    +
    +  // @ts-ignore incorrect types from khroma
    +  return khroma.rgba(r, g, b, opacity);
    +};
    +
    +const getStyles = (options: FlowChartStyleOptions) =>
    +  `.label {
    +    font-family: ${options.fontFamily};
    +    color: ${options.nodeTextColor || options.textColor};
    +  }
    +  .cluster-label text {
    +    fill: ${options.titleColor};
    +  }
    +  .cluster-label span,p {
    +    color: ${options.titleColor};
    +  }
    +
    +  .label text,span,p {
    +    fill: ${options.nodeTextColor || options.textColor};
    +    color: ${options.nodeTextColor || options.textColor};
    +  }
    +
    +  .node rect,
    +  .node circle,
    +  .node ellipse,
    +  .node polygon,
    +  .node path {
    +    fill: ${options.mainBkg};
    +    stroke: ${options.nodeBorder};
    +    stroke-width: 1px;
    +  }
    +  .flowchart-label text {
    +    text-anchor: middle;
    +  }
    +  // .flowchart-label .text-outer-tspan {
    +  //   text-anchor: middle;
    +  // }
    +  // .flowchart-label .text-inner-tspan {
    +  //   text-anchor: start;
    +  // }
    +
    +  .node .label {
    +    text-align: center;
    +  }
    +  .node.clickable {
    +    cursor: pointer;
    +  }
    +
    +  .arrowheadPath {
    +    fill: ${options.arrowheadColor};
    +  }
    +
    +  .edgePath .path {
    +    stroke: ${options.lineColor};
    +    stroke-width: 2.0px;
    +  }
    +
    +  .flowchart-link {
    +    stroke: ${options.lineColor};
    +    fill: none;
    +  }
    +
    +  .edgeLabel {
    +    background-color: ${options.edgeLabelBackground};
    +    rect {
    +      opacity: 0.5;
    +      background-color: ${options.edgeLabelBackground};
    +      fill: ${options.edgeLabelBackground};
    +    }
    +    text-align: center;
    +  }
    +
    +  /* For html labels only */
    +  .labelBkg {
    +    background-color: ${fade(options.edgeLabelBackground, 0.5)};
    +    // background-color:
    +  }
    +
    +  .cluster rect {
    +    fill: ${options.clusterBkg};
    +    stroke: ${options.clusterBorder};
    +    stroke-width: 1px;
    +  }
    +
    +  .cluster text {
    +    fill: ${options.titleColor};
    +  }
    +
    +  .cluster span,p {
    +    color: ${options.titleColor};
    +  }
    +  /* .cluster div {
    +    color: ${options.titleColor};
    +  } */
    +
    +  div.mermaidTooltip {
    +    position: absolute;
    +    text-align: center;
    +    max-width: 200px;
    +    padding: 2px;
    +    font-family: ${options.fontFamily};
    +    font-size: 12px;
    +    background: ${options.tertiaryColor};
    +    border: 1px solid ${options.border2};
    +    border-radius: 2px;
    +    pointer-events: none;
    +    z-index: 100;
    +  }
    +
    +  .flowchartTitleText {
    +    text-anchor: middle;
    +    font-size: 18px;
    +    fill: ${options.textColor};
    +  }
    +`;
    +
    +export default getStyles;
    diff --git a/packages/mermaid/src/diagrams/flowchart/swimlane/swimlaneRenderer.js b/packages/mermaid/src/diagrams/flowchart/swimlane/swimlaneRenderer.js
    new file mode 100644
    index 0000000000..5b7d5976f1
    --- /dev/null
    +++ b/packages/mermaid/src/diagrams/flowchart/swimlane/swimlaneRenderer.js
    @@ -0,0 +1,400 @@
    +import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
    +import { select, curveLinear, selectAll } from 'd3';
    +import { swimlaneLayout } from './swimlane-layout.js';
    +import { insertNode } from '../../../dagre-wrapper/nodes.js';
    +import flowDb from '../flowDb.js';
    +import { getConfig } from '../../../config.js';
    +import { getStylesFromArray } from '../../../utils.js';
    +import setupGraph, { addEdges, addVertices } from './setup-graph.js';
    +import { render } from '../../../dagre-wrapper/index.js';
    +import { log } from '../../../logger.js';
    +import { setupGraphViewbox } from '../../../setupGraphViewbox.js';
    +import common, { evaluate } from '../../common/common.js';
    +import { addHtmlLabel } from 'dagre-d3-es/src/dagre-js/label/add-html-label.js';
    +import { insertEdge, positionEdgeLabel } from '../../../dagre-wrapper/edges.js';
    +import {
    +  clear as clearGraphlib,
    +  clusterDb,
    +  adjustClustersAndEdges,
    +  findNonClusterChild,
    +  sortNodesByHierarchy,
    +} from '../../../dagre-wrapper/mermaid-graphlib.js';
    +
    +const conf = {};
    +export const setConf = function (cnf) {
    +  const keys = Object.keys(cnf);
    +  for (const key of keys) {
    +    conf[key] = cnf[key];
    +  }
    +};
    +
    +/**
    + *
    + * @param element
    + * @param graph
    + * @param layout
    + * @param elem
    + * @param conf
    + */
    +async function swimlaneRender(layout, vert, elem, g, id, conf) {
    +  let max;
    +  // draw nodes from layout.graph to element
    +  const nodes = layout.graph.nodes();
    +
    +  // lanes are the swimlanes
    +  const lanes = layout.lanes;
    +
    +  const nodesElements = elem.insert('g').attr('class', 'nodes');
    +  // for each node, draw a rect, with a child text inside as label
    +  for (const node of nodes) {
    +    const nodeFromLayout = layout.graph.node(node);
    +    const vertex = vert[node];
    +    //Initialise the node
    +    /**
    +     * Variable for storing the classes for the vertex
    +     *
    +     * @type {string}
    +     */
    +    let classStr = 'default';
    +    if (vertex.classes.length > 0) {
    +      classStr = vertex.classes.join(' ');
    +    }
    +    classStr = classStr + ' swimlane-label';
    +    const styles = getStylesFromArray(vertex.styles);
    +
    +    // Use vertex id as text in the box if no text is provided by the graph definition
    +    let vertexText = vertex.text !== undefined ? vertex.text : vertex.id;
    +
    +    // We create a SVG label, either by delegating to addHtmlLabel or manually
    +    let vertexNode;
    +    log.info('vertex', vertex, vertex.labelType);
    +    if (vertex.labelType === 'markdown') {
    +      log.info('vertex', vertex, vertex.labelType);
    +    } else {
    +      if (evaluate(getConfig().flowchart.htmlLabels)) {
    +        // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
    +        const node = {
    +          label: vertexText.replace(
    +            /fa[blrs]?:fa-[\w-]+/g,
    +            (s) => ``
    +          ),
    +        };
    +        vertexNode = addHtmlLabel(elem, node).node();
    +        vertexNode.parentNode.removeChild(vertexNode);
    +      } else {
    +        const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text');
    +        svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:'));
    +
    +        const rows = vertexText.split(common.lineBreakRegex);
    +
    +        for (const row of rows) {
    +          const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan');
    +          tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve');
    +          tspan.setAttribute('dy', '1em');
    +          tspan.setAttribute('x', '1');
    +          tspan.textContent = row;
    +          svgLabel.appendChild(tspan);
    +        }
    +        vertexNode = svgLabel;
    +      }
    +    }
    +
    +    let radious = 0;
    +    let _shape = '';
    +    // Set the shape based parameters
    +    switch (vertex.type) {
    +      case 'round':
    +        radious = 5;
    +        _shape = 'rect';
    +        break;
    +      case 'square':
    +        _shape = 'rect';
    +        break;
    +      case 'diamond':
    +        _shape = 'question';
    +        break;
    +      case 'hexagon':
    +        _shape = 'hexagon';
    +        break;
    +      case 'odd':
    +        _shape = 'rect_left_inv_arrow';
    +        break;
    +      case 'lean_right':
    +        _shape = 'lean_right';
    +        break;
    +      case 'lean_left':
    +        _shape = 'lean_left';
    +        break;
    +      case 'trapezoid':
    +        _shape = 'trapezoid';
    +        break;
    +      case 'inv_trapezoid':
    +        _shape = 'inv_trapezoid';
    +        break;
    +      case 'odd_right':
    +        _shape = 'rect_left_inv_arrow';
    +        break;
    +      case 'circle':
    +        _shape = 'circle';
    +        break;
    +      case 'ellipse':
    +        _shape = 'ellipse';
    +        break;
    +      case 'stadium':
    +        _shape = 'stadium';
    +        break;
    +      case 'subroutine':
    +        _shape = 'subroutine';
    +        break;
    +      case 'cylinder':
    +        _shape = 'cylinder';
    +        break;
    +      case 'group':
    +        _shape = 'rect';
    +        break;
    +      case 'doublecircle':
    +        _shape = 'doublecircle';
    +        break;
    +      default:
    +        _shape = 'rect';
    +    }
    +    // Add the node
    +    let nodeObj = {
    +      labelStyle: styles.labelStyle,
    +      shape: _shape,
    +      labelText: vertexText,
    +      labelType: vertex.labelType,
    +      rx: radious,
    +      ry: radious,
    +      class: classStr,
    +      style: styles.style,
    +      id: vertex.id,
    +      link: vertex.link,
    +      linkTarget: vertex.linkTarget,
    +      // tooltip: diagObj.db.getTooltip(vertex.id) || '',
    +      // domId: diagObj.db.lookUpDomId(vertex.id),
    +      haveCallback: vertex.haveCallback,
    +      width: vertex.type === 'group' ? 500 : undefined,
    +      dir: vertex.dir,
    +      type: vertex.type,
    +      props: vertex.props,
    +      padding: getConfig().flowchart.padding,
    +      x: nodeFromLayout.x,
    +      y: nodeFromLayout.y,
    +    };
    +
    +    let boundingBox;
    +    let nodeEl;
    +
    +    // Add the element to the DOM
    +
    +    nodeEl = await insertNode(nodesElements, nodeObj, vertex.dir);
    +    boundingBox = nodeEl.node().getBBox();
    +    nodeEl.attr('transform', `translate(${nodeObj.x}, ${nodeObj.y / 2})`);
    +  }
    +
    +  return elem;
    +}
    +
    +/**
    + * Returns the all the styles from classDef statements in the graph definition.
    + *
    + * @param text
    + * @param diagObj
    + * @returns {object} ClassDef styles
    + */
    +export const getClasses = function (text, diagObj) {
    +  log.info('Extracting classes');
    +  diagObj.db.clear();
    +  try {
    +    // Parse the graph definition
    +    diagObj.parse(text);
    +    return diagObj.db.getClasses();
    +  } catch (e) {
    +    return;
    +  }
    +};
    +
    +/**
    + * Draws a flowchart in the tag with id: id based on the graph definition in text.
    + *
    + * @param text
    + * @param id
    + */
    +
    +export const draw = async function (text, id, _version, diagObj) {
    +  log.info('Drawing flowchart');
    +  diagObj.db.clear();
    +  flowDb.setGen('gen-2');
    +  // Parse the graph definition
    +  diagObj.parser.parse(text);
    +
    +  const { securityLevel, flowchart: conf } = getConfig();
    +
    +  // Handle root and document for when rendering in sandbox mode
    +  let sandboxElement;
    +  if (securityLevel === 'sandbox') {
    +    sandboxElement = select('#i' + id);
    +  }
    +  const root =
    +    securityLevel === 'sandbox'
    +      ? select(sandboxElement.nodes()[0].contentDocument.body)
    +      : select('body');
    +  const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document;
    +
    +  // create g as a graphlib graph using setupGraph from setup-graph.js
    +  const g = setupGraph(diagObj, id, root, doc);
    +
    +  let subG;
    +  const subGraphs = diagObj.db.getSubGraphs();
    +  log.info('Subgraphs - ', subGraphs);
    +  for (let i = subGraphs.length - 1; i >= 0; i--) {
    +    subG = subGraphs[i];
    +    log.info('Subgraph - ', subG);
    +    diagObj.db.addVertex(
    +      subG.id,
    +      { text: subG.title, type: subG.labelType },
    +      'group',
    +      undefined,
    +      subG.classes,
    +      subG.dir
    +    );
    +  }
    +
    +  // Fetch the vertices/nodes and edges/links from the parsed graph definition
    +  const vert = diagObj.db.getVertices();
    +
    +  const edges = diagObj.db.getEdges();
    +
    +  log.info('Edges', edges);
    +
    +  const svg = root.select('#' + id);
    +
    +  svg.append('g');
    +
    +  // Run the renderer. This is what draws the final graph.
    +  // const element = root.select('#' + id + ' g');
    +  console.log('diagObj', diagObj);
    +  console.log('subGraphs', diagObj.db.getSubGraphs());
    +  const layout = swimlaneLayout(g, diagObj);
    +  console.log('custom layout', layout);
    +
    +  // draw lanes as vertical lines
    +  const lanesElements = svg.insert('g').attr('class', 'lanes');
    +
    +  let laneCount = 0;
    +
    +  for (const lane of layout.lanes) {
    +    laneCount++;
    +
    +    //draw lane header as rectangle with lane title centered in it
    +    const laneHeader = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
    +
    +    // Set attributes for the rectangle
    +    laneHeader.setAttribute('x', lane.x); // x-coordinate of the top-left corner
    +    laneHeader.setAttribute('y', -50); // y-coordinate of the top-left corner
    +    laneHeader.setAttribute('width', lane.width); // width of the rectangle
    +    laneHeader.setAttribute('height', '50'); // height of the rectangle
    +    if (laneCount % 2 == 0) {
    +      //set light blue color for even lanes
    +      laneHeader.setAttribute('fill', 'blue'); // fill color of the rectangle
    +    } else {
    +      //set white color odd lanes
    +      laneHeader.setAttribute('fill', 'grey'); // fill color of the rectangle
    +    }
    +
    +    laneHeader.setAttribute('stroke', 'black'); // color of the stroke/border
    +    laneHeader.setAttribute('stroke-width', '2'); // width of the stroke/border
    +
    +    // Append the rectangle to the SVG element
    +    lanesElements.node().appendChild(laneHeader);
    +
    +    //draw lane title
    +    const laneTitle = document.createElementNS('http://www.w3.org/2000/svg', 'text');
    +
    +    // Set attributes for the rectangle
    +    laneTitle.setAttribute('x', lane.x + lane.width / 2); // x-coordinate of the top-left corner
    +    laneTitle.setAttribute('y', -50 + 50 / 2); // y-coordinate of the top-left corner
    +    laneTitle.setAttribute('width', lane.width); // width of the rectangle
    +    laneTitle.setAttribute('height', '50'); // height of the rectangle
    +    laneTitle.setAttribute('fill', 'white'); // fill color of the rectangle
    +    laneTitle.setAttribute('stroke-width', '1'); // width of the stroke/border
    +    laneTitle.setAttribute('text-anchor', 'middle'); // width of the stroke/border
    +    laneTitle.setAttribute('alignment-baseline', 'middle'); // width of the stroke/border
    +    laneTitle.setAttribute('font-size', '20'); // width of the stroke/border
    +    laneTitle.textContent = lane.title;
    +
    +    // Append the rectangle to the SVG element
    +    lanesElements.node().appendChild(laneTitle);
    +
    +    //draw lane
    +
    +    // Create a  element
    +    const rectangle = document.createElementNS('http://www.w3.org/2000/svg', 'rect');
    +
    +    // Set attributes for the rectangle
    +    rectangle.setAttribute('x', lane.x); // x-coordinate of the top-left corner
    +    rectangle.setAttribute('y', 0); // y-coordinate of the top-left corner
    +    rectangle.setAttribute('width', lane.width); // width of the rectangle
    +    rectangle.setAttribute('height', '500'); // height of the rectangle
    +
    +    if (laneCount % 2 == 0) {
    +      //set light blue color for even lanes
    +      rectangle.setAttribute('fill', 'lightblue'); // fill color of the rectangle
    +    } else {
    +      //set white color odd lanes
    +      rectangle.setAttribute('fill', '#ffffff'); // fill color of the rectangle
    +    }
    +
    +    rectangle.setAttribute('stroke', 'black'); // color of the stroke/border
    +    rectangle.setAttribute('stroke-width', '2'); // width of the stroke/border
    +
    +    // Append the rectangle to the SVG element
    +    lanesElements.node().appendChild(rectangle);
    +  }
    +
    +  // append lanesElements to elem
    +  svg.node().appendChild(lanesElements.node());
    +
    +  // add lane headers
    +  const laneHeaders = svg.insert('g').attr('class', 'laneHeaders');
    +
    +  addEdges(edges, g, diagObj);
    +
    +  g.edges().forEach(function (e) {
    +    const edge = g.edge(e);
    +    log.info('Edge ' + e.v + ' -> ' + e.w + ': ' + JSON.stringify(edge), edge);
    +    const edgePaths = svg.insert('g').attr('class', 'edgePaths');
    +    //create edge points based on start and end node
    +
    +    //get start node x, y coordinates
    +    const sourceNode = layout.graph.node(e.v);
    +    //get end node x, y coordinates
    +    sourceNode.x = sourceNode.x;
    +    sourceNode.y = sourceNode.y;
    +
    +    const targetNode = layout.graph.node(e.w);
    +    targetNode.x = targetNode.x;
    +    targetNode.y = targetNode.y;
    +
    +    edge.points = [];
    +    edge.points.push({ x: sourceNode.x, y: sourceNode.y / 2 });
    +    edge.points.push({ x: targetNode.x, y: targetNode.y / 2 });
    +
    +    const paths = insertEdge(edgePaths, e, edge, clusterDb, 'flowchart', g);
    +    //positionEdgeLabel(edge, paths);
    +  });
    +  await swimlaneRender(layout, vert, svg, g, id, conf);
    +
    +  // utils.insertTitle(svg, 'flowchartTitleText', conf.titleTopMargin, diagObj.db.getDiagramTitle());
    +
    +  setupGraphViewbox(g, svg, conf.diagramPadding, conf.useMaxWidth);
    +};
    +
    +export default {
    +  setConf,
    +  addVertices,
    +  addEdges,
    +  getClasses,
    +  draw,
    +};
    
    From ccdb8035012b221317d3804c54f3354c0517989d Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Tue, 5 Sep 2023 15:15:08 +0200
    Subject: [PATCH 15/97] Rendering, interim
    
    ---
     packages/mermaid/src/dagre-wrapper/nodes.js   |  28 +--
     .../mermaid/src/dagre-wrapper/shapes/util.js  |   3 +
     .../mermaid/src/diagrams/block/blockDB.ts     |   3 -
     .../src/diagrams/block/blockRenderer.ts       |   7 +-
     packages/mermaid/src/diagrams/block/layout.ts |   5 -
     .../src/diagrams/block/renderHelpers.ts       | 167 ++++--------------
     6 files changed, 57 insertions(+), 156 deletions(-)
    
    diff --git a/packages/mermaid/src/dagre-wrapper/nodes.js b/packages/mermaid/src/dagre-wrapper/nodes.js
    index e6a9d982a2..e9324171b9 100644
    --- a/packages/mermaid/src/dagre-wrapper/nodes.js
    +++ b/packages/mermaid/src/dagre-wrapper/nodes.js
    @@ -323,8 +323,12 @@ const rect = async (parent, node) => {
     
       // const totalWidth = bbox.width + node.padding * 2;
       // const totalHeight = bbox.height + node.padding * 2;
    -  const totalWidth = bbox.width + node.padding;
    -  const totalHeight = bbox.height + node.padding;
    +  const totalWidth = node.positioned ? node.width : bbox.width + node.padding;
    +  const totalHeight = node.positioned ? node.height : bbox.height + node.padding;
    +  const x = node.positioned ? node.x - node.width / 2 - halfPadding : -bbox.width / 2 - halfPadding;
    +  const y = node.positioned
    +    ? node.y - node.height / 2 - halfPadding
    +    : -bbox.height / 2 - halfPadding;
       rect
         .attr('class', 'basic label-container')
         .attr('style', node.style)
    @@ -332,8 +336,8 @@ const rect = async (parent, node) => {
         .attr('ry', node.ry)
         // .attr('x', -bbox.width / 2 - node.padding)
         // .attr('y', -bbox.height / 2 - node.padding)
    -    .attr('x', -bbox.width / 2 - halfPadding)
    -    .attr('y', -bbox.height / 2 - halfPadding)
    +    .attr('x', x)
    +    .attr('y', y)
         .attr('width', totalWidth)
         .attr('height', totalHeight);
     
    @@ -1037,14 +1041,14 @@ export const positionNode = (node) => {
       const padding = 8;
       const diff = node.diff || 0;
       if (node.clusterNode) {
    -      el.attr(
    -        'transform',
    -        'translate(' +
    -          (node.x + diff - node.width / 2) +
    -          ', ' +
    -          (node.y - node.height / 2 - padding) +
    -          ')'
    -      );
    +    el.attr(
    +      'transform',
    +      'translate(' +
    +        (node.x + diff - node.width / 2) +
    +        ', ' +
    +        (node.y - node.height / 2 - padding) +
    +        ')'
    +    );
       } else {
         el.attr('transform', 'translate(' + node.x + ', ' + node.y + ')');
       }
    diff --git a/packages/mermaid/src/dagre-wrapper/shapes/util.js b/packages/mermaid/src/dagre-wrapper/shapes/util.js
    index 3eaedb4b9f..2230547fff 100644
    --- a/packages/mermaid/src/dagre-wrapper/shapes/util.js
    +++ b/packages/mermaid/src/dagre-wrapper/shapes/util.js
    @@ -113,6 +113,9 @@ export const labelHelper = async (parent, node, _classes, isNode) => {
         label.attr('transform', 'translate(' + -bbox.width / 2 + ', ' + -bbox.height / 2 + ')');
       }
       label.insert('rect', ':first-child');
    +  // if (node.positioned) {
    +  //   shapeSvg.attr('transform', 'translate(' + node.x + ', ' + node.y + ')');
    +  // }
       return { shapeSvg, bbox, halfPadding, label };
     };
     
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index 039353830e..84c6536050 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -103,17 +103,14 @@ const getColumns = (blockid: string): number => {
     
     type IGetBlocks = () => Block[];
     const getBlocks: IGetBlocks = () => {
    -  log.info('Block in test', blocks, blocks[0].id);
       return blocks || [];
     };
     type IGetBlock = (id: string) => Block | undefined;
     const getBlock: IGetBlock = (id: string) => {
    -  log.info('Block in test', blocks, blocks[0].id);
       return blockDatabase[id];
     };
     type ISetBlock = (block: Block) => void;
     const setBlock: ISetBlock = (block: Block) => {
    -  log.info('Block in test', blocks, blocks[0].id);
       blockDatabase[block.id] = block;
     };
     
    diff --git a/packages/mermaid/src/diagrams/block/blockRenderer.ts b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    index 0dac714d42..932537786b 100644
    --- a/packages/mermaid/src/diagrams/block/blockRenderer.ts
    +++ b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    @@ -1,6 +1,6 @@
     import { Diagram } from '../../Diagram.js';
     import * as configApi from '../../config.js';
    -import { calculateBlockSizes } from './renderHelpers.js';
    +import { calculateBlockSizes, insertBlocks } from './renderHelpers.js';
     import { layout } from './layout.js';
     import { setupGraphViewbox } from '../../setupGraphViewbox.js';
     import {
    @@ -42,14 +42,15 @@ export const draw = async function (
       const nodes = svg.insert('g').attr('class', 'block');
       await calculateBlockSizes(nodes, bl, db);
       const bounds = layout(db);
    +  await insertBlocks(nodes, bl, db);
     
       console.log('Here', bl);
     
       // Establish svg dimensions and get width and height
       //
       // const bounds = nodes.node().getBoundingClientRect();
    -  const height = bounds.height;
    -  const width = bounds.width;
    +  const height = bounds.height + 600;
    +  const width = bounds.width + 699;
       const useMaxWidth = false;
       configureSvgSize(svg, height, width, useMaxWidth);
       console.log('Here Bounds', bounds);
    diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts
    index 65b99c1543..2d61002295 100644
    --- a/packages/mermaid/src/diagrams/block/layout.ts
    +++ b/packages/mermaid/src/diagrams/block/layout.ts
    @@ -42,13 +42,9 @@ function layoutBLock(block: Block, db: BlockDB) {
     }
     
     function positionBlock(block: Block, db: BlockDB) {
    -  console.log('Here Positioning', block?.size?.node);
    -  // const o = db.getBlock(block.id);
    -  // const node;
       if (block?.size?.node) {
         const node = block?.size?.node;
         const size = block?.size;
    -    console.log('Here as well', node);
         if (node) {
           node.attr(
             'transform',
    @@ -70,7 +66,6 @@ let maxY = 0;
     function findBounds(block: Block) {
       if (block.size) {
         const { x, y, width, height } = block.size;
    -    console.log('Here', minX, minY, x, y, width, height);
         if (x - width < minX) {
           minX = x - width;
         }
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index 34d8baa054..1b29b45363 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -5,7 +5,7 @@ import { ContainerElement } from 'd3';
     import type { Block } from './blockTypes.js';
     import { BlockDB } from './blockDB.js';
     
    -function getNodeFromBlock(block: Block, db: BlockDB) {
    +function getNodeFromBlock(block: Block, db: BlockDB, positioned: boolean = false) {
       const vertex = block;
     
       /**
    @@ -93,6 +93,7 @@ function getNodeFromBlock(block: Block, db: BlockDB) {
       // Use vertex id as text in the box if no text is provided by the graph definition
       const vertexText = vertex.label;
     
    +  const bounds = vertex.size || { width: 0, height: 0, x: 0, y: 0 };
       // Add the node
       const node = {
         labelStyle: styles.labelStyle,
    @@ -111,160 +112,60 @@ function getNodeFromBlock(block: Block, db: BlockDB) {
         // haveCallback: vertex.haveCallback,
         // width: vertex.type === 'group' ? 500 : undefined,
         // dir: vertex.dir,
    +    width: bounds.width,
    +    height: bounds.height,
    +    x: bounds.x,
    +    y: bounds.y,
    +    positioned,
         type: vertex.type,
         // props: vertex.props,
         padding: getConfig()?.flowchart?.padding || 0,
       };
       return node;
     }
    -
    +type IOperation = (elem: any, block: any, db: any) => Promise;
     async function calculateBlockSize(elem: any, block: any, db: any) {
    -  console.log('Here befoire 3');
    -  const node = getNodeFromBlock(block, db);
    +  const node = getNodeFromBlock(block, db, false);
       if (node.type === 'group') return;
     
       // Add the element to the DOM to size it
       const nodeEl = await insertNode(elem, node);
       const boundingBox = nodeEl.node().getBBox();
       const obj = db.getBlock(node.id);
    -  console.log('Here el', nodeEl);
       obj.size = { width: boundingBox.width, height: boundingBox.height, x: 0, y: 0, node: nodeEl };
    +  console.log('Here boundsíng', boundingBox.width);
       db.setBlock(obj);
    -  // nodeEl.remove();
    +  nodeEl.remove();
     }
     
    -export async function calculateBlockSizes(elem: ContainerElement, blocks: Block[], db: BlockDB) {
    -  console.log('Here before 2');
    +export async function insertBlockPositioned(elem: any, block: any, db: any) {
    +  console.log('Here insertBlockPositioned');
    +  const node = getNodeFromBlock(block, db, true);
    +  if (node.type === 'group') return;
    +
    +  // Add the element to the DOM to size it
    +  const obj = db.getBlock(node.id);
    +  const nodeEl = await insertNode(elem, node);
    +}
    +
    +export async function performOperations(
    +  elem: ContainerElement,
    +  blocks: Block[],
    +  db: BlockDB,
    +  operation: IOperation
    +) {
       for (const block of blocks) {
    -    await calculateBlockSize(elem, block, db);
    +    await operation(elem, block, db);
         if (block.children) {
    -      await calculateBlockSizes(elem, block.children, db);
    +      await performOperations(elem, block.children, db, operation);
         }
       }
     }
    -export async function insertBlockPositioned(elem: any, block: any, db: any) {
    -  const vertex = block;
    -
    -  /**
    -   * Variable for storing the classes for the vertex
    -   *
    -   * @type {string}
    -   */
    -  let classStr = 'default';
    -  if ((vertex?.classes?.length || []) > 0) {
    -    classStr = vertex.classes.join(' ');
    -  }
    -  classStr = classStr + ' flowchart-label';
    -
    -  // We create a SVG label, either by delegating to addHtmlLabel or manually
    -  let vertexNode;
    -  const labelData = { width: 0, height: 0 };
    -
    -  let radious = 0;
    -  let _shape = '';
    -  let layoutOptions = {};
    -  // Set the shape based parameters
    -  switch (vertex.type) {
    -    case 'round':
    -      radious = 5;
    -      _shape = 'rect';
    -      break;
    -    case 'square':
    -      _shape = 'rect';
    -      break;
    -    case 'diamond':
    -      _shape = 'question';
    -      layoutOptions = {
    -        portConstraints: 'FIXED_SIDE',
    -      };
    -      break;
    -    case 'hexagon':
    -      _shape = 'hexagon';
    -      break;
    -    case 'odd':
    -      _shape = 'rect_left_inv_arrow';
    -      break;
    -    case 'lean_right':
    -      _shape = 'lean_right';
    -      break;
    -    case 'lean_left':
    -      _shape = 'lean_left';
    -      break;
    -    case 'trapezoid':
    -      _shape = 'trapezoid';
    -      break;
    -    case 'inv_trapezoid':
    -      _shape = 'inv_trapezoid';
    -      break;
    -    case 'odd_right':
    -      _shape = 'rect_left_inv_arrow';
    -      break;
    -    case 'circle':
    -      _shape = 'circle';
    -      break;
    -    case 'ellipse':
    -      _shape = 'ellipse';
    -      break;
    -    case 'stadium':
    -      _shape = 'stadium';
    -      break;
    -    case 'subroutine':
    -      _shape = 'subroutine';
    -      break;
    -    case 'cylinder':
    -      _shape = 'cylinder';
    -      break;
    -    case 'group':
    -      _shape = 'rect';
    -      break;
    -    case 'doublecircle':
    -      _shape = 'doublecircle';
    -      break;
    -    default:
    -      _shape = 'rect';
    -  }
     
    -  // const styles = getStylesFromArray(vertex.styles);
    -  const styles = getStylesFromArray([]);
    -
    -  // Use vertex id as text in the box if no text is provided by the graph definition
    -  const vertexText = vertex.label;
    -
    -  // Add the node
    -  const node = {
    -    labelStyle: styles.labelStyle,
    -    shape: _shape,
    -    labelText: vertexText,
    -    labelType: vertex.labelType,
    -    rx: radious,
    -    ry: radious,
    -    class: classStr,
    -    style: styles.style,
    -    id: vertex.id,
    -    link: vertex.link,
    -    linkTarget: vertex.linkTarget,
    -    // tooltip: diagObj.db.getTooltip(vertex.id) || '',
    -    // domId: diagObj.db.lookUpDomId(vertex.id),
    -    haveCallback: vertex.haveCallback,
    -    width: vertex.width,
    -    height: vertex.height,
    -    dir: vertex.dir,
    -    type: vertex.type,
    -    props: vertex.props,
    -    padding: getConfig()?.flowchart?.padding || 0,
    -  };
    -  let boundingBox;
    -  let nodeEl;
    +export async function calculateBlockSizes(elem: ContainerElement, blocks: Block[], db: BlockDB) {
    +  await performOperations(elem, blocks, db, calculateBlockSize);
    +}
     
    -  // Add the element to the DOM
    -  if (node.type !== 'group') {
    -    nodeEl = await insertNode(elem, node, vertex.dir);
    -    // nodeEl.remove();
    -    boundingBox = nodeEl.node().getBBox();
    -    if (node.id) {
    -      const obj = db.getBlock(node.id);
    -      obj.size = { width: boundingBox.width, height: boundingBox.height, x: 0, y: 0, node: nodeEl };
    -      db.setBlock(obj);
    -    }
    -  }
    +export async function insertBlocks(elem: ContainerElement, blocks: Block[], db: BlockDB) {
    +  await performOperations(elem, blocks, db, insertBlockPositioned);
     }
    
    From 836d3a87beb2b585fad9ac6e5b90f835fb876222 Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Thu, 14 Sep 2023 10:11:43 +0200
    Subject: [PATCH 16/97] WIP
    
    ---
     cypress/platform/knsv2.html                   | 12 ++-
     packages/mermaid/src/dagre-wrapper/nodes.js   | 98 +++++++++----------
     .../src/diagrams/block/blockRenderer.ts       | 22 +++--
     packages/mermaid/src/diagrams/block/layout.ts | 19 ++--
     .../src/diagrams/block/renderHelpers.ts       |  3 +-
     5 files changed, 84 insertions(+), 70 deletions(-)
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index 4609331dd5..36afc1d035 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -26,6 +26,8 @@
           }
           .mermaid {
             border: 1px solid #ddd;
    +        margin: 10px;
    +        background: pink;
           }
           .mermaid2 {
             display: none;
    @@ -38,6 +40,7 @@
             background-size: 20px 20px;
             background-position: 0 0, 10px 10px;
             background-repeat: repeat;
    +        border: 1px solid red;
           }
           .malware {
             position: fixed;
    @@ -62,10 +65,13 @@
       
         
     block-beta
    -  id1("Wide 1")
    +  %% id1("Wide 1")
       id2("2")
    -  id3("3")
    -  id4("A final one")
    +  block
    +      id3
    +      id4
    +  end
    +  %% id4("A final one")
     
         
    diff --git a/packages/mermaid/src/dagre-wrapper/nodes.js b/packages/mermaid/src/dagre-wrapper/nodes.js
    index e9324171b9..9e57fb2b0c 100644
    --- a/packages/mermaid/src/dagre-wrapper/nodes.js
    +++ b/packages/mermaid/src/dagre-wrapper/nodes.js
    @@ -27,7 +27,7 @@ const question = async (parent, node) => {
       questionElem.attr('style', node.style);
       updateNodeBounds(node, questionElem);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         log.warn('Intersect called');
         return intersect.polygon(node, points, point);
       };
    @@ -52,7 +52,7 @@ const choice = (parent, node) => {
       const choice = shapeSvg.insert('polygon', ':first-child').attr(
         'points',
         points
    -      .map(function (d) {
    +      .map(function(d) {
             return d.x + ',' + d.y;
           })
           .join(' ')
    @@ -62,7 +62,7 @@ const choice = (parent, node) => {
       node.width = 28;
       node.height = 28;
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.circle(node, 14, point);
       };
     
    @@ -89,7 +89,7 @@ const hexagon = async (parent, node) => {
       hex.attr('style', node.style);
       updateNodeBounds(node, hex);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -115,7 +115,7 @@ const rect_left_inv_arrow = async (parent, node) => {
       node.width = w + h;
       node.height = h;
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -138,7 +138,7 @@ const lean_right = async (parent, node) => {
       el.attr('style', node.style);
       updateNodeBounds(node, el);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -161,7 +161,7 @@ const lean_left = async (parent, node) => {
       el.attr('style', node.style);
       updateNodeBounds(node, el);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -184,7 +184,7 @@ const trapezoid = async (parent, node) => {
       el.attr('style', node.style);
       updateNodeBounds(node, el);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -207,7 +207,7 @@ const inv_trapezoid = async (parent, node) => {
       el.attr('style', node.style);
       updateNodeBounds(node, el);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -231,7 +231,7 @@ const rect_right_inv_arrow = async (parent, node) => {
       el.attr('style', node.style);
       updateNodeBounds(node, el);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -281,7 +281,7 @@ const cylinder = async (parent, node) => {
     
       updateNodeBounds(node, el);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         const pos = intersect.rect(node, point);
         const x = pos.x - node.x;
     
    @@ -325,17 +325,13 @@ const rect = async (parent, node) => {
       // const totalHeight = bbox.height + node.padding * 2;
       const totalWidth = node.positioned ? node.width : bbox.width + node.padding;
       const totalHeight = node.positioned ? node.height : bbox.height + node.padding;
    -  const x = node.positioned ? node.x - node.width / 2 - halfPadding : -bbox.width / 2 - halfPadding;
    -  const y = node.positioned
    -    ? node.y - node.height / 2 - halfPadding
    -    : -bbox.height / 2 - halfPadding;
    +  const x = node.positioned ? -totalWidth / 2 : -bbox.width / 2 - halfPadding;
    +  const y = node.positioned ? -totalHeight / 2 : -bbox.height / 2 - halfPadding;
       rect
         .attr('class', 'basic label-container')
         .attr('style', node.style)
         .attr('rx', node.rx)
         .attr('ry', node.ry)
    -    // .attr('x', -bbox.width / 2 - node.padding)
    -    // .attr('y', -bbox.height / 2 - node.padding)
         .attr('x', x)
         .attr('y', y)
         .attr('width', totalWidth)
    @@ -354,7 +350,7 @@ const rect = async (parent, node) => {
     
       updateNodeBounds(node, rect);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.rect(node, point);
       };
     
    @@ -387,7 +383,7 @@ const labelRect = async (parent, node) => {
     
       updateNodeBounds(node, rect);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.rect(node, point);
       };
     
    @@ -499,20 +495,20 @@ const rectWithTitle = (parent, node) => {
       select(descr).attr(
         'transform',
         'translate( ' +
    -      // (titleBox.width - bbox.width) / 2 +
    -      (bbox.width > titleBox.width ? 0 : (titleBox.width - bbox.width) / 2) +
    -      ', ' +
    -      (titleBox.height + halfPadding + 5) +
    -      ')'
    +    // (titleBox.width - bbox.width) / 2 +
    +    (bbox.width > titleBox.width ? 0 : (titleBox.width - bbox.width) / 2) +
    +    ', ' +
    +    (titleBox.height + halfPadding + 5) +
    +    ')'
       );
       select(text).attr(
         'transform',
         'translate( ' +
    -      // (titleBox.width - bbox.width) / 2 +
    -      (bbox.width < titleBox.width ? 0 : -(titleBox.width - bbox.width) / 2) +
    -      ', ' +
    -      0 +
    -      ')'
    +    // (titleBox.width - bbox.width) / 2 +
    +    (bbox.width < titleBox.width ? 0 : -(titleBox.width - bbox.width) / 2) +
    +    ', ' +
    +    0 +
    +    ')'
       );
       // Get the size of the label
     
    @@ -541,7 +537,7 @@ const rectWithTitle = (parent, node) => {
     
       updateNodeBounds(node, rect);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.rect(node, point);
       };
     
    @@ -567,7 +563,7 @@ const stadium = async (parent, node) => {
     
       updateNodeBounds(node, rect);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.rect(node, point);
       };
     
    @@ -591,7 +587,7 @@ const circle = async (parent, node) => {
     
       updateNodeBounds(node, circle);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         log.info('Circle intersect', node, bbox.width / 2 + halfPadding, point);
         return intersect.circle(node, bbox.width / 2 + halfPadding, point);
       };
    @@ -629,7 +625,7 @@ const doublecircle = async (parent, node) => {
     
       updateNodeBounds(node, outerCircle);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         log.info('DoubleCircle intersect', node, bbox.width / 2 + halfPadding + gap, point);
         return intersect.circle(node, bbox.width / 2 + halfPadding + gap, point);
       };
    @@ -659,7 +655,7 @@ const subroutine = async (parent, node) => {
       el.attr('style', node.style);
       updateNodeBounds(node, el);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -678,7 +674,7 @@ const start = (parent, node) => {
     
       updateNodeBounds(node, circle);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.circle(node, 7, point);
       };
     
    @@ -710,7 +706,7 @@ const forkJoin = (parent, node, dir) => {
       updateNodeBounds(node, shape);
       node.height = node.height + node.padding / 2;
       node.width = node.width + node.padding / 2;
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.rect(node, point);
       };
     
    @@ -731,7 +727,7 @@ const end = (parent, node) => {
     
       updateNodeBounds(node, circle);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.circle(node, 7, point);
       };
     
    @@ -896,10 +892,10 @@ const class_box = (parent, node) => {
       select(classTitleLabel).attr(
         'transform',
         'translate( ' +
    -      ((-1 * maxWidth) / 2 + diffX) +
    -      ', ' +
    -      ((-1 * maxHeight) / 2 + verticalPos) +
    -      ')'
    +    ((-1 * maxWidth) / 2 + diffX) +
    +    ', ' +
    +    ((-1 * maxHeight) / 2 + verticalPos) +
    +    ')'
       );
       verticalPos += classTitleBBox.height + rowPadding;
     
    @@ -916,10 +912,10 @@ const class_box = (parent, node) => {
         select(lbl).attr(
           'transform',
           'translate( ' +
    -        -maxWidth / 2 +
    -        ', ' +
    -        ((-1 * maxHeight) / 2 + verticalPos + lineHeight / 2) +
    -        ')'
    +      -maxWidth / 2 +
    +      ', ' +
    +      ((-1 * maxHeight) / 2 + verticalPos + lineHeight / 2) +
    +      ')'
         );
         //get the height of the bounding box of each member if exists
         const memberBBox = lbl?.getBBox();
    @@ -954,7 +950,7 @@ const class_box = (parent, node) => {
     
       updateNodeBounds(node, rect);
     
    -  node.intersect = function (point) {
    +  node.intersect = function(point) {
         return intersect.rect(node, point);
       };
     
    @@ -1030,8 +1026,8 @@ export const clear = () => {
     };
     
     export const positionNode = (node) => {
    +  console.log('Node id = ', node.id);
       const el = nodeElems[node.id];
    -
       log.trace(
         'Transforming node',
         node.diff,
    @@ -1044,10 +1040,10 @@ export const positionNode = (node) => {
         el.attr(
           'transform',
           'translate(' +
    -        (node.x + diff - node.width / 2) +
    -        ', ' +
    -        (node.y - node.height / 2 - padding) +
    -        ')'
    +      (node.x + diff - node.width / 2) +
    +      ', ' +
    +      (node.y - node.height / 2 - padding) +
    +      ')'
         );
       } else {
         el.attr('transform', 'translate(' + node.x + ', ' + node.y + ')');
    diff --git a/packages/mermaid/src/diagrams/block/blockRenderer.ts b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    index 932537786b..a8bf1fe49a 100644
    --- a/packages/mermaid/src/diagrams/block/blockRenderer.ts
    +++ b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    @@ -16,6 +16,7 @@ import type { Block } from './blockTypes.js';
     // import { diagram as BlockDiagram } from './blockDiagram.js';
     import { configureSvgSize } from '../../setupGraphViewbox.js';
     import { Uid } from '../../rendering-util/uid.js';
    +import { pad } from 'lodash';
     
     export const draw = async function (
       text: string,
    @@ -42,19 +43,28 @@ export const draw = async function (
       const nodes = svg.insert('g').attr('class', 'block');
       await calculateBlockSizes(nodes, bl, db);
       const bounds = layout(db);
    +  console.log('Here blocks', bl);
       await insertBlocks(nodes, bl, db);
     
    -  console.log('Here', bl);
    +  // console.log('Here', bl);
     
       // Establish svg dimensions and get width and height
       //
    -  // const bounds = nodes.node().getBoundingClientRect();
    -  const height = bounds.height + 600;
    -  const width = bounds.width + 699;
    +  // const bounds2 = nodes.node().getBoundingClientRect();
    +  const bounds2 = bounds;
    +  const padding = 10;
    +  // Why, oh why ????
    +  const magicFactor = Math.max(1, Math.round(0.125 * (bounds2.width / bounds2.height)));
    +  const height = bounds2.height + magicFactor + 10;
    +  const width = bounds2.width + 10;
       const useMaxWidth = false;
       configureSvgSize(svg, height, width, useMaxWidth);
    -  console.log('Here Bounds', bounds);
    -  svg.attr('viewBox', `${bounds.x} ${bounds.y} ${bounds.width} ${bounds.height}`);
    +  console.log('Here Bounds', bounds, bounds2);
    +  svg.attr(
    +    'viewBox',
    +    `${bounds2.x - 5} ${bounds2.y - 5} ${bounds2.width + 10} ${bounds2.height + 10}`
    +  );
    +  // svg.attr('viewBox', `${-200} ${-200} ${400} ${400}`);
     
       // Prepare data for construction based on diagObj.db
       // This must be a mutable object with `nodes` and `links` properties:
    diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts
    index 2d61002295..b745ce1b9f 100644
    --- a/packages/mermaid/src/diagrams/block/layout.ts
    +++ b/packages/mermaid/src/diagrams/block/layout.ts
    @@ -66,17 +66,17 @@ let maxY = 0;
     function findBounds(block: Block) {
       if (block.size) {
         const { x, y, width, height } = block.size;
    -    if (x - width < minX) {
    -      minX = x - width;
    +    if (x - width / 2 < minX) {
    +      minX = x - width / 2;
         }
    -    if (y - height < minY) {
    -      minY = y - height;
    +    if (y - height / 2 < minY) {
    +      minY = y - height / 2;
         }
    -    if (x > maxX) {
    -      maxX = x;
    +    if (x + width / 2 > maxX) {
    +      maxX = x + width / 2;
         }
    -    if (y > maxY) {
    -      maxY = y;
    +    if (y + height / 2 > maxY) {
    +      maxY = y + height / 2;
         }
       }
       if (block.children) {
    @@ -90,13 +90,14 @@ export function layout(db: BlockDB) {
       const blocks = db.getBlocks();
       const root = { id: 'root', type: 'composite', children: blocks } as Block;
       layoutBLock(root, db);
    -  positionBlock(root, db);
    +  // positionBlock(root, db);
     
       minX = 0;
       minY = 0;
       maxX = 0;
       maxY = 0;
       findBounds(root);
    +  console.log('Here maxX', maxX);
       const height = maxY - minY;
       const width = maxX - minX;
       return { x: minX, y: minY, width, height };
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index 1b29b45363..cb7833050d 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -1,5 +1,5 @@
     import { getStylesFromArray } from '../../utils.js';
    -import { insertNode } from '../../dagre-wrapper/nodes.js';
    +import { insertNode, positionNode } from '../../dagre-wrapper/nodes.js';
     import { getConfig } from '../../config.js';
     import { ContainerElement } from 'd3';
     import type { Block } from './blockTypes.js';
    @@ -146,6 +146,7 @@ export async function insertBlockPositioned(elem: any, block: any, db: any) {
       // Add the element to the DOM to size it
       const obj = db.getBlock(node.id);
       const nodeEl = await insertNode(elem, node);
    +  positionNode(node);
     }
     
     export async function performOperations(
    
    From b4e32542e8ad26a39605603051302f0adf6a679d Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Tue, 3 Oct 2023 12:56:47 +0200
    Subject: [PATCH 17/97] #3358 Recursive positioning
    
    ---
     cypress/platform/knsv2.html                   | 10 +++-
     .../mermaid/src/diagrams/block/blockDB.ts     |  6 ++-
     packages/mermaid/src/diagrams/block/layout.ts | 50 ++++++++++++-------
     .../src/diagrams/block/parser/block.jison     |  2 +-
     .../src/diagrams/block/renderHelpers.ts       | 11 ++--
     5 files changed, 55 insertions(+), 24 deletions(-)
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index 36afc1d035..786ee26927 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -68,11 +68,19 @@
       %% id1("Wide 1")
       id2("2")
       block
    -      id3
    +      id3["I am a wide one"]
           id4
       end
       %% id4("A final one")
     
    +    
    +
    +block-beta
    +
    +      id3["I am a wide one"]
    +      id4
    +
    +
         
     flowchart RL
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index 84c6536050..50af7965fa 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -26,7 +26,11 @@ const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
           parent.columns = columns;
         } else {
           if (!block.label) {
    -        block.label = block.id;
    +        if (block.type === 'composite') {
    +          block.label = 'x';
    +        } else {
    +          block.label = block.id;
    +        }
           }
           blockDatabase[block.id] = block;
     
    diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts
    index b745ce1b9f..e008d78827 100644
    --- a/packages/mermaid/src/diagrams/block/layout.ts
    +++ b/packages/mermaid/src/diagrams/block/layout.ts
    @@ -1,10 +1,12 @@
     import { BlockDB } from './blockDB.js';
     import type { Block } from './blockTypes.js';
     
    -function layoutBLock(block: Block, db: BlockDB) {
    +function calcBlockSizes(block: Block, db: BlockDB) {
    +  let totalWidth = 0;
    +  let totalHeight = 0;
       if (block.children) {
         for (const child of block.children) {
    -      layoutBLock(child, db);
    +      calcBlockSizes(child, db);
         }
         // find max width of children
         let maxWidth = 0;
    @@ -27,9 +29,9 @@ function layoutBLock(block: Block, db: BlockDB) {
           }
         }
     
    -    // Position items
    +    // Position items relative to self
         let x = 0;
    -    let y = 0;
    +    const y = 0;
         const padding = 10;
         for (const child of block.children) {
           if (child.size) {
    @@ -37,26 +39,38 @@ function layoutBLock(block: Block, db: BlockDB) {
             child.size.y = y;
             x += maxWidth + padding;
           }
    +      if (x > totalWidth) {
    +        totalWidth = x;
    +      }
    +      if (y > totalHeight) {
    +        totalHeight = y;
    +      }
         }
       }
    +  if (block.children?.length > 0) {
    +    block.size = { width: totalWidth, height: totalHeight, x: 0, y: 0 };
    +  }
    +  console.log('layoutBlock (done)', block);
     }
     
    -function positionBlock(block: Block, db: BlockDB) {
    -  if (block?.size?.node) {
    -    const node = block?.size?.node;
    -    const size = block?.size;
    -    if (node) {
    -      node.attr(
    -        'transform',
    -        'translate(' + (size.x - size.width / 2) + ', ' + (size.y - size.height / 2) + ')'
    -      );
    -    }
    +function positionBlock(parent: Block, block: Block, db: BlockDB) {
    +  console.log('layout position block', parent.id, parent?.size?.x, block.id, block?.size?.x);
    +  let x = 0;
    +  let y = 0;
    +  if (parent) {
    +    x = parent?.size?.x || 0;
    +    y = parent?.size?.y || 0;
    +  }
    +  if (block.size) {
    +    block.size.x = block.size.x + x - block.size.width / 2;
    +    block.size.y = block.size.y + y;
       }
       if (block.children) {
         for (const child of block.children) {
    -      positionBlock(child, db);
    +      positionBlock(block, child, db);
         }
       }
    +  // console.log('layout position block', block);
     }
     let minX = 0;
     let minY = 0;
    @@ -89,8 +103,10 @@ function findBounds(block: Block) {
     export function layout(db: BlockDB) {
       const blocks = db.getBlocks();
       const root = { id: 'root', type: 'composite', children: blocks } as Block;
    -  layoutBLock(root, db);
    -  // positionBlock(root, db);
    +  calcBlockSizes(root, db);
    +  console.log('layout getBlocks', db.getBlocks());
    +  // Position blocks relative to parents
    +  positionBlock(root, root, db);
     
       minX = 0;
       minY = 0;
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index 9cc220ff40..32b7c28e25 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -191,7 +191,7 @@ columnsStatement
     
     blockStatement
       : id-block nodeStatement document end { yy.getLogger().info('Rule: id-block statement : ', $2, $3); const id2 = yy.generateId(); $$ = { ...$2, children: $3 }; }
    -  | block document end { yy.getLogger().info('Rule: blockStatement : ', $1, $2, $3); const id = yy.generateId(); $$ = { id, type:'composite', label:id, children: $2 }; }
    +  | block document end { yy.getLogger().info('Rule: blockStatement : ', $1, $2, $3); const id = yy.generateId(); $$ = { id, type:'composite', label:'', children: $2 }; }
       ;
     
     
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index cb7833050d..a17cda607d 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -5,7 +5,7 @@ import { ContainerElement } from 'd3';
     import type { Block } from './blockTypes.js';
     import { BlockDB } from './blockDB.js';
     
    -function getNodeFromBlock(block: Block, db: BlockDB, positioned: boolean = false) {
    +function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
       const vertex = block;
     
       /**
    @@ -126,7 +126,9 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned: boolean = false
     type IOperation = (elem: any, block: any, db: any) => Promise;
     async function calculateBlockSize(elem: any, block: any, db: any) {
       const node = getNodeFromBlock(block, db, false);
    -  if (node.type === 'group') return;
    +  if (node.type === 'group') {
    +    return;
    +  }
     
       // Add the element to the DOM to size it
       const nodeEl = await insertNode(elem, node);
    @@ -141,8 +143,9 @@ async function calculateBlockSize(elem: any, block: any, db: any) {
     export async function insertBlockPositioned(elem: any, block: any, db: any) {
       console.log('Here insertBlockPositioned');
       const node = getNodeFromBlock(block, db, true);
    -  if (node.type === 'group') return;
    -
    +  // if (node.type === 'composite') {
    +  //   return;
    +  // }
       // Add the element to the DOM to size it
       const obj = db.getBlock(node.id);
       const nodeEl = await insertNode(elem, node);
    
    From f00871a6b467b9a77cf794924378a0656d3858d8 Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Tue, 3 Oct 2023 14:19:08 +0200
    Subject: [PATCH 18/97] #3358 Recursive positioning
    
    ---
     cypress/platform/knsv2.html                   |  11 +-
     packages/mermaid/src/dagre-wrapper/nodes.js   | 137 +++++++++----
     .../mermaid/src/diagrams/block/blockDB.ts     |   2 +-
     packages/mermaid/src/diagrams/block/layout.ts |  40 ++--
     .../src/diagrams/block/renderHelpers.ts       |   5 +
     packages/mermaid/src/diagrams/block/styles.ts |  10 +-
     ....timestamp-1696335530501-05072b5e79635.mjs | 190 ++++++++++++++++++
     7 files changed, 326 insertions(+), 69 deletions(-)
     create mode 100644 vite.config.ts.timestamp-1696335530501-05072b5e79635.mjs
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index 786ee26927..6e69533eb6 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -69,12 +69,15 @@
       id2("2")
       block
           id3["I am a wide one"]
    -      id4
    +      block
    +        id44("A final one")
    +        id45("B final one")
    +      end
       end
    -  %% id4("A final one")
    +  id4("Another final one")
     
         
    -
    +    
     block-beta
     
           id3["I am a wide one"]
    @@ -84,7 +87,9 @@
         
     flowchart RL
    +  subgraph "`one`"
         id
    +  end
         
     flowchart RL
    diff --git a/packages/mermaid/src/dagre-wrapper/nodes.js b/packages/mermaid/src/dagre-wrapper/nodes.js
    index 9e57fb2b0c..b95265f311 100644
    --- a/packages/mermaid/src/dagre-wrapper/nodes.js
    +++ b/packages/mermaid/src/dagre-wrapper/nodes.js
    @@ -27,7 +27,7 @@ const question = async (parent, node) => {
       questionElem.attr('style', node.style);
       updateNodeBounds(node, questionElem);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         log.warn('Intersect called');
         return intersect.polygon(node, points, point);
       };
    @@ -52,7 +52,7 @@ const choice = (parent, node) => {
       const choice = shapeSvg.insert('polygon', ':first-child').attr(
         'points',
         points
    -      .map(function(d) {
    +      .map(function (d) {
             return d.x + ',' + d.y;
           })
           .join(' ')
    @@ -62,7 +62,7 @@ const choice = (parent, node) => {
       node.width = 28;
       node.height = 28;
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.circle(node, 14, point);
       };
     
    @@ -89,7 +89,7 @@ const hexagon = async (parent, node) => {
       hex.attr('style', node.style);
       updateNodeBounds(node, hex);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -115,7 +115,7 @@ const rect_left_inv_arrow = async (parent, node) => {
       node.width = w + h;
       node.height = h;
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -138,7 +138,7 @@ const lean_right = async (parent, node) => {
       el.attr('style', node.style);
       updateNodeBounds(node, el);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -161,7 +161,7 @@ const lean_left = async (parent, node) => {
       el.attr('style', node.style);
       updateNodeBounds(node, el);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -184,7 +184,7 @@ const trapezoid = async (parent, node) => {
       el.attr('style', node.style);
       updateNodeBounds(node, el);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -207,7 +207,7 @@ const inv_trapezoid = async (parent, node) => {
       el.attr('style', node.style);
       updateNodeBounds(node, el);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -231,7 +231,7 @@ const rect_right_inv_arrow = async (parent, node) => {
       el.attr('style', node.style);
       updateNodeBounds(node, el);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -281,7 +281,7 @@ const cylinder = async (parent, node) => {
     
       updateNodeBounds(node, el);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         const pos = intersect.rect(node, point);
         const x = pos.x - node.x;
     
    @@ -350,7 +350,55 @@ const rect = async (parent, node) => {
     
       updateNodeBounds(node, rect);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
    +    return intersect.rect(node, point);
    +  };
    +
    +  return shapeSvg;
    +};
    +
    +const composite = async (parent, node) => {
    +  console.log('This got called');
    +  const { shapeSvg, bbox, halfPadding } = await labelHelper(
    +    parent,
    +    node,
    +    'node ' + node.classes,
    +    true
    +  );
    +
    +  // add the rect
    +  const rect = shapeSvg.insert('rect', ':first-child');
    +
    +  // const totalWidth = bbox.width + node.padding * 2;
    +  // const totalHeight = bbox.height + node.padding * 2;
    +  const totalWidth = node.positioned ? node.width : bbox.width + node.padding;
    +  const totalHeight = node.positioned ? node.height : bbox.height + node.padding;
    +  const x = node.positioned ? -totalWidth / 2 : -bbox.width / 2 - halfPadding;
    +  const y = node.positioned ? -totalHeight / 2 : -bbox.height / 2 - halfPadding;
    +  rect
    +    .attr('class', 'basic cluster composite label-container')
    +    .attr('style', node.style)
    +    .attr('rx', node.rx)
    +    .attr('ry', node.ry)
    +    .attr('x', x)
    +    .attr('y', y)
    +    .attr('width', totalWidth)
    +    .attr('height', totalHeight);
    +
    +  if (node.props) {
    +    const propKeys = new Set(Object.keys(node.props));
    +    if (node.props.borders) {
    +      applyNodePropertyBorders(rect, node.props.borders, totalWidth, totalHeight);
    +      propKeys.delete('borders');
    +    }
    +    propKeys.forEach((propKey) => {
    +      log.warn(`Unknown node property ${propKey}`);
    +    });
    +  }
    +
    +  updateNodeBounds(node, rect);
    +
    +  node.intersect = function (point) {
         return intersect.rect(node, point);
       };
     
    @@ -383,7 +431,7 @@ const labelRect = async (parent, node) => {
     
       updateNodeBounds(node, rect);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.rect(node, point);
       };
     
    @@ -495,20 +543,20 @@ const rectWithTitle = (parent, node) => {
       select(descr).attr(
         'transform',
         'translate( ' +
    -    // (titleBox.width - bbox.width) / 2 +
    -    (bbox.width > titleBox.width ? 0 : (titleBox.width - bbox.width) / 2) +
    -    ', ' +
    -    (titleBox.height + halfPadding + 5) +
    -    ')'
    +      // (titleBox.width - bbox.width) / 2 +
    +      (bbox.width > titleBox.width ? 0 : (titleBox.width - bbox.width) / 2) +
    +      ', ' +
    +      (titleBox.height + halfPadding + 5) +
    +      ')'
       );
       select(text).attr(
         'transform',
         'translate( ' +
    -    // (titleBox.width - bbox.width) / 2 +
    -    (bbox.width < titleBox.width ? 0 : -(titleBox.width - bbox.width) / 2) +
    -    ', ' +
    -    0 +
    -    ')'
    +      // (titleBox.width - bbox.width) / 2 +
    +      (bbox.width < titleBox.width ? 0 : -(titleBox.width - bbox.width) / 2) +
    +      ', ' +
    +      0 +
    +      ')'
       );
       // Get the size of the label
     
    @@ -537,7 +585,7 @@ const rectWithTitle = (parent, node) => {
     
       updateNodeBounds(node, rect);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.rect(node, point);
       };
     
    @@ -563,7 +611,7 @@ const stadium = async (parent, node) => {
     
       updateNodeBounds(node, rect);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.rect(node, point);
       };
     
    @@ -587,7 +635,7 @@ const circle = async (parent, node) => {
     
       updateNodeBounds(node, circle);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         log.info('Circle intersect', node, bbox.width / 2 + halfPadding, point);
         return intersect.circle(node, bbox.width / 2 + halfPadding, point);
       };
    @@ -625,7 +673,7 @@ const doublecircle = async (parent, node) => {
     
       updateNodeBounds(node, outerCircle);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         log.info('DoubleCircle intersect', node, bbox.width / 2 + halfPadding + gap, point);
         return intersect.circle(node, bbox.width / 2 + halfPadding + gap, point);
       };
    @@ -655,7 +703,7 @@ const subroutine = async (parent, node) => {
       el.attr('style', node.style);
       updateNodeBounds(node, el);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.polygon(node, points, point);
       };
     
    @@ -674,7 +722,7 @@ const start = (parent, node) => {
     
       updateNodeBounds(node, circle);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.circle(node, 7, point);
       };
     
    @@ -706,7 +754,7 @@ const forkJoin = (parent, node, dir) => {
       updateNodeBounds(node, shape);
       node.height = node.height + node.padding / 2;
       node.width = node.width + node.padding / 2;
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.rect(node, point);
       };
     
    @@ -727,7 +775,7 @@ const end = (parent, node) => {
     
       updateNodeBounds(node, circle);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.circle(node, 7, point);
       };
     
    @@ -892,10 +940,10 @@ const class_box = (parent, node) => {
       select(classTitleLabel).attr(
         'transform',
         'translate( ' +
    -    ((-1 * maxWidth) / 2 + diffX) +
    -    ', ' +
    -    ((-1 * maxHeight) / 2 + verticalPos) +
    -    ')'
    +      ((-1 * maxWidth) / 2 + diffX) +
    +      ', ' +
    +      ((-1 * maxHeight) / 2 + verticalPos) +
    +      ')'
       );
       verticalPos += classTitleBBox.height + rowPadding;
     
    @@ -912,10 +960,10 @@ const class_box = (parent, node) => {
         select(lbl).attr(
           'transform',
           'translate( ' +
    -      -maxWidth / 2 +
    -      ', ' +
    -      ((-1 * maxHeight) / 2 + verticalPos + lineHeight / 2) +
    -      ')'
    +        -maxWidth / 2 +
    +        ', ' +
    +        ((-1 * maxHeight) / 2 + verticalPos + lineHeight / 2) +
    +        ')'
         );
         //get the height of the bounding box of each member if exists
         const memberBBox = lbl?.getBBox();
    @@ -950,7 +998,7 @@ const class_box = (parent, node) => {
     
       updateNodeBounds(node, rect);
     
    -  node.intersect = function(point) {
    +  node.intersect = function (point) {
         return intersect.rect(node, point);
       };
     
    @@ -959,6 +1007,7 @@ const class_box = (parent, node) => {
     
     const shapes = {
       rhombus: question,
    +  composite,
       question,
       rect,
       labelRect,
    @@ -1040,10 +1089,10 @@ export const positionNode = (node) => {
         el.attr(
           'transform',
           'translate(' +
    -      (node.x + diff - node.width / 2) +
    -      ', ' +
    -      (node.y - node.height / 2 - padding) +
    -      ')'
    +        (node.x + diff - node.width / 2) +
    +        ', ' +
    +        (node.y - node.height / 2 - padding) +
    +        ')'
         );
       } else {
         el.attr('transform', 'translate(' + node.x + ', ' + node.y + ')');
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index 50af7965fa..2dce9e323e 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -27,7 +27,7 @@ const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
         } else {
           if (!block.label) {
             if (block.type === 'composite') {
    -          block.label = 'x';
    +          block.label = '';
             } else {
               block.label = block.id;
             }
    diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts
    index e008d78827..8756646ef5 100644
    --- a/packages/mermaid/src/diagrams/block/layout.ts
    +++ b/packages/mermaid/src/diagrams/block/layout.ts
    @@ -2,15 +2,17 @@ import { BlockDB } from './blockDB.js';
     import type { Block } from './blockTypes.js';
     
     function calcBlockSizes(block: Block, db: BlockDB) {
    -  let totalWidth = 0;
    -  let totalHeight = 0;
    +  const totalWidth = 0;
    +  const totalHeight = 0;
    +  let maxWidth = 0;
    +  let maxHeight = 0;
    +  const padding = 20;
    +
       if (block.children) {
         for (const child of block.children) {
           calcBlockSizes(child, db);
         }
         // find max width of children
    -    let maxWidth = 0;
    -    let maxHeight = 0;
         for (const child of block.children) {
           const { width, height, x, y } = child.size || { width: 0, height: 0, x: 0, y: 0 };
           if (width > maxWidth) {
    @@ -30,39 +32,41 @@ function calcBlockSizes(block: Block, db: BlockDB) {
         }
     
         // Position items relative to self
    -    let x = 0;
    +    let x = -padding / 2;
         const y = 0;
    -    const padding = 10;
    +
    +    let accumulatedPaddingX = 0;
         for (const child of block.children) {
           if (child.size) {
             child.size.x = x;
             child.size.y = y;
             x += maxWidth + padding;
           }
    -      if (x > totalWidth) {
    -        totalWidth = x;
    -      }
    -      if (y > totalHeight) {
    -        totalHeight = y;
    -      }
    +      accumulatedPaddingX += padding;
         }
       }
       if (block.children?.length > 0) {
    -    block.size = { width: totalWidth, height: totalHeight, x: 0, y: 0 };
    +    const numChildren = block.children.length;
    +    block.size = {
    +      width: numChildren * (maxWidth + padding) + padding,
    +      height: totalHeight + 4 * padding,
    +      x: 0,
    +      y: 0,
    +    };
       }
       console.log('layoutBlock (done)', block);
     }
     
     function positionBlock(parent: Block, block: Block, db: BlockDB) {
       console.log('layout position block', parent.id, parent?.size?.x, block.id, block?.size?.x);
    -  let x = 0;
    +  let parentX = 0;
       let y = 0;
       if (parent) {
    -    x = parent?.size?.x || 0;
    +    parentX = parent?.size?.x || 0;
         y = parent?.size?.y || 0;
       }
    -  if (block.size) {
    -    block.size.x = block.size.x + x - block.size.width / 2;
    +  if (block.size && block.id !== 'root') {
    +    block.size.x = parentX + block.size.x + -block.size.width / 2;
         block.size.y = block.size.y + y;
       }
       if (block.children) {
    @@ -104,9 +108,9 @@ export function layout(db: BlockDB) {
       const blocks = db.getBlocks();
       const root = { id: 'root', type: 'composite', children: blocks } as Block;
       calcBlockSizes(root, db);
    -  console.log('layout getBlocks', db.getBlocks());
       // Position blocks relative to parents
       positionBlock(root, root, db);
    +  console.log('getBlocks', JSON.stringify(db.getBlocks(), null, 2));
     
       minX = 0;
       minY = 0;
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index a17cda607d..5bbe279e7f 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -26,12 +26,17 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
       let radious = 0;
       let _shape = '';
       let layoutOptions = {};
    +  console.log('This is the type:', vertex.type);
       // Set the shape based parameters
       switch (vertex.type) {
         case 'round':
           radious = 5;
           _shape = 'rect';
           break;
    +    case 'composite':
    +      radious = 4;
    +      _shape = 'composite';
    +      break;
         case 'square':
           _shape = 'rect';
           break;
    diff --git a/packages/mermaid/src/diagrams/block/styles.ts b/packages/mermaid/src/diagrams/block/styles.ts
    index a4af4f1283..e1194f0d11 100644
    --- a/packages/mermaid/src/diagrams/block/styles.ts
    +++ b/packages/mermaid/src/diagrams/block/styles.ts
    @@ -42,6 +42,8 @@ const getStyles = (options: FlowChartStyleOptions) =>
         color: ${options.titleColor};
       }
     
    +
    +
       .label text,span,p {
         fill: ${options.nodeTextColor || options.textColor};
         color: ${options.nodeTextColor || options.textColor};
    @@ -103,9 +105,11 @@ const getStyles = (options: FlowChartStyleOptions) =>
         // background-color:
       }
     
    -  .cluster rect {
    -    fill: ${options.clusterBkg};
    -    stroke: ${options.clusterBorder};
    +  .node .cluster {
    +    // fill: ${fade(options.mainBkg, 0.5)};
    +    fill: ${fade(options.clusterBkg, 0.5)};
    +    stroke: ${fade(options.clusterBorder, 0.2)};
    +    box-shadow: rgba(50, 50, 93, 0.25) 0px 13px 27px -5px, rgba(0, 0, 0, 0.3) 0px 8px 16px -8px;
         stroke-width: 1px;
       }
     
    diff --git a/vite.config.ts.timestamp-1696335530501-05072b5e79635.mjs b/vite.config.ts.timestamp-1696335530501-05072b5e79635.mjs
    new file mode 100644
    index 0000000000..e020937df9
    --- /dev/null
    +++ b/vite.config.ts.timestamp-1696335530501-05072b5e79635.mjs
    @@ -0,0 +1,190 @@
    +// .vite/jisonTransformer.ts
    +import jison from "file:///Users/knsv/source/git/mermaid/node_modules/.pnpm/jison@0.4.18/node_modules/jison/lib/jison.js";
    +var transformJison = (src) => {
    +  const parser = new jison.Generator(src, {
    +    moduleType: "js",
    +    "token-stack": true
    +  });
    +  const source = parser.generate({ moduleMain: "() => {}" });
    +  const exporter = `
    +	parser.parser = parser;
    +	export { parser };
    +	export default parser;
    +	`;
    +  return `${source} ${exporter}`;
    +};
    +
    +// .vite/jisonPlugin.ts
    +var fileRegex = /\.(jison)$/;
    +function jison2() {
    +  return {
    +    name: "jison",
    +    transform(src, id) {
    +      if (fileRegex.test(id)) {
    +        return {
    +          code: transformJison(src),
    +          map: null
    +          // provide source map if available
    +        };
    +      }
    +    }
    +  };
    +}
    +
    +// .vite/jsonSchemaPlugin.ts
    +import { load, JSON_SCHEMA } from "file:///Users/knsv/source/git/mermaid/node_modules/.pnpm/js-yaml@4.1.0/node_modules/js-yaml/dist/js-yaml.mjs";
    +import assert from "node:assert";
    +import Ajv2019 from "file:///Users/knsv/source/git/mermaid/node_modules/.pnpm/ajv@8.12.0/node_modules/ajv/dist/2019.js";
    +var MERMAID_CONFIG_DIAGRAM_KEYS = [
    +  "flowchart",
    +  "sequence",
    +  "gantt",
    +  "journey",
    +  "class",
    +  "state",
    +  "er",
    +  "pie",
    +  "quadrantChart",
    +  "requirement",
    +  "mindmap",
    +  "timeline",
    +  "gitGraph",
    +  "c4",
    +  "sankey"
    +];
    +function generateDefaults(mermaidConfigSchema) {
    +  const ajv = new Ajv2019({
    +    useDefaults: true,
    +    allowUnionTypes: true,
    +    strict: true
    +  });
    +  ajv.addKeyword({
    +    keyword: "meta:enum",
    +    // used by jsonschema2md
    +    errors: false
    +  });
    +  ajv.addKeyword({
    +    keyword: "tsType",
    +    // used by json-schema-to-typescript
    +    errors: false
    +  });
    +  const mermaidDefaultConfig = {};
    +  assert.ok(mermaidConfigSchema.$defs);
    +  const baseDiagramConfig = mermaidConfigSchema.$defs.BaseDiagramConfig;
    +  for (const key of MERMAID_CONFIG_DIAGRAM_KEYS) {
    +    const subSchemaRef = mermaidConfigSchema.properties[key].$ref;
    +    const [root, defs, defName] = subSchemaRef.split("/");
    +    assert.strictEqual(root, "#");
    +    assert.strictEqual(defs, "$defs");
    +    const subSchema = {
    +      $schema: mermaidConfigSchema.$schema,
    +      $defs: mermaidConfigSchema.$defs,
    +      ...mermaidConfigSchema.$defs[defName]
    +    };
    +    const validate2 = ajv.compile(subSchema);
    +    mermaidDefaultConfig[key] = {};
    +    for (const required of subSchema.required ?? []) {
    +      if (subSchema.properties[required] === void 0 && baseDiagramConfig.properties[required]) {
    +        mermaidDefaultConfig[key][required] = baseDiagramConfig.properties[required].default;
    +      }
    +    }
    +    if (!validate2(mermaidDefaultConfig[key])) {
    +      throw new Error(
    +        `schema for subconfig ${key} does not have valid defaults! Errors were ${JSON.stringify(
    +          validate2.errors,
    +          void 0,
    +          2
    +        )}`
    +      );
    +    }
    +  }
    +  const validate = ajv.compile(mermaidConfigSchema);
    +  if (!validate(mermaidDefaultConfig)) {
    +    throw new Error(
    +      `Mermaid config JSON Schema does not have valid defaults! Errors were ${JSON.stringify(
    +        validate.errors,
    +        void 0,
    +        2
    +      )}`
    +    );
    +  }
    +  return mermaidDefaultConfig;
    +}
    +function jsonSchemaPlugin() {
    +  return {
    +    name: "json-schema-plugin",
    +    transform(src, id) {
    +      const idAsUrl = new URL(id, "file:///");
    +      if (!idAsUrl.pathname.endsWith("schema.yaml")) {
    +        return;
    +      }
    +      if (idAsUrl.searchParams.get("only-defaults")) {
    +        const jsonSchema = load(src, {
    +          filename: idAsUrl.pathname,
    +          // only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
    +          // e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
    +          schema: JSON_SCHEMA
    +        });
    +        return {
    +          code: `export default ${JSON.stringify(generateDefaults(jsonSchema), void 0, 2)};`,
    +          map: null
    +          // no source map
    +        };
    +      } else {
    +        return {
    +          code: `export default ${JSON.stringify(
    +            load(src, {
    +              filename: idAsUrl.pathname,
    +              // only allow JSON types in our YAML doc (will probably be default in YAML 1.3)
    +              // e.g. `true` will be parsed a boolean `true`, `True` will be parsed as string `"True"`.
    +              schema: JSON_SCHEMA
    +            }),
    +            void 0,
    +            2
    +          )};`,
    +          map: null
    +          // provide source map if available
    +        };
    +      }
    +    }
    +  };
    +}
    +
    +// vite.config.ts
    +import typescript from "file:///Users/knsv/source/git/mermaid/node_modules/.pnpm/@rollup+plugin-typescript@11.1.1_typescript@5.1.3/node_modules/@rollup/plugin-typescript/dist/es/index.js";
    +import { defineConfig } from "file:///Users/knsv/source/git/mermaid/node_modules/.pnpm/vitest@0.33.0_@vitest+ui@0.33.0_jsdom@22.0.0/node_modules/vitest/dist/config.js";
    +var vite_config_default = defineConfig({
    +  resolve: {
    +    extensions: [".js"]
    +  },
    +  plugins: [
    +    jison2(),
    +    jsonSchemaPlugin(),
    +    // handles .schema.yaml JSON Schema files
    +    // @ts-expect-error According to the type definitions, rollup plugins are incompatible with vite
    +    typescript({ compilerOptions: { declaration: false } })
    +  ],
    +  test: {
    +    environment: "jsdom",
    +    globals: true,
    +    // TODO: should we move this to a mermaid-core package?
    +    setupFiles: ["packages/mermaid/src/tests/setup.ts"],
    +    coverage: {
    +      provider: "v8",
    +      reporter: ["text", "json", "html", "lcov"],
    +      reportsDirectory: "./coverage/vitest",
    +      exclude: ["**/node_modules/**", "**/tests/**", "**/__mocks__/**"]
    +    }
    +  },
    +  build: {
    +    /** If you set esmExternals to true, this plugins assumes that
    +     all external dependencies are ES modules */
    +    commonjsOptions: {
    +      esmExternals: true
    +    }
    +  }
    +});
    +export {
    +  vite_config_default as default
    +};
    +//# sourceMappingURL=data:application/json;base64,ewogICJ2ZXJzaW9uIjogMywKICAic291cmNlcyI6IFsiLnZpdGUvamlzb25UcmFuc2Zvcm1lci50cyIsICIudml0ZS9qaXNvblBsdWdpbi50cyIsICIudml0ZS9qc29uU2NoZW1hUGx1Z2luLnRzIiwgInZpdGUuY29uZmlnLnRzIl0sCiAgInNvdXJjZXNDb250ZW50IjogWyJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL1VzZXJzL2tuc3Yvc291cmNlL2dpdC9tZXJtYWlkLy52aXRlXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCIvVXNlcnMva25zdi9zb3VyY2UvZ2l0L21lcm1haWQvLnZpdGUvamlzb25UcmFuc2Zvcm1lci50c1wiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9pbXBvcnRfbWV0YV91cmwgPSBcImZpbGU6Ly8vVXNlcnMva25zdi9zb3VyY2UvZ2l0L21lcm1haWQvLnZpdGUvamlzb25UcmFuc2Zvcm1lci50c1wiO2ltcG9ydCBqaXNvbiBmcm9tICdqaXNvbic7XG5cbmV4cG9ydCBjb25zdCB0cmFuc2Zvcm1KaXNvbiA9IChzcmM6IHN0cmluZyk6IHN0cmluZyA9PiB7XG4gIGNvbnN0IHBhcnNlciA9IG5ldyBqaXNvbi5HZW5lcmF0b3Ioc3JjLCB7XG4gICAgbW9kdWxlVHlwZTogJ2pzJyxcbiAgICAndG9rZW4tc3RhY2snOiB0cnVlLFxuICB9KTtcbiAgY29uc3Qgc291cmNlID0gcGFyc2VyLmdlbmVyYXRlKHsgbW9kdWxlTWFpbjogJygpID0+IHt9JyB9KTtcbiAgY29uc3QgZXhwb3J0ZXIgPSBgXG5cdHBhcnNlci5wYXJzZXIgPSBwYXJzZXI7XG5cdGV4cG9ydCB7IHBhcnNlciB9O1xuXHRleHBvcnQgZGVmYXVsdCBwYXJzZXI7XG5cdGA7XG4gIHJldHVybiBgJHtzb3VyY2V9ICR7ZXhwb3J0ZXJ9YDtcbn07XG4iLCAiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIi9Vc2Vycy9rbnN2L3NvdXJjZS9naXQvbWVybWFpZC8udml0ZVwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL1VzZXJzL2tuc3Yvc291cmNlL2dpdC9tZXJtYWlkLy52aXRlL2ppc29uUGx1Z2luLnRzXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ltcG9ydF9tZXRhX3VybCA9IFwiZmlsZTovLy9Vc2Vycy9rbnN2L3NvdXJjZS9naXQvbWVybWFpZC8udml0ZS9qaXNvblBsdWdpbi50c1wiO2ltcG9ydCB7IHRyYW5zZm9ybUppc29uIH0gZnJvbSAnLi9qaXNvblRyYW5zZm9ybWVyLmpzJztcbmNvbnN0IGZpbGVSZWdleCA9IC9cXC4oamlzb24pJC87XG5cbmV4cG9ydCBkZWZhdWx0IGZ1bmN0aW9uIGppc29uKCkge1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdqaXNvbicsXG5cbiAgICB0cmFuc2Zvcm0oc3JjOiBzdHJpbmcsIGlkOiBzdHJpbmcpIHtcbiAgICAgIGlmIChmaWxlUmVnZXgudGVzdChpZCkpIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjb2RlOiB0cmFuc2Zvcm1KaXNvbihzcmMpLFxuICAgICAgICAgIG1hcDogbnVsbCwgLy8gcHJvdmlkZSBzb3VyY2UgbWFwIGlmIGF2YWlsYWJsZVxuICAgICAgICB9O1xuICAgICAgfVxuICAgIH0sXG4gIH07XG59XG4iLCAiY29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2Rpcm5hbWUgPSBcIi9Vc2Vycy9rbnN2L3NvdXJjZS9naXQvbWVybWFpZC8udml0ZVwiO2NvbnN0IF9fdml0ZV9pbmplY3RlZF9vcmlnaW5hbF9maWxlbmFtZSA9IFwiL1VzZXJzL2tuc3Yvc291cmNlL2dpdC9tZXJtYWlkLy52aXRlL2pzb25TY2hlbWFQbHVnaW4udHNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL1VzZXJzL2tuc3Yvc291cmNlL2dpdC9tZXJtYWlkLy52aXRlL2pzb25TY2hlbWFQbHVnaW4udHNcIjtpbXBvcnQgeyBsb2FkLCBKU09OX1NDSEVNQSB9IGZyb20gJ2pzLXlhbWwnO1xuaW1wb3J0IGFzc2VydCBmcm9tICdub2RlOmFzc2VydCc7XG5pbXBvcnQgQWp2MjAxOSwgeyB0eXBlIEpTT05TY2hlbWFUeXBlIH0gZnJvbSAnYWp2L2Rpc3QvMjAxOS5qcyc7XG5pbXBvcnQgeyBQbHVnaW5PcHRpb24gfSBmcm9tICd2aXRlJztcblxuaW1wb3J0IHR5cGUgeyBNZXJtYWlkQ29uZmlnLCBCYXNlRGlhZ3JhbUNvbmZpZyB9IGZyb20gJy4uL3BhY2thZ2VzL21lcm1haWQvc3JjL2NvbmZpZy50eXBlLmpzJztcblxuLyoqXG4gKiBBbGwgb2YgdGhlIGtleXMgaW4gdGhlIG1lcm1haWQgY29uZmlnIHRoYXQgaGF2ZSBhIG1lcm1haWQgZGlhZ3JhbSBjb25maWcuXG4gKi9cbmNvbnN0IE1FUk1BSURfQ09ORklHX0RJQUdSQU1fS0VZUyA9IFtcbiAgJ2Zsb3djaGFydCcsXG4gICdzZXF1ZW5jZScsXG4gICdnYW50dCcsXG4gICdqb3VybmV5JyxcbiAgJ2NsYXNzJyxcbiAgJ3N0YXRlJyxcbiAgJ2VyJyxcbiAgJ3BpZScsXG4gICdxdWFkcmFudENoYXJ0JyxcbiAgJ3JlcXVpcmVtZW50JyxcbiAgJ21pbmRtYXAnLFxuICAndGltZWxpbmUnLFxuICAnZ2l0R3JhcGgnLFxuICAnYzQnLFxuICAnc2Fua2V5Jyxcbl0gYXMgY29uc3Q7XG5cbi8qKlxuICogR2VuZXJhdGUgZGVmYXVsdCB2YWx1ZXMgZnJvbSB0aGUgSlNPTiBTY2hlbWEuXG4gKlxuICogQUpWIGRvZXMgbm90IHN1cHBvcnQgbmVzdGVkIGRlZmF1bHQgdmFsdWVzIHlldCAob3IgZGVmYXVsdCB2YWx1ZXMgd2l0aCAkcmVmKSxcbiAqIHNvIHdlIG5lZWQgdG8gbWFudWFsbHkgZmluZCB0aGVtICh0aGlzIG1heSBiZSBmaXhlZCBpbiBhanYgdjkpLlxuICpcbiAqIEBwYXJhbSBtZXJtYWlkQ29uZmlnU2NoZW1hIC0gVGhlIE1lcm1haWQgSlNPTiBTY2hlbWEgdG8gdXNlLlxuICogQHJldHVybnMgVGhlIGRlZmF1bHQgbWVybWFpZCBjb25maWcgb2JqZWN0LlxuICovXG5mdW5jdGlvbiBnZW5lcmF0ZURlZmF1bHRzKG1lcm1haWRDb25maWdTY2hlbWE6IEpTT05TY2hlbWFUeXBlPE1lcm1haWRDb25maWc+KSB7XG4gIGNvbnN0IGFqdiA9IG5ldyBBanYyMDE5KHtcbiAgICB1c2VEZWZhdWx0czogdHJ1ZSxcbiAgICBhbGxvd1VuaW9uVHlwZXM6IHRydWUsXG4gICAgc3RyaWN0OiB0cnVlLFxuICB9KTtcblxuICBhanYuYWRkS2V5d29yZCh7XG4gICAga2V5d29yZDogJ21ldGE6ZW51bScsIC8vIHVzZWQgYnkganNvbnNjaGVtYTJtZFxuICAgIGVycm9yczogZmFsc2UsXG4gIH0pO1xuICBhanYuYWRkS2V5d29yZCh7XG4gICAga2V5d29yZDogJ3RzVHlwZScsIC8vIHVzZWQgYnkganNvbi1zY2hlbWEtdG8tdHlwZXNjcmlwdFxuICAgIGVycm9yczogZmFsc2UsXG4gIH0pO1xuXG4gIC8vIGFqdiBjdXJyZW50bHkgZG9lc24ndCBzdXBwb3J0IG5lc3RlZCBkZWZhdWx0IHZhbHVlcywgc2VlIGh0dHBzOi8vZ2l0aHViLmNvbS9hanYtdmFsaWRhdG9yL2Fqdi9pc3N1ZXMvMTcxOFxuICAvLyAobWF5IGJlIGZpeGVkIGluIHY5KSBzbyB3ZSBuZWVkIHRvIG1hbnVhbGx5IHVzZSBzdWItc2NoZW1hc1xuICBjb25zdCBtZXJtYWlkRGVmYXVsdENvbmZpZyA9IHt9O1xuXG4gIGFzc2VydC5vayhtZXJtYWlkQ29uZmlnU2NoZW1hLiRkZWZzKTtcbiAgY29uc3QgYmFzZURpYWdyYW1Db25maWcgPSBtZXJtYWlkQ29uZmlnU2NoZW1hLiRkZWZzLkJhc2VEaWFncmFtQ29uZmlnO1xuXG4gIGZvciAoY29uc3Qga2V5IG9mIE1FUk1BSURfQ09ORklHX0RJQUdSQU1fS0VZUykge1xuICAgIGNvbnN0IHN1YlNjaGVtYVJlZiA9IG1lcm1haWRDb25maWdTY2hlbWEucHJvcGVydGllc1trZXldLiRyZWY7XG4gICAgY29uc3QgW3Jvb3QsIGRlZnMsIGRlZk5hbWVdID0gc3ViU2NoZW1hUmVmLnNwbGl0KCcvJyk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKHJvb3QsICcjJyk7XG4gICAgYXNzZXJ0LnN0cmljdEVxdWFsKGRlZnMsICckZGVmcycpO1xuICAgIGNvbnN0IHN1YlNjaGVtYSA9IHtcbiAgICAgICRzY2hlbWE6IG1lcm1haWRDb25maWdTY2hlbWEuJHNjaGVtYSxcbiAgICAgICRkZWZzOiBtZXJtYWlkQ29uZmlnU2NoZW1hLiRkZWZzLFxuICAgICAgLi4ubWVybWFpZENvbmZpZ1NjaGVtYS4kZGVmc1tkZWZOYW1lXSxcbiAgICB9IGFzIEpTT05TY2hlbWFUeXBlPEJhc2VEaWFncmFtQ29uZmlnPjtcblxuICAgIGNvbnN0IHZhbGlkYXRlID0gYWp2LmNvbXBpbGUoc3ViU2NoZW1hKTtcblxuICAgIG1lcm1haWREZWZhdWx0Q29uZmlnW2tleV0gPSB7fTtcblxuICAgIGZvciAoY29uc3QgcmVxdWlyZWQgb2Ygc3ViU2NoZW1hLnJlcXVpcmVkID8/IFtdKSB7XG4gICAgICBpZiAoc3ViU2NoZW1hLnByb3BlcnRpZXNbcmVxdWlyZWRdID09PSB1bmRlZmluZWQgJiYgYmFzZURpYWdyYW1Db25maWcucHJvcGVydGllc1tyZXF1aXJlZF0pIHtcbiAgICAgICAgbWVybWFpZERlZmF1bHRDb25maWdba2V5XVtyZXF1aXJlZF0gPSBiYXNlRGlhZ3JhbUNvbmZpZy5wcm9wZXJ0aWVzW3JlcXVpcmVkXS5kZWZhdWx0O1xuICAgICAgfVxuICAgIH1cbiAgICBpZiAoIXZhbGlkYXRlKG1lcm1haWREZWZhdWx0Q29uZmlnW2tleV0pKSB7XG4gICAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICAgIGBzY2hlbWEgZm9yIHN1YmNvbmZpZyAke2tleX0gZG9lcyBub3QgaGF2ZSB2YWxpZCBkZWZhdWx0cyEgRXJyb3JzIHdlcmUgJHtKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICB2YWxpZGF0ZS5lcnJvcnMsXG4gICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgIDJcbiAgICAgICAgKX1gXG4gICAgICApO1xuICAgIH1cbiAgfVxuXG4gIGNvbnN0IHZhbGlkYXRlID0gYWp2LmNvbXBpbGUobWVybWFpZENvbmZpZ1NjaGVtYSk7XG5cbiAgaWYgKCF2YWxpZGF0ZShtZXJtYWlkRGVmYXVsdENvbmZpZykpIHtcbiAgICB0aHJvdyBuZXcgRXJyb3IoXG4gICAgICBgTWVybWFpZCBjb25maWcgSlNPTiBTY2hlbWEgZG9lcyBub3QgaGF2ZSB2YWxpZCBkZWZhdWx0cyEgRXJyb3JzIHdlcmUgJHtKU09OLnN0cmluZ2lmeShcbiAgICAgICAgdmFsaWRhdGUuZXJyb3JzLFxuICAgICAgICB1bmRlZmluZWQsXG4gICAgICAgIDJcbiAgICAgICl9YFxuICAgICk7XG4gIH1cblxuICByZXR1cm4gbWVybWFpZERlZmF1bHRDb25maWc7XG59XG5cbi8qKlxuICogVml0ZSBwbHVnaW4gdGhhdCBoYW5kbGVzIEpTT04gU2NoZW1hcyBzYXZlZCBhcyBhIGAuc2NoZW1hLnlhbWxgIGZpbGUuXG4gKlxuICogVXNlIGBteS1leGFtcGxlLnNjaGVtYS55YW1sP29ubHktZGVmYXVsdHM9dHJ1ZWAgdG8gb25seSBsb2FkIHRoZSBkZWZhdWx0IHZhbHVlcy5cbiAqL1xuZXhwb3J0IGRlZmF1bHQgZnVuY3Rpb24ganNvblNjaGVtYVBsdWdpbigpOiBQbHVnaW5PcHRpb24ge1xuICByZXR1cm4ge1xuICAgIG5hbWU6ICdqc29uLXNjaGVtYS1wbHVnaW4nLFxuICAgIHRyYW5zZm9ybShzcmM6IHN0cmluZywgaWQ6IHN0cmluZykge1xuICAgICAgY29uc3QgaWRBc1VybCA9IG5ldyBVUkwoaWQsICdmaWxlOi8vLycpO1xuXG4gICAgICBpZiAoIWlkQXNVcmwucGF0aG5hbWUuZW5kc1dpdGgoJ3NjaGVtYS55YW1sJykpIHtcbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICBpZiAoaWRBc1VybC5zZWFyY2hQYXJhbXMuZ2V0KCdvbmx5LWRlZmF1bHRzJykpIHtcbiAgICAgICAgY29uc3QganNvblNjaGVtYSA9IGxvYWQoc3JjLCB7XG4gICAgICAgICAgZmlsZW5hbWU6IGlkQXNVcmwucGF0aG5hbWUsXG4gICAgICAgICAgLy8gb25seSBhbGxvdyBKU09OIHR5cGVzIGluIG91ciBZQU1MIGRvYyAod2lsbCBwcm9iYWJseSBiZSBkZWZhdWx0IGluIFlBTUwgMS4zKVxuICAgICAgICAgIC8vIGUuZy4gYHRydWVgIHdpbGwgYmUgcGFyc2VkIGEgYm9vbGVhbiBgdHJ1ZWAsIGBUcnVlYCB3aWxsIGJlIHBhcnNlZCBhcyBzdHJpbmcgYFwiVHJ1ZVwiYC5cbiAgICAgICAgICBzY2hlbWE6IEpTT05fU0NIRU1BLFxuICAgICAgICB9KSBhcyBKU09OU2NoZW1hVHlwZTxNZXJtYWlkQ29uZmlnPjtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjb2RlOiBgZXhwb3J0IGRlZmF1bHQgJHtKU09OLnN0cmluZ2lmeShnZW5lcmF0ZURlZmF1bHRzKGpzb25TY2hlbWEpLCB1bmRlZmluZWQsIDIpfTtgLFxuICAgICAgICAgIG1hcDogbnVsbCwgLy8gbm8gc291cmNlIG1hcFxuICAgICAgICB9O1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgcmV0dXJuIHtcbiAgICAgICAgICBjb2RlOiBgZXhwb3J0IGRlZmF1bHQgJHtKU09OLnN0cmluZ2lmeShcbiAgICAgICAgICAgIGxvYWQoc3JjLCB7XG4gICAgICAgICAgICAgIGZpbGVuYW1lOiBpZEFzVXJsLnBhdGhuYW1lLFxuICAgICAgICAgICAgICAvLyBvbmx5IGFsbG93IEpTT04gdHlwZXMgaW4gb3VyIFlBTUwgZG9jICh3aWxsIHByb2JhYmx5IGJlIGRlZmF1bHQgaW4gWUFNTCAxLjMpXG4gICAgICAgICAgICAgIC8vIGUuZy4gYHRydWVgIHdpbGwgYmUgcGFyc2VkIGEgYm9vbGVhbiBgdHJ1ZWAsIGBUcnVlYCB3aWxsIGJlIHBhcnNlZCBhcyBzdHJpbmcgYFwiVHJ1ZVwiYC5cbiAgICAgICAgICAgICAgc2NoZW1hOiBKU09OX1NDSEVNQSxcbiAgICAgICAgICAgIH0pLFxuICAgICAgICAgICAgdW5kZWZpbmVkLFxuICAgICAgICAgICAgMlxuICAgICAgICAgICl9O2AsXG4gICAgICAgICAgbWFwOiBudWxsLCAvLyBwcm92aWRlIHNvdXJjZSBtYXAgaWYgYXZhaWxhYmxlXG4gICAgICAgIH07XG4gICAgICB9XG4gICAgfSxcbiAgfTtcbn1cbiIsICJjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfZGlybmFtZSA9IFwiL1VzZXJzL2tuc3Yvc291cmNlL2dpdC9tZXJtYWlkXCI7Y29uc3QgX192aXRlX2luamVjdGVkX29yaWdpbmFsX2ZpbGVuYW1lID0gXCIvVXNlcnMva25zdi9zb3VyY2UvZ2l0L21lcm1haWQvdml0ZS5jb25maWcudHNcIjtjb25zdCBfX3ZpdGVfaW5qZWN0ZWRfb3JpZ2luYWxfaW1wb3J0X21ldGFfdXJsID0gXCJmaWxlOi8vL1VzZXJzL2tuc3Yvc291cmNlL2dpdC9tZXJtYWlkL3ZpdGUuY29uZmlnLnRzXCI7aW1wb3J0IGppc29uIGZyb20gJy4vLnZpdGUvamlzb25QbHVnaW4uanMnO1xuaW1wb3J0IGpzb25TY2hlbWFQbHVnaW4gZnJvbSAnLi8udml0ZS9qc29uU2NoZW1hUGx1Z2luLmpzJztcbmltcG9ydCB0eXBlc2NyaXB0IGZyb20gJ0Byb2xsdXAvcGx1Z2luLXR5cGVzY3JpcHQnO1xuaW1wb3J0IHsgZGVmaW5lQ29uZmlnIH0gZnJvbSAndml0ZXN0L2NvbmZpZyc7XG5cbmV4cG9ydCBkZWZhdWx0IGRlZmluZUNvbmZpZyh7XG4gIHJlc29sdmU6IHtcbiAgICBleHRlbnNpb25zOiBbJy5qcyddLFxuICB9LFxuICBwbHVnaW5zOiBbXG4gICAgamlzb24oKSxcbiAgICBqc29uU2NoZW1hUGx1Z2luKCksIC8vIGhhbmRsZXMgLnNjaGVtYS55YW1sIEpTT04gU2NoZW1hIGZpbGVzXG4gICAgLy8gQHRzLWV4cGVjdC1lcnJvciBBY2NvcmRpbmcgdG8gdGhlIHR5cGUgZGVmaW5pdGlvbnMsIHJvbGx1cCBwbHVnaW5zIGFyZSBpbmNvbXBhdGlibGUgd2l0aCB2aXRlXG4gICAgdHlwZXNjcmlwdCh7IGNvbXBpbGVyT3B0aW9uczogeyBkZWNsYXJhdGlvbjogZmFsc2UgfSB9KSxcbiAgXSxcbiAgdGVzdDoge1xuICAgIGVudmlyb25tZW50OiAnanNkb20nLFxuICAgIGdsb2JhbHM6IHRydWUsXG4gICAgLy8gVE9ETzogc2hvdWxkIHdlIG1vdmUgdGhpcyB0byBhIG1lcm1haWQtY29yZSBwYWNrYWdlP1xuICAgIHNldHVwRmlsZXM6IFsncGFja2FnZXMvbWVybWFpZC9zcmMvdGVzdHMvc2V0dXAudHMnXSxcbiAgICBjb3ZlcmFnZToge1xuICAgICAgcHJvdmlkZXI6ICd2OCcsXG4gICAgICByZXBvcnRlcjogWyd0ZXh0JywgJ2pzb24nLCAnaHRtbCcsICdsY292J10sXG4gICAgICByZXBvcnRzRGlyZWN0b3J5OiAnLi9jb3ZlcmFnZS92aXRlc3QnLFxuICAgICAgZXhjbHVkZTogWycqKi9ub2RlX21vZHVsZXMvKionLCAnKiovdGVzdHMvKionLCAnKiovX19tb2Nrc19fLyoqJ10sXG4gICAgfSxcbiAgfSxcbiAgYnVpbGQ6IHtcbiAgICAvKiogSWYgeW91IHNldCBlc21FeHRlcm5hbHMgdG8gdHJ1ZSwgdGhpcyBwbHVnaW5zIGFzc3VtZXMgdGhhdFxuICAgICBhbGwgZXh0ZXJuYWwgZGVwZW5kZW5jaWVzIGFyZSBFUyBtb2R1bGVzICovXG5cbiAgICBjb21tb25qc09wdGlvbnM6IHtcbiAgICAgIGVzbUV4dGVybmFsczogdHJ1ZSxcbiAgICB9LFxuICB9LFxufSk7XG4iXSwKICAibWFwcGluZ3MiOiAiO0FBQXdTLE9BQU8sV0FBVztBQUVuVCxJQUFNLGlCQUFpQixDQUFDLFFBQXdCO0FBQ3JELFFBQU0sU0FBUyxJQUFJLE1BQU0sVUFBVSxLQUFLO0FBQUEsSUFDdEMsWUFBWTtBQUFBLElBQ1osZUFBZTtBQUFBLEVBQ2pCLENBQUM7QUFDRCxRQUFNLFNBQVMsT0FBTyxTQUFTLEVBQUUsWUFBWSxXQUFXLENBQUM7QUFDekQsUUFBTSxXQUFXO0FBQUE7QUFBQTtBQUFBO0FBQUE7QUFLakIsU0FBTyxHQUFHLFVBQVU7QUFDdEI7OztBQ2JBLElBQU0sWUFBWTtBQUVILFNBQVJBLFNBQXlCO0FBQzlCLFNBQU87QUFBQSxJQUNMLE1BQU07QUFBQSxJQUVOLFVBQVUsS0FBYSxJQUFZO0FBQ2pDLFVBQUksVUFBVSxLQUFLLEVBQUUsR0FBRztBQUN0QixlQUFPO0FBQUEsVUFDTCxNQUFNLGVBQWUsR0FBRztBQUFBLFVBQ3hCLEtBQUs7QUFBQTtBQUFBLFFBQ1A7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFDRjs7O0FDaEJ3UyxTQUFTLE1BQU0sbUJBQW1CO0FBQzFVLE9BQU8sWUFBWTtBQUNuQixPQUFPLGFBQXNDO0FBUTdDLElBQU0sOEJBQThCO0FBQUEsRUFDbEM7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUFBLEVBQ0E7QUFBQSxFQUNBO0FBQUEsRUFDQTtBQUNGO0FBV0EsU0FBUyxpQkFBaUIscUJBQW9EO0FBQzVFLFFBQU0sTUFBTSxJQUFJLFFBQVE7QUFBQSxJQUN0QixhQUFhO0FBQUEsSUFDYixpQkFBaUI7QUFBQSxJQUNqQixRQUFRO0FBQUEsRUFDVixDQUFDO0FBRUQsTUFBSSxXQUFXO0FBQUEsSUFDYixTQUFTO0FBQUE7QUFBQSxJQUNULFFBQVE7QUFBQSxFQUNWLENBQUM7QUFDRCxNQUFJLFdBQVc7QUFBQSxJQUNiLFNBQVM7QUFBQTtBQUFBLElBQ1QsUUFBUTtBQUFBLEVBQ1YsQ0FBQztBQUlELFFBQU0sdUJBQXVCLENBQUM7QUFFOUIsU0FBTyxHQUFHLG9CQUFvQixLQUFLO0FBQ25DLFFBQU0sb0JBQW9CLG9CQUFvQixNQUFNO0FBRXBELGFBQVcsT0FBTyw2QkFBNkI7QUFDN0MsVUFBTSxlQUFlLG9CQUFvQixXQUFXLEdBQUcsRUFBRTtBQUN6RCxVQUFNLENBQUMsTUFBTSxNQUFNLE9BQU8sSUFBSSxhQUFhLE1BQU0sR0FBRztBQUNwRCxXQUFPLFlBQVksTUFBTSxHQUFHO0FBQzVCLFdBQU8sWUFBWSxNQUFNLE9BQU87QUFDaEMsVUFBTSxZQUFZO0FBQUEsTUFDaEIsU0FBUyxvQkFBb0I7QUFBQSxNQUM3QixPQUFPLG9CQUFvQjtBQUFBLE1BQzNCLEdBQUcsb0JBQW9CLE1BQU0sT0FBTztBQUFBLElBQ3RDO0FBRUEsVUFBTUMsWUFBVyxJQUFJLFFBQVEsU0FBUztBQUV0Qyx5QkFBcUIsR0FBRyxJQUFJLENBQUM7QUFFN0IsZUFBVyxZQUFZLFVBQVUsWUFBWSxDQUFDLEdBQUc7QUFDL0MsVUFBSSxVQUFVLFdBQVcsUUFBUSxNQUFNLFVBQWEsa0JBQWtCLFdBQVcsUUFBUSxHQUFHO0FBQzFGLDZCQUFxQixHQUFHLEVBQUUsUUFBUSxJQUFJLGtCQUFrQixXQUFXLFFBQVEsRUFBRTtBQUFBLE1BQy9FO0FBQUEsSUFDRjtBQUNBLFFBQUksQ0FBQ0EsVUFBUyxxQkFBcUIsR0FBRyxDQUFDLEdBQUc7QUFDeEMsWUFBTSxJQUFJO0FBQUEsUUFDUix3QkFBd0IsaURBQWlELEtBQUs7QUFBQSxVQUM1RUEsVUFBUztBQUFBLFVBQ1Q7QUFBQSxVQUNBO0FBQUEsUUFDRjtBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUVBLFFBQU0sV0FBVyxJQUFJLFFBQVEsbUJBQW1CO0FBRWhELE1BQUksQ0FBQyxTQUFTLG9CQUFvQixHQUFHO0FBQ25DLFVBQU0sSUFBSTtBQUFBLE1BQ1Isd0VBQXdFLEtBQUs7QUFBQSxRQUMzRSxTQUFTO0FBQUEsUUFDVDtBQUFBLFFBQ0E7QUFBQSxNQUNGO0FBQUEsSUFDRjtBQUFBLEVBQ0Y7QUFFQSxTQUFPO0FBQ1Q7QUFPZSxTQUFSLG1CQUFrRDtBQUN2RCxTQUFPO0FBQUEsSUFDTCxNQUFNO0FBQUEsSUFDTixVQUFVLEtBQWEsSUFBWTtBQUNqQyxZQUFNLFVBQVUsSUFBSSxJQUFJLElBQUksVUFBVTtBQUV0QyxVQUFJLENBQUMsUUFBUSxTQUFTLFNBQVMsYUFBYSxHQUFHO0FBQzdDO0FBQUEsTUFDRjtBQUVBLFVBQUksUUFBUSxhQUFhLElBQUksZUFBZSxHQUFHO0FBQzdDLGNBQU0sYUFBYSxLQUFLLEtBQUs7QUFBQSxVQUMzQixVQUFVLFFBQVE7QUFBQTtBQUFBO0FBQUEsVUFHbEIsUUFBUTtBQUFBLFFBQ1YsQ0FBQztBQUNELGVBQU87QUFBQSxVQUNMLE1BQU0sa0JBQWtCLEtBQUssVUFBVSxpQkFBaUIsVUFBVSxHQUFHLFFBQVcsQ0FBQztBQUFBLFVBQ2pGLEtBQUs7QUFBQTtBQUFBLFFBQ1A7QUFBQSxNQUNGLE9BQU87QUFDTCxlQUFPO0FBQUEsVUFDTCxNQUFNLGtCQUFrQixLQUFLO0FBQUEsWUFDM0IsS0FBSyxLQUFLO0FBQUEsY0FDUixVQUFVLFFBQVE7QUFBQTtBQUFBO0FBQUEsY0FHbEIsUUFBUTtBQUFBLFlBQ1YsQ0FBQztBQUFBLFlBQ0Q7QUFBQSxZQUNBO0FBQUEsVUFDRjtBQUFBLFVBQ0EsS0FBSztBQUFBO0FBQUEsUUFDUDtBQUFBLE1BQ0Y7QUFBQSxJQUNGO0FBQUEsRUFDRjtBQUNGOzs7QUNuSkEsT0FBTyxnQkFBZ0I7QUFDdkIsU0FBUyxvQkFBb0I7QUFFN0IsSUFBTyxzQkFBUSxhQUFhO0FBQUEsRUFDMUIsU0FBUztBQUFBLElBQ1AsWUFBWSxDQUFDLEtBQUs7QUFBQSxFQUNwQjtBQUFBLEVBQ0EsU0FBUztBQUFBLElBQ1BDLE9BQU07QUFBQSxJQUNOLGlCQUFpQjtBQUFBO0FBQUE7QUFBQSxJQUVqQixXQUFXLEVBQUUsaUJBQWlCLEVBQUUsYUFBYSxNQUFNLEVBQUUsQ0FBQztBQUFBLEVBQ3hEO0FBQUEsRUFDQSxNQUFNO0FBQUEsSUFDSixhQUFhO0FBQUEsSUFDYixTQUFTO0FBQUE7QUFBQSxJQUVULFlBQVksQ0FBQyxxQ0FBcUM7QUFBQSxJQUNsRCxVQUFVO0FBQUEsTUFDUixVQUFVO0FBQUEsTUFDVixVQUFVLENBQUMsUUFBUSxRQUFRLFFBQVEsTUFBTTtBQUFBLE1BQ3pDLGtCQUFrQjtBQUFBLE1BQ2xCLFNBQVMsQ0FBQyxzQkFBc0IsZUFBZSxpQkFBaUI7QUFBQSxJQUNsRTtBQUFBLEVBQ0Y7QUFBQSxFQUNBLE9BQU87QUFBQTtBQUFBO0FBQUEsSUFJTCxpQkFBaUI7QUFBQSxNQUNmLGNBQWM7QUFBQSxJQUNoQjtBQUFBLEVBQ0Y7QUFDRixDQUFDOyIsCiAgIm5hbWVzIjogWyJqaXNvbiIsICJ2YWxpZGF0ZSIsICJqaXNvbiJdCn0K
    
    From c8d155c455d95e28ee55b4a9913a8a9125f49139 Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Tue, 3 Oct 2023 20:12:33 +0200
    Subject: [PATCH 19/97] #3358 Recursive positioning
    
    ---
     cypress/platform/knsv2.html                   |  27 +++-
     packages/mermaid/src/diagrams/block/layout.ts | 116 +++++++++++++++---
     2 files changed, 118 insertions(+), 25 deletions(-)
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index 6e69533eb6..205db1c78d 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -65,8 +65,8 @@
       
         
     block-beta
    -  %% id1("Wide 1")
    -  id2("2")
    +  id1("Wide 1")
    +  %%id2("2")
       block
           id3["I am a wide one"]
           block
    @@ -79,9 +79,26 @@
         
     block-beta
    -
    -      id3["I am a wide one"]
    -      id4
    +  id1
    +  block
    +  id2
    +  end
    +    
    +
    +block-beta
    +  id1["Hello"]
    +  block
    +    id2["to"]
    +    id3["the"]
    +    id4["World"]
    +  end
    +    
    +
    +block-beta
    +  block
    +    id2["I am a wide one"]
    +    id1
    +  end
     
     
         
    diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts index 8756646ef5..31810693b6 100644 --- a/packages/mermaid/src/diagrams/block/layout.ts +++ b/packages/mermaid/src/diagrams/block/layout.ts @@ -1,12 +1,14 @@ import { BlockDB } from './blockDB.js'; import type { Block } from './blockTypes.js'; +const padding = 10; + function calcBlockSizes(block: Block, db: BlockDB) { + console.log('calculateSize (start)', block.id, block?.size?.x, block?.size?.width); const totalWidth = 0; const totalHeight = 0; let maxWidth = 0; let maxHeight = 0; - const padding = 20; if (block.children) { for (const child of block.children) { @@ -15,6 +17,7 @@ function calcBlockSizes(block: Block, db: BlockDB) { // find max width of children for (const child of block.children) { const { width, height, x, y } = child.size || { width: 0, height: 0, x: 0, y: 0 }; + // console.log('APA', child.id, width, height, x, y); if (width > maxWidth) { maxWidth = width; } @@ -28,22 +31,24 @@ function calcBlockSizes(block: Block, db: BlockDB) { if (child.size) { child.size.width = maxWidth; child.size.height = maxHeight; + child.size.x = 0; + child.size.y = 0; } } - // Position items relative to self - let x = -padding / 2; - const y = 0; + // // Position items relative to self + // let x = -padding / 2; + // const y = 0; - let accumulatedPaddingX = 0; - for (const child of block.children) { - if (child.size) { - child.size.x = x; - child.size.y = y; - x += maxWidth + padding; - } - accumulatedPaddingX += padding; - } + // let accumulatedPaddingX = 0; + // for (const child of block.children) { + // if (child.size) { + // child.size.x = x; + // child.size.y = y; + // x += maxWidth + padding; + // } + // accumulatedPaddingX += padding; + // } } if (block.children?.length > 0) { const numChildren = block.children.length; @@ -54,19 +59,88 @@ function calcBlockSizes(block: Block, db: BlockDB) { y: 0, }; } - console.log('layoutBlock (done)', block); + console.log('calculateSize APA (done)', block.id, block.size.x, block.size.width); +} + +function layoutBlocks(block: Block, db: BlockDB) { + console.log('layout blocks (block)', block.id, 'x:', block.size.x, 'width:', block.size.width); + if ( + block.children && // find max width of children + block.children.length > 0 + ) { + const width = block?.children[0]?.size?.width || 0; + const widthOfChildren = block.children.length * width + (block.children.length - 1) * padding; + let posX = (block?.size?.x || 0) - widthOfChildren / 2; + const posY = 0; + const parentX = block?.size?.x || 0 - block.children.length; + const parentWidth = block?.size?.width || 0; + + console.log('widthOfChildren', widthOfChildren, 'posX', posX, 'parentX', parentX); + + // let first = true; + for (const child of block.children) { + console.log( + 'layout blocks (child)', + child.id, + 'x:', + child?.size?.x, + 'width:', + child?.size?.width, + 'posX:', + posX, + block?.size?.x, + widthOfChildren / 2, + widthOfChildren / 2 + ); + + if (!child.size) { + continue; + } + const { width, height } = child.size; + child.size.x = posX + width / 2; + posX += width + padding; + child.size.y = posY; + // posY += height + padding; + if (child.children) { + layoutBlocks(child, db); + } + } + } } function positionBlock(parent: Block, block: Block, db: BlockDB) { - console.log('layout position block', parent.id, parent?.size?.x, block.id, block?.size?.x); + console.log( + 'layout position block', + parent.id, + parent?.size?.x, + block.id, + block?.size?.x, + 'width:', + block?.size?.width + ); let parentX = 0; + let parentWidth = 0; let y = 0; - if (parent) { + if (parent.id !== 'root') { parentX = parent?.size?.x || 0; + parentWidth = parent?.size?.width || 0; y = parent?.size?.y || 0; } if (block.size && block.id !== 'root') { - block.size.x = parentX + block.size.x + -block.size.width / 2; + console.log( + 'layout position block (calc)', + 'x:', + parentX, + parentWidth / 2, + block.id, + 'x:', + block.size.x, + block.size.width + ); + // block.size.x = parentX + block.size.x + -block.size.width / 2; + block.size.x = + parentX < 0 ? parentX + block.size.x : parentX + block.size.x + -block.size.width / 2; + // block.size.x = parentX - parentWidth + Math.abs(block.size.x) / 2; block.size.y = block.size.y + y; } if (block.children) { @@ -82,10 +156,11 @@ let maxX = 0; let maxY = 0; function findBounds(block: Block) { - if (block.size) { + if (block.size && block.id !== 'root') { const { x, y, width, height } = block.size; if (x - width / 2 < minX) { minX = x - width / 2; + // console.log('Here APA minX', block.id, x, width, minX); } if (y - height / 2 < minY) { minY = y - height / 2; @@ -108,8 +183,9 @@ export function layout(db: BlockDB) { const blocks = db.getBlocks(); const root = { id: 'root', type: 'composite', children: blocks } as Block; calcBlockSizes(root, db); + layoutBlocks(root, db); // Position blocks relative to parents - positionBlock(root, root, db); + // positionBlock(root, root, db); console.log('getBlocks', JSON.stringify(db.getBlocks(), null, 2)); minX = 0; @@ -117,7 +193,7 @@ export function layout(db: BlockDB) { maxX = 0; maxY = 0; findBounds(root); - console.log('Here maxX', maxX); + // console.log('Here maxX', minX, '--', maxX); const height = maxY - minY; const width = maxX - minX; return { x: minX, y: minY, width, height }; From da79b371fe1d45a36637dec21d2ab3781079b6d8 Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Wed, 4 Oct 2023 10:44:29 +0200 Subject: [PATCH 20/97] #3358 Recursive positioning paddings --- cypress/platform/knsv2.html | 7 ++++++- packages/mermaid/src/diagrams/block/layout.ts | 2 +- 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index 205db1c78d..fb68469a57 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -77,6 +77,7 @@ id4("Another final one")
    +
     block-beta
       id1
    @@ -88,17 +89,21 @@
     block-beta
       id1["Hello"]
       block
    +    columns 2
         id2["to"]
         id3["the"]
         id4["World"]
    +    id5["World"]
       end
         
    -
    +    
     block-beta
    +  columns 2
       block
         id2["I am a wide one"]
         id1
       end
    +  id[Next row]
     
     
         
    diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts index 31810693b6..9c9b1bd7e9 100644 --- a/packages/mermaid/src/diagrams/block/layout.ts +++ b/packages/mermaid/src/diagrams/block/layout.ts @@ -54,7 +54,7 @@ function calcBlockSizes(block: Block, db: BlockDB) { const numChildren = block.children.length; block.size = { width: numChildren * (maxWidth + padding) + padding, - height: totalHeight + 4 * padding, + height: maxHeight + 2 * padding, x: 0, y: 0, }; From a641fd51e8c06ba313dd4272ea6a799b9ed0f49a Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Sun, 15 Oct 2023 22:21:25 +0200 Subject: [PATCH 21/97] #3358 Adding support for column statements --- cypress/platform/knsv2.html | 59 +++-- .../mermaid/src/diagrams/block/blockDB.ts | 13 +- .../src/diagrams/block/blockRenderer.ts | 119 ++-------- .../mermaid/src/diagrams/block/blockTypes.ts | 1 + .../mermaid/src/diagrams/block/layout.spec.ts | 13 ++ packages/mermaid/src/diagrams/block/layout.ts | 203 ++++++++++++------ .../src/diagrams/block/renderHelpers.ts | 23 +- 7 files changed, 223 insertions(+), 208 deletions(-) create mode 100644 packages/mermaid/src/diagrams/block/layout.spec.ts diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index fb68469a57..0325eb659e 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -65,27 +65,62 @@
     block-beta
    -  id1("Wide 1")
    -  %%id2("2")
       block
    -      id3["I am a wide one"]
    -      block
    -        id44("A final one")
    -        id45("B final one")
    -      end
    +  columns 1
    +    id1
    +    id2
    +    id3("Wider then")
       end
    -  id4("Another final one")
    -
    +  id4
         
    -
    +    
    +block-beta
    +  block
    +  columns 1
    +  block
    +    columns 3
    +    id1
    +    id2
    +    id2.1
    +    %%id2.2
    +  end
    +  id48
    +  end
    +  id3
    +%%  id3
    +%%  id4
    +  %% block
    +    %% columns 2
    +    %% id2
    +    %% id3
    +  %% end
    +    
    +
    +block-beta
    +  block
    +    columns 1
    +    id1
    +    id2
    +    %%id2.1
    +  end
    +  id3
    +%%  id3
    +%%  id4
    +  %% block
    +    %% columns 2
    +    %% id2
    +    %% id3
    +  %% end
    +    
    +
     block-beta
       id1
       block
       id2
       end
         
    -
    +    
     block-beta
       id1["Hello"]
       block
    @@ -96,7 +131,7 @@
         id5["World"]
       end
         
    -
    +    
     block-beta
       columns 2
       block
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index 2dce9e323e..f9578a4e78 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -1,9 +1,8 @@
     // import type { BlockDB } from './blockTypes.js';
     import type { DiagramDB } from '../../diagram-api/types.js';
    -import { BlockConfig, BlockType, Block, Link } from './blockTypes.js';
    +import type { BlockConfig, BlockType, Block, Link } from './blockTypes.js';
     
     import * as configApi from '../../config.js';
    -// import common from '../common/common.js';
     import {
       // setAccTitle,
       // getAccTitle,
    @@ -37,9 +36,8 @@ const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
           if (block.children) {
             populateBlockDatabase(block.children, block);
           }
    -      if (block.type !== 'column-setting') {
    -        children.push(block);
    -      }
    +
    +      children.push(block);
         }
       }
       parent.children = children;
    @@ -79,9 +77,10 @@ export const generateId = () => {
     
     type ISetHierarchy = (block: Block[]) => void;
     const setHierarchy = (block: Block[]): void => {
    +  rootBlock.children = block;
       populateBlockDatabase(block, rootBlock);
    -  log.debug('The hierarchy', JSON.stringify(block, null, 2));
    -  blocks = block;
    +  log.debug('The hierarchy', JSON.stringify(rootBlock, null, 2));
    +  blocks = rootBlock.children;
     };
     
     type IAddLink = (link: Link) => Link;
    diff --git a/packages/mermaid/src/diagrams/block/blockRenderer.ts b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    index a8bf1fe49a..2b691358cc 100644
    --- a/packages/mermaid/src/diagrams/block/blockRenderer.ts
    +++ b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    @@ -7,16 +7,14 @@ import {
       select as d3select,
       scaleOrdinal as d3scaleOrdinal,
       schemeTableau10 as d3schemeTableau10,
    -  ContainerElement,
     } from 'd3';
    +import { log } from '../../logger.js';
     
     import { BlockDB } from './blockDB.js';
     import type { Block } from './blockTypes.js';
     
     // import { diagram as BlockDiagram } from './blockDiagram.js';
     import { configureSvgSize } from '../../setupGraphViewbox.js';
    -import { Uid } from '../../rendering-util/uid.js';
    -import { pad } from 'lodash';
     
     export const draw = async function (
       text: string,
    @@ -43,27 +41,28 @@ export const draw = async function (
       const nodes = svg.insert('g').attr('class', 'block');
       await calculateBlockSizes(nodes, bl, db);
       const bounds = layout(db);
    -  console.log('Here blocks', bl);
    +  log.debug('Here blocks', bl);
       await insertBlocks(nodes, bl, db);
     
    -  // console.log('Here', bl);
    +  // log.debug('Here', bl);
     
       // Establish svg dimensions and get width and height
       //
       // const bounds2 = nodes.node().getBoundingClientRect();
    -  const bounds2 = bounds;
    -  const padding = 10;
       // Why, oh why ????
    -  const magicFactor = Math.max(1, Math.round(0.125 * (bounds2.width / bounds2.height)));
    -  const height = bounds2.height + magicFactor + 10;
    -  const width = bounds2.width + 10;
    -  const useMaxWidth = false;
    -  configureSvgSize(svg, height, width, useMaxWidth);
    -  console.log('Here Bounds', bounds, bounds2);
    -  svg.attr(
    -    'viewBox',
    -    `${bounds2.x - 5} ${bounds2.y - 5} ${bounds2.width + 10} ${bounds2.height + 10}`
    -  );
    +  if (bounds) {
    +    const bounds2 = bounds;
    +    const magicFactor = Math.max(1, Math.round(0.125 * (bounds2.width / bounds2.height)));
    +    const height = bounds2.height + magicFactor + 10;
    +    const width = bounds2.width + 10;
    +    const useMaxWidth = false;
    +    configureSvgSize(svg, height, width, useMaxWidth);
    +    log.debug('Here Bounds', bounds, bounds2);
    +    svg.attr(
    +      'viewBox',
    +      `${bounds2.x - 5} ${bounds2.y - 5} ${bounds2.width + 10} ${bounds2.height + 10}`
    +    );
    +  }
       // svg.attr('viewBox', `${-200} ${-200} ${400} ${400}`);
     
       // Prepare data for construction based on diagObj.db
    @@ -83,92 +82,6 @@ export const draw = async function (
         y?: number;
       }
     
    -  const blocks: LayedBlock[] = [
    -    {
    -      ID: 'ApplicationLayer',
    -      label: 'Application Layer',
    -      x: 0,
    -      y: 0,
    -      children: [
    -        {
    -          ID: 'UserInterface',
    -          label: 'User Interface (WPF, HTML5/CSS3, Swing)',
    -          x: 0,
    -          y: 50,
    -        },
    -      ],
    -    },
    -    {
    -      ID: 'PresentationLayer',
    -      label: 'Presentation Layer',
    -      x: 0,
    -      y: 50,
    -      children: [
    -        {
    -          ID: 'Smack',
    -          label: 'J2SE Mobil App (Smack)',
    -        },
    -        {
    -          ID: 'JsJAC',
    -          label: 'Java Script Browser App (JsJAC)',
    -        },
    -        {
    -          ID: 'babelim',
    -          label: '.NET Windows App (Babel-im)',
    -        },
    -      ],
    -    },
    -    {
    -      ID: 'SessionLayer',
    -      label: 'Session Layer',
    -      x: 0,
    -      y: 100,
    -      children: [
    -        {
    -          ID: 'XMPP',
    -          label: 'XMPP Component',
    -        },
    -        {
    -          children: [
    -            {
    -              ID: 'Authentication',
    -              label: 'Authentication',
    -            },
    -            {
    -              ID: 'Authorization',
    -              label: 'Authorization',
    -            },
    -          ],
    -        },
    -        {
    -          ID: 'LDAP',
    -          label: 'LDAP, DB, POP',
    -        },
    -      ],
    -    },
    -    {
    -      ID: 'NetworkLayer',
    -      label: 'Network Layer',
    -      x: 0,
    -      y: 150,
    -      children: [
    -        { ID: 'HTTP', label: 'HTTP' },
    -        { ID: 'SOCK', label: 'SOCK' },
    -      ],
    -    },
    -    {
    -      ID: 'DataLayer',
    -      label: 'Data Layer',
    -      x: 0,
    -      y: 200,
    -      children: [
    -        { ID: 'XMPP', label: 'XMPP' },
    -        { ID: 'BDB', label: 'Business DB' },
    -        { ID: 'AD', label: 'Active Directory' },
    -      ],
    -    },
    -  ];
    -
       // Get color scheme for the graph
       const colorScheme = d3scaleOrdinal(d3schemeTableau10);
     };
    diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts
    index 5a4431c0ae..f26d83fcc7 100644
    --- a/packages/mermaid/src/diagrams/block/blockTypes.ts
    +++ b/packages/mermaid/src/diagrams/block/blockTypes.ts
    @@ -39,6 +39,7 @@ export interface Block {
       };
       node?: any;
       columns?: number; // | TBlockColumnsDefaultValue;
    +  classes?: string[];
     }
     
     export interface Link {
    diff --git a/packages/mermaid/src/diagrams/block/layout.spec.ts b/packages/mermaid/src/diagrams/block/layout.spec.ts
    new file mode 100644
    index 0000000000..1de79c880c
    --- /dev/null
    +++ b/packages/mermaid/src/diagrams/block/layout.spec.ts
    @@ -0,0 +1,13 @@
    +// @ts-ignore: jison doesn't export types
    +import { calculateBlockPosition } from './layout.js';
    +
    +describe('Layout', function () {
    +  it('It shoud calulatepositions correctly', () => {
    +    expect(calculateBlockPosition(2, 0)).toEqual({ px: 0, py: 0 });
    +    expect(calculateBlockPosition(2, 1)).toEqual({ px: 1, py: 0 });
    +    expect(calculateBlockPosition(2, 2)).toEqual({ px: 0, py: 1 });
    +    expect(calculateBlockPosition(2, 3)).toEqual({ px: 1, py: 1 });
    +    expect(calculateBlockPosition(2, 4)).toEqual({ px: 0, py: 2 });
    +    expect(calculateBlockPosition(1, 3)).toEqual({ px: 0, py: 2 });
    +  });
    +});
    diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts
    index 9c9b1bd7e9..741445806e 100644
    --- a/packages/mermaid/src/diagrams/block/layout.ts
    +++ b/packages/mermaid/src/diagrams/block/layout.ts
    @@ -1,10 +1,41 @@
     import { BlockDB } from './blockDB.js';
     import type { Block } from './blockTypes.js';
    +import { log } from '../../logger.js';
    +const padding = 8;
     
    -const padding = 10;
    +interface BlockPosition {
    +  px: number;
    +  py: number;
    +}
    +
    +export function calculateBlockPosition(columns: number, position: number): BlockPosition {
    +  // Ensure that columns is a positive integer
    +  if (columns === 0 || !Number.isInteger(columns)) {
    +    throw new Error('Columns must be an integer !== 0.');
    +  }
    +
    +  // Ensure that position is a non-negative integer
    +  if (position < 0 || !Number.isInteger(position)) {
    +    throw new Error('Position must be a non-negative integer.');
    +  }
    +
    +  if (columns < 0) {
    +    // Auto coulumns is set
    +    return { px: position, py: 0 };
    +  }
    +  if (columns === 1) {
    +    // Auto coulumns is set
    +    return { px: 0, py: position };
    +  }
    +  // Calculate posX and posY
    +  const px = position % columns;
    +  const py = Math.floor(position / columns);
    +
    +  return { px, py };
    +}
     
     function calcBlockSizes(block: Block, db: BlockDB) {
    -  console.log('calculateSize (start)', block.id, block?.size?.x, block?.size?.width);
    +  log.debug('calculateSize (start)', block.id, block?.size?.x, block?.size?.width);
       const totalWidth = 0;
       const totalHeight = 0;
       let maxWidth = 0;
    @@ -17,7 +48,7 @@ function calcBlockSizes(block: Block, db: BlockDB) {
         // find max width of children
         for (const child of block.children) {
           const { width, height, x, y } = child.size || { width: 0, height: 0, x: 0, y: 0 };
    -      // console.log('APA', child.id, width, height, x, y);
    +      // log.debug('APA', child.id, width, height, x, y);
           if (width > maxWidth) {
             maxWidth = width;
           }
    @@ -51,105 +82,133 @@ function calcBlockSizes(block: Block, db: BlockDB) {
         // }
       }
       if (block.children?.length > 0) {
    +    const columns = block.columns || -1;
    +    const numItems = block.children.length;
    +
    +    // The width and height in number blocks
    +    let xSize = block.children?.length;
    +    if (columns > 0 && columns < numItems) {
    +      xSize = columns;
    +    }
    +    const ySize = Math.ceil(numItems / xSize);
    +
    +    log.debug(
    +      '(calc)',
    +      block.id,
    +      'xSize',
    +      xSize,
    +      'ySize',
    +      ySize,
    +      'columns',
    +      columns,
    +      block.children.length
    +    );
    +
         const numChildren = block.children.length;
         block.size = {
    -      width: numChildren * (maxWidth + padding) + padding,
    -      height: maxHeight + 2 * padding,
    +      // width: numChildren * (maxWidth + padding) + padding,
    +      width: xSize * (maxWidth + padding) + padding,
    +      // height: maxHeight + 2 * padding,
    +      height: ySize * (maxHeight + padding) + padding,
           x: 0,
           y: 0,
         };
       }
    -  console.log('calculateSize APA (done)', block.id, block.size.x, block.size.width);
    +  log.debug('calculateSize APA (done)', block.id, block?.size?.x, block?.size?.width);
     }
     
     function layoutBlocks(block: Block, db: BlockDB) {
    -  console.log('layout blocks (block)', block.id, 'x:', block.size.x, 'width:', block.size.width);
    +  log.debug(
    +    'layout blocks (=>layoutBlocks)',
    +    block.id,
    +    'x:',
    +    block?.size?.x,
    +    'width:',
    +    block?.size?.width
    +  );
    +  const columns = block.columns || -1;
    +  log.debug('layoutBlocks columns', block.id, '=>', columns);
       if (
         block.children && // find max width of children
         block.children.length > 0
       ) {
         const width = block?.children[0]?.size?.width || 0;
         const widthOfChildren = block.children.length * width + (block.children.length - 1) * padding;
    -    let posX = (block?.size?.x || 0) - widthOfChildren / 2;
    -    const posY = 0;
    -    const parentX = block?.size?.x || 0 - block.children.length;
    -    const parentWidth = block?.size?.width || 0;
     
    -    console.log('widthOfChildren', widthOfChildren, 'posX', posX, 'parentX', parentX);
    +    log.debug('widthOfChildren', widthOfChildren, 'posX');
     
         // let first = true;
    +    let columnPos = -1;
         for (const child of block.children) {
    -      console.log(
    -        'layout blocks (child)',
    -        child.id,
    -        'x:',
    -        child?.size?.x,
    -        'width:',
    -        child?.size?.width,
    -        'posX:',
    -        posX,
    -        block?.size?.x,
    -        widthOfChildren / 2,
    -        widthOfChildren / 2
    -      );
    +      columnPos++;
    +
    +      // log.debug(
    +      //   'layout blocks (child)',
    +      //   child.id,
    +      //   'x:',
    +      //   child?.size?.x,
    +      //   'width:',
    +      //   child?.size?.width,
    +      //   'posX:',
    +      //   posX,
    +      //   block?.size?.x,
    +      //   widthOfChildren / 2,
    +      //   widthOfChildren / 2
    +      // );
     
           if (!child.size) {
             continue;
           }
           const { width, height } = child.size;
    -      child.size.x = posX + width / 2;
    -      posX += width + padding;
    -      child.size.y = posY;
    +      const { px, py } = calculateBlockPosition(columns, columnPos);
    +      log.debug(
    +        'layout blocks (child) px, py (',
    +        block?.size?.x,
    +        ',',
    +        block?.size?.y,
    +        ')',
    +        'parent:',
    +        block.id,
    +        width / 2,
    +        padding
    +      );
    +      if (block.size) {
    +        child.size.x =
    +          block.size.x - block.size.width / 2 + px * (width + padding) + width / 2 + padding;
    +        // child.size.x = px * (width + padding) - block.size.width / 2;
    +        // posX += width + padding;
    +        // child.size.y = py * (height + padding) + height / 2 + padding;
    +        child.size.y =
    +          block.size.y - block.size.height / 2 + py * (height + padding) + height / 2 + padding;
    +
    +        log.debug(
    +          'layout blocks (calc) px, py',
    +          'id:',
    +          child.id,
    +          '=>',
    +          'x:',
    +          child.size.x,
    +          'y:',
    +          child.size.y
    +        );
    +      }
    +
           // posY += height + padding;
           if (child.children) {
             layoutBlocks(child, db);
           }
         }
       }
    -}
    -
    -function positionBlock(parent: Block, block: Block, db: BlockDB) {
    -  console.log(
    -    'layout position block',
    -    parent.id,
    -    parent?.size?.x,
    +  log.debug(
    +    'layout blocks (<==layoutBlocks)',
         block.id,
    +    'x:',
         block?.size?.x,
         'width:',
         block?.size?.width
       );
    -  let parentX = 0;
    -  let parentWidth = 0;
    -  let y = 0;
    -  if (parent.id !== 'root') {
    -    parentX = parent?.size?.x || 0;
    -    parentWidth = parent?.size?.width || 0;
    -    y = parent?.size?.y || 0;
    -  }
    -  if (block.size && block.id !== 'root') {
    -    console.log(
    -      'layout position block (calc)',
    -      'x:',
    -      parentX,
    -      parentWidth / 2,
    -      block.id,
    -      'x:',
    -      block.size.x,
    -      block.size.width
    -    );
    -    // block.size.x = parentX + block.size.x + -block.size.width / 2;
    -    block.size.x =
    -      parentX < 0 ? parentX + block.size.x : parentX + block.size.x + -block.size.width / 2;
    -    // block.size.x = parentX - parentWidth + Math.abs(block.size.x) / 2;
    -    block.size.y = block.size.y + y;
    -  }
    -  if (block.children) {
    -    for (const child of block.children) {
    -      positionBlock(block, child, db);
    -    }
    -  }
    -  // console.log('layout position block', block);
     }
    +
     let minX = 0;
     let minY = 0;
     let maxX = 0;
    @@ -160,7 +219,7 @@ function findBounds(block: Block) {
         const { x, y, width, height } = block.size;
         if (x - width / 2 < minX) {
           minX = x - width / 2;
    -      // console.log('Here APA minX', block.id, x, width, minX);
    +      // log.debug('Here APA minX', block.id, x, width, minX);
         }
         if (y - height / 2 < minY) {
           minY = y - height / 2;
    @@ -180,20 +239,22 @@ function findBounds(block: Block) {
     }
     
     export function layout(db: BlockDB) {
    -  const blocks = db.getBlocks();
    -  const root = { id: 'root', type: 'composite', children: blocks } as Block;
    +  const root = db.getBlock('root');
    +  if (!root) {
    +    return;
    +  }
       calcBlockSizes(root, db);
       layoutBlocks(root, db);
       // Position blocks relative to parents
       // positionBlock(root, root, db);
    -  console.log('getBlocks', JSON.stringify(db.getBlocks(), null, 2));
    +  log.debug('getBlocks', JSON.stringify(root, null, 2));
     
       minX = 0;
       minY = 0;
       maxX = 0;
       maxY = 0;
       findBounds(root);
    -  // console.log('Here maxX', minX, '--', maxX);
    +  // log.debug('Here maxX', minX, '--', maxX);
       const height = maxY - minY;
       const width = maxX - minX;
       return { x: minX, y: minY, width, height };
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index 5bbe279e7f..04832d97fb 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -5,28 +5,23 @@ import { ContainerElement } from 'd3';
     import type { Block } from './blockTypes.js';
     import { BlockDB } from './blockDB.js';
     
    +interface Node {
    +  classes: string;
    +}
    +
     function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
       const vertex = block;
     
    -  /**
    -   * Variable for storing the classes for the vertex
    -   *
    -   * @type {string}
    -   */
       let classStr = 'default';
    -  if ((vertex?.classes?.length || []) > 0) {
    -    classStr = vertex.classes.join(' ');
    +  if ((vertex?.classes?.length || 0) > 0) {
    +    classStr = (vertex?.classes || []).join(' ');
       }
       classStr = classStr + ' flowchart-label';
     
       // We create a SVG label, either by delegating to addHtmlLabel or manually
    -  let vertexNode;
    -  const labelData = { width: 0, height: 0 };
    -
       let radious = 0;
       let _shape = '';
       let layoutOptions = {};
    -  console.log('This is the type:', vertex.type);
       // Set the shape based parameters
       switch (vertex.type) {
         case 'round':
    @@ -140,20 +135,18 @@ async function calculateBlockSize(elem: any, block: any, db: any) {
       const boundingBox = nodeEl.node().getBBox();
       const obj = db.getBlock(node.id);
       obj.size = { width: boundingBox.width, height: boundingBox.height, x: 0, y: 0, node: nodeEl };
    -  console.log('Here boundsíng', boundingBox.width);
       db.setBlock(obj);
       nodeEl.remove();
     }
     
     export async function insertBlockPositioned(elem: any, block: any, db: any) {
    -  console.log('Here insertBlockPositioned');
       const node = getNodeFromBlock(block, db, true);
       // if (node.type === 'composite') {
       //   return;
       // }
       // Add the element to the DOM to size it
    -  const obj = db.getBlock(node.id);
    -  const nodeEl = await insertNode(elem, node);
    +  // const obj = db.getBlock(node.id);
    +  // const nodeEl = await insertNode(elem, node);
       positionNode(node);
     }
     
    
    From 74a9e86e747de8ebf93a149428a806a442dc746f Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Sun, 15 Oct 2023 22:55:29 +0200
    Subject: [PATCH 22/97] #3358 Putting the elements back in
    
    ---
     packages/mermaid/src/diagrams/block/renderHelpers.ts | 4 ++--
     1 file changed, 2 insertions(+), 2 deletions(-)
    
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index 04832d97fb..7c1f7c6f92 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -145,8 +145,8 @@ export async function insertBlockPositioned(elem: any, block: any, db: any) {
       //   return;
       // }
       // Add the element to the DOM to size it
    -  // const obj = db.getBlock(node.id);
    -  // const nodeEl = await insertNode(elem, node);
    +  const obj = db.getBlock(node.id);
    +  const nodeEl = await insertNode(elem, node);
       positionNode(node);
     }
     
    
    From 5619f8771bd40db0f07045b47345d717a5b87b00 Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Fri, 20 Oct 2023 12:13:49 +0200
    Subject: [PATCH 23/97] #3358 Adding support for space blocks and different
     shapes
    
    ---
     cypress/platform/knsv2.html | 49 +++++++++++++++++++++++++++----------
     1 file changed, 36 insertions(+), 13 deletions(-)
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index 0325eb659e..6d5c9846b6 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -27,7 +27,6 @@
           .mermaid {
             border: 1px solid #ddd;
             margin: 10px;
    -        background: pink;
           }
           .mermaid2 {
             display: none;
    @@ -40,7 +39,7 @@
             background-size: 20px 20px;
             background-position: 0 0, 10px 10px;
             background-repeat: repeat;
    -        border: 1px solid red;
    +        border: 2px solid rgb(131, 142, 205);
           }
           .malware {
             position: fixed;
    @@ -63,29 +62,53 @@
         
       
       
    -    
    +    
     block-beta
       block
    +    id3("Wider then")
    +  end
    +    
    +
    +block-beta
    +    columns 3
    +    space:2
    +    id1("Wider then")
    +    space:9
    +    space
    +    id2{{"Wider then"}}
    +    space
    +    id3("Wider then")
    +    space
    +    space
    +    
    +
    +block-beta
       columns 1
    +  block
         id1
         id2
    -    id3("Wider then")
    +    block
    +      columns 1
    +      id3("Wider then")
    +      id5(("id5"))
    +    end
       end
       id4
         
     block-beta
    -  block
       columns 1
       block
    -    columns 3
    -    id1
    -    id2
    -    id2.1
    -    %%id2.2
    -  end
    -  id48
    +    columns 1
    +    block
    +      columns 3
    +      id1
    +      id2
    +      id2.1(("XYZ"))
    +      %%id2.2
    +    end
    +    id48
       end
       id3
     %%  id3
    @@ -124,7 +147,7 @@
     block-beta
       id1["Hello"]
       block
    -    columns 2
    +    columns 3
         id2["to"]
         id3["the"]
         id4["World"]
    
    From f3f25c7874d879b7d607d63abef481e8c1b591fc Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Fri, 20 Oct 2023 12:30:25 +0200
    Subject: [PATCH 24/97] #3358 Adding support for space blocks and different
     shapes
    
    ---
     packages/mermaid/src/dagre-wrapper/nodes.js   |  2 -
     .../mermaid/src/diagrams/block/blockDB.ts     | 38 ++++++++++++++++++-
     packages/mermaid/src/diagrams/block/layout.ts |  3 --
     .../src/diagrams/block/parser/block.jison     | 10 ++++-
     .../src/diagrams/block/parser/block.spec.ts   | 10 ++---
     .../src/diagrams/block/renderHelpers.ts       | 18 ++++++---
     6 files changed, 63 insertions(+), 18 deletions(-)
    
    diff --git a/packages/mermaid/src/dagre-wrapper/nodes.js b/packages/mermaid/src/dagre-wrapper/nodes.js
    index b95265f311..78bcfea999 100644
    --- a/packages/mermaid/src/dagre-wrapper/nodes.js
    +++ b/packages/mermaid/src/dagre-wrapper/nodes.js
    @@ -358,7 +358,6 @@ const rect = async (parent, node) => {
     };
     
     const composite = async (parent, node) => {
    -  console.log('This got called');
       const { shapeSvg, bbox, halfPadding } = await labelHelper(
         parent,
         node,
    @@ -1075,7 +1074,6 @@ export const clear = () => {
     };
     
     export const positionNode = (node) => {
    -  console.log('Node id = ', node.id);
       const el = nodeElems[node.id];
       log.trace(
         'Transforming node',
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index f9578a4e78..6b787009d9 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -13,6 +13,7 @@ import {
       clear as commonClear,
     } from '../../commonDb.js';
     import { log } from '../../logger.js';
    +import clone from 'lodash-es/clone.js';
     
     // Initialize the node database for simple lookups
     let blockDatabase: Record = {};
    @@ -37,7 +38,16 @@ const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
             populateBlockDatabase(block.children, block);
           }
     
    -      children.push(block);
    +      if (block.type === 'space') {
    +        for (let j = 0; j < block.width; j++) {
    +          const newBlock = clone(block);
    +          newBlock.id = newBlock.id + '-' + j;
    +          blockDatabase[newBlock.id] = newBlock;
    +          children.push(newBlock);
    +        }
    +      } else {
    +        children.push(block);
    +      }
         }
       }
       parent.children = children;
    @@ -57,12 +67,38 @@ const clear = (): void => {
     
     type ITypeStr2Type = (typeStr: string) => BlockType;
     export function typeStr2Type(typeStr: string) {
    +  log.debug('typeStr2Type', typeStr);
       // TODO: add all types
       switch (typeStr) {
         case '[]':
           return 'square';
         case '()':
    +      log.debug('we have a round');
           return 'round';
    +    case '(())':
    +      return 'circle';
    +    case '>]':
    +      return 'rect_left_inv_arrow';
    +    case '{}':
    +      return 'question';
    +    case '{{}}':
    +      return 'hexagon';
    +    case '([])':
    +      return 'stadium';
    +    case '[[]]':
    +      return 'subroutine';
    +    case '[()]':
    +      return 'cylinder';
    +    case '((()))':
    +      return 'doublecircle';
    +    case '[//]':
    +      return 'lean_right';
    +    case '[\\\\]':
    +      return 'lean_left';
    +    case '[/\\]':
    +      return 'trapezoid';
    +    case '[\\/]':
    +      return 'inv_trapezoid';
         default:
           return 'square';
       }
    diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts
    index 741445806e..f9a6cd3f9e 100644
    --- a/packages/mermaid/src/diagrams/block/layout.ts
    +++ b/packages/mermaid/src/diagrams/block/layout.ts
    @@ -104,11 +104,8 @@ function calcBlockSizes(block: Block, db: BlockDB) {
           block.children.length
         );
     
    -    const numChildren = block.children.length;
         block.size = {
    -      // width: numChildren * (maxWidth + padding) + padding,
           width: xSize * (maxWidth + padding) + padding,
    -      // height: maxHeight + 2 * padding,
           height: ySize * (maxHeight + padding) + padding,
           x: 0,
           y: 0,
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index 32b7c28e25..b2975b610d 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -13,6 +13,7 @@
     %x acc_descr
     %x acc_descr_multiline
     %x string
    +%x space
     %x md_string
     %x NODE
     
    @@ -43,6 +44,9 @@ CRLF \u000D\u000A
     ["]                     this.pushState("string");
     ["]             this.popState();
     [^"]*           return "STR";
    +space[:]\d+            {  yytext = yytext.replace(/space\:/,'');yy.getLogger().info('SPACE NUM (LEX)', yytext); return 'SPACE_BLOCK'; }
    +space                  { yytext = '1'; yy.getLogger().info('COLUMNS (LEX)', yytext); return 'SPACE_BLOCK'; }
    +[^"]*           return "STR";
     "style"               return 'STYLE';
     "default"             return 'DEFAULT';
     "linkStyle"           return 'LINKSTYLE';
    @@ -64,7 +68,7 @@ accDescr\s*"{"\s*                                { this.pushState("acc_descr_mul
     .*direction\s+LR[^\n]*                                      return 'direction_lr';
     
     // Start of nodes with shapes and description
    -"-)"                   { yy.getLogger().info('Lex: -)'); this.pushState('NODE');return 'NODE_D START'; }
    +"-)"                   { yy.getLogger().info('Lex: -)'); this.pushState('NODE');return 'NODE_DSTART'; }
     "(-"                   { yy.getLogger().info('Lex: (-'); this.pushState('NODE');return 'NODE_DSTART'; }
     "))"                   { yy.getLogger().info('Lex: ))'); this.pushState('NODE');return 'NODE_DSTART';  }
     ")"                    { yy.getLogger().info('Lex: )'); this.pushState('NODE');return 'NODE_DSTART';      }
    @@ -167,6 +171,8 @@ link
     statement
       : nodeStatement
       | columnsStatement
    +  | SPACE_BLOCK
    +    { const num=parseInt($1); const spaceId = yy.generateId(); $$ = { id: spaceId, type:'space', label:'', width: num, children: [] }}
       | blockStatement
     //   SPACELIST node       { yy.getLogger().info('Node: ',$2.id);yy.addNode($1.length, $2.id, $2.descr, $2.type);  }
     // 	| SPACELIST ICON       { yy.getLogger().info('Icon: ',$2);yy.decorateNode({icon: $2}); }
    @@ -182,7 +188,7 @@ statement
     
     nodeStatement
       : nodeStatement link node { yy.getLogger().info('Rule: nodeStatement (nodeStatement link node) '); $$ = {id: $1.id}; }
    -  | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); $$ = {id: $1.id, label: $1.label, type: yy.typeStr2Type($1)}; }
    +  | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); $$ = {id: $1.id, label: $1.label, type: yy.typeStr2Type($1.typeStr)}; }
       ;
     
     columnsStatement
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.spec.ts b/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    index adb814be22..bf32afc5e6 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    +++ b/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    @@ -163,7 +163,7 @@ describe('Block diagram', function () {
     
           expect(blocks[0].children.length).toBe(2);
           expect(blocks[0].id).not.toBe(undefined);
    -      expect(blocks[0].label).toBe(blocks[0].id);
    +      expect(blocks[0].label).toBe('');
           expect(blocks[0].type).toBe('composite');
     
           const aBlock = blocks[0].children[0];
    @@ -196,12 +196,12 @@ describe('Block diagram', function () {
     
           expect(blocks[0].children.length).toBe(2);
           expect(blocks[0].id).not.toBe(undefined);
    -      expect(blocks[0].label).toBe(blocks[0].id);
    +      expect(blocks[0].label).toBe('');
           expect(blocks[0].type).toBe('composite');
     
           expect(secondComposite.children.length).toBe(1);
           expect(secondComposite.id).not.toBe(undefined);
    -      expect(secondComposite.label).toBe(secondComposite.id);
    +      expect(secondComposite.label).toBe('');
           expect(secondComposite.type).toBe('composite');
     
           expect(aBlock.id).not.toBe(aBlock);
    @@ -284,7 +284,7 @@ describe('Block diagram', function () {
     
           block.parse(str);
         });
    -    it.skip('empty blocks', async () => {
    +    it('empty blocks', async () => {
           const str = `block-beta
             columns 3
             space
    @@ -308,7 +308,7 @@ describe('Block diagram', function () {
             columns 2
             mc["Memcache"]:2::black
             `;
    -
    +      const apa = 'apan hopar i träden';
           block.parse(str);
         });
     
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index 7c1f7c6f92..78cce974c3 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -22,15 +22,21 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
       let radious = 0;
       let _shape = '';
       let layoutOptions = {};
    +  let padding;
       // Set the shape based parameters
       switch (vertex.type) {
         case 'round':
           radious = 5;
           _shape = 'rect';
           break;
    +    // case 'composite-subgraph':
    +    //   radious = 0;
    +    //   _shape = 'composite';
    +    //   break;
         case 'composite':
    -      radious = 4;
    +      radious = 0;
           _shape = 'composite';
    +      padding = 0;
           break;
         case 'square':
           _shape = 'rect';
    @@ -119,7 +125,7 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
         positioned,
         type: vertex.type,
         // props: vertex.props,
    -    padding: getConfig()?.flowchart?.padding || 0,
    +    padding: padding ?? (getConfig()?.flowchart?.padding || 0),
       };
       return node;
     }
    @@ -139,15 +145,17 @@ async function calculateBlockSize(elem: any, block: any, db: any) {
       nodeEl.remove();
     }
     
    -export async function insertBlockPositioned(elem: any, block: any, db: any) {
    +export async function insertBlockPositioned(elem: any, block: Block, db: any) {
       const node = getNodeFromBlock(block, db, true);
       // if (node.type === 'composite') {
       //   return;
       // }
       // Add the element to the DOM to size it
       const obj = db.getBlock(node.id);
    -  const nodeEl = await insertNode(elem, node);
    -  positionNode(node);
    +  if (obj.type !== 'space') {
    +    const nodeEl = await insertNode(elem, node);
    +    positionNode(node);
    +  }
     }
     
     export async function performOperations(
    
    From 7198fe55a9312f12fdf810b9538585fe5f0d8d49 Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Thu, 26 Oct 2023 22:01:44 +0200
    Subject: [PATCH 25/97] Parsing of block arrows with directions, creating a
     dedicated new node for this.
    
    ---
     cypress/platform/knsv2.html                   | 27 ++++----
     packages/mermaid/src/dagre-wrapper/nodes.js   | 27 ++++++++
     .../mermaid/src/diagrams/block/blockDB.ts     |  2 +
     .../mermaid/src/diagrams/block/blockTypes.ts  |  3 +
     .../src/diagrams/block/parser/block.jison     | 61 +++++++++++--------
     .../src/diagrams/block/renderHelpers.ts       |  3 +
     6 files changed, 83 insertions(+), 40 deletions(-)
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index 6d5c9846b6..315c33b210 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -62,24 +62,23 @@
         
       
       
    -    
    +    
     block-beta
    -  block
    -    id3("Wider then")
    -  end
    +      blockArrowId<["Label"]>(right, down)
         
    -
    +    
     block-beta
         columns 3
    -    space:2
    -    id1("Wider then")
    -    space:9
    -    space
    -    id2{{"Wider then"}}
    -    space
    -    id3("Wider then")
    -    space
    -    space
    +    space:3
    +    ida idb idc
    +    id1  id2
    +      blockArrowId<["Label"]>(right)
    +      blockArrowId2<["Label"]>(left)
    +      blockArrowId3<["Label"]>(up)
    +      blockArrowId4<["Label"]>(down)
    +      blockArrowId5<["Label"]>(x)
    +      blockArrowId6<["Label"]>(y)
    +      blockArrowId6<["Label"]>(x, down)
         
     block-beta
    diff --git a/packages/mermaid/src/dagre-wrapper/nodes.js b/packages/mermaid/src/dagre-wrapper/nodes.js
    index 78bcfea999..41578f5849 100644
    --- a/packages/mermaid/src/dagre-wrapper/nodes.js
    +++ b/packages/mermaid/src/dagre-wrapper/nodes.js
    @@ -95,6 +95,32 @@ const hexagon = async (parent, node) => {
     
       return shapeSvg;
     };
    +const block_arrow = async (parent, node) => {
    +  const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
    +
    +  const f = 2;
    +  const h = bbox.height + node.padding;
    +  const m = h / f;
    +  const w = bbox.width + 2 * m + node.padding;
    +  const points = [
    +    { x: m, y: 0 },
    +    { x: w - m, y: 0 },
    +    { x: w, y: -h / 2 },
    +    { x: w - m, y: -h },
    +    { x: m, y: -h },
    +    { x: 0, y: -h / 2 },
    +  ];
    +
    +  const hex = insertPolygonShape(shapeSvg, w, h, points);
    +  hex.attr('style', node.style);
    +  updateNodeBounds(node, hex);
    +
    +  node.intersect = function (point) {
    +    return intersect.polygon(node, points, point);
    +  };
    +
    +  return shapeSvg;
    +};
     
     const rect_left_inv_arrow = async (parent, node) => {
       const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
    @@ -1016,6 +1042,7 @@ const shapes = {
       doublecircle,
       stadium,
       hexagon,
    +  block_arrow,
       rect_left_inv_arrow,
       lean_right,
       lean_left,
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index 6b787009d9..a3ef97e247 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -99,6 +99,8 @@ export function typeStr2Type(typeStr: string) {
           return 'trapezoid';
         case '[\\/]':
           return 'inv_trapezoid';
    +    case '<[]>':
    +      return 'block_arrow';
         default:
           return 'square';
       }
    diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts
    index f26d83fcc7..001cd7bdaf 100644
    --- a/packages/mermaid/src/diagrams/block/blockTypes.ts
    +++ b/packages/mermaid/src/diagrams/block/blockTypes.ts
    @@ -7,6 +7,8 @@ export interface BlockConfig extends BaseDiagramConfig {
     export type BlockType =
       | 'column-setting'
       | 'round'
    +  | 'block_arrow'
    +  | 'space'
       | 'square'
       | 'diamond'
       | 'hexagon'
    @@ -40,6 +42,7 @@ export interface Block {
       node?: any;
       columns?: number; // | TBlockColumnsDefaultValue;
       classes?: string[];
    +  directions?: string[];
     }
     
     export interface Link {
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index b2975b610d..91d26faf37 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -16,6 +16,8 @@
     %x space
     %x md_string
     %x NODE
    +%x BLOCK_ARROW
    +%x ARROW_DIR
     
     
     // as per section 6.1 of RFC 2234 [2]
    @@ -42,11 +44,10 @@ CRLF \u000D\u000A
     [^`"]+        { return "MD_STR";}
     [`]["]          { this.popState();}
     ["]                     this.pushState("string");
    -["]             this.popState();
    -[^"]*           return "STR";
    +["]             { log.debug('LEX: POPPING STR:', yytext);this.popState();}
    +[^"]*           { log.debug('LEX: STR ebd:', yytext); return "STR";}
     space[:]\d+            {  yytext = yytext.replace(/space\:/,'');yy.getLogger().info('SPACE NUM (LEX)', yytext); return 'SPACE_BLOCK'; }
     space                  { yytext = '1'; yy.getLogger().info('COLUMNS (LEX)', yytext); return 'SPACE_BLOCK'; }
    -[^"]*           return "STR";
     "style"               return 'STYLE';
     "default"             return 'DEFAULT';
     "linkStyle"           return 'LINKSTYLE';
    @@ -68,15 +69,15 @@ accDescr\s*"{"\s*                                { this.pushState("acc_descr_mul
     .*direction\s+LR[^\n]*                                      return 'direction_lr';
     
     // Start of nodes with shapes and description
    -"-)"                   { yy.getLogger().info('Lex: -)'); this.pushState('NODE');return 'NODE_DSTART'; }
    -"(-"                   { yy.getLogger().info('Lex: (-'); this.pushState('NODE');return 'NODE_DSTART'; }
    -"))"                   { yy.getLogger().info('Lex: ))'); this.pushState('NODE');return 'NODE_DSTART';  }
    -")"                    { yy.getLogger().info('Lex: )'); this.pushState('NODE');return 'NODE_DSTART';      }
    -"(("                   { yy.getLogger().info('Lex: )'); this.pushState('NODE');return 'NODE_DSTART'; }
    -"{{"                   { yy.getLogger().info('Lex: )'); this.pushState('NODE');return 'NODE_DSTART'; }
    -"("                    { yy.getLogger().info('Lex: )'); this.pushState('NODE');return 'NODE_DSTART'; }
    -"["                    { yy.getLogger().info('Lex: ['); this.pushState('NODE');return 'NODE_DSTART'; }
    -"(["                   { yy.getLogger().info('Lex: )'); this.pushState('NODE');return 'NODE_DSTART'; }
    +"-)"                   { yy.getLogger().info('Lexa: -)'); this.pushState('NODE');return 'NODE_DSTART'; }
    +"(-"                   { yy.getLogger().info('Lexa: (-'); this.pushState('NODE');return 'NODE_DSTART'; }
    +"))"                   { yy.getLogger().info('Lexa: ))'); this.pushState('NODE');return 'NODE_DSTART';  }
    +")"                    { yy.getLogger().info('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART';      }
    +"(("                   { yy.getLogger().info('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; }
    +"{{"                   { yy.getLogger().info('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; }
    +"("                    { yy.getLogger().info('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; }
    +"["                    { yy.getLogger().info('Lexa: ['); this.pushState('NODE');return 'NODE_DSTART'; }
    +"(["                   { yy.getLogger().info('Lexa: (['); this.pushState('NODE');return 'NODE_DSTART'; }
     "[["                   { this.pushState('NODE');return 'NODE_DSTART'; }
     "[|"                   { this.pushState('NODE');return 'NODE_DSTART'; }
     "[("                   { this.pushState('NODE');return 'NODE_DSTART'; }
    @@ -85,19 +86,23 @@ accDescr\s*"{"\s*                                { this.pushState("acc_descr_mul
     "[/"                   { this.pushState('NODE');return 'NODE_DSTART'; }
     "[\\"                  { this.pushState('NODE');return 'NODE_DSTART'; }
     
    +"<["                   { this.pushState('BLOCK_ARROW');log.debug('LEX ARR START');return 'BLOCK_ARROW_START'; }
     
    -[^\(\[\n\-\)\{\}]+     { yy.getLogger().info('Lex: NODE_ID', yytext);return 'NODE_ID'; }
    +[^\(\[\n\-\)\{\}\s\<]+     { yy.getLogger().info('Lex: NODE_ID', yytext);return 'NODE_ID'; }
     <>                { yy.getLogger().info('Lex: EOF', yytext);return 'EOF'; }
     
     // Handling of strings in node
    +["][`]           { this.pushState("md_string");}
     ["][`]           { this.pushState("md_string");}
     [^`"]+      { return "NODE_DESCR";}
     [`]["]      { this.popState();}
     ["]              { yy.getLogger().info('Lex: Starting string');this.pushState("string");}
    -[^"]+          { yy.getLogger().info('Lex: NODE_DESCR:', yytext); return "NODE_DESCR";}
    -["]            {this.popState();}
    +["]              { yy.getLogger().info('LEX ARR: Starting string');this.pushState("string");}
    +[^"]+          { log.debug('LEX: NODE_DESCR:', yytext); return "NODE_DESCR";}
    +["]            {log.debug('LEX POPPING');this.popState();}
     
     // Node end of shape
    +\]\>             { this.popState();yy.getLogger().info('Lex: ]>'); return "NODE_DEND"; }
     [\)]\)           { this.popState();yy.getLogger().info('Lex: ))'); return "NODE_DEND"; }
     [\)]             { this.popState();yy.getLogger().info('Lex: )');  return "NODE_DEND"; }
     [\]]             { this.popState();yy.getLogger().info('Lex: ]'); return "NODE_DEND"; }
    @@ -111,6 +116,15 @@ accDescr\s*"{"\s*                                { this.pushState("acc_descr_mul
     "/]"             { this.popState();yy.getLogger().info('Lex: /]'); return "NODE_DEND"; }
     ")]"             { this.popState();yy.getLogger().info('Lex: )]'); return "NODE_DEND"; }
     
    +"]>"\s*"("       { log.debug('Lex: =>BAE');  this.pushState('ARROW_DIR');  }
    +","?right\s*           { log.debug('Lex (right): dir:',yytext);return "DIR"; }
    +","?left\s*            { log.debug('Lex (left):',yytext);return "DIR"; }
    +","?x\s*               { log.debug('Lex (x):',yytext); return "DIR"; }
    +","?y\s*               { log.debug('Lex (y):',yytext); return "DIR"; }
    +","?up\s*              { log.debug('Lex (up):',yytext); return "DIR"; }
    +","?\s*down\s*     { yytext = yytext.replace(/^,\s*/, ''); log.debug('Lex (down):',yytext); return "DIR"; }
    +")"\s*             { yytext=']>';log.debug('Lex (ARROW_DIR end):',yytext);this.popState();this.popState();return "BLOCK_ARROW_END"; }
    +
     // Edges
     \s*[xo<]?\-\-+[-xo>]\s*                 { yy.getLogger().info('Lex: LINK', '#'+yytext+'#'); return 'LINK'; }
     \s*[xo<]?\=\=+[=xo>]\s*                 { yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; }
    @@ -174,16 +188,6 @@ statement
       | SPACE_BLOCK
         { const num=parseInt($1); const spaceId = yy.generateId(); $$ = { id: spaceId, type:'space', label:'', width: num, children: [] }}
       | blockStatement
    -//   SPACELIST node       { yy.getLogger().info('Node: ',$2.id);yy.addNode($1.length, $2.id, $2.descr, $2.type);  }
    -// 	| SPACELIST ICON       { yy.getLogger().info('Icon: ',$2);yy.decorateNode({icon: $2}); }
    -// 	| SPACELIST CLASS      { yy.decorateNode({class: $2}); }
    -//   | SPACELINE { yy.getLogger().info('SPACELIST');}
    -// 	|
    -//    node					       { yy.getLogger().info('Node: ',$1.id);yy.addNode(0, $1.id, $1.descr, $1.type);  }
    -// 	| ICON                 { yy.decorateNode({icon: $1}); }
    -// 	| CLASS                { yy.decorateNode({class: $1}); }
    -//   // | SPACELIST
    -
     	;
     
     nodeStatement
    @@ -200,7 +204,6 @@ blockStatement
       | block document end { yy.getLogger().info('Rule: blockStatement : ', $1, $2, $3); const id = yy.generateId(); $$ = { id, type:'composite', label:'', children: $2 }; }
       ;
     
    -
     node
       : NODE_ID
       { yy.getLogger().info("Rule: node (NODE_ID seperator): ", $1); $$ = { id: $1 }; }
    @@ -210,9 +213,15 @@ node
       // { yy.getLogger().info("Rule: node (nodeShapeNLabel seperator): ", $1, $2, $3); }
       ;
     
    +dirList: DIR { yy.getLogger().info("Rule: dirList: ", $1); $$ = [$1]; }
    +  | DIR dirList { yy.getLogger().info("Rule: dirList: ", $1, $2); $$ = [$1].concat($2); }
    +  ;
    +
     nodeShapeNLabel
       :   NODE_DSTART STR NODE_DEND
     	      { yy.getLogger().info("Rule: nodeShapeNLabel: ", $1, $2, $3); $$ = { typeStr: $1 + $3, label: $2 }; }
    +	|    BLOCK_ARROW_START STR dirList BLOCK_ARROW_END
    +    	      { yy.getLogger().info("Rule: BLOCK_ARROW nodeShapeNLabel: ", $1, $2, $3, $4); $$ = { typeStr: $1 + $4, label: $2, directions: $3}; }
       ;
     
     %%
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index 78cce974c3..142de0c5cd 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -50,6 +50,9 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
         case 'hexagon':
           _shape = 'hexagon';
           break;
    +    case 'block_arrow':
    +      _shape = 'block_arrow';
    +      break;
         case 'odd':
           _shape = 'rect_left_inv_arrow';
           break;
    
    From 03c59adaede3cc0ce5dac3d81683fe5820a90cc6 Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Thu, 26 Oct 2023 22:02:16 +0200
    Subject: [PATCH 26/97] Parsing of block arrows with directions, creating a
     dedicated new node for this.
    
    ---
     packages/mermaid/src/diagrams/block/blockDB.ts    | 6 +++---
     packages/mermaid/src/diagrams/block/blockTypes.ts | 2 ++
     2 files changed, 5 insertions(+), 3 deletions(-)
    
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index a3ef97e247..3cc9ec11d7 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -22,8 +22,7 @@ const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
       const children = [];
       for (const block of blockList) {
         if (block.type === 'column-setting') {
    -      const columns = block.columns || -1;
    -      parent.columns = columns;
    +      parent.columns = block.columns || -1;
         } else {
           if (!block.label) {
             if (block.type === 'composite') {
    @@ -39,7 +38,8 @@ const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
           }
     
           if (block.type === 'space') {
    -        for (let j = 0; j < block.width; j++) {
    +        const w = block.width || 1;
    +        for (let j = 0; j < w; j++) {
               const newBlock = clone(block);
               newBlock.id = newBlock.id + '-' + j;
               blockDatabase[newBlock.id] = newBlock;
    diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts
    index 001cd7bdaf..a65e5db324 100644
    --- a/packages/mermaid/src/diagrams/block/blockTypes.ts
    +++ b/packages/mermaid/src/diagrams/block/blockTypes.ts
    @@ -17,6 +17,7 @@ export type BlockType =
       | 'lean_left'
       | 'trapezoid'
       | 'inv_trapezoid'
    +  | 'rect_left_inv_arrow'
       | 'odd_right'
       | 'circle'
       | 'ellipse'
    @@ -28,6 +29,7 @@ export type BlockType =
       | 'composite';
     
     export interface Block {
    +  width?: number;
       id: string;
       label?: string;
       parent?: Block;
    
    From df858dc7b61272621a4f4c9c4fc3c1f2d146c500 Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Mon, 20 Nov 2023 14:00:25 +0100
    Subject: [PATCH 27/97] #3358 Adding arrows to syntax
    
    ---
     cypress/platform/knsv2.html                   |  10 +-
     .../src/dagre-wrapper/blockArrowHelper.js     | 218 ++++++++++++++++++
     packages/mermaid/src/dagre-wrapper/nodes.js   |  35 ++-
     .../mermaid/src/diagrams/block/blockDB.ts     |   8 +-
     .../src/diagrams/block/parser/block.jison     |  49 ++--
     .../src/diagrams/block/renderHelpers.ts       |   1 +
     .../src/diagrams/flowchart/flowRenderer-v2.js |   4 +-
     .../src/diagrams/flowchart/parser/flow.jison  |   8 +-
     8 files changed, 290 insertions(+), 43 deletions(-)
     create mode 100644 packages/mermaid/src/dagre-wrapper/blockArrowHelper.js
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index 315c33b210..ab5c0aa3cc 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -62,9 +62,17 @@
         
       
       
    +    
    +block-beta
    +      columns 3
    +      space blockArrowId1<["down"]>(down) space
    +      blockArrowId2<["right"]>(right) blockArrowId3<["Sync"]>(x, y) blockArrowId4<["left"]>(left)
    +      space blockArrowId5<["up"]>(up) space
    +      blockArrowId6<["x"]>(x) space blockArrowId7<["y"]>(y)
    +    
     block-beta
    -      blockArrowId<["Label"]>(right, down)
    +      A("APA") --> B("GORILLA")
         
     block-beta
    diff --git a/packages/mermaid/src/dagre-wrapper/blockArrowHelper.js b/packages/mermaid/src/dagre-wrapper/blockArrowHelper.js
    new file mode 100644
    index 0000000000..60ff77a57a
    --- /dev/null
    +++ b/packages/mermaid/src/dagre-wrapper/blockArrowHelper.js
    @@ -0,0 +1,218 @@
    +const expandAndDeduplicateDirections = (directions) => {
    +  const uniqueDirections = new Set();
    +
    +  for (const direction of directions) {
    +    switch (direction) {
    +      case 'x':
    +        uniqueDirections.add('right');
    +        uniqueDirections.add('left');
    +        break;
    +      case 'y':
    +        uniqueDirections.add('up');
    +        uniqueDirections.add('down');
    +        break;
    +      default:
    +        uniqueDirections.add(direction);
    +        break;
    +    }
    +  }
    +
    +  return uniqueDirections;
    +};
    +export const getArrowPoints = (directions, bbox, node) => {
    +  const ud = expandAndDeduplicateDirections(directions);
    +
    +  // console.log('block_arrow abc123', node.id, node.directions, ud);
    +
    +  const f = 2;
    +  const h = bbox.height + 2 * node.padding;
    +  const m = h / f;
    +  const w = bbox.width + 2 * m + node.padding;
    +  const p = node.padding / 2;
    +
    +  let points = [];
    +
    +  if (ud.has('right') && ud.has('left') && ud.has('up') && ud.has('down')) {
    +    // SQUARE
    +    points = [
    +      // Bottom
    +      { x: 0, y: 0 },
    +      { x: m, y: 0 },
    +      { x: w / 2, y: 2 * p },
    +      { x: w - m, y: 0 },
    +      { x: w, y: 0 },
    +
    +      // Right
    +      { x: w, y: -h / 3 },
    +      { x: w + 2 * p, y: -h / 2 },
    +      { x: w, y: (-2 * h) / 3 },
    +      { x: w, y: -h },
    +
    +      // Top
    +      { x: w - m, y: -h },
    +      { x: w / 2, y: -h - 2 * p },
    +      { x: m, y: -h },
    +
    +      // Left
    +      { x: 0, y: -h },
    +      { x: 0, y: (-2 * h) / 3 },
    +      { x: -2 * p, y: -h / 2 },
    +      { x: 0, y: -h / 3 },
    +    ];
    +  } else if (ud.has('right') && ud.has('left') && ud.has('up')) {
    +    // RECTANGLE_VERTICAL (Top Open)
    +    points = [
    +      { x: m, y: 0 },
    +      { x: w - m, y: 0 },
    +      { x: w, y: -h / 2 },
    +      { x: w - m, y: -h },
    +      { x: m, y: -h },
    +      { x: 0, y: -h / 2 },
    +    ];
    +  } else if (ud.has('right') && ud.has('left') && ud.has('down')) {
    +    // RECTANGLE_VERTICAL (Bottom Open)
    +    points = [
    +      { x: 0, y: 0 },
    +      { x: m, y: -h },
    +      { x: w - m, y: -h },
    +      { x: w, y: 0 },
    +    ];
    +  } else if (ud.has('right') && ud.has('up') && ud.has('down')) {
    +    // RECTANGLE_HORIZONTAL (Right Open)
    +    points = [
    +      { x: 0, y: 0 },
    +      { x: w, y: -m },
    +      { x: w, y: -h + m },
    +      { x: 0, y: -h },
    +    ];
    +  } else if (ud.has('left') && ud.has('up') && ud.has('down')) {
    +    // RECTANGLE_HORIZONTAL (Left Open)
    +    points = [
    +      { x: w, y: 0 },
    +      { x: 0, y: -m },
    +      { x: 0, y: -h + m },
    +      { x: w, y: -h },
    +    ];
    +  } else if (ud.has('right') && ud.has('left')) {
    +    // HORIZONTAL_LINE
    +    points = [
    +      { x: m, y: 0 },
    +      { x: m, y: -p },
    +      { x: w - m, y: -p },
    +      { x: w - m, y: 0 },
    +      { x: w, y: -h / 2 },
    +      { x: w - m, y: -h },
    +      { x: w - m, y: -h + p },
    +      { x: m, y: -h + p },
    +      { x: m, y: -h },
    +      { x: 0, y: -h / 2 },
    +    ];
    +  } else if (ud.has('up') && ud.has('down')) {
    +    // VERTICAL_LINE
    +    points = [
    +      // Bottom center
    +      { x: w / 2, y: 0 },
    +      // Left pont of bottom arrow
    +      { x: 0, y: -p },
    +      { x: m, y: -p },
    +      // Left top over vertical section
    +      { x: m, y: -h + p },
    +      { x: 0, y: -h + p },
    +      // Top of arrow
    +      { x: w / 2, y: -h },
    +      { x: w, y: -h + p },
    +      // Top of right vertical bar
    +      { x: w - m, y: -h + p },
    +      { x: w - m, y: -p },
    +      { x: w, y: -p },
    +    ];
    +  } else if (ud.has('right') && ud.has('up')) {
    +    // ANGLE_RT
    +    points = [
    +      { x: 0, y: 0 },
    +      { x: w, y: -m },
    +      { x: 0, y: -h },
    +    ];
    +  } else if (ud.has('right') && ud.has('down')) {
    +    // ANGLE_RB
    +    points = [
    +      { x: 0, y: 0 },
    +      { x: w, y: 0 },
    +      { x: 0, y: -h },
    +    ];
    +  } else if (ud.has('left') && ud.has('up')) {
    +    // ANGLE_LT
    +    points = [
    +      { x: w, y: 0 },
    +      { x: 0, y: -m },
    +      { x: w, y: -h },
    +    ];
    +  } else if (ud.has('left') && ud.has('down')) {
    +    // ANGLE_LB
    +    points = [
    +      { x: w, y: 0 },
    +      { x: 0, y: 0 },
    +      { x: w, y: -h },
    +    ];
    +  } else if (ud.has('right')) {
    +    // ARROW_RIGHT
    +    points = [
    +      { x: m, y: -p },
    +      { x: m, y: -p },
    +      { x: w - m, y: -p },
    +      { x: w - m, y: 0 },
    +      { x: w, y: -h / 2 },
    +      { x: w - m, y: -h },
    +      { x: w - m, y: -h + p },
    +      // top left corner of arrow
    +      { x: m, y: -h + p },
    +      { x: m, y: -h + p },
    +    ];
    +  } else if (ud.has('left')) {
    +    // ARROW_LEFT
    +    points = [
    +      { x: m, y: 0 },
    +      { x: m, y: -p },
    +      // Two points, the right corners
    +      { x: w - m, y: -p },
    +      { x: w - m, y: -h + p },
    +      { x: m, y: -h + p },
    +      { x: m, y: -h },
    +      { x: 0, y: -h / 2 },
    +    ];
    +  } else if (ud.has('up')) {
    +    // ARROW_TOP
    +    points = [
    +      // Bottom center
    +      { x: m, y: -p },
    +      // Left top over vertical section
    +      { x: m, y: -h + p },
    +      { x: 0, y: -h + p },
    +      // Top of arrow
    +      { x: w / 2, y: -h },
    +      { x: w, y: -h + p },
    +      // Top of right vertical bar
    +      { x: w - m, y: -h + p },
    +      { x: w - m, y: -p },
    +    ];
    +  } else if (ud.has('down')) {
    +    // ARROW_BOTTOM
    +    points = [
    +      // Bottom center
    +      { x: w / 2, y: 0 },
    +      // Left pont of bottom arrow
    +      { x: 0, y: -p },
    +      { x: m, y: -p },
    +      // Left top over vertical section
    +      { x: m, y: -h + p },
    +      { x: w - m, y: -h + p },
    +      { x: w - m, y: -p },
    +      { x: w, y: -p },
    +    ];
    +  } else {
    +    // POINT
    +    points = [{ x: 0, y: 0 }];
    +  }
    +
    +  return points;
    +};
    diff --git a/packages/mermaid/src/dagre-wrapper/nodes.js b/packages/mermaid/src/dagre-wrapper/nodes.js
    index 41578f5849..afe1b3a3fe 100644
    --- a/packages/mermaid/src/dagre-wrapper/nodes.js
    +++ b/packages/mermaid/src/dagre-wrapper/nodes.js
    @@ -7,6 +7,7 @@ import createLabel from './createLabel.js';
     import note from './shapes/note.js';
     import { parseMember } from '../diagrams/class/svgDraw.js';
     import { evaluate } from '../diagrams/common/common.js';
    +import { getArrowPoints } from './blockArrowHelper.js';
     
     const question = async (parent, node) => {
       const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
    @@ -14,6 +15,7 @@ const question = async (parent, node) => {
       const w = bbox.width + node.padding;
       const h = bbox.height + node.padding;
       const s = w + h;
    +
       const points = [
         { x: s / 2, y: 0 },
         { x: s, y: -s / 2 },
    @@ -95,21 +97,33 @@ const hexagon = async (parent, node) => {
     
       return shapeSvg;
     };
    +
     const block_arrow = async (parent, node) => {
       const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true);
     
       const f = 2;
    -  const h = bbox.height + node.padding;
    +  const h = bbox.height + 2 * node.padding;
       const m = h / f;
       const w = bbox.width + 2 * m + node.padding;
    -  const points = [
    -    { x: m, y: 0 },
    -    { x: w - m, y: 0 },
    -    { x: w, y: -h / 2 },
    -    { x: w - m, y: -h },
    -    { x: m, y: -h },
    -    { x: 0, y: -h / 2 },
    -  ];
    +
    +  const p = node.padding / 2;
    +  //
    +  // const points = [
    +  //   { x: m, y: 0 },
    +  //   { x: m, y: -p },
    +  //   { x: w - m, y: -p },
    +  //   { x: w - m, y: 0 },
    +  //   // Right point
    +  //   { x: w, y: -h / 2 },
    +  //   // Point moving left and up from right point
    +  //   { x: w - m, y: -h },
    +  //   { x: w - m, y: -h + p },
    +  //   { x: m, y: -h + p },
    +  //   { x: m, y: -h },
    +  //   { x: 0, y: -h / 2 },
    +  // ];
    +
    +  const points = getArrowPoints(node.directions, bbox, node);
     
       const hex = insertPolygonShape(shapeSvg, w, h, points);
       hex.attr('style', node.style);
    @@ -1085,6 +1099,9 @@ export const insertNode = async (elem, node, dir) => {
       if (node.class) {
         el.attr('class', 'node default ' + node.class);
       }
    +  // MC Special
    +  newEl.attr('data-node', 'true');
    +  newEl.attr('data-id', node.id);
     
       nodeElems[node.id] = newEl;
     
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index 3cc9ec11d7..86f0b78bbb 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -66,9 +66,8 @@ const clear = (): void => {
     };
     
     type ITypeStr2Type = (typeStr: string) => BlockType;
    -export function typeStr2Type(typeStr: string) {
    +export function typeStr2Type(typeStr: string): BlockType {
       log.debug('typeStr2Type', typeStr);
    -  // TODO: add all types
       switch (typeStr) {
         case '[]':
           return 'square';
    @@ -80,7 +79,7 @@ export function typeStr2Type(typeStr: string) {
         case '>]':
           return 'rect_left_inv_arrow';
         case '{}':
    -      return 'question';
    +      return 'diamond';
         case '{{}}':
           return 'hexagon';
         case '([])':
    @@ -115,9 +114,10 @@ export const generateId = () => {
     
     type ISetHierarchy = (block: Block[]) => void;
     const setHierarchy = (block: Block[]): void => {
    +  // log.debug('The hierarchy', JSON.stringify(block, null, 2));
       rootBlock.children = block;
       populateBlockDatabase(block, rootBlock);
    -  log.debug('The hierarchy', JSON.stringify(rootBlock, null, 2));
    +  // log.debug('The hierarchy', JSON.stringify(rootBlock, null, 2));
       blocks = rootBlock.children;
     };
     
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index 91d26faf37..448ce0f415 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -44,8 +44,8 @@ CRLF \u000D\u000A
     [^`"]+        { return "MD_STR";}
     [`]["]          { this.popState();}
     ["]                     this.pushState("string");
    -["]             { log.debug('LEX: POPPING STR:', yytext);this.popState();}
    -[^"]*           { log.debug('LEX: STR ebd:', yytext); return "STR";}
    +["]             { yy.getLogger().debug('LEX: POPPING STR:', yytext);this.popState();}
    +[^"]*           { yy.getLogger().debug('LEX: STR ebd:', yytext); return "STR";}
     space[:]\d+            {  yytext = yytext.replace(/space\:/,'');yy.getLogger().info('SPACE NUM (LEX)', yytext); return 'SPACE_BLOCK'; }
     space                  { yytext = '1'; yy.getLogger().info('COLUMNS (LEX)', yytext); return 'SPACE_BLOCK'; }
     "style"               return 'STYLE';
    @@ -86,7 +86,7 @@ accDescr\s*"{"\s*                                { this.pushState("acc_descr_mul
     "[/"                   { this.pushState('NODE');return 'NODE_DSTART'; }
     "[\\"                  { this.pushState('NODE');return 'NODE_DSTART'; }
     
    -"<["                   { this.pushState('BLOCK_ARROW');log.debug('LEX ARR START');return 'BLOCK_ARROW_START'; }
    +"<["                   { this.pushState('BLOCK_ARROW');yy.getLogger().debug('LEX ARR START');return 'BLOCK_ARROW_START'; }
     
     [^\(\[\n\-\)\{\}\s\<]+     { yy.getLogger().info('Lex: NODE_ID', yytext);return 'NODE_ID'; }
     <>                { yy.getLogger().info('Lex: EOF', yytext);return 'EOF'; }
    @@ -98,8 +98,8 @@ accDescr\s*"{"\s*                                { this.pushState("acc_descr_mul
     [`]["]      { this.popState();}
     ["]              { yy.getLogger().info('Lex: Starting string');this.pushState("string");}
     ["]              { yy.getLogger().info('LEX ARR: Starting string');this.pushState("string");}
    -[^"]+          { log.debug('LEX: NODE_DESCR:', yytext); return "NODE_DESCR";}
    -["]            {log.debug('LEX POPPING');this.popState();}
    +[^"]+          { yy.getLogger().debug('LEX: NODE_DESCR:', yytext); return "NODE_DESCR";}
    +["]            {yy.getLogger().debug('LEX POPPING');this.popState();}
     
     // Node end of shape
     \]\>             { this.popState();yy.getLogger().info('Lex: ]>'); return "NODE_DEND"; }
    @@ -116,14 +116,14 @@ accDescr\s*"{"\s*                                { this.pushState("acc_descr_mul
     "/]"             { this.popState();yy.getLogger().info('Lex: /]'); return "NODE_DEND"; }
     ")]"             { this.popState();yy.getLogger().info('Lex: )]'); return "NODE_DEND"; }
     
    -"]>"\s*"("       { log.debug('Lex: =>BAE');  this.pushState('ARROW_DIR');  }
    -","?right\s*           { log.debug('Lex (right): dir:',yytext);return "DIR"; }
    -","?left\s*            { log.debug('Lex (left):',yytext);return "DIR"; }
    -","?x\s*               { log.debug('Lex (x):',yytext); return "DIR"; }
    -","?y\s*               { log.debug('Lex (y):',yytext); return "DIR"; }
    -","?up\s*              { log.debug('Lex (up):',yytext); return "DIR"; }
    -","?\s*down\s*     { yytext = yytext.replace(/^,\s*/, ''); log.debug('Lex (down):',yytext); return "DIR"; }
    -")"\s*             { yytext=']>';log.debug('Lex (ARROW_DIR end):',yytext);this.popState();this.popState();return "BLOCK_ARROW_END"; }
    +"]>"\s*"("       { yy.getLogger().debug('Lex: =>BAE');  this.pushState('ARROW_DIR');  }
    +","?\s*right\s*           { yytext = yytext.replace(/^,\s*/, ''); yy.getLogger().debug('Lex (right): dir:',yytext);return "DIR"; }
    +","?\s*left\s*            { yytext = yytext.replace(/^,\s*/, ''); yy.getLogger().debug('Lex (left):',yytext);return "DIR"; }
    +","?\s*x\s*               { yytext = yytext.replace(/^,\s*/, ''); yy.getLogger().debug('Lex (x):',yytext); return "DIR"; }
    +","?\s*y\s*               { yytext = yytext.replace(/^,\s*/, ''); yy.getLogger().debug('Lex (y):',yytext); return "DIR"; }
    +","?\s*up\s*              { yytext = yytext.replace(/^,\s*/, ''); yy.getLogger().debug('Lex (up):',yytext); return "DIR"; }
    +","?\s*down\s*     { yytext = yytext.replace(/^,\s*/, ''); yy.getLogger().debug('Lex (down):',yytext); return "DIR"; }
    +")"\s*             { yytext=']>';yy.getLogger().debug('Lex (ARROW_DIR end):',yytext);this.popState();this.popState();return "BLOCK_ARROW_END"; }
     
     // Edges
     \s*[xo<]?\-\-+[-xo>]\s*                 { yy.getLogger().info('Lex: LINK', '#'+yytext+'#'); return 'LINK'; }
    @@ -157,7 +157,7 @@ seperator
       ;
     
     start: BLOCK_DIAGRAM_KEY document EOF
    -  { yy.setHierarchy($2); }
    +  { yy.getLogger().info("Rule: hierarchy: ", $2); yy.setHierarchy($2); }
       ;
     
     
    @@ -171,8 +171,8 @@ stop
     
     //array of statements
     document
    -	: statement { yy.getLogger().info("Rule: statement: ", $1); $$ = [$1]; }
    -	| statement document { yy.getLogger().info("Rule: document statement: ", $1, $2); $$ = [$1].concat($2); }
    +	: statement { yy.getLogger().info("Rule: statement: ", $1); typeof $1.length === 'number'?$$ = $1:$$ = [$1]; }
    +	| statement document { yy.getLogger().info("Rule: statement #2: ", $1); $$ = [$1].concat($2); }
     	;
     
     link
    @@ -191,12 +191,12 @@ statement
     	;
     
     nodeStatement
    -  : nodeStatement link node { yy.getLogger().info('Rule: nodeStatement (nodeStatement link node) '); $$ = {id: $1.id}; }
    -  | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); $$ = {id: $1.id, label: $1.label, type: yy.typeStr2Type($1.typeStr)}; }
    +  : nodeStatement link node { yy.getLogger().info('Rule: (nodeStatement link node) ', $1, $2, $3); $$ = [{id: $1.id, label: $1.label, type:$1.type, directions: $1.directions}, {id: $3.id, label: $3.label, type: yy.typeStr2Type($3.typeStr), directions: $3.directions}]; }
    +  | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); $$ = {id: $1.id, label: $1.label, type: yy.typeStr2Type($1.typeStr), directions: $1.directions}; }
       ;
     
     columnsStatement
    -  : COLUMNS { yy.getLogger().info("COLUMNS: ", $1); $$ = {type: 'column-setting', columns: $1 === 'auto'?-1:parseInt($1) } }
    +  : COLUMNS { yy.getLogger().info('APA123', this? this:'na'); yy.getLogger().info("COLUMNS: ", $1); $$ = {type: 'column-setting', columns: $1 === 'auto'?-1:parseInt($1) } }
       ;
     
     blockStatement
    @@ -207,10 +207,11 @@ blockStatement
     node
       : NODE_ID
       { yy.getLogger().info("Rule: node (NODE_ID seperator): ", $1); $$ = { id: $1 }; }
    -  |NODE_ID nodeShapeNLabel
    -    { yy.getLogger().info("Rule: node (NODE_ID nodeShapeNLabel seperator): ", $1, $2); $$ = { id: $1, label: $2.label, typeStr: $2.typeStr };}
    -  // |nodeShapeNLabel seperator
    -  // { yy.getLogger().info("Rule: node (nodeShapeNLabel seperator): ", $1, $2, $3); }
    +  | NODE_ID nodeShapeNLabel
    +  {
    +    yy.getLogger().info("Rule: node (NODE_ID nodeShapeNLabel seperator): ", $1, $2);
    +    $$ = { id: $1, label: $2.label, typeStr: $2.typeStr, directions: $2.directions };
    +  }
       ;
     
     dirList: DIR { yy.getLogger().info("Rule: dirList: ", $1); $$ = [$1]; }
    @@ -221,7 +222,7 @@ nodeShapeNLabel
       :   NODE_DSTART STR NODE_DEND
     	      { yy.getLogger().info("Rule: nodeShapeNLabel: ", $1, $2, $3); $$ = { typeStr: $1 + $3, label: $2 }; }
     	|    BLOCK_ARROW_START STR dirList BLOCK_ARROW_END
    -    	      { yy.getLogger().info("Rule: BLOCK_ARROW nodeShapeNLabel: ", $1, $2, $3, $4); $$ = { typeStr: $1 + $4, label: $2, directions: $3}; }
    +    	      { yy.getLogger().info("Rule: BLOCK_ARROW nodeShapeNLabel: ", $1, $2, " #3:",$3, $4); $$ = { typeStr: $1 + $4, label: $2, directions: $3}; }
       ;
     
     %%
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index 142de0c5cd..125cd29978 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -114,6 +114,7 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
         class: classStr,
         style: styles.style,
         id: vertex.id,
    +    directions: vertex.directions,
         // link: vertex.link,
         // linkTarget: vertex.linkTarget,
         // tooltip: diagObj.db.getTooltip(vertex.id) || '',
    diff --git a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js
    index 23f94942c2..a887511d57 100644
    --- a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js
    +++ b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js
    @@ -360,8 +360,10 @@ export const getClasses = function (text, diagObj) {
      *
      * @param text
      * @param id
    + * @param _version
    + * @param diagObj
      */
    -
    +// [MermaidChart: 33a97b35-1f95-4ce9-81b5-3038669bc170]
     export const draw = async function (text, id, _version, diagObj) {
       log.info('Drawing flowchart');
       diagObj.db.clear();
    diff --git a/packages/mermaid/src/diagrams/flowchart/parser/flow.jison b/packages/mermaid/src/diagrams/flowchart/parser/flow.jison
    index 70fb491625..1957b4555c 100644
    --- a/packages/mermaid/src/diagrams/flowchart/parser/flow.jison
    +++ b/packages/mermaid/src/diagrams/flowchart/parser/flow.jison
    @@ -332,7 +332,7 @@ spaceList
     
     statement
         : verticeStatement separator
    -    { /* console.warn('finat vs', $1.nodes); */ $$=$1.nodes}
    +    { $$=$1.nodes}
         | styleStatement separator
         {$$=[];}
         | linkStyleStatement separator
    @@ -359,9 +359,9 @@ statement
     
     separator: NEWLINE | SEMI | EOF ;
     
    - 
    +
     verticeStatement: verticeStatement link node
    -        { /* console.warn('vs',$1.stmt,$3); */ yy.addLink($1.stmt,$3,$2); $$ = { stmt: $3, nodes: $3.concat($1.nodes) } }
    +        {/* console.warn('vs',$1.stmt,$3); */ yy.addLink($1.stmt,$3,$2); $$ = { stmt: $3, nodes: $3.concat($1.nodes) } }
         |  verticeStatement link node spaceList
             { /* console.warn('vs',$1.stmt,$3); */ yy.addLink($1.stmt,$3,$2); $$ = { stmt: $3, nodes: $3.concat($1.nodes) } }
         |node spaceList {/*console.warn('noda', $1);*/ $$ = {stmt: $1, nodes:$1 }}
    @@ -377,7 +377,7 @@ node: styledVertex
     styledVertex: vertex
             { /* console.warn('nod', $1); */ $$ = $1;}
         | vertex STYLE_SEPARATOR idString
    -        {$$ = $1;yy.setClass($1,$3)}
    +        { $$ = $1;yy.setClass($1,$3)}
         ;
     
     vertex:  idString SQS text SQE
    
    From 2ed4469029874a3750d3962ee37731e1c2d6b39e Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Thu, 4 Jan 2024 14:15:30 +0100
    Subject: [PATCH 28/97] #3358 Adding arrows to rendering
    
    ---
     cypress/platform/knsv2.html                   | 12 ++--
     packages/mermaid/src/dagre-wrapper/edges.js   |  3 +-
     .../mermaid/src/diagrams/block/blockDB.ts     | 69 +++++++++++++++++--
     .../src/diagrams/block/blockRenderer.ts       | 14 +++-
     .../mermaid/src/diagrams/block/blockTypes.ts  |  8 +++
     .../src/diagrams/block/parser/block.jison     | 11 ++-
     .../src/diagrams/block/renderHelpers.ts       | 68 ++++++++++++++++++
     7 files changed, 169 insertions(+), 16 deletions(-)
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index ab5c0aa3cc..80512993a4 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -72,7 +72,10 @@
         
     block-beta
    -      A("APA") --> B("GORILLA")
    +      columns 3
    +      A space space:3 B("GORILLA")
    +      A("APA") --o B
    +
         
     block-beta
    @@ -144,11 +147,8 @@
       %% end
         
    -block-beta
    -  id1
    -  block
    -  id2
    -  end
    +      flowchart LR
    +      a1 -- apa --> b1
         
     block-beta
    diff --git a/packages/mermaid/src/dagre-wrapper/edges.js b/packages/mermaid/src/dagre-wrapper/edges.js
    index 1581658b05..6563903293 100644
    --- a/packages/mermaid/src/dagre-wrapper/edges.js
    +++ b/packages/mermaid/src/dagre-wrapper/edges.js
    @@ -371,11 +371,12 @@ const cutPathAtIntersect = (_points, boundryNode) => {
     //(edgePaths, e, edge, clusterDb, diagramtype, graph)
     export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph) {
       let points = edge.points;
    +  log.info('abc88 InsertEdge: edge=', edge, 'e=', e);
       let pointsHasChanged = false;
       const tail = graph.node(e.v);
       var head = graph.node(e.w);
    +  log.info('abc88 InsertEdge (head & tail): ', head, tail);
     
    -  log.info('abc88 InsertEdge: ', edge);
       if (head.intersect && tail.intersect) {
         points = points.slice(1, edge.points.length - 1);
         points.unshift(tail.intersect(points[0]));
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index 86f0b78bbb..f5876849e5 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -17,12 +17,21 @@ import clone from 'lodash-es/clone.js';
     
     // Initialize the node database for simple lookups
     let blockDatabase: Record = {};
    -
    +let edgeList: Block[] = [];
    +let edgeCount: Record = {};
     const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
       const children = [];
       for (const block of blockList) {
         if (block.type === 'column-setting') {
           parent.columns = block.columns || -1;
    +    } else if (block.type === 'edge') {
    +      if (edgeCount[block.id]) {
    +        edgeCount[block.id]++;
    +      } else {
    +        edgeCount[block.id] = 1;
    +      }
    +      block.id = edgeCount[block.id] + '-' + block.id;
    +      edgeList.push(block);
         } else {
           if (!block.label) {
             if (block.type === 'composite') {
    @@ -31,7 +40,18 @@ const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
               block.label = block.id;
             }
           }
    -      blockDatabase[block.id] = block;
    +      const newBlock = !blockDatabase[block.id];
    +      if (newBlock) {
    +        blockDatabase[block.id] = block;
    +      } else {
    +        // Add newer relevant data to aggregated node
    +        if (block.type !== 'na') {
    +          blockDatabase[block.id].type = block.type;
    +        }
    +        if (block.label !== block.id) {
    +          blockDatabase[block.id].label = block.label;
    +        }
    +      }
     
           if (block.children) {
             populateBlockDatabase(block.children, block);
    @@ -46,7 +66,9 @@ const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
               children.push(newBlock);
             }
           } else {
    -        children.push(block);
    +        if (newBlock) {
    +          children.push(block);
    +        }
           }
         }
       }
    @@ -63,6 +85,9 @@ const clear = (): void => {
       rootBlock = { id: 'root', type: 'composite', children: [], columns: -1 } as Block;
       blockDatabase = { root: rootBlock };
       blocks = [] as Block[];
    +
    +  edgeList = [];
    +  edgeCount = {};
     };
     
     type ITypeStr2Type = (typeStr: string) => BlockType;
    @@ -101,7 +126,29 @@ export function typeStr2Type(typeStr: string): BlockType {
         case '<[]>':
           return 'block_arrow';
         default:
    -      return 'square';
    +      return 'na';
    +  }
    +}
    +
    +type IEdgeTypeStr2Type = (typeStr: string) => string;
    +export function edgeTypeStr2Type(typeStr: string): string {
    +  log.debug('typeStr2Type', typeStr);
    +  switch (typeStr) {
    +    case '==':
    +      return 'thick';
    +    default:
    +      return 'normal';
    +  }
    +}
    +type IEdgeStrToEdgeDataType = (typeStr: string) => string;
    +export function edgeStrToEdgeData(typeStr: string): string {
    +  switch (typeStr.trim()) {
    +    case '--x':
    +      return 'arrow_cross';
    +    case '--o':
    +      return 'arrow_circle';
    +    default:
    +      return 'arrow_point';
       }
     }
     
    @@ -114,10 +161,10 @@ export const generateId = () => {
     
     type ISetHierarchy = (block: Block[]) => void;
     const setHierarchy = (block: Block[]): void => {
    -  // log.debug('The hierarchy', JSON.stringify(block, null, 2));
    +  log.debug('The hierarchy', JSON.stringify(block, null, 2));
       rootBlock.children = block;
       populateBlockDatabase(block, rootBlock);
    -  // log.debug('The hierarchy', JSON.stringify(rootBlock, null, 2));
    +  log.debug('The hierarchy', JSON.stringify(rootBlock, null, 2));
       blocks = rootBlock.children;
     };
     
    @@ -146,6 +193,10 @@ type IGetBlocks = () => Block[];
     const getBlocks: IGetBlocks = () => {
       return blocks || [];
     };
    +type IGetEdges = () => Block[];
    +const getEdges: IGetEdges = () => {
    +  return edgeList;
    +};
     type IGetBlock = (id: string) => Block | undefined;
     const getBlock: IGetBlock = (id: string) => {
       return blockDatabase[id];
    @@ -166,12 +217,15 @@ export interface BlockDB extends DiagramDB {
       getConfig: () => BlockConfig | undefined;
       addLink: IAddLink;
       getLogger: IGetLogger;
    +  getEdges: IGetEdges;
       getBlocks: IGetBlocks;
       getBlock: IGetBlock;
       setBlock: ISetBlock;
       getLinks: IGetLinks;
       getColumns: IGetColumns;
       typeStr2Type: ITypeStr2Type;
    +  edgeTypeStr2Type: IEdgeTypeStr2Type;
    +  edgeStrToEdgeData: IEdgeStrToEdgeDataType;
       setHierarchy: ISetHierarchy;
       generateId: IGenerateId;
     }
    @@ -180,8 +234,11 @@ const db: BlockDB = {
       getConfig: () => configApi.getConfig().block,
       addLink: addLink,
       typeStr2Type: typeStr2Type,
    +  edgeTypeStr2Type: edgeTypeStr2Type,
    +  edgeStrToEdgeData,
       getLogger, // TODO: remove
       getBlocks,
    +  getEdges,
       getLinks,
       setHierarchy,
       getBlock,
    diff --git a/packages/mermaid/src/diagrams/block/blockRenderer.ts b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    index 2b691358cc..991adda3f3 100644
    --- a/packages/mermaid/src/diagrams/block/blockRenderer.ts
    +++ b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    @@ -1,8 +1,9 @@
     import { Diagram } from '../../Diagram.js';
     import * as configApi from '../../config.js';
    -import { calculateBlockSizes, insertBlocks } from './renderHelpers.js';
    +import { calculateBlockSizes, insertBlocks, insertEdges } from './renderHelpers.js';
     import { layout } from './layout.js';
     import { setupGraphViewbox } from '../../setupGraphViewbox.js';
    +import insertMarkers from '../../dagre-wrapper/markers.js';
     import {
       select as d3select,
       scaleOrdinal as d3scaleOrdinal,
    @@ -36,13 +37,22 @@ export const draw = async function (
       // @ts-ignore TODO root.select is not callable
       const svg = securityLevel === 'sandbox' ? root.select(`[id="${id}"]`) : d3select(`[id="${id}"]`);
     
    +  // Define the supported markers for the diagram
    +  const markers = ['point', 'circle', 'cross'];
    +
    +  // Add the marker definitions to the svg as marker tags
    +  // insertMarkers(svg, markers, diagObj.type, diagObj.arrowMarkerAbsolute);
    +  insertMarkers(svg, markers, diagObj.type, true);
    +
       const bl = db.getBlocks();
    +  const edges = db.getEdges();
     
       const nodes = svg.insert('g').attr('class', 'block');
       await calculateBlockSizes(nodes, bl, db);
       const bounds = layout(db);
    -  log.debug('Here blocks', bl);
    +  // log.debug('Here be blocks', bl);
       await insertBlocks(nodes, bl, db);
    +  await insertEdges(nodes, edges, bl, db);
     
       // log.debug('Here', bl);
     
    diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts
    index a65e5db324..4be03d9599 100644
    --- a/packages/mermaid/src/diagrams/block/blockTypes.ts
    +++ b/packages/mermaid/src/diagrams/block/blockTypes.ts
    @@ -5,7 +5,9 @@ export interface BlockConfig extends BaseDiagramConfig {
     }
     
     export type BlockType =
    +  | 'na'
       | 'column-setting'
    +  | 'edge'
       | 'round'
       | 'block_arrow'
       | 'space'
    @@ -29,9 +31,15 @@ export type BlockType =
       | 'composite';
     
     export interface Block {
    +  // When the block have the type edge, the start and end are the id of the source and target blocks
    +  start?: string;
    +  end?: string;
    +  arrowTypeEnd?: string;
    +  arrowTypeStart?: string;
       width?: number;
       id: string;
       label?: string;
    +  intersect?: any;
       parent?: Block;
       type?: BlockType;
       children: Block[];
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index 448ce0f415..d5e0ff8285 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -191,10 +191,19 @@ statement
     	;
     
     nodeStatement
    -  : nodeStatement link node { yy.getLogger().info('Rule: (nodeStatement link node) ', $1, $2, $3); $$ = [{id: $1.id, label: $1.label, type:$1.type, directions: $1.directions}, {id: $3.id, label: $3.label, type: yy.typeStr2Type($3.typeStr), directions: $3.directions}]; }
    +  : nodeStatement link node {
    +    yy.getLogger().info('Rule: (nodeStatement link node) ', $1, $2, $3, 'abc88 typestr =>',$2);
    +    const edgeData = yy.edgeStrToEdgeData($2)
    +    $$ = [
    +      {id: $1.id, label: $1.label, type:$1.type, directions: $1.directions},
    +      {id: $1.id + '-' + $3.id, start: $1.id, end: $3.id, label: $3.label, type: 'edge', directions: $3.directions, arrowTypeEnd: edgeData, arrowTypeStart: 'arrow_open' },
    +      {id: $3.id, label: $3.label, type: yy.typeStr2Type($3.typeStr), directions: $3.directions}
    +      ];
    +    }
       | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); $$ = {id: $1.id, label: $1.label, type: yy.typeStr2Type($1.typeStr), directions: $1.directions}; }
       ;
     
    +
     columnsStatement
       : COLUMNS { yy.getLogger().info('APA123', this? this:'na'); yy.getLogger().info("COLUMNS: ", $1); $$ = {type: 'column-setting', columns: $1 === 'auto'?-1:parseInt($1) } }
       ;
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index 125cd29978..73933426d3 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -1,5 +1,7 @@
     import { getStylesFromArray } from '../../utils.js';
     import { insertNode, positionNode } from '../../dagre-wrapper/nodes.js';
    +import { insertEdge } from '../../dagre-wrapper/edges.js';
    +import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
     import { getConfig } from '../../config.js';
     import { ContainerElement } from 'd3';
     import type { Block } from './blockTypes.js';
    @@ -127,6 +129,7 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
         x: bounds.x,
         y: bounds.y,
         positioned,
    +    intersect: undefined,
         type: vertex.type,
         // props: vertex.props,
         padding: padding ?? (getConfig()?.flowchart?.padding || 0),
    @@ -158,6 +161,7 @@ export async function insertBlockPositioned(elem: any, block: Block, db: any) {
       const obj = db.getBlock(node.id);
       if (obj.type !== 'space') {
         const nodeEl = await insertNode(elem, node);
    +    block.intersect = node?.intersect;
         positionNode(node);
       }
     }
    @@ -183,3 +187,67 @@ export async function calculateBlockSizes(elem: ContainerElement, blocks: Block[
     export async function insertBlocks(elem: ContainerElement, blocks: Block[], db: BlockDB) {
       await performOperations(elem, blocks, db, insertBlockPositioned);
     }
    +
    +export async function insertEdges(
    +  elem: ContainerElement,
    +  edges: Block[],
    +  blocks: Block[],
    +  db: BlockDB
    +) {
    +  const g = new graphlib.Graph({
    +    multigraph: true,
    +    compound: true,
    +  });
    +  g.setGraph({
    +    rankdir: 'TB',
    +    nodesep: 10,
    +    ranksep: 10,
    +    marginx: 8,
    +    marginy: 8,
    +  });
    +
    +  for (const block of blocks) {
    +    if (block.size) {
    +      g.setNode(block.id, {
    +        width: block.size.width,
    +        height: block.size.height,
    +        intersect: block.intersect,
    +      });
    +    }
    +  }
    +
    +  // log.debug('abc88 edges', edges);
    +  for (const edge of edges) {
    +    // elem, e, edge, clusterDb, diagramType, graph;
    +    if (edge.start && edge.end) {
    +      const startBlock = db.getBlock(edge.start);
    +      const endBlock = db.getBlock(edge.end);
    +
    +      if (startBlock?.size && endBlock?.size) {
    +        const start = startBlock.size;
    +        const end = endBlock.size;
    +        const points = [
    +          { x: start.x, y: start.y },
    +          { x: start.x + (end.x - start.x) / 2, y: start.y + (end.y - start.y) / 2 },
    +          { x: end.x, y: end.y },
    +        ];
    +        // edge.points = points;
    +        await insertEdge(
    +          elem,
    +          { v: edge.start, w: edge.end, name: edge.id },
    +          {
    +            ...edge,
    +            // arrowHead: 'normal',
    +            arrowTypeEnd: edge.arrowTypeEnd,
    +            arrowTypeStart: edge.arrowTypeStart,
    +            points,
    +            classes: 'edge-thickness-normal edge-pattern-solid flowchart-link LS-a1 LE-b1',
    +          },
    +          undefined,
    +          'block',
    +          g
    +        );
    +      }
    +    }
    +  }
    +}
    
    From d0eca268ad854ceb0fe736c1144cf73f876c4fe4 Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Thu, 4 Jan 2024 16:05:19 +0100
    Subject: [PATCH 29/97] #3358 Multiple arrows
    
    ---
     cypress/platform/knsv2.html                   | 37 ++++++++++++++++++-
     packages/mermaid/src/dagre-wrapper/edges.js   |  6 ++-
     .../mermaid/src/diagrams/block/blockDB.ts     | 27 ++++++++++++--
     .../src/diagrams/block/blockRenderer.ts       |  3 +-
     .../src/diagrams/block/parser/block.jison     | 22 +++++++----
     .../src/diagrams/block/renderHelpers.ts       |  8 +++-
     6 files changed, 86 insertions(+), 17 deletions(-)
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index 80512993a4..cefce1fb8c 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -73,8 +73,41 @@
         
     block-beta
           columns 3
    -      A space space:3 B("GORILLA")
    -      A("APA") --o B
    +      A
    +      space
    +      block
    +        E
    +        F
    +      end
    +      E --> A
    +    
    +
    +block-beta
    +      columns 3
    +      C space A space B
    +      B --> A
    +      B --> C
    +      block
    +        D
    +        E
    +      end
    +      E --> A
    +    
    +
    +block-beta
    +      columns 2
    +      C A B
    +      block
    +        D
    +        E
    +      end
    +    
    +
    +block-beta
    +      columns 2
    +      A B C D
    +      A --o B
    +      A --> C
     
         
    diff --git a/packages/mermaid/src/dagre-wrapper/edges.js b/packages/mermaid/src/dagre-wrapper/edges.js
    index 6563903293..8a71cc594e 100644
    --- a/packages/mermaid/src/dagre-wrapper/edges.js
    +++ b/packages/mermaid/src/dagre-wrapper/edges.js
    @@ -375,9 +375,9 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph
       let pointsHasChanged = false;
       const tail = graph.node(e.v);
       var head = graph.node(e.w);
    -  log.info('abc88 InsertEdge (head & tail): ', head, tail);
    +  log.info('abc88 InsertEdge (head & tail): ', e.v, head, ' --- ', e.w, tail);
     
    -  if (head.intersect && tail.intersect) {
    +  if (head?.intersect && tail?.intersect) {
         points = points.slice(1, edge.points.length - 1);
         points.unshift(tail.intersect(points[0]));
         log.info(
    @@ -387,6 +387,8 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph
           head.intersect(points[points.length - 1])
         );
         points.push(head.intersect(points[points.length - 1]));
    +  } else {
    +    log.info('abc88 No intersect');
       }
       if (edge.toCluster) {
         log.info('to cluster abc88', clusterDb[edge.toCluster]);
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index f5876849e5..c3861feab9 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -19,7 +19,9 @@ import clone from 'lodash-es/clone.js';
     let blockDatabase: Record = {};
     let edgeList: Block[] = [];
     let edgeCount: Record = {};
    -const populateBlockDatabase = (blockList: Block[], parent: Block): void => {
    +
    +const populateBlockDatabase = (_blockList: Block[], parent: Block): void => {
    +  const blockList = _blockList.flat();
       const children = [];
       for (const block of blockList) {
         if (block.type === 'column-setting') {
    @@ -161,10 +163,10 @@ export const generateId = () => {
     
     type ISetHierarchy = (block: Block[]) => void;
     const setHierarchy = (block: Block[]): void => {
    -  log.debug('The hierarchy', JSON.stringify(block, null, 2));
    +  log.debug('The document from parsing', JSON.stringify(block, null, 2));
       rootBlock.children = block;
       populateBlockDatabase(block, rootBlock);
    -  log.debug('The hierarchy', JSON.stringify(rootBlock, null, 2));
    +  log.debug('The document after popuplation', JSON.stringify(rootBlock, null, 2));
       blocks = rootBlock.children;
     };
     
    @@ -190,6 +192,23 @@ const getColumns = (blockid: string): number => {
     };
     
     type IGetBlocks = () => Block[];
    +/**
    + * Returns all the blocks as a flat array
    + * @returns
    + */
    +const getBlocksFlat: IGetBlocks = () => {
    +  const result: Block[] = [];
    +  console.log('abc88 getBlocksFlat', blockDatabase);
    +  const keys = Object.keys(blockDatabase);
    +  for (const key of keys) {
    +    result.push(blockDatabase[key]);
    +  }
    +  return result;
    +};
    +/**
    + * Returns the the hirarchy of blocks
    + * @returns
    + */
     const getBlocks: IGetBlocks = () => {
       return blocks || [];
     };
    @@ -218,6 +237,7 @@ export interface BlockDB extends DiagramDB {
       addLink: IAddLink;
       getLogger: IGetLogger;
       getEdges: IGetEdges;
    +  getBlocksFlat: IGetBlocks;
       getBlocks: IGetBlocks;
       getBlock: IGetBlock;
       setBlock: ISetBlock;
    @@ -237,6 +257,7 @@ const db: BlockDB = {
       edgeTypeStr2Type: edgeTypeStr2Type,
       edgeStrToEdgeData,
       getLogger, // TODO: remove
    +  getBlocksFlat,
       getBlocks,
       getEdges,
       getLinks,
    diff --git a/packages/mermaid/src/diagrams/block/blockRenderer.ts b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    index 991adda3f3..77e9cd9392 100644
    --- a/packages/mermaid/src/diagrams/block/blockRenderer.ts
    +++ b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    @@ -45,6 +45,7 @@ export const draw = async function (
       insertMarkers(svg, markers, diagObj.type, true);
     
       const bl = db.getBlocks();
    +  const blArr = db.getBlocksFlat();
       const edges = db.getEdges();
     
       const nodes = svg.insert('g').attr('class', 'block');
    @@ -52,7 +53,7 @@ export const draw = async function (
       const bounds = layout(db);
       // log.debug('Here be blocks', bl);
       await insertBlocks(nodes, bl, db);
    -  await insertEdges(nodes, edges, bl, db);
    +  await insertEdges(nodes, edges, blArr, db);
     
       // log.debug('Here', bl);
     
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index d5e0ff8285..579639d060 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -18,6 +18,7 @@
     %x NODE
     %x BLOCK_ARROW
     %x ARROW_DIR
    +%x LLABEL
     
     
     // as per section 6.1 of RFC 2234 [2]
    @@ -45,7 +46,7 @@ CRLF \u000D\u000A
     [`]["]          { this.popState();}
     ["]                     this.pushState("string");
     ["]             { yy.getLogger().debug('LEX: POPPING STR:', yytext);this.popState();}
    -[^"]*           { yy.getLogger().debug('LEX: STR ebd:', yytext); return "STR";}
    +[^"]*           { yy.getLogger().debug('LEX: STR end:', yytext); return "STR";}
     space[:]\d+            {  yytext = yytext.replace(/space\:/,'');yy.getLogger().info('SPACE NUM (LEX)', yytext); return 'SPACE_BLOCK'; }
     space                  { yytext = '1'; yy.getLogger().info('COLUMNS (LEX)', yytext); return 'SPACE_BLOCK'; }
     "style"               return 'STYLE';
    @@ -130,9 +131,14 @@ accDescr\s*"{"\s*                                { this.pushState("acc_descr_mul
     \s*[xo<]?\=\=+[=xo>]\s*                 { yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; }
     \s*[xo<]?\-?\.+\-[xo>]?\s*              { yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; }
     \s*\~\~[\~]+\s*                         { yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; }
    -\s*[xo<]?\-\-\s*                        { yy.getLogger().info('Lex: START_LINK', yytext); return 'START_LINK'; }
    -\s*[xo<]?\=\=\s*                        { yy.getLogger().info('Lex: START_LINK', yytext); return 'START_LINK'; }
    -\s*[xo<]?\-\.\s*                        { yy.getLogger().info('Lex: START_LINK', yytext); return 'START_LINK'; }
    +\s*[xo<]?\-\-\s*                        { yy.getLogger().info('Lex: START_LINK', yytext);this.pushState("LLABEL");return 'START_LINK'; }
    +\s*[xo<]?\=\=\s*                        { yy.getLogger().info('Lex: START_LINK', yytext);this.pushState("LLABEL");return 'START_LINK'; }
    +\s*[xo<]?\-\.\s*                        { yy.getLogger().info('Lex: START_LINK', yytext);this.pushState("LLABEL");return 'START_LINK'; }
    +["][`]           { this.pushState("md_string");}
    +["]              { yy.getLogger().info('Lex: Starting string');this.pushState("string"); return "LINK_LABEL";}
    +\s*[xo<]?\-\-+[-xo>]\s*                 { this.popState(); yy.getLogger().info('Lex: LINK', '#'+yytext+'#'); return 'LINK'; }
    +\s*[xo<]?\=\=+[=xo>]\s*                 { this.popState(); yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; }
    +\s*[xo<]?\-?\.+\-[xo>]?\s*              { this.popState(); yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; }
     
     /lex
     
    @@ -177,9 +183,9 @@ document
     
     link
       : LINK
    -  { yy.getLogger().info("Rule: link: ", $1); }
    -  | START_LINK
    -  { yy.getLogger().info("Rule: link: ", $1); }
    +  { yy.getLogger().info("Rule: link: ", $1, yytext); }
    +  | START_LINK LINK_LABEL STR LINK
    +  { yy.getLogger().info("Rule: LABEL link: ", $1, $3, $4); $$=$4; }
       ;
     
     statement
    @@ -192,7 +198,7 @@ statement
     
     nodeStatement
       : nodeStatement link node {
    -    yy.getLogger().info('Rule: (nodeStatement link node) ', $1, $2, $3, 'abc88 typestr =>',$2);
    +    yy.getLogger().info('Rule: (nodeStatement link node) ', $1, $2, $3, 'abc88 typestr: ',$2);
         const edgeData = yy.edgeStrToEdgeData($2)
         $$ = [
           {id: $1.id, label: $1.label, type:$1.type, directions: $1.directions},
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index 73933426d3..a6daa7651c 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -134,6 +134,7 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
         // props: vertex.props,
         padding: padding ?? (getConfig()?.flowchart?.padding || 0),
       };
    +  console.log('abc88 return node', vertex.id, node);
       return node;
     }
     type IOperation = (elem: any, block: any, db: any) => Promise;
    @@ -208,6 +209,7 @@ export async function insertEdges(
     
       for (const block of blocks) {
         if (block.size) {
    +      console.log('abc88 block', block, block.id);
           g.setNode(block.id, {
             width: block.size.width,
             height: block.size.height,
    @@ -216,12 +218,16 @@ export async function insertEdges(
         }
       }
     
    -  // log.debug('abc88 edges', edges);
    +  console.log('abc88 edges', edges);
       for (const edge of edges) {
         // elem, e, edge, clusterDb, diagramType, graph;
         if (edge.start && edge.end) {
           const startBlock = db.getBlock(edge.start);
    +      const startBlock2 = g.node(edge.start);
           const endBlock = db.getBlock(edge.end);
    +      const endBlock2 = g.node(edge.end);
    +      console.log('abc88 startBlock', startBlock2);
    +      console.log('abc88 endBlock', endBlock2);
     
           if (startBlock?.size && endBlock?.size) {
             const start = startBlock.size;
    
    From 72135c294ebdc2b009e3b7f63800f1d524b28eb0 Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Thu, 4 Jan 2024 16:28:13 +0100
    Subject: [PATCH 30/97] #3358 Edge labels
    
    ---
     cypress/platform/knsv2.html                        |  2 +-
     .../mermaid/src/diagrams/block/parser/block.jison  | 10 +++++-----
     .../mermaid/src/diagrams/block/renderHelpers.ts    | 14 ++++++++++++--
     3 files changed, 18 insertions(+), 8 deletions(-)
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index cefce1fb8c..82381d3cfa 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -79,7 +79,7 @@
             E
             F
           end
    -      E --> A
    +      E -- "apa" --> A
         
     block-beta
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index 579639d060..13932abd1d 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -183,9 +183,9 @@ document
     
     link
       : LINK
    -  { yy.getLogger().info("Rule: link: ", $1, yytext); }
    +  { yy.getLogger().info("Rule: link: ", $1, yytext); $$={edgeTypeStr: $1, label:''}; }
       | START_LINK LINK_LABEL STR LINK
    -  { yy.getLogger().info("Rule: LABEL link: ", $1, $3, $4); $$=$4; }
    +  { yy.getLogger().info("Rule: LABEL link: ", $1, $3, $4); $$={edgeTypeStr: $4, label:$3}; }
       ;
     
     statement
    @@ -198,11 +198,11 @@ statement
     
     nodeStatement
       : nodeStatement link node {
    -    yy.getLogger().info('Rule: (nodeStatement link node) ', $1, $2, $3, 'abc88 typestr: ',$2);
    -    const edgeData = yy.edgeStrToEdgeData($2)
    +    yy.getLogger().info('Rule: (nodeStatement link node) ', $1, $2, $3, 'abc88 typestr: ',$2.edgeTypeStr);
    +    const edgeData = yy.edgeStrToEdgeData($2.edgeTypeStr)
         $$ = [
           {id: $1.id, label: $1.label, type:$1.type, directions: $1.directions},
    -      {id: $1.id + '-' + $3.id, start: $1.id, end: $3.id, label: $3.label, type: 'edge', directions: $3.directions, arrowTypeEnd: edgeData, arrowTypeStart: 'arrow_open' },
    +      {id: $1.id + '-' + $3.id, start: $1.id, end: $3.id, label: $2.label, type: 'edge', directions: $3.directions, arrowTypeEnd: edgeData, arrowTypeStart: 'arrow_open' },
           {id: $3.id, label: $3.label, type: yy.typeStr2Type($3.typeStr), directions: $3.directions}
           ];
         }
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index a6daa7651c..107139ff60 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -1,6 +1,6 @@
     import { getStylesFromArray } from '../../utils.js';
     import { insertNode, positionNode } from '../../dagre-wrapper/nodes.js';
    -import { insertEdge } from '../../dagre-wrapper/edges.js';
    +import { insertEdge, insertEdgeLabel } from '../../dagre-wrapper/edges.js';
     import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
     import { getConfig } from '../../config.js';
     import { ContainerElement } from 'd3';
    @@ -243,7 +243,6 @@ export async function insertEdges(
               { v: edge.start, w: edge.end, name: edge.id },
               {
                 ...edge,
    -            // arrowHead: 'normal',
                 arrowTypeEnd: edge.arrowTypeEnd,
                 arrowTypeStart: edge.arrowTypeStart,
                 points,
    @@ -253,6 +252,17 @@ export async function insertEdges(
               'block',
               g
             );
    +        if (edge.label) {
    +          await insertEdgeLabel(elem, {
    +            ...edge,
    +            label: edge.label,
    +            labelStyle: 'stroke: #333; stroke-width: 1.5px;fill:none;',
    +            arrowTypeEnd: edge.arrowTypeEnd,
    +            arrowTypeStart: edge.arrowTypeStart,
    +            points,
    +            classes: 'edge-thickness-normal edge-pattern-solid flowchart-link LS-a1 LE-b1',
    +          });
    +        }
           }
         }
       }
    
    From 275e01acba557addbf2d863bf963946f1ee512e9 Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Fri, 5 Jan 2024 15:13:15 +0100
    Subject: [PATCH 31/97] #3358 Adding support for classDef and class statements
    
    ---
     cypress/platform/knsv2.html                   |  19 ++-
     .../mermaid/src/diagrams/block/blockDB.ts     | 118 +++++++++++++++++-
     .../src/diagrams/block/blockRenderer.ts       |  17 +++
     .../mermaid/src/diagrams/block/blockTypes.ts  |  10 ++
     .../src/diagrams/block/parser/block.jison     |  35 +++++-
     .../src/diagrams/block/renderHelpers.ts       |   2 +
     .../src/diagrams/flowchart/flowRenderer-v2.js |   2 +-
     packages/mermaid/src/mermaidAPI.ts            |   3 +
     8 files changed, 200 insertions(+), 6 deletions(-)
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index 82381d3cfa..a6553304c6 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -73,6 +73,22 @@
         
     block-beta
           columns 3
    +      classDef green fill:#9f6,stroke:#333,stroke-width:2px;
    +      A
    +      B
    +      class A green
    +    
    +
    +stateDiagram-v2
    +      classDef green fill:#9f6,stroke:#333,stroke-width:2px;
    +      A
    +      class A green
    +
    +    
    +
    +block-beta
    +      columns 3
    +      classDef green fill:#9f6,stroke:#333,stroke-width:2px;
           A
           space
           block
    @@ -80,6 +96,7 @@
             F
           end
           E -- "apa" --> A
    +
         
     block-beta
    @@ -538,7 +555,7 @@
             // console.error('Mermaid error: ', err);
           };
           mermaid.initialize({
    -        // theme: 'forest',
    +        theme: 'forest',
             startOnLoad: true,
             logLevel: 0,
             flowchart: {
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index c3861feab9..4a3a6a1465 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -1,6 +1,6 @@
     // import type { BlockDB } from './blockTypes.js';
     import type { DiagramDB } from '../../diagram-api/types.js';
    -import type { BlockConfig, BlockType, Block, Link } from './blockTypes.js';
    +import type { BlockConfig, BlockType, Block, Link, ClassDef } from './blockTypes.js';
     
     import * as configApi from '../../config.js';
     import {
    @@ -20,10 +20,112 @@ let blockDatabase: Record = {};
     let edgeList: Block[] = [];
     let edgeCount: Record = {};
     
    +const COLOR_KEYWORD = 'color';
    +const FILL_KEYWORD = 'fill';
    +const BG_FILL = 'bgFill';
    +const STYLECLASS_SEP = ',';
    +
    +let classes = {} as Record;
    +
    +/**
    + * Called when the parser comes across a (style) class definition
    + * @example classDef my-style fill:#f96;
    + *
    + * @param {string} id - the id of this (style) class
    + * @param  {string | null} styleAttributes - the string with 1 or more style attributes (each separated by a comma)
    + */
    +export const addStyleClass = function (id: string, styleAttributes = '') {
    +  // create a new style class object with this id
    +  if (classes[id] === undefined) {
    +    classes[id] = { id: id, styles: [], textStyles: [] }; // This is a classDef
    +  }
    +  const foundClass = classes[id];
    +  if (styleAttributes !== undefined && styleAttributes !== null) {
    +    styleAttributes.split(STYLECLASS_SEP).forEach((attrib) => {
    +      // remove any trailing ;
    +      const fixedAttrib = attrib.replace(/([^;]*);/, '$1').trim();
    +
    +      // replace some style keywords
    +      if (attrib.match(COLOR_KEYWORD)) {
    +        const newStyle1 = fixedAttrib.replace(FILL_KEYWORD, BG_FILL);
    +        const newStyle2 = newStyle1.replace(COLOR_KEYWORD, FILL_KEYWORD);
    +        foundClass.textStyles.push(newStyle2);
    +      }
    +      foundClass.styles.push(fixedAttrib);
    +    });
    +  }
    +};
    +
    +/**
    + * Add a (style) class or css class to a state with the given id.
    + * If the state isn't already in the list of known states, add it.
    + * Might be called by parser when a style class or CSS class should be applied to a state
    + *
    + * @param {string | string[]} itemIds The id or a list of ids of the item(s) to apply the css class to
    + * @param {string} cssClassName CSS class name
    + */
    +export const setCssClass = function (itemIds: string, cssClassName: string) {
    +  console.log('abc88 setCssClass enter', itemIds, cssClassName);
    +  itemIds.split(',').forEach(function (id: string) {
    +    let foundBlock = blockDatabase[id];
    +    if (foundBlock === undefined) {
    +      const trimmedId = id.trim();
    +      blockDatabase[trimmedId] = { id: trimmedId, type: 'na', children: [] } as Block;
    +      foundBlock = blockDatabase[trimmedId];
    +    }
    +    if (!foundBlock.classes) {
    +      foundBlock.classes = [];
    +    }
    +    foundBlock.classes.push(cssClassName);
    +    console.log('abc88 setCssClass', foundBlock);
    +  });
    +};
    +
    +// /**
    +//  * Add a style to a state with the given id.
    +//  * @example style stateId fill:#f9f,stroke:#333,stroke-width:4px
    +//  *   where 'style' is the keyword
    +//  *   stateId is the id of a state
    +//  *   the rest of the string is the styleText (all of the attributes to be applied to the state)
    +//  *
    +//  * @param itemId The id of item to apply the style to
    +//  * @param styleText - the text of the attributes for the style
    +//  */
    +// export const setStyle = function (itemId, styleText) {
    +//   const item = getState(itemId);
    +//   if (item !== undefined) {
    +//     item.textStyles.push(styleText);
    +//   }
    +// };
    +
    +// /**
    +//  * Add a text style to a state with the given id
    +//  *
    +//  * @param itemId The id of item to apply the css class to
    +//  * @param cssClassName CSS class name
    +//  */
    +// export const setTextStyle = function (itemId, cssClassName) {
    +//   const item = getState(itemId);
    +//   if (item !== undefined) {
    +//     item.textStyles.push(cssClassName);
    +//   }
    +// };
    +
     const populateBlockDatabase = (_blockList: Block[], parent: Block): void => {
       const blockList = _blockList.flat();
       const children = [];
       for (const block of blockList) {
    +    if (block.type === 'classDef') {
    +      console.log('abc88 classDef', block);
    +      addStyleClass(block.id, block.css);
    +      continue;
    +    }
    +    if (block.type === 'applyClass') {
    +      console.log('abc88 applyClass', block);
    +      // addStyleClass(block.id, block.css);
    +      setCssClass(block.id, block.styleClass);
    +      continue;
    +    }
         if (block.type === 'column-setting') {
           parent.columns = block.columns || -1;
         } else if (block.type === 'edge') {
    @@ -87,6 +189,7 @@ const clear = (): void => {
       rootBlock = { id: 'root', type: 'composite', children: [], columns: -1 } as Block;
       blockDatabase = { root: rootBlock };
       blocks = [] as Block[];
    +  classes = {} as Record;
     
       edgeList = [];
       edgeCount = {};
    @@ -166,7 +269,7 @@ const setHierarchy = (block: Block[]): void => {
       log.debug('The document from parsing', JSON.stringify(block, null, 2));
       rootBlock.children = block;
       populateBlockDatabase(block, rootBlock);
    -  log.debug('The document after popuplation', JSON.stringify(rootBlock, null, 2));
    +  log.debug('abc88 The document after popuplation', JSON.stringify(rootBlock, null, 2));
       blocks = rootBlock.children;
     };
     
    @@ -231,6 +334,15 @@ const getLinks: IGetLinks = () => links;
     type IGetLogger = () => Console;
     const getLogger: IGetLogger = () => console;
     
    +type IGetClasses = () => Record;
    +/**
    + * Return all of the style classes
    + * @returns {{} | any | classes}
    + */
    +export const getClasses = function () {
    +  console.log('abc88 block db getClasses', classes);
    +  return classes;
    +};
     export interface BlockDB extends DiagramDB {
       clear: () => void;
       getConfig: () => BlockConfig | undefined;
    @@ -243,6 +355,7 @@ export interface BlockDB extends DiagramDB {
       setBlock: ISetBlock;
       getLinks: IGetLinks;
       getColumns: IGetColumns;
    +  getClasses: IGetClasses;
       typeStr2Type: ITypeStr2Type;
       edgeTypeStr2Type: IEdgeTypeStr2Type;
       edgeStrToEdgeData: IEdgeStrToEdgeDataType;
    @@ -271,6 +384,7 @@ const db: BlockDB = {
       // getDiagramTitle,
       // setDiagramTitle,
       getColumns,
    +  getClasses,
       clear,
       generateId,
     };
    diff --git a/packages/mermaid/src/diagrams/block/blockRenderer.ts b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    index 77e9cd9392..69f0eefb0b 100644
    --- a/packages/mermaid/src/diagrams/block/blockRenderer.ts
    +++ b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    @@ -17,6 +17,22 @@ import type { Block } from './blockTypes.js';
     // import { diagram as BlockDiagram } from './blockDiagram.js';
     import { configureSvgSize } from '../../setupGraphViewbox.js';
     
    +/**
    + * Returns the all the styles from classDef statements in the graph definition.
    + *
    + * @param text
    + * @param diagObj
    + * @returns {object} ClassDef styles
    + */
    +export const getClasses = function (text: any, diagObj: any) {
    +  log.info('abc88 Extracting classes', diagObj.db.getClasses());
    +  try {
    +    return diagObj.db.getClasses();
    +  } catch (e) {
    +    return;
    +  }
    +};
    +
     export const draw = async function (
       text: string,
       id: string,
    @@ -99,4 +115,5 @@ export const draw = async function (
     
     export default {
       draw,
    +  getClasses,
     };
    diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts
    index 4be03d9599..241ad39349 100644
    --- a/packages/mermaid/src/diagrams/block/blockTypes.ts
    +++ b/packages/mermaid/src/diagrams/block/blockTypes.ts
    @@ -28,6 +28,8 @@ export type BlockType =
       | 'cylinder'
       | 'group'
       | 'doublecircle'
    +  | 'classDef'
    +  | 'applyClass'
       | 'composite';
     
     export interface Block {
    @@ -53,9 +55,17 @@ export interface Block {
       columns?: number; // | TBlockColumnsDefaultValue;
       classes?: string[];
       directions?: string[];
    +  css?: string;
    +  styleClass?: string;
     }
     
     export interface Link {
       source: Block;
       target: Block;
     }
    +
    +export interface ClassDef {
    +  id: string;
    +  textStyles: string[];
    +  styles: string[];
    +}
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index 13932abd1d..9228a3b8a0 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -19,6 +19,10 @@
     %x BLOCK_ARROW
     %x ARROW_DIR
     %x LLABEL
    +%x CLASS
    +%x CLASS_STYLE
    +%x CLASSDEF
    +%x CLASSDEFID
     
     
     // as per section 6.1 of RFC 2234 [2]
    @@ -53,8 +57,16 @@ space                  { yytext = '1'; yy.getLogger().info('COLUMNS (LEX)', yyte
     "default"             return 'DEFAULT';
     "linkStyle"           return 'LINKSTYLE';
     "interpolate"         return 'INTERPOLATE';
    -"classDef"            return 'CLASSDEF';
    -"class"               return 'CLASS';
    +
    +"classDef"\s+   { this.pushState('CLASSDEF'); return 'classDef'; }
    +DEFAULT\s+            { this.popState(); this.pushState('CLASSDEFID'); return 'DEFAULT_CLASSDEF_ID' }
    +\w+\s+                { this.popState(); this.pushState('CLASSDEFID'); return 'CLASSDEF_ID' }
    +[^\n]*              { this.popState(); return 'CLASSDEF_STYLEOPTS' }
    +
    +"class"\s+      { this.pushState('CLASS'); return 'class'; }
    +(\w+)+((","\s*\w+)*)     { this.popState(); this.pushState('CLASS_STYLE'); return 'CLASSENTITY_IDS' }
    +[^\n]*             { this.popState(); return 'STYLECLASS' }
    +
     accTitle\s*":"\s*                                               { this.pushState("acc_title");return 'acc_title'; }
     (?!\n|;|#)*[^\n]*                                    { this.popState(); return "acc_title_value"; }
     accDescr\s*":"\s*                                               { this.pushState("acc_descr");return 'acc_descr'; }
    @@ -194,6 +206,8 @@ statement
       | SPACE_BLOCK
         { const num=parseInt($1); const spaceId = yy.generateId(); $$ = { id: spaceId, type:'space', label:'', width: num, children: [] }}
       | blockStatement
    +  | classDefStatement
    +  | cssClassStatement
     	;
     
     nodeStatement
    @@ -240,4 +254,21 @@ nodeShapeNLabel
         	      { yy.getLogger().info("Rule: BLOCK_ARROW nodeShapeNLabel: ", $1, $2, " #3:",$3, $4); $$ = { typeStr: $1 + $4, label: $2, directions: $3}; }
       ;
     
    +
    +classDefStatement
    +  : classDef CLASSDEF_ID CLASSDEF_STYLEOPTS {
    +      $$ = { type: 'classDef', id: $2.trim(), css: $3.trim() };
    +      }
    +  | classDef DEFAULT CLASSDEF_STYLEOPTS {
    +      $$ = { type: 'classDef', id: $2.trim(), css: $3.trim() };
    +      }
    +  ;
    +
    +cssClassStatement
    +    : class CLASSENTITY_IDS STYLECLASS {
    +        //console.log('apply class: id(s): ',$2, '  style class: ', $3);
    +        $$={ type: 'applyClass', id: $2.trim(), styleClass: $3.trim() };
    +        }
    +    ;
    +
     %%
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index 107139ff60..ebe88efdc1 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -16,8 +16,10 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
     
       let classStr = 'default';
       if ((vertex?.classes?.length || 0) > 0) {
    +    console.log('abc88 vertex.classes', block.id, vertex?.classes);
         classStr = (vertex?.classes || []).join(' ');
       }
    +  console.log('abc88 vertex.classes done');
       classStr = classStr + ' flowchart-label';
     
       // We create a SVG label, either by delegating to addHtmlLabel or manually
    diff --git a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js
    index a887511d57..7c964b4e7e 100644
    --- a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js
    +++ b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js
    @@ -363,7 +363,7 @@ export const getClasses = function (text, diagObj) {
      * @param _version
      * @param diagObj
      */
    -// [MermaidChart: 33a97b35-1f95-4ce9-81b5-3038669bc170]
    +
     export const draw = async function (text, id, _version, diagObj) {
       log.info('Drawing flowchart');
       diagObj.db.clear();
    diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts
    index 4d8d952906..467f60c4e4 100644
    --- a/packages/mermaid/src/mermaidAPI.ts
    +++ b/packages/mermaid/src/mermaidAPI.ts
    @@ -39,6 +39,7 @@ const CLASSDEF_DIAGRAMS = [
       'flowchart-elk',
       'stateDiagram',
       'stateDiagram-v2',
    +  'block',
     ];
     const MAX_TEXTLENGTH = 50_000;
     const MAX_TEXTLENGTH_EXCEEDED_MSG =
    @@ -203,6 +204,8 @@ export const createCssStyles = (
         cssStyles += `\n:root { --mermaid-alt-font-family: ${config.altFontFamily}}`;
       }
     
    +  console.log('abc88 expr check', !isEmpty(classDefs), classDefs);
    +
       // classDefs defined in the diagram text
       if (!isEmpty(classDefs) && CLASSDEF_DIAGRAMS.includes(graphType)) {
         const htmlLabels = config.htmlLabels || config.flowchart?.htmlLabels; // TODO why specifically check the Flowchart diagram config?
    
    From 818cb2fd7665e9cc3b305bfe17de737f1b55ff16 Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Fri, 5 Jan 2024 20:56:57 +0100
    Subject: [PATCH 32/97] #3358 Adding support for style statements
    
    ---
     cypress/platform/knsv2.html                   | 38 ++++++++++++++-----
     .../mermaid/src/diagrams/block/blockDB.ts     | 27 +++++++++++--
     .../mermaid/src/diagrams/block/blockTypes.ts  |  2 +
     .../src/diagrams/block/parser/block.jison     | 15 +++++++-
     .../src/diagrams/block/renderHelpers.ts       |  9 ++---
     .../src/diagrams/flowchart/flowRenderer-v2.js |  2 +-
     packages/mermaid/src/mermaidAPI.ts            |  1 -
     7 files changed, 74 insertions(+), 20 deletions(-)
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index a6553304c6..5dc87325c7 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -72,18 +72,38 @@
         
     block-beta
    -      columns 3
    +columns 3
    +  space Browser space
    +  space:3
    +
    +    A
    +    B
    +    C
    +
    +    space:3
    +    space
    +    db{{"This is the text in the box"}}
    +
           classDef green fill:#9f6,stroke:#333,stroke-width:2px;
    -      A
    -      B
    -      class A green
    -    
    -
    -stateDiagram-v2
    -      classDef green fill:#9f6,stroke:#333,stroke-width:2px;
    -      A
    +      style B fill:#f9F,stroke:#333,stroke-width:4px
           class A green
     
    +      Browser --> A
    +      Browser --> B
    +      Browser --> C
    +      A --> db
    +      B --> db
    +      C--> db
    +
    +      block
    +        D
    +        E
    +      end
    +    
    +
    +flowchart
    +      B
    +      style B fill:#f9F,stroke:#333,stroke-width:4px
         
     block-beta
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index 4a3a6a1465..4ee5343fad 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -56,6 +56,20 @@ export const addStyleClass = function (id: string, styleAttributes = '') {
       }
     };
     
    +/**
    + * Called when the parser comes across a (style) class definition
    + * @example classDef my-style fill:#f96;
    + *
    + * @param {string} id - the id of this (style) class
    + * @param  {string | null} styles - the string with 1 or more style attributes (each separated by a comma)
    + */
    +export const addStyle2Node = function (id: string, styles = '') {
    +  let foundBlock = blockDatabase[id];
    +  if (styles !== undefined && styles !== null) {
    +    foundBlock.styles = styles.split(STYLECLASS_SEP);
    +  }
    +};
    +
     /**
      * Add a (style) class or css class to a state with the given id.
      * If the state isn't already in the list of known states, add it.
    @@ -116,14 +130,21 @@ const populateBlockDatabase = (_blockList: Block[], parent: Block): void => {
       const children = [];
       for (const block of blockList) {
         if (block.type === 'classDef') {
    -      console.log('abc88 classDef', block);
    +      // console.log('abc88 classDef', block);
           addStyleClass(block.id, block.css);
           continue;
         }
         if (block.type === 'applyClass') {
    -      console.log('abc88 applyClass', block);
    +      // console.log('abc88 applyClass', block);
    +      // addStyleClass(block.id, block.css);
    +      setCssClass(block.id, block?.styleClass || '');
    +      continue;
    +    }
    +    if (block.type === 'applyStyles') {
    +      console.log('abc88 applyStyles', block);
    +      addStyle2Node(block.id, block.styles);
           // addStyleClass(block.id, block.css);
    -      setCssClass(block.id, block.styleClass);
    +      // setCssClass(block.id, block.styles);
           continue;
         }
         if (block.type === 'column-setting') {
    diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts
    index 241ad39349..0cee35e445 100644
    --- a/packages/mermaid/src/diagrams/block/blockTypes.ts
    +++ b/packages/mermaid/src/diagrams/block/blockTypes.ts
    @@ -30,6 +30,7 @@ export type BlockType =
       | 'doublecircle'
       | 'classDef'
       | 'applyClass'
    +  | 'applyStyles'
       | 'composite';
     
     export interface Block {
    @@ -57,6 +58,7 @@ export interface Block {
       directions?: string[];
       css?: string;
       styleClass?: string;
    +  styles?: string[];
     }
     
     export interface Link {
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index 9228a3b8a0..86faa1d84b 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -23,6 +23,8 @@
     %x CLASS_STYLE
     %x CLASSDEF
     %x CLASSDEFID
    +%x STYLE_STMNT
    +%x STYLE_DEFINITION
     
     
     // as per section 6.1 of RFC 2234 [2]
    @@ -53,7 +55,6 @@ CRLF \u000D\u000A
     [^"]*           { yy.getLogger().debug('LEX: STR end:', yytext); return "STR";}
     space[:]\d+            {  yytext = yytext.replace(/space\:/,'');yy.getLogger().info('SPACE NUM (LEX)', yytext); return 'SPACE_BLOCK'; }
     space                  { yytext = '1'; yy.getLogger().info('COLUMNS (LEX)', yytext); return 'SPACE_BLOCK'; }
    -"style"               return 'STYLE';
     "default"             return 'DEFAULT';
     "linkStyle"           return 'LINKSTYLE';
     "interpolate"         return 'INTERPOLATE';
    @@ -67,6 +68,10 @@ space                  { yytext = '1'; yy.getLogger().info('COLUMNS (LEX)', yyte
     (\w+)+((","\s*\w+)*)     { this.popState(); this.pushState('CLASS_STYLE'); return 'CLASSENTITY_IDS' }
     [^\n]*             { this.popState(); return 'STYLECLASS' }
     
    +"style"\s+      { this.pushState('STYLE_STMNT'); return 'style'; }
    +(\w+)+((","\s*\w+)*)     { this.popState(); this.pushState('STYLE_DEFINITION'); return 'STYLE_ENTITY_IDS' }
    +[^\n]*             { this.popState(); return 'STYLE_DEFINITION_DATA' }
    +
     accTitle\s*":"\s*                                               { this.pushState("acc_title");return 'acc_title'; }
     (?!\n|;|#)*[^\n]*                                    { this.popState(); return "acc_title_value"; }
     accDescr\s*":"\s*                                               { this.pushState("acc_descr");return 'acc_descr'; }
    @@ -208,6 +213,7 @@ statement
       | blockStatement
       | classDefStatement
       | cssClassStatement
    +  | styleStatement
     	;
     
     nodeStatement
    @@ -271,4 +277,11 @@ cssClassStatement
             }
         ;
     
    +styleStatement
    +    : style STYLE_ENTITY_IDS STYLE_DEFINITION_DATA {
    +        console.log('abc88 apply class: id(s): ',$2, '  style class: ', $3);
    +        $$={ type: 'applyStyles', id: $2.trim(), styles: $3.trim() };
    +        }
    +    ;
    +
     %%
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index ebe88efdc1..130f031ca0 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -16,10 +16,9 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
     
       let classStr = 'default';
       if ((vertex?.classes?.length || 0) > 0) {
    -    console.log('abc88 vertex.classes', block.id, vertex?.classes);
         classStr = (vertex?.classes || []).join(' ');
       }
    -  console.log('abc88 vertex.classes done');
    +  console.log('abc88 vertex.classes styles', block.id, vertex?.styles);
       classStr = classStr + ' flowchart-label';
     
       // We create a SVG label, either by delegating to addHtmlLabel or manually
    @@ -100,8 +99,8 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
           _shape = 'rect';
       }
     
    -  // const styles = getStylesFromArray(vertex.styles);
    -  const styles = getStylesFromArray([]);
    +  const styles = getStylesFromArray(vertex?.styles || '');
    +  // const styles = getStylesFromArray([]);
     
       // Use vertex id as text in the box if no text is provided by the graph definition
       const vertexText = vertex.label;
    @@ -116,7 +115,7 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
         rx: radious,
         ry: radious,
         class: classStr,
    -    style: styles.style,
    +    style: styles.style, // + 'fill:#9f9;stroke:#333;stroke-width:4px;',
         id: vertex.id,
         directions: vertex.directions,
         // link: vertex.link,
    diff --git a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js
    index 7c964b4e7e..6f219f1665 100644
    --- a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js
    +++ b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js
    @@ -169,7 +169,7 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) {
           padding: getConfig().flowchart.padding,
         });
     
    -    log.info('setNode', {
    +    log.info('abc88 setNode', {
           labelStyle: styles.labelStyle,
           labelType: vertex.labelType,
           shape: _shape,
    diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts
    index 467f60c4e4..80837fd342 100644
    --- a/packages/mermaid/src/mermaidAPI.ts
    +++ b/packages/mermaid/src/mermaidAPI.ts
    @@ -513,7 +513,6 @@ const render = async function (
       const a11yTitle: string | undefined = diag.db.getAccTitle?.();
       const a11yDescr: string | undefined = diag.db.getAccDescription?.();
       addA11yInfo(diagramType, svgNode, a11yTitle, a11yDescr);
    -
       // -------------------------------------------------------------------------------
       // Clean up SVG code
       root.select(`[id="${id}"]`).selectAll('foreignobject > *').attr('xmlns', XMLNS_XHTML_STD);
    
    From 809c4501645d5e553bd32b102b5417ff2adb406d Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Mon, 8 Jan 2024 11:49:34 +0100
    Subject: [PATCH 33/97] #3358 Support for adding tests and fixed issues for
     some shapes
    
    ---
     cypress/integration/rendering/block.spec.ts   | 304 ++++++++++++++++++
     cypress/platform/knsv2.html                   | 177 ++--------
     .../src/diagrams/block/parser/block.jison     |  45 +--
     .../src/diagrams/block/renderHelpers.ts       |   2 +-
     4 files changed, 350 insertions(+), 178 deletions(-)
     create mode 100644 cypress/integration/rendering/block.spec.ts
    
    diff --git a/cypress/integration/rendering/block.spec.ts b/cypress/integration/rendering/block.spec.ts
    new file mode 100644
    index 0000000000..d43c8db10d
    --- /dev/null
    +++ b/cypress/integration/rendering/block.spec.ts
    @@ -0,0 +1,304 @@
    +import { imgSnapshotTest } from '../../helpers/util';
    +
    +describe('Block diagram', () => {
    +  it('BL1: should calculate the block widths', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +  columns 2
    +  block
    +    id2["I am a wide one"]
    +    id1
    +  end
    +  id["Next row"]
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL2: should handle colums statement in sub-blocks', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +  id1["Hello"]
    +  block
    +    columns 3
    +    id2["to"]
    +    id3["the"]
    +    id4["World"]
    +    id5["World"]
    +  end
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL3: should align block widths and handle colums statement in sub-blocks', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +  block
    +    columns 1
    +    id1
    +    id2
    +    id2.1
    +  end
    +  id3
    +  id4
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL4: should align block widths and handle colums statements in deeper sub-blocks then 1 level', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +  columns 1
    +  block
    +    columns 1
    +    block
    +      columns 3
    +      id1
    +      id2
    +      id2.1(("XYZ"))
    +    end
    +    id48
    +  end
    +  id3
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL5: should align block widths and handle colums statements in deeper sub-blocks then 1 level (alt)', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +  columns 1
    +  block
    +    id1
    +    id2
    +    block
    +      columns 1
    +      id3("Wider then")
    +      id5(("id5"))
    +    end
    +  end
    +  id4
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL6: should handle block arrows and spece statements', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +    columns 3
    +    space:3
    +    ida idb idc
    +    id1  id2
    +      blockArrowId<["Label"]>(right)
    +      blockArrowId2<["Label"]>(left)
    +      blockArrowId3<["Label"]>(up)
    +      blockArrowId4<["Label"]>(down)
    +      blockArrowId5<["Label"]>(x)
    +      blockArrowId6<["Label"]>(y)
    +      blockArrowId6<["Label"]>(x, down)
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL7: should handle different types of edges', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +      columns 3
    +      A space:5
    +      A --o B
    +      A --> C
    +      A --x D
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL8: should handle sub-blocks without columns statements', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +      columns 2
    +      C A B
    +      block
    +        D
    +        E
    +      end
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL9: should handle edges from blocks in sub blocks to other blocks', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +      columns 3
    +      B space
    +      block
    +        D
    +      end
    +      D --> B
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL10: should handle edges from composite blocks', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +      columns 3
    +      B space
    +      block BL
    +        D
    +      end
    +      BL --> B
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL11: should handle edges to composite blocks', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +      columns 3
    +      B space
    +      block BL
    +        D
    +      end
    +      B --> BL
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL12: edges should handle labels', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +      A
    +      space
    +      A -- "apa" --> E
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL13: should handle block arrows in different directions', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +      columns 3
    +      space blockArrowId1<["down"]>(down) space
    +      blockArrowId2<["right"]>(right) blockArrowId3<["Sync"]>(x, y) blockArrowId4<["left"]>(left)
    +      space blockArrowId5<["up"]>(up) space
    +      blockArrowId6<["x"]>(x) space blockArrowId7<["y"]>(y)
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL14: should style statements and class statements', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +    A
    +    B
    +    classDef blue fill:#66f,stroke:#333,stroke-width:2px;
    +    class A blue
    +    style B fill:#f9F,stroke:#333,stroke-width:4px
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL15: width alignment - D and E should share available space', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +  block
    +    D
    +    E
    +  end
    +  db("This is the text in the box")
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL16: width alignment - C should be as wide as the composite block', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +  block
    +    A("This is the text")
    +    B
    +  end
    +  C
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL16: width alignment - blocks shold be equal in width', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +    A("This is the text")
    +    B
    +    C
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL17: block types 1 - square, rounded and circle', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +    A["square"]
    +    B("rounded")
    +    C(("circle"))
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL18: block types 2 - odd, diamond and hexagon', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +    A>"rect_left_inv_arrow"]
    +    B{"diamond"}
    +    C{{"hexagon"}}
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL19: block types 3 - stadium', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +    A(["stadium"])
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL20: block types 4 - lean right, lean left, trapezoid and inv trapezoid', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +    A[/"lean right"/]
    +    B[\"lean left"\]
    +    C[/"trapezoid"\]
    +    D[\"trapezoid alt"/]
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL21: block types 1 - square, rounded and circle', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +    A["square"]
    +    B("rounded")
    +    C(("circle"))
    +      `,
    +      {}
    +    );
    +  });
    +});
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index 5dc87325c7..d84557ffee 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -64,184 +64,45 @@
       
         
     block-beta
    -      columns 3
    -      space blockArrowId1<["down"]>(down) space
    -      blockArrowId2<["right"]>(right) blockArrowId3<["Sync"]>(x, y) blockArrowId4<["left"]>(left)
    -      space blockArrowId5<["up"]>(up) space
    -      blockArrowId6<["x"]>(x) space blockArrowId7<["y"]>(y)
    -    
    -
    -block-beta
    -columns 3
    -  space Browser space
    -  space:3
    -
    -    A
    -    B
    -    C
    -
    -    space:3
    -    space
    -    db{{"This is the text in the box"}}
    -
    -      classDef green fill:#9f6,stroke:#333,stroke-width:2px;
    -      style B fill:#f9F,stroke:#333,stroke-width:4px
    -      class A green
    -
    -      Browser --> A
    -      Browser --> B
    -      Browser --> C
    -      A --> db
    -      B --> db
    -      C--> db
    -
    -      block
    -        D
    -        E
    -      end
    -    
    -
    -flowchart
    -      B
    -      style B fill:#f9F,stroke:#333,stroke-width:4px
    -    
    -
    -block-beta
    -      columns 3
    -      classDef green fill:#9f6,stroke:#333,stroke-width:2px;
    -      A
    -      space
    -      block
    -        E
    -        F
    -      end
    -      E -- "apa" --> A
    -
    +    A["square"]
    +    B("rounded")
    +    C(("circle"))
         
     block-beta
    -      columns 3
    -      C space A space B
    -      B --> A
    -      B --> C
    -      block
    -        D
    -        E
    -      end
    -      E --> A
    -    
    -
    -block-beta
    -      columns 2
    -      C A B
    -      block
    -        D
    -        E
    -      end
    +    A>"rect_left_inv_arrow"]
    +    B{"diamond"}
    +    C{{"hexagon"}}
         
     block-beta
    -      columns 2
    -      A B C D
    -      A --o B
    -      A --> C
    -
    +    A(["stadium"])
         
    -
    +    
     block-beta
    -    columns 3
    -    space:3
    -    ida idb idc
    -    id1  id2
    -      blockArrowId<["Label"]>(right)
    -      blockArrowId2<["Label"]>(left)
    -      blockArrowId3<["Label"]>(up)
    -      blockArrowId4<["Label"]>(down)
    -      blockArrowId5<["Label"]>(x)
    -      blockArrowId6<["Label"]>(y)
    -      blockArrowId6<["Label"]>(x, down)
    +    %% A[["subroutine"]]
    +    %% B[("cylinder")]
    +    C>"surprise"]
         
     block-beta
    -  columns 1
    -  block
    -    id1
    -    id2
    -    block
    -      columns 1
    -      id3("Wider then")
    -      id5(("id5"))
    -    end
    -  end
    -  id4
    +    A[/"lean right"/]
    +    B[\"lean left"\]
    +    C[/"trapezoid"\]
    +    D[\"trapezoid"/]
         
    -block-beta
    -  columns 1
    -  block
    -    columns 1
    -    block
    -      columns 3
    -      id1
    -      id2
    -      id2.1(("XYZ"))
    -      %%id2.2
    -    end
    -    id48
    -  end
    -  id3
    -%%  id3
    -%%  id4
    -  %% block
    -    %% columns 2
    -    %% id2
    -    %% id3
    -  %% end
    -    
    -
    -block-beta
    -  block
    -    columns 1
    -    id1
    -    id2
    -    %%id2.1
    -  end
    -  id3
    -%%  id3
    -%%  id4
    -  %% block
    -    %% columns 2
    -    %% id2
    -    %% id3
    -  %% end
    +flowchart
    +      B
    +      style B fill:#f9F,stroke:#333,stroke-width:4px
         
    +
           flowchart LR
           a1 -- apa --> b1
         
    -
    -block-beta
    -  id1["Hello"]
    -  block
    -    columns 3
    -    id2["to"]
    -    id3["the"]
    -    id4["World"]
    -    id5["World"]
    -  end
    -    
    -
    -block-beta
    -  columns 2
    -  block
    -    id2["I am a wide one"]
    -    id1
    -  end
    -  id[Next row]
    -
     
    -    
     flowchart RL
       subgraph "`one`"
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index 86faa1d84b..be4bed8095 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -86,27 +86,49 @@ accDescr\s*"{"\s*                                { this.pushState("acc_descr_mul
     .*direction\s+RL[^\n]*                                      return 'direction_rl';
     .*direction\s+LR[^\n]*                                      return 'direction_lr';
     
    +// Node end of shape
    +"((("             { this.popState();yy.getLogger().info('Lex: (('); return "NODE_DEND"; }
    +")))"             { this.popState();yy.getLogger().info('Lex: (('); return "NODE_DEND"; }
    +[\)]\)           { this.popState();yy.getLogger().info('Lex: ))'); return "NODE_DEND"; }
    +"}}"             { this.popState();yy.getLogger().info('Lex: (('); return "NODE_DEND"; }
    +"}"             { this.popState();yy.getLogger().info('Lex: (('); return "NODE_DEND"; }
    +"(-"             { this.popState();yy.getLogger().info('Lex: (-'); return "NODE_DEND"; }
    +"-)"             { this.popState();yy.getLogger().info('Lex: -)'); return "NODE_DEND"; }
    +"(("             { this.popState();yy.getLogger().info('Lex: (('); return "NODE_DEND"; }
    +"]]"             { this.popState();yy.getLogger().info('Lex: ]]'); return "NODE_DEND"; }
    +"("              { this.popState();yy.getLogger().info('Lex: (');  return "NODE_DEND";  }
    +"])"             { this.popState();yy.getLogger().info('Lex: ])'); return "NODE_DEND"; }
    +"\\]"             { this.popState();yy.getLogger().info('Lex: /]'); return "NODE_DEND"; }
    +"/]"             { this.popState();yy.getLogger().info('Lex: /]'); return "NODE_DEND"; }
    +")]"             { this.popState();yy.getLogger().info('Lex: )]'); return "NODE_DEND"; }
    +[\)]             { this.popState();yy.getLogger().info('Lex: )');  return "NODE_DEND"; }
    +\]\>             { this.popState();yy.getLogger().info('Lex: ]>'); return "NODE_DEND"; }
    +[\]]             { this.popState();yy.getLogger().info('Lex: ]'); return "NODE_DEND"; }
    +
     // Start of nodes with shapes and description
     "-)"                   { yy.getLogger().info('Lexa: -)'); this.pushState('NODE');return 'NODE_DSTART'; }
     "(-"                   { yy.getLogger().info('Lexa: (-'); this.pushState('NODE');return 'NODE_DSTART'; }
     "))"                   { yy.getLogger().info('Lexa: ))'); this.pushState('NODE');return 'NODE_DSTART';  }
     ")"                    { yy.getLogger().info('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART';      }
    +"((("                  { yy.getLogger().info('Lex: (((');  this.pushState('NODE');return 'NODE_DSTART'; }
     "(("                   { yy.getLogger().info('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; }
     "{{"                   { yy.getLogger().info('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; }
    -"("                    { yy.getLogger().info('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; }
    -"["                    { yy.getLogger().info('Lexa: ['); this.pushState('NODE');return 'NODE_DSTART'; }
    +"{"                   { yy.getLogger().info('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; }
    +">"                   { yy.getLogger().info('Lexc: >'); this.pushState('NODE');return 'NODE_DSTART'; }
     "(["                   { yy.getLogger().info('Lexa: (['); this.pushState('NODE');return 'NODE_DSTART'; }
    +"("                    { yy.getLogger().info('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; }
     "[["                   { this.pushState('NODE');return 'NODE_DSTART'; }
     "[|"                   { this.pushState('NODE');return 'NODE_DSTART'; }
     "[("                   { this.pushState('NODE');return 'NODE_DSTART'; }
    -"((("                  { this.pushState('NODE');return 'NODE_DSTART'; }
     ")))"                  { this.pushState('NODE');return 'NODE_DSTART'; }
    +"[\\"                   { this.pushState('NODE');return 'NODE_DSTART'; }
     "[/"                   { this.pushState('NODE');return 'NODE_DSTART'; }
     "[\\"                  { this.pushState('NODE');return 'NODE_DSTART'; }
    +"["                    { yy.getLogger().info('Lexa: ['); this.pushState('NODE');return 'NODE_DSTART'; }
     
     "<["                   { this.pushState('BLOCK_ARROW');yy.getLogger().debug('LEX ARR START');return 'BLOCK_ARROW_START'; }
     
    -[^\(\[\n\-\)\{\}\s\<]+     { yy.getLogger().info('Lex: NODE_ID', yytext);return 'NODE_ID'; }
    +[^\(\[\n\-\)\{\}\s\<\>]+     { yy.getLogger().info('Lex: NODE_ID', yytext);return 'NODE_ID'; }
     <>                { yy.getLogger().info('Lex: EOF', yytext);return 'EOF'; }
     
     // Handling of strings in node
    @@ -119,21 +141,6 @@ accDescr\s*"{"\s*                                { this.pushState("acc_descr_mul
     [^"]+          { yy.getLogger().debug('LEX: NODE_DESCR:', yytext); return "NODE_DESCR";}
     ["]            {yy.getLogger().debug('LEX POPPING');this.popState();}
     
    -// Node end of shape
    -\]\>             { this.popState();yy.getLogger().info('Lex: ]>'); return "NODE_DEND"; }
    -[\)]\)           { this.popState();yy.getLogger().info('Lex: ))'); return "NODE_DEND"; }
    -[\)]             { this.popState();yy.getLogger().info('Lex: )');  return "NODE_DEND"; }
    -[\]]             { this.popState();yy.getLogger().info('Lex: ]'); return "NODE_DEND"; }
    -"}}"             { this.popState();yy.getLogger().info('Lex: (('); return "NODE_DEND"; }
    -"(-"             { this.popState();yy.getLogger().info('Lex: (-'); return "NODE_DEND"; }
    -"-)"             { this.popState();yy.getLogger().info('Lex: -)'); return "NODE_DEND"; }
    -"(("             { this.popState();yy.getLogger().info('Lex: (('); return "NODE_DEND"; }
    -"("              { this.popState();yy.getLogger().info('Lex: (');  return "NODE_DEND";  }
    -"])"             { this.popState();yy.getLogger().info('Lex: ])'); return "NODE_DEND"; }
    -"]]"             { this.popState();yy.getLogger().info('Lex: ]]'); return "NODE_DEND"; }
    -"/]"             { this.popState();yy.getLogger().info('Lex: /]'); return "NODE_DEND"; }
    -")]"             { this.popState();yy.getLogger().info('Lex: )]'); return "NODE_DEND"; }
    -
     "]>"\s*"("       { yy.getLogger().debug('Lex: =>BAE');  this.pushState('ARROW_DIR');  }
     ","?\s*right\s*           { yytext = yytext.replace(/^,\s*/, ''); yy.getLogger().debug('Lex (right): dir:',yytext);return "DIR"; }
     ","?\s*left\s*            { yytext = yytext.replace(/^,\s*/, ''); yy.getLogger().debug('Lex (left):',yytext);return "DIR"; }
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index 130f031ca0..1179597966 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -71,7 +71,7 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
         case 'inv_trapezoid':
           _shape = 'inv_trapezoid';
           break;
    -    case 'odd_right':
    +    case 'rect_left_inv_arrow':
           _shape = 'rect_left_inv_arrow';
           break;
         case 'circle':
    
    From 7043892e871d0c413ec63dc1570a8ef738d15568 Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Mon, 8 Jan 2024 14:03:42 +0100
    Subject: [PATCH 34/97] #3358 Fix for layout where a siebling has wider siize
    
    ---
     cypress/integration/rendering/block.spec.ts   | 35 +++++++
     cypress/platform/knsv2.html                   | 48 +++++++++-
     .../mermaid/src/diagrams/block/blockDB.ts     | 11 +--
     .../src/diagrams/block/blockRenderer.ts       |  2 +-
     packages/mermaid/src/diagrams/block/layout.ts | 91 ++++++++++++-------
     .../src/diagrams/block/parser/block.jison     |  3 +-
     .../src/diagrams/block/renderHelpers.ts       |  6 --
     .../flowchart/elk/flowRenderer-elk.js         |  3 +-
     .../src/diagrams/flowchart/flowRenderer-v2.js |  2 +-
     packages/mermaid/src/mermaidAPI.ts            |  2 +-
     10 files changed, 147 insertions(+), 56 deletions(-)
    
    diff --git a/cypress/integration/rendering/block.spec.ts b/cypress/integration/rendering/block.spec.ts
    index d43c8db10d..7856f534d7 100644
    --- a/cypress/integration/rendering/block.spec.ts
    +++ b/cypress/integration/rendering/block.spec.ts
    @@ -301,4 +301,39 @@ describe('Block diagram', () => {
           {}
         );
       });
    +
    +  it('BL22: sizing - it should be possible to make a block wider', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +      A("rounded):2
    +      B:2
    +      C
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL23: sizing - it should be possieble to make a composite block wider', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +      block:2
    +        A
    +      end
    +      B
    +      `,
    +      {}
    +    );
    +  });
    +
    +  it('BL23: sizing - it should be possieble to make a composite block wider', () => {
    +    imgSnapshotTest(
    +      `block-beta
    +      block:2
    +        A
    +      end
    +      B
    +      `,
    +      {}
    +    );
    +  });
     });
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index d84557ffee..4fed7a9626 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -62,6 +62,52 @@
         
       
       
    +    
    +block-beta
    +columns 3
    +  space Browser space
    +  space:3
    +
    +    A
    +    B
    +    C
    +
    +    space:3
    +    space
    +    db{{"This is the text in the box"}}
    +
    +      classDef green fill:#9f6,stroke:#333,stroke-width:2px;
    +      style B fill:#f9F,stroke:#333,stroke-width:4px
    +      class A green
    +
    +      Browser --> A
    +      Browser --> B
    +      Browser --> C
    +      A --> db
    +      B --> db
    +      C--> db
    +
    +      block
    +        D
    +        E
    +      end
    +    
    +
    +block-beta
    +  block
    +    D
    +    E
    +  end
    +  db("This is the text in the box")
    +    
    +
    +block-beta
    +
    +      block
    +        D
    +      end
    +      A["A: I am a wide one"]
    +    
     block-beta
         A["square"]
    @@ -78,7 +124,7 @@
     block-beta
         A(["stadium"])
         
    -
    +    
     block-beta
         %% A[["subroutine"]]
         %% B[("cylinder")]
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index 4ee5343fad..e575f06805 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -79,7 +79,6 @@ export const addStyle2Node = function (id: string, styles = '') {
      * @param {string} cssClassName CSS class name
      */
     export const setCssClass = function (itemIds: string, cssClassName: string) {
    -  console.log('abc88 setCssClass enter', itemIds, cssClassName);
       itemIds.split(',').forEach(function (id: string) {
         let foundBlock = blockDatabase[id];
         if (foundBlock === undefined) {
    @@ -91,7 +90,6 @@ export const setCssClass = function (itemIds: string, cssClassName: string) {
           foundBlock.classes = [];
         }
         foundBlock.classes.push(cssClassName);
    -    console.log('abc88 setCssClass', foundBlock);
       });
     };
     
    @@ -130,21 +128,15 @@ const populateBlockDatabase = (_blockList: Block[], parent: Block): void => {
       const children = [];
       for (const block of blockList) {
         if (block.type === 'classDef') {
    -      // console.log('abc88 classDef', block);
           addStyleClass(block.id, block.css);
           continue;
         }
         if (block.type === 'applyClass') {
    -      // console.log('abc88 applyClass', block);
    -      // addStyleClass(block.id, block.css);
           setCssClass(block.id, block?.styleClass || '');
           continue;
         }
         if (block.type === 'applyStyles') {
    -      console.log('abc88 applyStyles', block);
    -      addStyle2Node(block.id, block.styles);
    -      // addStyleClass(block.id, block.css);
    -      // setCssClass(block.id, block.styles);
    +      addStyle2Node(block.id, block?.styles);
           continue;
         }
         if (block.type === 'column-setting') {
    @@ -361,7 +353,6 @@ type IGetClasses = () => Record;
      * @returns {{} | any | classes}
      */
     export const getClasses = function () {
    -  console.log('abc88 block db getClasses', classes);
       return classes;
     };
     export interface BlockDB extends DiagramDB {
    diff --git a/packages/mermaid/src/diagrams/block/blockRenderer.ts b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    index 69f0eefb0b..10d2f29066 100644
    --- a/packages/mermaid/src/diagrams/block/blockRenderer.ts
    +++ b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    @@ -25,7 +25,7 @@ import { configureSvgSize } from '../../setupGraphViewbox.js';
      * @returns {object} ClassDef styles
      */
     export const getClasses = function (text: any, diagObj: any) {
    -  log.info('abc88 Extracting classes', diagObj.db.getClasses());
    +  log.info('Extracting classes', diagObj.db.getClasses());
       try {
         return diagObj.db.getClasses();
       } catch (e) {
    diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts
    index f9a6cd3f9e..1b110fc64d 100644
    --- a/packages/mermaid/src/diagrams/block/layout.ts
    +++ b/packages/mermaid/src/diagrams/block/layout.ts
    @@ -34,28 +34,38 @@ export function calculateBlockPosition(columns: number, position: number): Block
       return { px, py };
     }
     
    -function calcBlockSizes(block: Block, db: BlockDB) {
    -  log.debug('calculateSize (start)', block.id, block?.size?.x, block?.size?.width);
    +const getMaxChildSize = (block: Block) => {
    +  let maxWidth = 0;
    +  let maxHeight = 0;
    +  // find max width of children
    +  for (const child of block.children) {
    +    const { width, height, x, y } = child.size || { width: 0, height: 0, x: 0, y: 0 };
    +    log.debug('abc88', child.id, width, height, x, y);
    +    if (width > maxWidth) {
    +      maxWidth = width;
    +    }
    +    if (height > maxHeight) {
    +      maxHeight = height;
    +    }
    +  }
    +  return { width: maxWidth, height: maxHeight };
    +};
    +
    +function setBlockSizes(block: Block, db: BlockDB, sieblingWidth: number = 0) {
    +  log.debug('calculateSize abc88 (start)', block.id, block?.size?.x, block?.size?.width);
       const totalWidth = 0;
       const totalHeight = 0;
       let maxWidth = 0;
       let maxHeight = 0;
     
    -  if (block.children) {
    +  if (block.children?.length > 0) {
         for (const child of block.children) {
    -      calcBlockSizes(child, db);
    +      setBlockSizes(child, db);
         }
         // find max width of children
    -    for (const child of block.children) {
    -      const { width, height, x, y } = child.size || { width: 0, height: 0, x: 0, y: 0 };
    -      // log.debug('APA', child.id, width, height, x, y);
    -      if (width > maxWidth) {
    -        maxWidth = width;
    -      }
    -      if (height > maxHeight) {
    -        maxHeight = height;
    -      }
    -    }
    +    const childSize = getMaxChildSize(block);
    +    maxWidth = childSize.width;
    +    maxHeight = childSize.height;
     
         // set width of block to max width of children
         for (const child of block.children) {
    @@ -66,22 +76,10 @@ function calcBlockSizes(block: Block, db: BlockDB) {
             child.size.y = 0;
           }
         }
    +    for (const child of block.children) {
    +      setBlockSizes(child, db, maxWidth);
    +    }
     
    -    // // Position items relative to self
    -    // let x = -padding / 2;
    -    // const y = 0;
    -
    -    // let accumulatedPaddingX = 0;
    -    // for (const child of block.children) {
    -    //   if (child.size) {
    -    //     child.size.x = x;
    -    //     child.size.y = y;
    -    //     x += maxWidth + padding;
    -    //   }
    -    //   accumulatedPaddingX += padding;
    -    // }
    -  }
    -  if (block.children?.length > 0) {
         const columns = block.columns || -1;
         const numItems = block.children.length;
     
    @@ -92,6 +90,33 @@ function calcBlockSizes(block: Block, db: BlockDB) {
         }
         const ySize = Math.ceil(numItems / xSize);
     
    +    let width = xSize * (maxWidth + padding) + padding;
    +    // If maxWidth
    +    if (width < sieblingWidth) {
    +      console.log(
    +        'Detected to small siebling: abc88',
    +        block.id,
    +        'sieblingWidth',
    +        sieblingWidth,
    +        'width',
    +        width
    +      );
    +      width = sieblingWidth;
    +      const childWidth = (sieblingWidth - xSize * padding - padding) / xSize;
    +      log.debug('Size indata abc88', block.id, 'childWidth', childWidth, 'maxWidth', maxWidth);
    +      log.debug('Size indata abc88 xSize', xSize, 'paddiong', padding);
    +
    +      // // set width of block to max width of children
    +      for (const child of block.children) {
    +        if (child.size) {
    +          child.size.width = childWidth;
    +          child.size.height = maxHeight;
    +          child.size.x = 0;
    +          child.size.y = 0;
    +        }
    +      }
    +    }
    +
         log.debug(
           '(calc)',
           block.id,
    @@ -105,13 +130,14 @@ function calcBlockSizes(block: Block, db: BlockDB) {
         );
     
         block.size = {
    -      width: xSize * (maxWidth + padding) + padding,
    +      width,
           height: ySize * (maxHeight + padding) + padding,
           x: 0,
           y: 0,
         };
       }
    -  log.debug('calculateSize APA (done)', block.id, block?.size?.x, block?.size?.width);
    +
    +  log.debug('calculateSize abc88 (done)', block.id, block?.size?.x, block?.size?.width);
     }
     
     function layoutBlocks(block: Block, db: BlockDB) {
    @@ -240,7 +266,8 @@ export function layout(db: BlockDB) {
       if (!root) {
         return;
       }
    -  calcBlockSizes(root, db);
    +
    +  setBlockSizes(root, db, 0);
       layoutBlocks(root, db);
       // Position blocks relative to parents
       // positionBlock(root, root, db);
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index be4bed8095..3f91a7d96e 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -225,7 +225,7 @@ statement
     
     nodeStatement
       : nodeStatement link node {
    -    yy.getLogger().info('Rule: (nodeStatement link node) ', $1, $2, $3, 'abc88 typestr: ',$2.edgeTypeStr);
    +    yy.getLogger().info('Rule: (nodeStatement link node) ', $1, $2, $3, ' typestr: ',$2.edgeTypeStr);
         const edgeData = yy.edgeStrToEdgeData($2.edgeTypeStr)
         $$ = [
           {id: $1.id, label: $1.label, type:$1.type, directions: $1.directions},
    @@ -286,7 +286,6 @@ cssClassStatement
     
     styleStatement
         : style STYLE_ENTITY_IDS STYLE_DEFINITION_DATA {
    -        console.log('abc88 apply class: id(s): ',$2, '  style class: ', $3);
             $$={ type: 'applyStyles', id: $2.trim(), styles: $3.trim() };
             }
         ;
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index 1179597966..757bbadb9b 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -18,7 +18,6 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
       if ((vertex?.classes?.length || 0) > 0) {
         classStr = (vertex?.classes || []).join(' ');
       }
    -  console.log('abc88 vertex.classes styles', block.id, vertex?.styles);
       classStr = classStr + ' flowchart-label';
     
       // We create a SVG label, either by delegating to addHtmlLabel or manually
    @@ -135,7 +134,6 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) {
         // props: vertex.props,
         padding: padding ?? (getConfig()?.flowchart?.padding || 0),
       };
    -  console.log('abc88 return node', vertex.id, node);
       return node;
     }
     type IOperation = (elem: any, block: any, db: any) => Promise;
    @@ -210,7 +208,6 @@ export async function insertEdges(
     
       for (const block of blocks) {
         if (block.size) {
    -      console.log('abc88 block', block, block.id);
           g.setNode(block.id, {
             width: block.size.width,
             height: block.size.height,
    @@ -219,7 +216,6 @@ export async function insertEdges(
         }
       }
     
    -  console.log('abc88 edges', edges);
       for (const edge of edges) {
         // elem, e, edge, clusterDb, diagramType, graph;
         if (edge.start && edge.end) {
    @@ -227,8 +223,6 @@ export async function insertEdges(
           const startBlock2 = g.node(edge.start);
           const endBlock = db.getBlock(edge.end);
           const endBlock2 = g.node(edge.end);
    -      console.log('abc88 startBlock', startBlock2);
    -      console.log('abc88 endBlock', endBlock2);
     
           if (startBlock?.size && endBlock?.size) {
             const start = startBlock.size;
    diff --git a/packages/mermaid/src/diagrams/flowchart/elk/flowRenderer-elk.js b/packages/mermaid/src/diagrams/flowchart/elk/flowRenderer-elk.js
    index 5ed06723e9..4d26f0afa3 100644
    --- a/packages/mermaid/src/diagrams/flowchart/elk/flowRenderer-elk.js
    +++ b/packages/mermaid/src/diagrams/flowchart/elk/flowRenderer-elk.js
    @@ -307,13 +307,12 @@ const getNextPosition = (position, edgeDirection, graphDirection) => {
         },
       };
       portPos.TD = portPos.TB;
    -  log.info('abc88', graphDirection, edgeDirection, position);
       return portPos[graphDirection][edgeDirection][position];
       // return 'south';
     };
     
     const getNextPort = (node, edgeDirection, graphDirection) => {
    -  log.info('getNextPort abc88', { node, edgeDirection, graphDirection });
    +  log.info('getNextPort', { node, edgeDirection, graphDirection });
       if (!portPos[node]) {
         switch (graphDirection) {
           case 'TB':
    diff --git a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js
    index 6f219f1665..7c964b4e7e 100644
    --- a/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js
    +++ b/packages/mermaid/src/diagrams/flowchart/flowRenderer-v2.js
    @@ -169,7 +169,7 @@ export const addVertices = function (vert, g, svgId, root, doc, diagObj) {
           padding: getConfig().flowchart.padding,
         });
     
    -    log.info('abc88 setNode', {
    +    log.info('setNode', {
           labelStyle: styles.labelStyle,
           labelType: vertex.labelType,
           shape: _shape,
    diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts
    index 80837fd342..aa5c1edeb9 100644
    --- a/packages/mermaid/src/mermaidAPI.ts
    +++ b/packages/mermaid/src/mermaidAPI.ts
    @@ -204,7 +204,7 @@ export const createCssStyles = (
         cssStyles += `\n:root { --mermaid-alt-font-family: ${config.altFontFamily}}`;
       }
     
    -  console.log('abc88 expr check', !isEmpty(classDefs), classDefs);
    +  console.log('expr check', !isEmpty(classDefs), classDefs);
     
       // classDefs defined in the diagram text
       if (!isEmpty(classDefs) && CLASSDEF_DIAGRAMS.includes(graphType)) {
    
    From 1d1875718dd6253e61edc2a062a736f8e6642e9c Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Mon, 8 Jan 2024 15:48:59 +0100
    Subject: [PATCH 35/97] #3358 Sieblinmg height alignment
    
    ---
     cypress/platform/knsv2.html                   | 32 +++-----
     .../mermaid/src/diagrams/block/blockDB.ts     |  9 ++-
     packages/mermaid/src/diagrams/block/layout.ts | 78 +++++++++++--------
     .../src/diagrams/block/parser/block.jison     |  6 +-
     4 files changed, 68 insertions(+), 57 deletions(-)
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index 4fed7a9626..eaa5382acd 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -64,33 +64,21 @@
       
         
     block-beta
    -columns 3
    -  space Browser space
    -  space:3
    -
    +columns 2
    +  db(("This is the text "))
    +  block
         A
    -    B
    -    C
    +  end
     
    -    space:3
    -    space
    -    db{{"This is the text in the box"}}
     
    -      classDef green fill:#9f6,stroke:#333,stroke-width:2px;
    -      style B fill:#f9F,stroke:#333,stroke-width:4px
    -      class A green
     
    -      Browser --> A
    -      Browser --> B
    -      Browser --> C
    -      A --> db
    -      B --> db
    -      C--> db
    +    
    +
    +block-beta
     
    -      block
    -        D
    -        E
    -      end
    +  A1:3
    +  A2:1
    +  A3
         
     block-beta
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index e575f06805..787084697d 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -173,7 +173,6 @@ const populateBlockDatabase = (_blockList: Block[], parent: Block): void => {
           if (block.children) {
             populateBlockDatabase(block.children, block);
           }
    -
           if (block.type === 'space') {
             const w = block.width || 1;
             for (let j = 0; j < w; j++) {
    @@ -186,6 +185,14 @@ const populateBlockDatabase = (_blockList: Block[], parent: Block): void => {
             if (newBlock) {
               children.push(block);
             }
    +        // const w = block.w || 1;
    +        // for (let j = 1; j < w; j++) {
    +        //   const newBlock = clone(block);
    +        //   newBlock.type = 'space';
    +        //   newBlock.id = newBlock.id + '-' + j;
    +        //   blockDatabase[newBlock.id] = newBlock;
    +        //   children.push(newBlock);
    +        // }
           }
         }
       }
    diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts
    index 1b110fc64d..cf62bd164d 100644
    --- a/packages/mermaid/src/diagrams/block/layout.ts
    +++ b/packages/mermaid/src/diagrams/block/layout.ts
    @@ -16,7 +16,7 @@ export function calculateBlockPosition(columns: number, position: number): Block
     
       // Ensure that position is a non-negative integer
       if (position < 0 || !Number.isInteger(position)) {
    -    throw new Error('Position must be a non-negative integer.');
    +    throw new Error('Position must be a non-negative integer.' + position);
       }
     
       if (columns < 0) {
    @@ -40,7 +40,6 @@ const getMaxChildSize = (block: Block) => {
       // find max width of children
       for (const child of block.children) {
         const { width, height, x, y } = child.size || { width: 0, height: 0, x: 0, y: 0 };
    -    log.debug('abc88', child.id, width, height, x, y);
         if (width > maxWidth) {
           maxWidth = width;
         }
    @@ -51,7 +50,12 @@ const getMaxChildSize = (block: Block) => {
       return { width: maxWidth, height: maxHeight };
     };
     
    -function setBlockSizes(block: Block, db: BlockDB, sieblingWidth: number = 0) {
    +function setBlockSizes(
    +  block: Block,
    +  db: BlockDB,
    +  sieblingWidth: number = 0,
    +  sieblingHeight: number = 0
    +) {
       log.debug('calculateSize abc88 (start)', block.id, block?.size?.x, block?.size?.width);
       const totalWidth = 0;
       const totalHeight = 0;
    @@ -70,27 +74,28 @@ function setBlockSizes(block: Block, db: BlockDB, sieblingWidth: number = 0) {
         // set width of block to max width of children
         for (const child of block.children) {
           if (child.size) {
    -        child.size.width = maxWidth;
    +        child.size.width = maxWidth * child.w + padding * (child.w - 1);
             child.size.height = maxHeight;
             child.size.x = 0;
             child.size.y = 0;
           }
         }
         for (const child of block.children) {
    -      setBlockSizes(child, db, maxWidth);
    +      setBlockSizes(child, db, maxWidth, maxHeight);
         }
     
         const columns = block.columns || -1;
         const numItems = block.children.length;
     
         // The width and height in number blocks
    -    let xSize = block.children?.length;
    +    let xSize = block.children.length;
         if (columns > 0 && columns < numItems) {
           xSize = columns;
         }
         const ySize = Math.ceil(numItems / xSize);
     
         let width = xSize * (maxWidth + padding) + padding;
    +    let height = ySize * (maxHeight + padding) + padding;
         // If maxWidth
         if (width < sieblingWidth) {
           console.log(
    @@ -98,19 +103,24 @@ function setBlockSizes(block: Block, db: BlockDB, sieblingWidth: number = 0) {
             block.id,
             'sieblingWidth',
             sieblingWidth,
    +        'sieblingHeight',
    +        sieblingHeight,
             'width',
             width
           );
           width = sieblingWidth;
    +      height = sieblingHeight;
           const childWidth = (sieblingWidth - xSize * padding - padding) / xSize;
    +      const childHeight = (sieblingHeight - ySize * padding - padding) / ySize;
           log.debug('Size indata abc88', block.id, 'childWidth', childWidth, 'maxWidth', maxWidth);
    +      log.debug('Size indata abc88', block.id, 'childHeight', childHeight, 'maxHeight', maxHeight);
           log.debug('Size indata abc88 xSize', xSize, 'paddiong', padding);
     
    -      // // set width of block to max width of children
    +      // set width of block to max width of children
           for (const child of block.children) {
             if (child.size) {
               child.size.width = childWidth;
    -          child.size.height = maxHeight;
    +          child.size.height = childHeight;
               child.size.x = 0;
               child.size.y = 0;
             }
    @@ -131,26 +141,35 @@ function setBlockSizes(block: Block, db: BlockDB, sieblingWidth: number = 0) {
     
         block.size = {
           width,
    -      height: ySize * (maxHeight + padding) + padding,
    +      height,
           x: 0,
           y: 0,
         };
       }
     
    -  log.debug('calculateSize abc88 (done)', block.id, block?.size?.x, block?.size?.width);
    +  log.debug(
    +    'setBlockSizes abc88 (done)',
    +    block.id,
    +    block?.size?.x,
    +    block?.size?.width,
    +    block?.size?.y,
    +    block?.size?.height
    +  );
     }
     
     function layoutBlocks(block: Block, db: BlockDB) {
       log.debug(
    -    'layout blocks (=>layoutBlocks)',
    +    'abc88 layout blocks (=>layoutBlocks)',
         block.id,
         'x:',
         block?.size?.x,
    +    'y:',
    +    block?.size?.y,
         'width:',
         block?.size?.width
       );
       const columns = block.columns || -1;
    -  log.debug('layoutBlocks columns', block.id, '=>', columns);
    +  log.debug('layoutBlocks columns abc88', block.id, '=>', columns);
       if (
         block.children && // find max width of children
         block.children.length > 0
    @@ -158,26 +177,12 @@ function layoutBlocks(block: Block, db: BlockDB) {
         const width = block?.children[0]?.size?.width || 0;
         const widthOfChildren = block.children.length * width + (block.children.length - 1) * padding;
     
    -    log.debug('widthOfChildren', widthOfChildren, 'posX');
    +    log.debug('widthOfChildren 88', widthOfChildren, 'posX');
     
         // let first = true;
    -    let columnPos = -1;
    +    let columnPos = 0;
         for (const child of block.children) {
    -      columnPos++;
    -
    -      // log.debug(
    -      //   'layout blocks (child)',
    -      //   child.id,
    -      //   'x:',
    -      //   child?.size?.x,
    -      //   'width:',
    -      //   child?.size?.width,
    -      //   'posX:',
    -      //   posX,
    -      //   block?.size?.x,
    -      //   widthOfChildren / 2,
    -      //   widthOfChildren / 2
    -      // );
    +      // columnPos++;
     
           if (!child.size) {
             continue;
    @@ -185,7 +190,12 @@ function layoutBlocks(block: Block, db: BlockDB) {
           const { width, height } = child.size;
           const { px, py } = calculateBlockPosition(columns, columnPos);
           log.debug(
    -        'layout blocks (child) px, py (',
    +        'abc88 layout blocks (child) id:',
    +        child.id,
    +        ' (px, py)',
    +        px,
    +        py,
    +        ' (',
             block?.size?.x,
             ',',
             block?.size?.y,
    @@ -205,7 +215,7 @@ function layoutBlocks(block: Block, db: BlockDB) {
               block.size.y - block.size.height / 2 + py * (height + padding) + height / 2 + padding;
     
             log.debug(
    -          'layout blocks (calc) px, py',
    +          'abc88 layout blocks (calc) px, py',
               'id:',
               child.id,
               '=>',
    @@ -220,6 +230,8 @@ function layoutBlocks(block: Block, db: BlockDB) {
           if (child.children) {
             layoutBlocks(child, db);
           }
    +      columnPos += parseInt(child?.w || 1);
    +      console.log('abc88', child, columnPos);
         }
       }
       log.debug(
    @@ -227,6 +239,8 @@ function layoutBlocks(block: Block, db: BlockDB) {
         block.id,
         'x:',
         block?.size?.x,
    +    'y:',
    +    block?.size?.y,
         'width:',
         block?.size?.width
       );
    @@ -267,7 +281,7 @@ export function layout(db: BlockDB) {
         return;
       }
     
    -  setBlockSizes(root, db, 0);
    +  setBlockSizes(root, db, 0, 0);
       layoutBlocks(root, db);
       // Position blocks relative to parents
       // positionBlock(root, root, db);
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index 3f91a7d96e..46e72e0ead 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -128,7 +128,7 @@ accDescr\s*"{"\s*                                { this.pushState("acc_descr_mul
     
     "<["                   { this.pushState('BLOCK_ARROW');yy.getLogger().debug('LEX ARR START');return 'BLOCK_ARROW_START'; }
     
    -[^\(\[\n\-\)\{\}\s\<\>]+     { yy.getLogger().info('Lex: NODE_ID', yytext);return 'NODE_ID'; }
    +[^\(\[\n\-\)\{\}\s\<\>:]+     { yy.getLogger().info('Lex: NODE_ID', yytext);return 'NODE_ID'; }
     <>                { yy.getLogger().info('Lex: EOF', yytext);return 'EOF'; }
     
     // Handling of strings in node
    @@ -163,6 +163,7 @@ accDescr\s*"{"\s*                                { this.pushState("acc_descr_mul
     \s*[xo<]?\-\-+[-xo>]\s*                 { this.popState(); yy.getLogger().info('Lex: LINK', '#'+yytext+'#'); return 'LINK'; }
     \s*[xo<]?\=\=+[=xo>]\s*                 { this.popState(); yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; }
     \s*[xo<]?\-?\.+\-[xo>]?\s*              { this.popState(); yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; }
    +':'\d+                   { yy.getLogger().info('Lex: COLON', yytext); yytext=yytext.slice(1);return 'SIZE'; }
     
     /lex
     
    @@ -233,7 +234,8 @@ nodeStatement
           {id: $3.id, label: $3.label, type: yy.typeStr2Type($3.typeStr), directions: $3.directions}
           ];
         }
    -  | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); $$ = {id: $1.id, label: $1.label, type: yy.typeStr2Type($1.typeStr), directions: $1.directions}; }
    +  | node SIZE { yy.getLogger().info('Rule: nodeStatement (abc88 node size) ', $1, $2); $$ = {id: $1.id, label: $1.label, type: yy.typeStr2Type($1.typeStr), directions: $1.directions, w: $2}; }
    +  | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); $$ = {id: $1.id, label: $1.label, type: yy.typeStr2Type($1.typeStr), directions: $1.directions, w:1}; }
       ;
     
     
    
    From bbc7fe616376bd5826bb5bf23f8f6666f88876ee Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Thu, 18 Jan 2024 10:22:09 +0100
    Subject: [PATCH 36/97] #3358 Fix for width of composite blocks
    
    ---
     cypress/platform/knsv2.html                   |  79 ++-
     .../mermaid/src/diagrams/block/blockDB.ts     |   1 +
     .../mermaid/src/diagrams/block/blockTypes.ts  |   1 +
     packages/mermaid/src/diagrams/block/layout.ts | 174 ++++-
     .../src/diagrams/block/parser/block.jison     |   4 +-
     packages/mermaid/src/docs/syntax/block.md     | 659 ++++++++++++++++++
     6 files changed, 875 insertions(+), 43 deletions(-)
     create mode 100644 packages/mermaid/src/docs/syntax/block.md
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index eaa5382acd..75b4418bd2 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -17,7 +17,7 @@
         
    +```
    +
    +**Example definition**
    +
    +```mermaid-example
    +block-beta
    +    A-->B[AAABBB]
    +    B-->D
    +    class A cssClass
    +```
    +
    +### Default class
    +
    +If a class is named default it will be assigned to all classes without specific class definitions.
    +
    +```
    +    classDef default fill:#f9f,stroke:#333,stroke-width:4px;
    +```
    +
    +## Basic support for fontawesome
    +
    +It is possible to add icons from fontawesome.
    +
    +The icons are accessed via the syntax fa:#icon class name#.
    +
    +```mermaid-example
    +flowchart TD
    +    B["fab:fa-twitter for peace"]
    +    B-->C[fa:fa-ban forbidden]
    +    B-->D(fa:fa-spinner)
    +    B-->E(A fa:fa-camera-retro perhaps?)
    +```
    +
    +Mermaid is compatible with Font Awesome up to verion 5, Free icons only. Check that the icons you use are from the [supported set of icons](https://fontawesome.com/v5/search?o=r&m=free).
    +
    +## Graph declarations with spaces between vertices and link and without semicolon
    +
    +- In graph declarations, the statements also can now end without a semicolon. After release 0.2.16, ending a graph statement with semicolon is just optional. So the below graph declaration is also valid along with the old declarations of the graph.
    +
    +- A single space is allowed between vertices and the link. However there should not be any space between a vertex and its text and a link and its text. The old syntax of graph declaration will also work and hence this new feature is optional and is introduced to improve readability.
    +
    +Below is the new declaration of the graph edges which is also valid along with the old declaration of the graph edges.
    +
    +```mermaid-example
    +block-beta
    +    A[Hard edge] -->|Link text| B(Round edge)
    +    B --> C{Decision}
    +    C -->|One| D[Result one]
    +    C -->|Two| E[Result two]
    +```
    +
    +## Configuration
    +
    +### Renderer
    +
    +The layout of the diagram is done with the renderer. The default renderer is dagre.
    +
    +Starting with Mermaid version 9.4, you can use an alternate renderer named elk. The elk renderer is better for larger and/or more complex diagrams.
    +
    +The _elk_ renderer is an experimenal feature.
    +You can change the renderer to elk by adding this directive:
    +
    +```
    +%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%%
    +```
    +
    +```note
    +Note that the site needs to use mermaid version 9.4+ for this to work and have this featured enabled in the lazy-loading configuration.
    +```
    +
    +### Width
    +
    +It is possible to adjust the width of the rendered flowchart.
    +
    +This is done by defining **mermaid.flowchartConfig** or by the CLI to use a JSON file with the configuration. How to use the CLI is described in the mermaidCLI page.
    +mermaid.flowchartConfig can be set to a JSON string with config parameters or the corresponding object.
    +
    +```javascript
    +mermaid.flowchartConfig = {
    +    width: 100%
    +}
    +```
    
    From a0d328d73465929fd98b19bda0c7b39670d7065d Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Thu, 18 Jan 2024 14:28:14 +0100
    Subject: [PATCH 37/97] #3358 Removed logging, fixed som tests
    
    ---
     cypress/platform/knsv2.html                   |  29 +-
     .../mermaid/src/dagre-wrapper/createLabel.js  |   2 +-
     .../mermaid/src/diagrams/block/blockDB.ts     |  10 +-
     .../src/diagrams/block/blockRenderer.ts       |   2 +-
     .../mermaid/src/diagrams/block/layout.spec.ts |   2 +-
     packages/mermaid/src/diagrams/block/layout.ts |  80 +-
     .../src/diagrams/block/parser/block.jison     | 158 ++--
     .../src/diagrams/block/parser/block.spec.ts   |  60 +-
     packages/mermaid/src/docs/syntax/block-old.md | 346 +++++++++
     packages/mermaid/src/docs/syntax/block.md     | 694 +++++++-----------
     packages/mermaid/src/mermaidAPI.ts            |   2 -
     11 files changed, 814 insertions(+), 571 deletions(-)
     create mode 100644 packages/mermaid/src/docs/syntax/block-old.md
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index 75b4418bd2..b2af1f5f9b 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -64,11 +64,24 @@
       
       
         
    +block-beta
    +        columns 3
    +        block1["Block 1"]
    +        blockArrow<["   "]>(right)
    +        block2["Block 2"]
    +    
    +
    +block-beta
    +columns 5
    +   A space B
    +   A --x B
    +    
    +
     block-beta
     columns 3
       a["A wide one"] b:2 c:2 d
         
    -
    +    
     block-beta
       block:e
           f
    @@ -96,7 +109,7 @@
       j
     
         
    -
    +    
     block-beta
     columns 3
       a b:2
    @@ -105,14 +118,14 @@
       end
       g h i
         
    -
    +    
     block-beta
     columns 3
       a b c
       e:3
       f g h
         
    -
    +    
     block-beta
     columns 1
       db(("DB"))
    @@ -128,14 +141,14 @@
       C --> D
       style B fill:#f9F,stroke:#333,stroke-width:4px
         
    -
    +    
     block-beta
     
       A1:3
       A2:1
       A3
         
    -
    +    
     block-beta
       block
         D
    @@ -143,7 +156,7 @@
       end
       db("This is the text in the box")
         
    -
    +    
     block-beta
     
           block
    @@ -151,7 +164,7 @@
           end
           A["A: I am a wide one"]
         
    -
    +    
     block-beta
         A["square"]
         B("rounded")
    diff --git a/packages/mermaid/src/dagre-wrapper/createLabel.js b/packages/mermaid/src/dagre-wrapper/createLabel.js
    index a8351c812f..adf5635f0e 100644
    --- a/packages/mermaid/src/dagre-wrapper/createLabel.js
    +++ b/packages/mermaid/src/dagre-wrapper/createLabel.js
    @@ -56,7 +56,7 @@ const createLabel = (_vertexText, style, isTitle, isNode) => {
       if (evaluate(getConfig().flowchart.htmlLabels)) {
         // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that?
         vertexText = vertexText.replace(/\\n|\n/g, '
    '); - log.info('vertexText' + vertexText); + log.debug('vertexText' + vertexText); const node = { isNode, label: decodeEntities(vertexText).replace( diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts index b410c238e4..7e7bd7528f 100644 --- a/packages/mermaid/src/diagrams/block/blockDB.ts +++ b/packages/mermaid/src/diagrams/block/blockDB.ts @@ -153,7 +153,7 @@ const populateBlockDatabase = (_blockList: Block[], parent: Block): void => { if (!block.label) { if (block.type === 'composite') { block.label = ''; - console.log('abc89 composite', block); + // log.debug('abc89 composite', block); } else { block.label = block.id; } @@ -175,6 +175,7 @@ const populateBlockDatabase = (_blockList: Block[], parent: Block): void => { populateBlockDatabase(block.children, block); } if (block.type === 'space') { + // log.debug('abc95 space', block); const w = block.width || 1; for (let j = 0; j < w; j++) { const newBlock = clone(block); @@ -182,6 +183,7 @@ const populateBlockDatabase = (_blockList: Block[], parent: Block): void => { blockDatabase[newBlock.id] = newBlock; children.push(newBlock); } + // log.debug('abc95 space2', children); } else { if (newBlock) { children.push(block); @@ -205,7 +207,7 @@ const links: Link[] = []; let rootBlock = { id: 'root', type: 'composite', children: [], columns: -1 } as Block; const clear = (): void => { - log.info('Clear called'); + log.debug('Clear called'); commonClear(); rootBlock = { id: 'root', type: 'composite', children: [], columns: -1 } as Block; blockDatabase = { root: rootBlock }; @@ -290,7 +292,7 @@ const setHierarchy = (block: Block[]): void => { log.debug('The document from parsing', JSON.stringify(block, null, 2)); rootBlock.children = block; populateBlockDatabase(block, rootBlock); - log.debug('abc88 The document after popuplation', JSON.stringify(rootBlock, null, 2)); + // log.debug('abc95 The document after popuplation', JSON.stringify(rootBlock, null, 2)); blocks = rootBlock.children; }; @@ -322,7 +324,7 @@ type IGetBlocks = () => Block[]; */ const getBlocksFlat: IGetBlocks = () => { const result: Block[] = []; - console.log('abc88 getBlocksFlat', blockDatabase); + // log.debug('abc88 getBlocksFlat', blockDatabase); const keys = Object.keys(blockDatabase); for (const key of keys) { result.push(blockDatabase[key]); diff --git a/packages/mermaid/src/diagrams/block/blockRenderer.ts b/packages/mermaid/src/diagrams/block/blockRenderer.ts index 10d2f29066..8bc5275746 100644 --- a/packages/mermaid/src/diagrams/block/blockRenderer.ts +++ b/packages/mermaid/src/diagrams/block/blockRenderer.ts @@ -25,7 +25,7 @@ import { configureSvgSize } from '../../setupGraphViewbox.js'; * @returns {object} ClassDef styles */ export const getClasses = function (text: any, diagObj: any) { - log.info('Extracting classes', diagObj.db.getClasses()); + log.debug('Extracting classes', diagObj.db.getClasses()); try { return diagObj.db.getClasses(); } catch (e) { diff --git a/packages/mermaid/src/diagrams/block/layout.spec.ts b/packages/mermaid/src/diagrams/block/layout.spec.ts index 1de79c880c..6c77c8fd19 100644 --- a/packages/mermaid/src/diagrams/block/layout.spec.ts +++ b/packages/mermaid/src/diagrams/block/layout.spec.ts @@ -8,6 +8,6 @@ describe('Layout', function () { expect(calculateBlockPosition(2, 2)).toEqual({ px: 0, py: 1 }); expect(calculateBlockPosition(2, 3)).toEqual({ px: 1, py: 1 }); expect(calculateBlockPosition(2, 4)).toEqual({ px: 0, py: 2 }); - expect(calculateBlockPosition(1, 3)).toEqual({ px: 0, py: 2 }); + expect(calculateBlockPosition(1, 3)).toEqual({ px: 0, py: 3 }); }); }); diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts index 205e03747c..e06d6ff10d 100644 --- a/packages/mermaid/src/diagrams/block/layout.ts +++ b/packages/mermaid/src/diagrams/block/layout.ts @@ -9,7 +9,7 @@ interface BlockPosition { } export function calculateBlockPosition(columns: number, position: number): BlockPosition { - console.log('calculateBlockPosition abc89', columns, position); + // log.debug('calculateBlockPosition abc89', columns, position); // Ensure that columns is a positive integer if (columns === 0 || !Number.isInteger(columns)) { throw new Error('Columns must be an integer !== 0.'); @@ -31,7 +31,7 @@ export function calculateBlockPosition(columns: number, position: number): Block // Calculate posX and posY const px = position % columns; const py = Math.floor(position / columns); - console.log('calculateBlockPosition abc89', columns, position, '=> (', px, py, ')'); + // log.debug('calculateBlockPosition abc89', columns, position, '=> (', px, py, ')'); return { px, py }; } @@ -39,10 +39,10 @@ const getMaxChildSize = (block: Block) => { let maxWidth = 0; let maxHeight = 0; // find max width of children - console.log('getMaxChildSize abc95 (start) parent:', block.id); + // log.debug('getMaxChildSize abc95 (start) parent:', block.id); for (const child of block.children) { const { width, height, x, y } = child.size || { width: 0, height: 0, x: 0, y: 0 }; - console.log( + log.debug( 'getMaxChildSize abc95 child:', child.id, 'width:', @@ -52,8 +52,12 @@ const getMaxChildSize = (block: Block) => { 'x:', x, 'y:', - y + y, + child.type ); + if (child.type === 'space') { + continue; + } if (width > maxWidth) { maxWidth = width / (block.w || 1); } @@ -70,15 +74,23 @@ function setBlockSizes( sieblingWidth: number = 0, sieblingHeight: number = 0 ) { - console.log( + log.debug( 'setBlockSizes abc95 (start)', block.id, block?.size?.x, 'block width =', - block?.size?.width, + block?.size, 'sieblingWidth', sieblingWidth ); + if (!block?.size?.width) { + block.size = { + width: sieblingWidth, + height: sieblingHeight, + x: 0, + y: 0, + }; + } const totalWidth = 0; const totalHeight = 0; let maxWidth = 0; @@ -92,31 +104,25 @@ function setBlockSizes( const childSize = getMaxChildSize(block); maxWidth = childSize.width; maxHeight = childSize.height; - console.log( - 'setBlockSizes abc95 maxWidth of', - block.id, - ':s children is ', - maxWidth, - maxHeight - ); + log.debug('setBlockSizes abc95 maxWidth of', block.id, ':s children is ', maxWidth, maxHeight); // set width of block to max width of children for (const child of block.children) { if (child.size) { - // console.log( - // 'abc95 Setting size of children of', - // block.id, - // 'id=', - // child.id, - // maxWidth, - // maxHeight, - // child.size - // ); + log.debug( + 'abc95 Setting size of children of', + block.id, + 'id=', + child.id, + maxWidth, + maxHeight, + child.size + ); child.size.width = maxWidth * child.w + padding * (child.w - 1); child.size.height = maxHeight; child.size.x = 0; child.size.y = 0; - console.log( + log.debug( 'abc95 updating size of ', block.id, ' children child:', @@ -129,9 +135,9 @@ function setBlockSizes( } } for (const child of block.children) { - // console.log('abc95 fin 2 Setting size', child.id, maxWidth, maxHeight, child.size); + // log.debug('abc95 fin 2 Setting size', child.id, maxWidth, maxHeight, child.size); setBlockSizes(child, db, maxWidth, maxHeight); - // console.log('abc95 fin 3 Setting size', child.id, maxWidth, maxHeight, child.size); + // log.debug('abc95 fin 3 Setting size', child.id, maxWidth, maxHeight, child.size); } const columns = block.columns || -1; @@ -151,7 +157,7 @@ function setBlockSizes( let height = ySize * (maxHeight + padding) + padding; // If maxWidth if (width < sieblingWidth) { - console.log( + log.debug( 'Detected to small siebling: abc95', block.id, 'sieblingWidth', @@ -180,7 +186,7 @@ function setBlockSizes( } } - console.log( + log.debug( 'abc95 (finale calc)', block.id, 'xSize', @@ -200,7 +206,7 @@ function setBlockSizes( const num = block.children.length; if (num > 0) { const childWidth = (width - num * padding - padding) / num; - // console.log('abc95 (finale calc) width', block.id, width, block.size?.width, childWidth); + // log.debug('abc95 (finale calc) width', block.id, width, block.size?.width, childWidth); for (const child of block.children) { if (child.size) { child.size.width = childWidth; @@ -216,7 +222,7 @@ function setBlockSizes( }; } - console.log( + log.debug( 'setBlockSizes abc94 (done)', block.id, block?.size?.x, @@ -228,7 +234,7 @@ function setBlockSizes( function layoutBlocks(block: Block, db: BlockDB) { log.debug( - 'abc89 layout blocks (=>layoutBlocks)', + 'abc85 layout blocks (=>layoutBlocks)', block.id, 'x:', block?.size?.x, @@ -238,7 +244,7 @@ function layoutBlocks(block: Block, db: BlockDB) { block?.size?.width ); const columns = block.columns || -1; - console.log('layoutBlocks columns abc91', block.id, '=>', columns, block); + log.debug('layoutBlocks columns abc95', block.id, '=>', columns, block); if ( block.children && // find max width of children block.children.length > 0 @@ -250,7 +256,7 @@ function layoutBlocks(block: Block, db: BlockDB) { // let first = true; let columnPos = 0; - console.log('abc91 block?.size?.x', block.id, block?.size?.x); + log.debug('abc91 block?.size?.x', block.id, block?.size?.x); let startingPosX = block?.size?.x ? block?.size?.x + (-block?.size?.width / 2 || 0) : -padding; let rowPos = 0; for (const child of block.children) { @@ -265,7 +271,7 @@ function layoutBlocks(block: Block, db: BlockDB) { rowPos = py; startingPosX = block?.size?.x || -padding; } - console.log( + log.debug( 'abc89 layout blocks (child) id:', child.id, 'Pos:', @@ -294,7 +300,7 @@ function layoutBlocks(block: Block, db: BlockDB) { const halfWidth = width / 2; child.size.x = startingPosX + padding + halfWidth; - console.log( + log.debug( 'abc91 layout blocks (calc) px, py', 'id:', child.id, @@ -323,7 +329,7 @@ function layoutBlocks(block: Block, db: BlockDB) { child.size.y = parent.size.y - parent.size.height / 2 + py * (height + padding) + height / 2 + padding; - console.log( + log.debug( 'abc88 layout blocks (calc) px, py', 'id:', child.id, @@ -347,7 +353,7 @@ function layoutBlocks(block: Block, db: BlockDB) { layoutBlocks(child, db); } columnPos += child?.w || 1; - console.log('abc88 columnsPos', child, columnPos); + log.debug('abc88 columnsPos', child, columnPos); } } log.debug( diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison index 9020cb7617..066b7be0fc 100644 --- a/packages/mermaid/src/diagrams/block/parser/block.jison +++ b/packages/mermaid/src/diagrams/block/parser/block.jison @@ -37,24 +37,24 @@ CRLF \u000D\u000A %% "block-beta" { return 'BLOCK_DIAGRAM_KEY'; } -"block"\s+ { yy.getLogger().info('Found space-block'); return 'block';} -"block"\n+ { yy.getLogger().info('Found nl-block'); return 'block';} -"block:" { yy.getLogger().info('Found space-block'); return 'id-block';} -// \s*\%\%.* { yy.getLogger().info('Found comment',yytext); } -[\s]+ { yy.getLogger().info('.', yytext); /* skip all whitespace */ } -[\n]+ {yy.getLogger().info('_', yytext); /* skip all whitespace */ } +"block"\s+ { yy.getLogger().debug('Found space-block'); return 'block';} +"block"\n+ { yy.getLogger().debug('Found nl-block'); return 'block';} +"block:" { yy.getLogger().debug('Found space-block'); return 'id-block';} +// \s*\%\%.* { yy.getLogger().debug('Found comment',yytext); } +[\s]+ { yy.getLogger().debug('.', yytext); /* skip all whitespace */ } +[\n]+ {yy.getLogger().debug('_', yytext); /* skip all whitespace */ } // [\n] return 'NL'; ({CRLF}|{LF}) { return 'NL' } "columns"\s+"auto" { yytext=-1; return 'COLUMNS'; } -"columns"\s+[\d]+ { yytext = yytext.replace(/columns\s+/,''); yy.getLogger().info('COLUMNS (LEX)', yytext); return 'COLUMNS'; } +"columns"\s+[\d]+ { yytext = yytext.replace(/columns\s+/,''); yy.getLogger().debug('COLUMNS (LEX)', yytext); return 'COLUMNS'; } ["][`] { this.pushState("md_string");} [^`"]+ { return "MD_STR";} [`]["] { this.popState();} ["] this.pushState("string"); ["] { yy.getLogger().debug('LEX: POPPING STR:', yytext);this.popState();} [^"]* { yy.getLogger().debug('LEX: STR end:', yytext); return "STR";} -space[:]\d+ { yytext = yytext.replace(/space\:/,'');yy.getLogger().info('SPACE NUM (LEX)', yytext); return 'SPACE_BLOCK'; } -space { yytext = '1'; yy.getLogger().info('COLUMNS (LEX)', yytext); return 'SPACE_BLOCK'; } +space[:]\d+ { yytext = yytext.replace(/space\:/,'');yy.getLogger().debug('SPACE NUM (LEX)', yytext); return 'SPACE_BLOCK'; } +space { yytext = '1'; yy.getLogger().debug('COLUMNS (LEX)', yytext); return 'SPACE_BLOCK'; } "default" return 'DEFAULT'; "linkStyle" return 'LINKSTYLE'; "interpolate" return 'INTERPOLATE'; @@ -87,36 +87,36 @@ accDescr\s*"{"\s* { this.pushState("acc_descr_mul .*direction\s+LR[^\n]* return 'direction_lr'; // Node end of shape -"(((" { this.popState();yy.getLogger().info('Lex: (('); return "NODE_DEND"; } -")))" { this.popState();yy.getLogger().info('Lex: (('); return "NODE_DEND"; } -[\)]\) { this.popState();yy.getLogger().info('Lex: ))'); return "NODE_DEND"; } -"}}" { this.popState();yy.getLogger().info('Lex: (('); return "NODE_DEND"; } -"}" { this.popState();yy.getLogger().info('Lex: (('); return "NODE_DEND"; } -"(-" { this.popState();yy.getLogger().info('Lex: (-'); return "NODE_DEND"; } -"-)" { this.popState();yy.getLogger().info('Lex: -)'); return "NODE_DEND"; } -"((" { this.popState();yy.getLogger().info('Lex: (('); return "NODE_DEND"; } -"]]" { this.popState();yy.getLogger().info('Lex: ]]'); return "NODE_DEND"; } -"(" { this.popState();yy.getLogger().info('Lex: ('); return "NODE_DEND"; } -"])" { this.popState();yy.getLogger().info('Lex: ])'); return "NODE_DEND"; } -"\\]" { this.popState();yy.getLogger().info('Lex: /]'); return "NODE_DEND"; } -"/]" { this.popState();yy.getLogger().info('Lex: /]'); return "NODE_DEND"; } -")]" { this.popState();yy.getLogger().info('Lex: )]'); return "NODE_DEND"; } -[\)] { this.popState();yy.getLogger().info('Lex: )'); return "NODE_DEND"; } -\]\> { this.popState();yy.getLogger().info('Lex: ]>'); return "NODE_DEND"; } -[\]] { this.popState();yy.getLogger().info('Lex: ]'); return "NODE_DEND"; } +"(((" { this.popState();yy.getLogger().debug('Lex: (('); return "NODE_DEND"; } +")))" { this.popState();yy.getLogger().debug('Lex: (('); return "NODE_DEND"; } +[\)]\) { this.popState();yy.getLogger().debug('Lex: ))'); return "NODE_DEND"; } +"}}" { this.popState();yy.getLogger().debug('Lex: (('); return "NODE_DEND"; } +"}" { this.popState();yy.getLogger().debug('Lex: (('); return "NODE_DEND"; } +"(-" { this.popState();yy.getLogger().debug('Lex: (-'); return "NODE_DEND"; } +"-)" { this.popState();yy.getLogger().debug('Lex: -)'); return "NODE_DEND"; } +"((" { this.popState();yy.getLogger().debug('Lex: (('); return "NODE_DEND"; } +"]]" { this.popState();yy.getLogger().debug('Lex: ]]'); return "NODE_DEND"; } +"(" { this.popState();yy.getLogger().debug('Lex: ('); return "NODE_DEND"; } +"])" { this.popState();yy.getLogger().debug('Lex: ])'); return "NODE_DEND"; } +"\\]" { this.popState();yy.getLogger().debug('Lex: /]'); return "NODE_DEND"; } +"/]" { this.popState();yy.getLogger().debug('Lex: /]'); return "NODE_DEND"; } +")]" { this.popState();yy.getLogger().debug('Lex: )]'); return "NODE_DEND"; } +[\)] { this.popState();yy.getLogger().debug('Lex: )'); return "NODE_DEND"; } +\]\> { this.popState();yy.getLogger().debug('Lex: ]>'); return "NODE_DEND"; } +[\]] { this.popState();yy.getLogger().debug('Lex: ]'); return "NODE_DEND"; } // Start of nodes with shapes and description -"-)" { yy.getLogger().info('Lexa: -)'); this.pushState('NODE');return 'NODE_DSTART'; } -"(-" { yy.getLogger().info('Lexa: (-'); this.pushState('NODE');return 'NODE_DSTART'; } -"))" { yy.getLogger().info('Lexa: ))'); this.pushState('NODE');return 'NODE_DSTART'; } -")" { yy.getLogger().info('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; } -"(((" { yy.getLogger().info('Lex: ((('); this.pushState('NODE');return 'NODE_DSTART'; } -"((" { yy.getLogger().info('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; } -"{{" { yy.getLogger().info('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; } -"{" { yy.getLogger().info('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; } -">" { yy.getLogger().info('Lexc: >'); this.pushState('NODE');return 'NODE_DSTART'; } -"([" { yy.getLogger().info('Lexa: (['); this.pushState('NODE');return 'NODE_DSTART'; } -"(" { yy.getLogger().info('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; } +"-)" { yy.getLogger().debug('Lexa: -)'); this.pushState('NODE');return 'NODE_DSTART'; } +"(-" { yy.getLogger().debug('Lexa: (-'); this.pushState('NODE');return 'NODE_DSTART'; } +"))" { yy.getLogger().debug('Lexa: ))'); this.pushState('NODE');return 'NODE_DSTART'; } +")" { yy.getLogger().debug('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; } +"(((" { yy.getLogger().debug('Lex: ((('); this.pushState('NODE');return 'NODE_DSTART'; } +"((" { yy.getLogger().debug('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; } +"{{" { yy.getLogger().debug('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; } +"{" { yy.getLogger().debug('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; } +">" { yy.getLogger().debug('Lexc: >'); this.pushState('NODE');return 'NODE_DSTART'; } +"([" { yy.getLogger().debug('Lexa: (['); this.pushState('NODE');return 'NODE_DSTART'; } +"(" { yy.getLogger().debug('Lexa: )'); this.pushState('NODE');return 'NODE_DSTART'; } "[[" { this.pushState('NODE');return 'NODE_DSTART'; } "[|" { this.pushState('NODE');return 'NODE_DSTART'; } "[(" { this.pushState('NODE');return 'NODE_DSTART'; } @@ -124,20 +124,20 @@ accDescr\s*"{"\s* { this.pushState("acc_descr_mul "[\\" { this.pushState('NODE');return 'NODE_DSTART'; } "[/" { this.pushState('NODE');return 'NODE_DSTART'; } "[\\" { this.pushState('NODE');return 'NODE_DSTART'; } -"[" { yy.getLogger().info('Lexa: ['); this.pushState('NODE');return 'NODE_DSTART'; } +"[" { yy.getLogger().debug('Lexa: ['); this.pushState('NODE');return 'NODE_DSTART'; } "<[" { this.pushState('BLOCK_ARROW');yy.getLogger().debug('LEX ARR START');return 'BLOCK_ARROW_START'; } -[^\(\[\n\-\)\{\}\s\<\>:]+ { yy.getLogger().info('Lex: NODE_ID', yytext);return 'NODE_ID'; } -<> { yy.getLogger().info('Lex: EOF', yytext);return 'EOF'; } +[^\(\[\n\-\)\{\}\s\<\>:]+ { yy.getLogger().debug('Lex: NODE_ID', yytext);return 'NODE_ID'; } +<> { yy.getLogger().debug('Lex: EOF', yytext);return 'EOF'; } // Handling of strings in node ["][`] { this.pushState("md_string");} ["][`] { this.pushState("md_string");} [^`"]+ { return "NODE_DESCR";} [`]["] { this.popState();} -["] { yy.getLogger().info('Lex: Starting string');this.pushState("string");} -["] { yy.getLogger().info('LEX ARR: Starting string');this.pushState("string");} +["] { yy.getLogger().debug('Lex: Starting string');this.pushState("string");} +["] { yy.getLogger().debug('LEX ARR: Starting string');this.pushState("string");} [^"]+ { yy.getLogger().debug('LEX: NODE_DESCR:', yytext); return "NODE_DESCR";} ["] {yy.getLogger().debug('LEX POPPING');this.popState();} @@ -151,19 +151,19 @@ accDescr\s*"{"\s* { this.pushState("acc_descr_mul ")"\s* { yytext=']>';yy.getLogger().debug('Lex (ARROW_DIR end):',yytext);this.popState();this.popState();return "BLOCK_ARROW_END"; } // Edges -\s*[xo<]?\-\-+[-xo>]\s* { yy.getLogger().info('Lex: LINK', '#'+yytext+'#'); return 'LINK'; } -\s*[xo<]?\=\=+[=xo>]\s* { yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; } -\s*[xo<]?\-?\.+\-[xo>]?\s* { yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; } -\s*\~\~[\~]+\s* { yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; } -\s*[xo<]?\-\-\s* { yy.getLogger().info('Lex: START_LINK', yytext);this.pushState("LLABEL");return 'START_LINK'; } -\s*[xo<]?\=\=\s* { yy.getLogger().info('Lex: START_LINK', yytext);this.pushState("LLABEL");return 'START_LINK'; } -\s*[xo<]?\-\.\s* { yy.getLogger().info('Lex: START_LINK', yytext);this.pushState("LLABEL");return 'START_LINK'; } +\s*[xo<]?\-\-+[-xo>]\s* { yy.getLogger().debug('Lex: LINK', '#'+yytext+'#'); return 'LINK'; } +\s*[xo<]?\=\=+[=xo>]\s* { yy.getLogger().debug('Lex: LINK', yytext); return 'LINK'; } +\s*[xo<]?\-?\.+\-[xo>]?\s* { yy.getLogger().debug('Lex: LINK', yytext); return 'LINK'; } +\s*\~\~[\~]+\s* { yy.getLogger().debug('Lex: LINK', yytext); return 'LINK'; } +\s*[xo<]?\-\-\s* { yy.getLogger().debug('Lex: START_LINK', yytext);this.pushState("LLABEL");return 'START_LINK'; } +\s*[xo<]?\=\=\s* { yy.getLogger().debug('Lex: START_LINK', yytext);this.pushState("LLABEL");return 'START_LINK'; } +\s*[xo<]?\-\.\s* { yy.getLogger().debug('Lex: START_LINK', yytext);this.pushState("LLABEL");return 'START_LINK'; } ["][`] { this.pushState("md_string");} -["] { yy.getLogger().info('Lex: Starting string');this.pushState("string"); return "LINK_LABEL";} -\s*[xo<]?\-\-+[-xo>]\s* { this.popState(); yy.getLogger().info('Lex: LINK', '#'+yytext+'#'); return 'LINK'; } -\s*[xo<]?\=\=+[=xo>]\s* { this.popState(); yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; } -\s*[xo<]?\-?\.+\-[xo>]?\s* { this.popState(); yy.getLogger().info('Lex: LINK', yytext); return 'LINK'; } -':'\d+ { yy.getLogger().info('Lex: COLON', yytext); yytext=yytext.slice(1);return 'SIZE'; } +["] { yy.getLogger().debug('Lex: Starting string');this.pushState("string"); return "LINK_LABEL";} +\s*[xo<]?\-\-+[-xo>]\s* { this.popState(); yy.getLogger().debug('Lex: LINK', '#'+yytext+'#'); return 'LINK'; } +\s*[xo<]?\=\=+[=xo>]\s* { this.popState(); yy.getLogger().debug('Lex: LINK', yytext); return 'LINK'; } +\s*[xo<]?\-?\.+\-[xo>]?\s* { this.popState(); yy.getLogger().debug('Lex: LINK', yytext); return 'LINK'; } +':'\d+ { yy.getLogger().debug('Lex: COLON', yytext); yytext=yytext.slice(1);return 'SIZE'; } /lex @@ -180,37 +180,37 @@ spaceLines seperator : NL - {yy.getLogger().info('Rule: seperator (NL) ');} + {yy.getLogger().debug('Rule: seperator (NL) ');} | SPACE - {yy.getLogger().info('Rule: seperator (Space) ');} + {yy.getLogger().debug('Rule: seperator (Space) ');} | EOF - {yy.getLogger().info('Rule: seperator (EOF) ');} + {yy.getLogger().debug('Rule: seperator (EOF) ');} ; start: BLOCK_DIAGRAM_KEY document EOF - { yy.getLogger().info("Rule: hierarchy: ", $2); yy.setHierarchy($2); } + { yy.getLogger().debug("Rule: hierarchy: ", $2); yy.setHierarchy($2); } ; stop - : NL {yy.getLogger().info('Stop NL ');} - | EOF {yy.getLogger().info('Stop EOF ');} + : NL {yy.getLogger().debug('Stop NL ');} + | EOF {yy.getLogger().debug('Stop EOF ');} // | SPACELINE - | stop NL {yy.getLogger().info('Stop NL2 ');} - | stop EOF {yy.getLogger().info('Stop EOF2 ');} + | stop NL {yy.getLogger().debug('Stop NL2 ');} + | stop EOF {yy.getLogger().debug('Stop EOF2 ');} ; //array of statements document - : statement { yy.getLogger().info("Rule: statement: ", $1); typeof $1.length === 'number'?$$ = $1:$$ = [$1]; } - | statement document { yy.getLogger().info("Rule: statement #2: ", $1); $$ = [$1].concat($2); } + : statement { yy.getLogger().debug("Rule: statement: ", $1); typeof $1.length === 'number'?$$ = $1:$$ = [$1]; } + | statement document { yy.getLogger().debug("Rule: statement #2: ", $1); $$ = [$1].concat($2); } ; link : LINK - { yy.getLogger().info("Rule: link: ", $1, yytext); $$={edgeTypeStr: $1, label:''}; } + { yy.getLogger().debug("Rule: link: ", $1, yytext); $$={edgeTypeStr: $1, label:''}; } | START_LINK LINK_LABEL STR LINK - { yy.getLogger().info("Rule: LABEL link: ", $1, $3, $4); $$={edgeTypeStr: $4, label:$3}; } + { yy.getLogger().debug("Rule: LABEL link: ", $1, $3, $4); $$={edgeTypeStr: $4, label:$3}; } ; statement @@ -226,7 +226,7 @@ statement nodeStatement : nodeStatement link node { - yy.getLogger().info('Rule: (nodeStatement link node) ', $1, $2, $3, ' typestr: ',$2.edgeTypeStr); + yy.getLogger().debug('Rule: (nodeStatement link node) ', $1, $2, $3, ' typestr: ',$2.edgeTypeStr); const edgeData = yy.edgeStrToEdgeData($2.edgeTypeStr) $$ = [ {id: $1.id, label: $1.label, type:$1.type, directions: $1.directions}, @@ -234,39 +234,39 @@ nodeStatement {id: $3.id, label: $3.label, type: yy.typeStr2Type($3.typeStr), directions: $3.directions} ]; } - | node SIZE { yy.getLogger().info('Rule: nodeStatement (abc88 node size) ', $1, $2); $$ = {id: $1.id, label: $1.label, type: yy.typeStr2Type($1.typeStr), directions: $1.directions, w: parseInt($2,10)}; } - | node { yy.getLogger().info('Rule: nodeStatement (node) ', $1); $$ = {id: $1.id, label: $1.label, type: yy.typeStr2Type($1.typeStr), directions: $1.directions, w:1}; } + | node SIZE { yy.getLogger().debug('Rule: nodeStatement (abc88 node size) ', $1, $2); $$ = {id: $1.id, label: $1.label, type: yy.typeStr2Type($1.typeStr), directions: $1.directions, w: parseInt($2,10)}; } + | node { yy.getLogger().debug('Rule: nodeStatement (node) ', $1); $$ = {id: $1.id, label: $1.label, type: yy.typeStr2Type($1.typeStr), directions: $1.directions, w:1}; } ; columnsStatement - : COLUMNS { yy.getLogger().info('APA123', this? this:'na'); yy.getLogger().info("COLUMNS: ", $1); $$ = {type: 'column-setting', columns: $1 === 'auto'?-1:parseInt($1) } } + : COLUMNS { yy.getLogger().debug('APA123', this? this:'na'); yy.getLogger().debug("COLUMNS: ", $1); $$ = {type: 'column-setting', columns: $1 === 'auto'?-1:parseInt($1) } } ; blockStatement - : id-block nodeStatement document end { yy.getLogger().info('Rule: id-block statement : ', $2, $3); const id2 = yy.generateId(); $$ = { ...$2, type:'composite', children: $3 }; } - | block document end { yy.getLogger().info('Rule: blockStatement : ', $1, $2, $3); const id = yy.generateId(); $$ = { id, type:'composite', label:'', children: $2 }; } + : id-block nodeStatement document end { yy.getLogger().debug('Rule: id-block statement : ', $2, $3); const id2 = yy.generateId(); $$ = { ...$2, type:'composite', children: $3 }; } + | block document end { yy.getLogger().debug('Rule: blockStatement : ', $1, $2, $3); const id = yy.generateId(); $$ = { id, type:'composite', label:'', children: $2 }; } ; node : NODE_ID - { yy.getLogger().info("Rule: node (NODE_ID seperator): ", $1); $$ = { id: $1 }; } + { yy.getLogger().debug("Rule: node (NODE_ID seperator): ", $1); $$ = { id: $1 }; } | NODE_ID nodeShapeNLabel { - yy.getLogger().info("Rule: node (NODE_ID nodeShapeNLabel seperator): ", $1, $2); + yy.getLogger().debug("Rule: node (NODE_ID nodeShapeNLabel seperator): ", $1, $2); $$ = { id: $1, label: $2.label, typeStr: $2.typeStr, directions: $2.directions }; } ; -dirList: DIR { yy.getLogger().info("Rule: dirList: ", $1); $$ = [$1]; } - | DIR dirList { yy.getLogger().info("Rule: dirList: ", $1, $2); $$ = [$1].concat($2); } +dirList: DIR { yy.getLogger().debug("Rule: dirList: ", $1); $$ = [$1]; } + | DIR dirList { yy.getLogger().debug("Rule: dirList: ", $1, $2); $$ = [$1].concat($2); } ; nodeShapeNLabel : NODE_DSTART STR NODE_DEND - { yy.getLogger().info("Rule: nodeShapeNLabel: ", $1, $2, $3); $$ = { typeStr: $1 + $3, label: $2 }; } + { yy.getLogger().debug("Rule: nodeShapeNLabel: ", $1, $2, $3); $$ = { typeStr: $1 + $3, label: $2 }; } | BLOCK_ARROW_START STR dirList BLOCK_ARROW_END - { yy.getLogger().info("Rule: BLOCK_ARROW nodeShapeNLabel: ", $1, $2, " #3:",$3, $4); $$ = { typeStr: $1 + $4, label: $2, directions: $3}; } + { yy.getLogger().debug("Rule: BLOCK_ARROW nodeShapeNLabel: ", $1, $2, " #3:",$3, $4); $$ = { typeStr: $1 + $4, label: $2, directions: $3}; } ; @@ -281,7 +281,7 @@ classDefStatement cssClassStatement : class CLASSENTITY_IDS STYLECLASS { - //console.log('apply class: id(s): ',$2, ' style class: ', $3); + //log.debug('apply class: id(s): ',$2, ' style class: ', $3); $$={ type: 'applyClass', id: $2.trim(), styleClass: $3.trim() }; } ; diff --git a/packages/mermaid/src/diagrams/block/parser/block.spec.ts b/packages/mermaid/src/diagrams/block/parser/block.spec.ts index bf32afc5e6..367edb8426 100644 --- a/packages/mermaid/src/diagrams/block/parser/block.spec.ts +++ b/packages/mermaid/src/diagrams/block/parser/block.spec.ts @@ -47,10 +47,10 @@ describe('Block diagram', function () { expect(blocks.length).toBe(2); expect(blocks[0].id).toBe('id1'); expect(blocks[0].label).toBe('id1'); - expect(blocks[0].type).toBe('square'); + expect(blocks[0].type).toBe('na'); expect(blocks[1].id).toBe('id2'); expect(blocks[1].label).toBe('id2'); - expect(blocks[1].type).toBe('square'); + expect(blocks[1].type).toBe('na'); }); it('a diagram with multiple nodes', async () => { const str = `block-beta @@ -64,13 +64,13 @@ describe('Block diagram', function () { expect(blocks.length).toBe(3); expect(blocks[0].id).toBe('id1'); expect(blocks[0].label).toBe('id1'); - expect(blocks[0].type).toBe('square'); + expect(blocks[0].type).toBe('na'); expect(blocks[1].id).toBe('id2'); expect(blocks[1].label).toBe('id2'); - expect(blocks[1].type).toBe('square'); + expect(blocks[1].type).toBe('na'); expect(blocks[2].id).toBe('id3'); expect(blocks[2].label).toBe('id3'); - expect(blocks[2].type).toBe('square'); + expect(blocks[2].type).toBe('na'); }); it('a node with a square shape and a label', async () => { @@ -86,7 +86,7 @@ describe('Block diagram', function () { expect(blocks[0].type).toBe('square'); expect(blocks[1].id).toBe('id2'); expect(blocks[1].label).toBe('id2'); - expect(blocks[1].type).toBe('square'); + expect(blocks[1].type).toBe('na'); }); it('a diagram with multiple nodes with edges', async () => { const str = `block-beta @@ -231,14 +231,14 @@ describe('Block diagram', function () { expect(compoundBlock.children.length).toBe(1); expect(compoundBlock.id).toBe('compoundBlock'); expect(compoundBlock.label).toBe('Compound block'); - expect(compoundBlock.type).toBe('square'); + expect(compoundBlock.type).toBe('composite'); expect(block2.id).toBe('block2'); expect(block2.label).toBe('Block 2'); expect(block2.type).toBe('square'); }); - it.skip('blocks mixed with compound blocks', async () => { - const str = `block + it('blocks mixed with compound blocks', async () => { + const str = `block-beta columns 1 block1["Block 1"] @@ -250,16 +250,43 @@ describe('Block diagram', function () { `; block.parse(str); + + const blocks = db.getBlocks(); + expect(blocks.length).toBe(2); + + const compoundBlock = blocks[1]; + const block2 = compoundBlock.children[0]; + + expect(compoundBlock.children.length).toBe(2); + + expect(block2.id).toBe('block2'); + expect(block2.label).toBe('Block 2'); + expect(block2.type).toBe('square'); }); - it.skip('Arrow blocks', async () => { - const str = `block + it('Arrow blocks', async () => { + const str = `block-beta columns 3 block1["Block 1"] - blockArrow + blockArrow<["   "]>(right) block2["Block 2"]`; block.parse(str); + + const blocks = db.getBlocks(); + expect(blocks.length).toBe(3); + + const block1 = blocks[0]; + const blockArrow = blocks[1]; + const block2 = blocks[2]; + + expect(block1.id).toBe('block1'); + expect(blockArrow.id).toBe('blockArrow'); + expect(block2.id).toBe('block2'); + expect(block2.label).toBe('Block 2'); + expect(block2.type).toBe('square'); + expect(blockArrow.type).toBe('block_arrow'); + console.log('blockArrow', blockArrow); }); it.skip('Arrow blocks with multiple points', async () => { const str = `block-beta @@ -275,7 +302,7 @@ describe('Block diagram', function () { block.parse(str); }); - it.skip('blocks with different widths', async () => { + it('blocks with different widths', async () => { const str = `block-beta columns 3 one["One Slot"] @@ -283,6 +310,13 @@ describe('Block diagram', function () { `; block.parse(str); + + const blocks = db.getBlocks(); + expect(blocks.length).toBe(2); + const one = blocks[0]; + const two = blocks[1]; + console.log('Obe and Two', one, two); + expect(two.w).toBe(2); }); it('empty blocks', async () => { const str = `block-beta diff --git a/packages/mermaid/src/docs/syntax/block-old.md b/packages/mermaid/src/docs/syntax/block-old.md new file mode 100644 index 0000000000..d2fd0b717a --- /dev/null +++ b/packages/mermaid/src/docs/syntax/block-old.md @@ -0,0 +1,346 @@ +--- +title: Block Diagram Syntax +outline: 'deep' # shows all h3 headings in outline in Vitepress +--- + +# Block Diagrams - Basic Syntax + +Block diagrams are a fundamental tool in technical and engineering documentation, offering a straightforward way to represent complex systems and processes. + +A block diagram, at its core, is a graphical representation of a system that uses blocks to depict different components or functions and arrows to show the relationship or flow between them. This form of diagram is invaluable in simplifying the understanding of large-scale systems, breaking them down into individual, easily digestible components. + +With block diagrams you can create clear, concise, and visually appealing representations of systems. This is particularly beneficial for technical teams and stakeholders who need to document, analyze, or communicate complex processes without getting entangled in the intricacies of detailed schematics. Whether it's for software architecture, network systems, or process management, Mermaid's block diagrams offer an accessible and efficient way to visualize and convey crucial information. + +```warning +If you are using the word "end" in a Flowchart block, capitalize the entire word or any of the letters (e.g., "End" or "END"), or apply this [workaround](https://github.com/mermaid-js/mermaid/issues/1444#issuecomment-639528897). Typing "end" in all lowercase letters will break the Flowchart. +``` + +### A block (default) + +```mermaid-example +--- +title: Block +--- +block-beta + id +``` + +```note +The id is what is displayed in the box. +``` + +### A block with text + +It is also possible to set text in the box that differs from the id. If this is done several times, it is the last text +found for the block that will be used. Also if you define edges for the block later on, you can omit text definitions. The +one previously defined will be used when rendering the box. + +```mermaid-example +--- +title: Node with text +--- +block-beta + id1[This is the text in the box] +``` + +#### Unicode text + +Use `"` to enclose the unicode text. + +```mermaid-example +block-beta + id["This ❤ Unicode"] +``` + +#### Markdown formatting + +Use double quotes and backticks "\` text \`" to enclose the markdown text. + +```mermaid-example +%%{init: {"flowchart": {"htmlLabels": false}} }%% +block-beta + markdown["`This **is** _Markdown_`"] + newLines["`Line1 + Line 2 + Line 3`"] + markdown --> newLines +``` + +## Block shapes + +### A block with round edges + +```mermaid-example +block-beta + id1(This is the text in the box) +``` + +### A stadium-shaped block + +```mermaid-example +block-beta + id1([This is the text in the box]) +``` + +### A block in a subroutine shape + +```mermaid-example +block-beta + id1[[This is the text in the box]] +``` + +### A block in a cylindrical shape + +```mermaid-example +block-beta + id1[(Database)] +``` + +### A block in the form of a circle + +```mermaid-example +block-beta + id1((This is the text in the circle)) +``` + +### A block in an asymmetric shape + +```mermaid-example +block-beta + id1>This is the text in the box] +``` + +### A block (rhombus) + +```mermaid-example +block-beta + id1{This is the text in the box} +``` + +### A hexagon block + +```mermaid-example +block-beta + id1{{This is the text in the box}} +``` + +### Parallelogram + +```mermaid-example +flowchart TD + id1[/This is the text in the box/] +``` + +### Parallelogram alt + +```mermaid-example +flowchart TD + id1[\This is the text in the box\] +``` + +### Trapezoid + +```mermaid-example +flowchart TD + A[/Christmas\] +``` + +### Trapezoid alt + +```mermaid-example +flowchart TD + B[\Go shopping/] +``` + +### Double circle + +```mermaid-example +flowchart TD + id1(((This is the text in the circle))) +``` + +## Links between blocks + +Blocks can be connected with links/edges. It is possible to have different types of links or attach a text string to a link. + +### A link with arrow head + +```mermaid-example +block-beta + A-->B +``` + +### An open link + +```mermaid-example +block-beta + A --- B +``` + +### Text on links + +```mermaid-example +block-beta + A-- This is the text! ---B +``` + +or + +```mermaid-example +block-beta + A---|This is the text|B +``` + +### A link with arrow head and text + +```mermaid-example +block-beta + A-->|text|B +``` + +or + +```mermaid-example +block-beta + A-- text -->B +``` + +### Dotted link + +```mermaid-example +block-beta + A-.->B; +``` + +### Dotted link with text + +```mermaid-example +block-beta + A-. text .-> B +``` + +### Thick link + +```mermaid-example +block-beta + A ==> B +``` + +### Thick link with text + +```mermaid-example +block-beta + A == text ==> B +``` + +### Different types of links + +There are new types of arrows supported as per below: + +```mermaid-example +block-beta + A --o B + B --x C +``` + +### Multi directional arrows + +There is the possibility to use multidirectional arrows. + +```mermaid-example +block-beta + A o--o B + B <--> C + C x--x D +``` + +## Special characters that break syntax + +It is possible to put text within quotes in order to render more troublesome characters. As in the example below: + +```mermaid-example +block-beta + id1["This is the (text) in the box"] +``` + +### Entity codes to escape characters + +It is possible to escape characters using the syntax exemplified here. + +```mermaid-example + block-beta + A["A double quote:#quot;"] -->B["A dec char:#9829;"] +``` + +Numbers given are base 10, so `#` can be encoded as `#35;`. It is also supported to use HTML character names. + +## Blocks in blocks + +``` +block-beta + block definition +end +``` + +An example below: + +```mermaid-example +block-beta + block + A["square"] + B("rounded") + end + C(("circle")) +``` + +### Comments + +Comments can be entered within a flow diagram, which will be ignored by the parser. Comments need to be on their own line, and must be prefaced with `%%` (double percent signs). Any text after the start of the comment to the next newline will be treated as a comment, including any flow syntax + +```mermaid +block-beta +%% this is a comment A -- text --> B{block} + A -- text --> B -- text2 --> C +``` + +## Styling and classes + +### Styling a block + +It is possible to apply specific styles such as a thicker border or a different background color to a block. + +```mermaid-example +block-beta + id1(Start)-->id2(Stop) + style id1 fill:#f9f,stroke:#333,stroke-width:4px + style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 +``` + +#### Classes + +More convenient than defining the style every time is to define a class of styles and attach this class to the blocks that +should have a different look. + +A class definition looks like the example below: + +``` + classDef className fill:#f9f,stroke:#333,stroke-width:4px; +``` + +Also, it is possible to define style to multiple classes in one statement: + +``` + classDef firstClassName,secondClassName font-size:12pt; +``` + +Attachment of a class to a block is done as per below: + +``` + class blockId1 className; +``` + +It is also possible to attach a class to a list of blocks in one statement: + +``` + class blockId1,blockId2 className; +``` diff --git a/packages/mermaid/src/docs/syntax/block.md b/packages/mermaid/src/docs/syntax/block.md index 20dc1c6c99..b1067d5b36 100644 --- a/packages/mermaid/src/docs/syntax/block.md +++ b/packages/mermaid/src/docs/syntax/block.md @@ -3,657 +3,501 @@ title: Block Diagram Syntax outline: 'deep' # shows all h3 headings in outline in Vitepress --- -# Block Diagrams - Basic Syntax +# Block Diagrams Documentation -Block diagrams are a fundamental tool in technical and engineering documentation, offering a straightforward way to represent complex systems and processes. +## 1. Introduction to Block Diagrams -A block diagram, at its core, is a graphical representation of a system that uses blocks to depict different components or functions and arrows to show the relationship or flow between them. This form of diagram is invaluable in simplifying the understanding of large-scale systems, breaking them down into individual, easily digestible components. +### Definition and Purpose -With block diagrams you can create clear, concise, and visually appealing representations of systems. This is particularly beneficial for technical teams and stakeholders who need to document, analyze, or communicate complex processes without getting entangled in the intricacies of detailed schematics. Whether it's for software architecture, network systems, or process management, Mermaid's block diagrams offer an accessible and efficient way to visualize and convey crucial information. +Block diagrams are an intuitive and efficient way to represent complex systems, processes, or architectures visually. They are composed of blocks and connectors, where blocks represent the fundamental components or functions, and connectors show the relationship or flow between these components. This method of diagramming is essential in various fields such as engineering, software development, and process management. -```warning -If you are using the word "end" in a Flowchart block, capitalize the entire word or any of the letters (e.g., "End" or "END"), or apply this [workaround](https://github.com/mermaid-js/mermaid/issues/1444#issuecomment-639528897). Typing "end" in all lowercase letters will break the Flowchart. -``` +The primary purpose of block diagrams is to provide a high-level view of a system, allowing for easy understanding and analysis without delving into the intricate details of each component. This makes them particularly useful for simplifying complex systems and for explaining the overall structure and interaction of components within a system. -### A block (default) +### General Use Cases -```mermaid-example ---- -title: Block ---- -block-beta - id -``` +Block diagrams have a wide range of applications across various industries and disciplines. Some of the key use cases include: -```note -The id is what is displayed in the box. -``` +- **Software Architecture**: In software development, block diagrams can be used to illustrate the architecture of a software application. This includes showing how different modules or services interact, data flow, and high-level component interaction. -### A block with text +- **Network Diagrams**: Block diagrams are ideal for representing network architectures in IT and telecommunications. They can depict how different network devices and services are interconnected, including routers, switches, firewalls, and the flow of data across the network. -It is also possible to set text in the box that differs from the id. If this is done several times, it is the last text -found for the block that will be used. Also if you define edges for the block later on, you can omit text definitions. The -one previously defined will be used when rendering the box. +- **Process Flowcharts**: In business and manufacturing, block diagrams can be employed to create process flowcharts. These flowcharts represent various stages of a business or manufacturing process, helping to visualize the sequence of steps, decision points, and the flow of control. -```mermaid-example ---- -title: Node with text ---- -block-beta - id1[This is the text in the box] -``` +- **Electrical Systems**: Engineers use block diagrams to represent electrical systems and circuitry. They can illustrate the high-level structure of an electrical system, the interaction between different electrical components, and the flow of electrical currents. -#### Unicode text +- **Educational Purposes**: Block diagrams are also extensively used in educational materials to explain complex concepts and systems in a simplified manner. They help in breaking down and visualizing scientific theories, engineering principles, and technological systems. -Use `"` to enclose the unicode text. +These examples demonstrate the versatility of block diagrams in providing clear and concise representations of complex systems. Their simplicity and clarity make them a valuable tool for professionals across various fields to communicate complex ideas effectively. -```mermaid-example -block-beta - id["This ❤ Unicode"] -``` +In the following sections, we will delve into the specifics of creating and manipulating block diagrams using Mermaid, covering everything from basic syntax to advanced configurations and styling. -#### Markdown formatting +Creating block diagrams with Mermaid is straightforward and accessible. This section introduces the basic syntax and structure needed to start building simple diagrams. Understanding these foundational concepts is key to efficiently utilizing Mermaid for more complex diagramming tasks. -Use double quotes and backticks "\` text \`" to enclose the markdown text. +### Simple Block Diagrams -```mermaid-example -%%{init: {"flowchart": {"htmlLabels": false}} }%% -block-beta - markdown["`This **is** _Markdown_`"] - newLines["`Line1 - Line 2 - Line 3`"] - markdown --> newLines -``` +#### Basic Structure -## Block shapes +At its core, a block diagram consists of blocks representing different entities or components. In Mermaid, these blocks are easily created using simple text labels. The most basic form of a block diagram can be a series of blocks without any connectors. -### A block with round edges +**Example - Simple Block Diagram**: +To create a simple block diagram with three blocks labeled 'a', 'b', and 'c', the syntax is as follows: ```mermaid-example block-beta - id1(This is the text in the box) + a b c ``` -### A stadium-shaped block +This example will produce a horizontal sequence of three blocks. Each block is automatically spaced and aligned for optimal readability. -```mermaid-example -block-beta - id1([This is the text in the box]) -``` +### Diagrams with Multiple Columns -### A block in a subroutine shape +#### Column Usage -```mermaid-example -block-beta - id1[[This is the text in the box]] -``` +While simple block diagrams are linear and straightforward, more complex systems may require a structured layout. Mermaid allows for the organization of blocks into multiple columns, facilitating the creation of more intricate and detailed diagrams. -### A block in a cylindrical shape +**Example - Multi-Column Diagram:** +In scenarios where you need to distribute blocks across multiple columns, you can specify the number of columns and arrange the blocks accordingly. Here's how to create a block diagram with three columns and four blocks, where the fourth block appears in a second row: ```mermaid-example block-beta - id1[(Database)] + columns 3 + a b c d ``` -### A block in the form of a circle +This syntax instructs Mermaid to arrange the blocks 'a', 'b', 'c', and 'd' across three columns, wrapping to the next row as needed. This feature is particularly useful for representing layered or multi-tiered systems, such as network layers or hierarchical structures. -```mermaid-example -block-beta - id1((This is the text in the circle)) -``` +These basic building blocks of Mermaid's block diagrams provide a foundation for more complex diagramming. The simplicity of the syntax allows for quick creation and iteration of diagrams, making it an efficient tool for visualizing ideas and concepts. In the next section, we'll explore advanced block configuration options, including setting block widths and creating composite blocks. -### A block in an asymmetric shape +## 3. Advanced Block Configuration -```mermaid-example -block-beta - id1>This is the text in the box] -``` +Building upon the basics, this section delves into more advanced features of block diagramming in Mermaid. These features allow for greater flexibility and complexity in diagram design, accommodating a wider range of use cases and scenarios. -### A block (rhombus) +### Setting Block Width -```mermaid-example -block-beta - id1{This is the text in the box} -``` +#### Spanning Multiple Columns + +In more complex diagrams, you may need blocks that span multiple columns to emphasize certain components or to represent larger entities. Mermaid allows for the adjustment of block widths to cover multiple columns, enhancing the diagram's readability and structure. -### A hexagon block +**Example - Block Spanning Multiple Columns**: +To create a block diagram where one block spans across two columns, you can specify the desired width for each block: ```mermaid-example block-beta - id1{{This is the text in the box}} + columns 3 + a["A wide one"] b:2 c:2 d ``` -### Parallelogram +In this example, the block labeled "A wide one" spans two columns, while blocks 'b', 'c', and 'd' are allocated their own columns. This flexibility in block sizing is crucial for accurately representing systems with components of varying significance or size. -```mermaid-example -flowchart TD - id1[/This is the text in the box/] -``` +### Creating Composite Blocks -### Parallelogram alt +#### Nested Blocks -```mermaid-example -flowchart TD - id1[\This is the text in the box\] -``` +Composite blocks, or blocks within blocks, are an advanced feature in Mermaid's block diagram syntax. They allow for the representation of nested or hierarchical systems, where one component encompasses several subcomponents. -### Trapezoid +**Example - Composite Blocks:** +Creating a composite block involves defining a parent block and then nesting other blocks within it. Here's how to define a composite block with nested elements: ```mermaid-example -flowchart TD - A[/Christmas\] +block-beta + block + D + end + A["A: I am a wide one"] ``` -### Trapezoid alt +In this syntax, 'D' is a nested block within a larger parent block. This feature is particularly useful for depicting complex structures, such as a server with multiple services or a department within a larger organizational framework. -```mermaid-example -flowchart TD - B[\Go shopping/] -``` +### Column Width Dynamics -### Double circle +#### Adjusting Widths + +Mermaid also allows for dynamic adjustment of column widths based on the content of the blocks. The width of the columns is determined by the widest block in the column, ensuring that the diagram remains balanced and readable. + +**Example - Dynamic Column Widths:** +In diagrams with varying block sizes, Mermaid automatically adjusts the column widths to fit the largest block in each column. Here's an example: ```mermaid-example -flowchart TD - id1(((This is the text in the circle))) +block-beta +columns 3 +a:3 +block:e:3 +f +end +g ``` -## Links between blocks +This example demonstrates how Mermaid dynamically adjusts the width of the columns to accommodate the widest block, in this case, 'a' and the composite block 'e'. This dynamic adjustment is essential for creating visually balanced and easy-to-understand diagrams. -Blocks can be connected with links/edges. It is possible to have different types of links or attach a text string to a link. +With these advanced configuration options, Mermaid's block diagrams can be tailored to represent a wide array of complex systems and structures. The flexibility offered by these features enables users to create diagrams that are both informative and visually appealing. In the following sections, we will explore further capabilities, including different block shapes and linking options. -### A link with arrow head +## 4. Block Varieties and Shapes -```mermaid-example -block-beta - A-->B -``` +Mermaid's block diagrams are not limited to standard rectangular shapes. A variety of block shapes are available, allowing for a more nuanced and tailored representation of different types of information or entities. This section outlines the different block shapes you can use in Mermaid and their specific applications. -### An open link +### Standard and Special Block Shapes -```mermaid-example -block-beta - A --- B -``` +Mermaid supports a range of block shapes to suit different diagramming needs, from basic geometric shapes to more specialized forms. + +#### Example - Round Edged Block -### Text on links +To create a block with round edges, which can be used to represent a softer or more flexible component: ```mermaid-example block-beta - A-- This is the text! ---B + id1(This is the text in the box) ``` -or +#### Example - Stadium-Shaped Block + +A stadium-shaped block, resembling an elongated circle, can be used for components that are process-oriented: ```mermaid-example block-beta - A---|This is the text|B + id1([This is the text in the box]) ``` -### A link with arrow head and text +#### Example - Subroutine Shape + +For representing subroutines or contained processes, a block with double vertical lines is useful: ```mermaid-example block-beta - A-->|text|B + id1[[This is the text in the box]] ``` -or +#### Example - Cylindrical Shape + +The cylindrical shape is ideal for representing databases or storage components: ```mermaid-example block-beta - A-- text -->B + id1[(Database)] ``` -### Dotted link +#### Example - Circle Shape + +A circle can be used for centralized or pivotal components: ```mermaid-example block-beta - A-.->B; + id1((This is the text in the circle)) ``` -### Dotted link with text +#### Example - Asymmetric, Rhombus, and Hexagon Shapes + +For decision points, use a rhombus, and for unique or specialized processes, asymmetric and hexagon shapes can be utilized: + +**Asymmetric** ```mermaid-example block-beta - A-. text .-> B + id1>This is the text in the box] ``` -### Thick link +**Rhombus** ```mermaid-example block-beta - A ==> B + id1{This is the text in the box} ``` -### Thick link with text +**Hexagon** ```mermaid-example block-beta - A == text ==> B + id1{{This is the text in the box}} ``` -### Different types of links +#### Example - Parallelogram and Trapezoid Shapes -There are new types of arrows supported as per below: +Parallelogram and trapezoid shapes are perfect for inputs/outputs and transitional processes: ```mermaid-example -block-beta - A --o B - B --x C +flowchart TD + id1[/This is the text in the box/] + id2[\This is the text in the box\] + A[/Christmas\] + B[\Go shopping/] ``` -### Multi directional arrows +#### Example - Double Circle -There is the possibility to use multidirectional arrows. +For highlighting critical or high-priority components, a double circle can be effective: ```mermaid-example -block-beta - A o--o B - B <--> C - C x--x D +flowchart TD + id1(((This is the text in the circle))) ``` -## Special characters that break syntax +### Block Arrows and Space Blocks + +Mermaid also offers unique shapes like block arrows and space blocks for directional flow and spacing. -It is possible to put text within quotes in order to render more troublesome characters. As in the example below: +#### Example - Block Arrows + +Block arrows can visually indicate direction or flow within a process: ```mermaid-example block-beta - id1["This is the (text) in the box"] + blockArrowId<["Label"]>(right) + blockArrowId2<["Label"]>(left) + blockArrowId3<["Label"]>(up) + blockArrowId4<["Label"]>(down) + blockArrowId5<["Label"]>(x) + blockArrowId6<["Label"]>(y) + blockArrowId6<["Label"]>(x, down) ``` -### Entity codes to escape characters +#### Example - Space Blocks -It is possible to escape characters using the syntax exemplified here. +Space blocks can be used to create intentional empty spaces in the diagram, which is useful for layout and readability: ```mermaid-example - block-beta - A["A double quote:#quot;"] -->B["A dec char:#9829;"] +block-beta + space:3 + ida idb idc ``` -Numbers given are base 10, so `#` can be encoded as `#35;`. It is also supported to use HTML character names. +Note that you can set how many columns the spece block occupied using the number notaion `space:num` where num is a number indicating the num columns width. You can alsio use `space` which defaults to one column. -## Blocks in blocks +The variety of shapes and special blocks in Mermaid enhances the expressive power of block diagrams, allowing for more accurate and context-specific representations. These options give users the flexibility to create diagrams that are both informative and visually appealing. In the next sections, we will explore the ways to connect these blocks and customize their appearance. -``` -block-beta - block definition -end -``` +### Standard and Special Block Shapes -An example below: +Discuss the various shapes available for blocks, including standard shapes and special forms like block arrows and space blocks. -```mermaid-example -block-beta - block - A["square"] - B("rounded") - end - C(("circle")) -``` +## 5. Connecting Blocks with Edges -You can also set an explicit id for the subgraph. +One of the key features of block diagrams in Mermaid is the ability to connect blocks using various types of edges or links. This section explores the different ways blocks can be interconnected to represent relationships and flows between components. -```mermaid-example -flowchart TB - c1-->a2 - subgraph ide1 [one] - a1-->a2 - end -``` +### Basic Linking and Arrow Types -### flowcharts +The most fundamental aspect of connecting blocks is the use of arrows or links. These connectors depict the relationships or the flow of information between the blocks. Mermaid offers a range of arrow types to suit different diagramming needs. -With the graphtype flowchart it is also possible to set edges to and from subgraphs as in the flowchart below. +**Example - Basic Links** + +A simple link with an arrow can be created to show direction or flow from one block to another: ```mermaid-example -flowchart TB - c1-->a2 - subgraph one - a1-->a2 - end - subgraph two - b1-->b2 - end - subgraph three - c1-->c2 - end - one --> two - three --> two - two --> c2 +block-beta + A-->B ``` -### Direction in subgraphs +This example illustrates a direct connection from block 'A' to block 'B', using a straightforward arrow. -With the graphtype flowcharts you can use the direction statement to set the direction which the subgraph will render like in this example. +**Example - Open Link:** +For connections that are less direct or to represent a different type of relationship, an open link (without an arrowhead) can be used: ```mermaid-example block-beta - subgraph TOP - direction TB - subgraph B1 - direction RL - i1 -->f1 - end - subgraph B2 - direction BT - i2 -->f2 - end - end - A --> TOP --> B - B1 --> B2 + A --- B ``` -## Markdown Strings +This syntax creates a line connecting 'A' and 'B', implying a relationship or connection without indicating a specific direction. -The "Markdown Strings" feature enhances flowcharts and mind maps by offering a more versatile string type, which supports text formatting options such as bold and italics, and automatically wraps text within labels. +### Text on Links + +In addition to connecting blocks, it's often necessary to describe or label the relationship. Mermaid allows for the inclusion of text on links, providing context to the connections. + +Example - Text with Links +To add text to a link, the syntax includes the text within the link definition: ```mermaid-example -%%{init: {"flowchart": {"htmlLabels": false}} }%% block-beta -subgraph "One" - a("`The **cat** - in the hat`") -- "edge label" --> b{{"`The **dog** in the hog`"}} -end -subgraph "`**Two**`" - c("`The **cat** - in the hat`") -- "`Bold **edge label**`" --> d("The dog in the hog") -end + A-- This is the text! ---B ``` -Formatting: - -- For bold text, use double asterisks (`**`) before and after the text. -- For italics, use single asterisks (`*`) before and after the text. -- With traditional strings, you needed to add `
    ` tags for text to wrap in blocks. However, markdown strings automatically wrap text when it becomes too long and allows you to start a new line by simply using a newline character instead of a `
    ` tag. +This example show how to add descriptive text to the links, enhancing the information conveyed by the diagram. -This feature is applicable to block labels, edge labels, and subgraph labels. +### Advanced Link Types -## Interaction +Mermaid also supports various advanced link types, such as dotted lines, thick links, and different arrowheads, to represent different kinds of relationships or interactions. -It is possible to bind a click event to a block, the click can lead to either a javascript callback or to a link which will be opened in a new browser tab. +**Example - Dotted and Thick Links** +A dotted link can be used to represent a weaker or less formal relationship: -```note -This functionality is disabled when using `securityLevel='strict'` and enabled when using `securityLevel='loose'`. -``` - -``` -click blockId callback -click blockId call callback() +```mermaid-example +block-beta + A-.->B ``` -- blockId is the id of the block -- callback is the name of a javascript function defined on the page displaying the graph, the function will be called with the blockId as parameter. - -Examples of tooltip usage below: +For a more pronounced connection, a thick link can be used: -```html - +```mermaid-example +block-beta + A==>B ``` -The tooltip text is surrounded in double quotes. The styles of the tooltip are set by the class `.mermaidTooltip`. +Example - Edges and Styles: ```mermaid-example block-beta - A-->B - B-->C - C-->D - click A callback "Tooltip for a callback" - click B "https://www.github.com" "This is a tooltip for a link" - click A call callback() "Tooltip for a callback" - click B href "https://www.github.com" "This is a tooltip for a link" +columns 1 + db(("DB")) + blockArrowId6<["   "]>(down) + block:ID + A + B["A wide one in the middle"] + C + end + space + D + ID --> D + C --> D + style B fill:#f9F,stroke:#333,stroke-width:4px ``` -> **Success** The tooltip functionality and the ability to link to urls are available from version 0.5.2. +## 6. Styling and Customization -?> Due to limitations with how Docsify handles JavaScript callback functions, an alternate working demo for the above code can be viewed at [this jsfiddle](https://jsfiddle.net/s37cjoau/3/). +Beyond the structure and layout of block diagrams, Mermaid offers extensive styling options. These customization features allow for the creation of more visually distinctive and informative diagrams. This section covers how to apply individual styles to blocks and how to use classes for consistent styling across multiple elements. -Links are opened in the same browser tab/window by default. It is possible to change this by adding a link target to the click definition (`_self`, `_blank`, `_parent` and `_top` are supported): +### Individual Block Styling -```mermaid-example -block-beta - A-->B - B-->C - C-->D - D-->E - click A "https://www.github.com" _blank - click B "https://www.github.com" "Open this in a new tab" _blank - click C href "https://www.github.com" _blank - click D href "https://www.github.com" "Open this in a new tab" _blank -``` - -Beginner's tip—a full example using interactive links in a html context: - -```html - -
    -    block-beta
    -        A-->B
    -        B-->C
    -        C-->D
    -        click A callback "Tooltip"
    -        click B "https://www.github.com" "This is a link"
    -        click C call callback() "Tooltip"
    -        click D href "https://www.github.com" "This is a link"
    -  
    - - - -``` - -### Comments - -Comments can be entered within a flow diagram, which will be ignored by the parser. Comments need to be on their own line, and must be prefaced with `%%` (double percent signs). Any text after the start of the comment to the next newline will be treated as a comment, including any flow syntax +Mermaid enables detailed styling of individual blocks, allowing you to apply various CSS properties such as color, stroke, and border thickness. This feature is especially useful for highlighting specific parts of a diagram or for adhering to certain visual themes. -```mermaid +#### Example - Styling a Single Block + +To apply custom styles to a block, you can use the `style` keyword followed by the block identifier and the desired CSS properties: + +```mermaid-example block-beta -%% this is a comment A -- text --> B{block} - A -- text --> B -- text2 --> C + id1(Start)-->id2(Stop) + style id1 fill:#f9f,stroke:#333,stroke-width:4px + style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 ``` -## Styling and classes - -### Styling links +In this example, a class named 'blue' is defined and applied to block 'A', while block 'B' receives individual styling. This demonstrates the flexibility of Mermaid in applying both shared and unique styles within the same diagram. -It is possible to style links. For instance, you might want to style a link that is going backwards in the flow. As links -have no ids in the same way as blocks, some other way of deciding what style the links should be attached to is required. -Instead of ids, the order number of when the link was defined in the graph is used, or use default to apply to all links. -In the example below the style defined in the linkStyle statement will belong to the fourth link in the graph: +The ability to style blocks individually or through classes provides a powerful tool for enhancing the visual impact and clarity of block diagrams. Whether emphasizing certain elements or maintaining a cohesive design across the diagram, these styling capabilities are central to effective diagramming. The next sections will present practical examples and use cases, followed by tips for troubleshooting common issues. -``` -linkStyle 3 stroke:#ff3,stroke-width:4px,color:red; -``` +### 7. Practical Examples and Use Cases -It is also possible to add style to multiple links in a single statement, by separating link numbers with commas: +The versatility of Mermaid's block diagrams becomes evident when applied to real-world scenarios. This section provides practical examples demonstrating the application of various features discussed in previous sections. These examples showcase how block diagrams can be used to represent complex systems and processes in an accessible and informative manner. -``` -linkStyle 1,2,7 color:blue; -``` +### Detailed Examples Illustrating Various Features -### Styling line curves +Combining the elements of structure, linking, and styling, we can create comprehensive diagrams that serve specific purposes in different contexts. -It is possible to style the type of curve used for lines between items, if the default method does not meet your needs. -Available curve styles include `basis`, `bumpX`, `bumpY`, `cardinal`, `catmullRom`, `linear`, `monotoneX`, `monotoneY`, -`natural`, `step`, `stepAfter`, and `stepBefore`. +#### Example - System Architecture -In this example, a left-to-right graph uses the `stepBefore` curve style: +Illustrating a simple software system architecture with interconnected components: -``` -%%{ init: { 'flowchart': { 'curve': 'stepBefore' } } }%% -graph LR +```mermaid +block-beta + columns 2 + Frontend Backend + Frontend-->Backend + Database[(Database)] + Backend-->Database + class Frontend,Backend fill:#f96,stroke:#333; + class Database fill:#9f9,stroke:#333; ``` -For a full list of available curves, including an explanation of custom curves, refer to -the [Shapes](https://github.com/d3/d3-shape/blob/main/README.md#curves) documentation in the -[d3-shape](https://github.com/d3/d3-shape/) project. +This example shows a basic architecture with a frontend, backend, and database. The blocks are styled to differentiate between types of components. -### Styling a block +#### Example - Business Process Flow -It is possible to apply specific styles such as a thicker border or a different background color to a block. +Representing a business process flow with decision points and multiple stages: ```mermaid-example block-beta - id1(Start)-->id2(Stop) - style id1 fill:#f9f,stroke:#333,stroke-width:4px - style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 + Start{Start} + Decision{Make Decision} + Process1[Process A] + Process2[Process B] + End((End)) + Start --> Decision + Decision -- Yes --> Process1 + Decision -- No --> Process2 + Process1 --> End + Process2 --> End + style Start fill:#f9f; + style End fill:#bbf; + ``` -#### Classes +This diagram depicts a simple decision-making process with two possible paths leading to an endpoint, demonstrating the use of different shapes and directional arrows. -More convenient than defining the style every time is to define a class of styles and attach this class to the blocks that -should have a different look. +### Real works Application Scenarios -A class definition looks like the example below: +Block diagrams can be employed in a variety of real-world scenarios. Here are a few examples: -``` - classDef className fill:#f9f,stroke:#333,stroke-width:4px; -``` +- **IT Network Layouts**: Visualize the structure of IT networks, showing how different devices and services are connected. +- **Educational Diagrams**: Explain complex scientific concepts, engineering systems, or historical timelines. +- **Organizational Charts**: Represent the hierarchy and relationships within an organization or department. -Also, it is possible to define style to multiple classes in one statement: +These practical examples and scenarios underscore the utility of Mermaid block diagrams in simplifying and effectively communicating complex information across various domains. -``` - classDef firstClassName,secondClassName font-size:12pt; -``` +The next section, 'Troubleshooting and Common Issues', will provide insights into resolving common challenges encountered when working with Mermaid block diagrams, ensuring a smooth diagramming experience. -Attachment of a class to a block is done as per below: +```mermaid-example -``` - class blockId1 className; ``` -It is also possible to attach a class to a list of blocks in one statement: +```mermaid-example -``` - class blockId1,blockId2 className; ``` -A shorter form of adding a class is to attach the classname to the block using the `:::`operator as per below: +## 8. Troubleshooting and Common Issues -```mermaid-example -block-beta - A:::someclass --> B - classDef someclass fill:#f96 -``` +Working with Mermaid block diagrams can sometimes present challenges, especially as the complexity of the diagrams increases. This section aims to provide guidance on resolving common issues and offers tips for managing more intricate diagram structures. -This form can be used when declaring multiple links between blocks: +### Common Syntax Errors -```mermaid-example -block-beta - A:::foo & B:::bar --> C:::foobar - classDef foo stroke:#f00 - classDef bar stroke:#0f0 - classDef foobar stroke:#00f -``` +Understanding and avoiding common syntax errors is key to a smooth experience with Mermaid diagrams. -### Css classes +#### Example - Incorrect Linking -It is also possible to predefine classes in css styles that can be applied from the graph definition as in the example -below: +A common mistake is incorrect linking syntax, which can lead to unexpected results or broken diagrams: -**Example style** - -```html - ``` - -**Example definition** - -```mermaid-example block-beta - A-->B[AAABBB] - B-->D - class A cssClass + A - B ``` -### Default class - -If a class is named default it will be assigned to all classes without specific class definitions. +**Correction**: +Ensure that links between blocks are correctly specified with arrows (--> or ---) to define the direction and type of connection: +```mermaid-example +block-beta + A --> B ``` - classDef default fill:#f9f,stroke:#333,stroke-width:4px; -``` - -## Basic support for fontawesome -It is possible to add icons from fontawesome. +#### Example - Misplaced Styling -The icons are accessed via the syntax fa:#icon class name#. +Applying styles in the wrong context or with incorrect syntax can lead to blocks not being styled as intended: ```mermaid-example -flowchart TD - B["fab:fa-twitter for peace"] - B-->C[fa:fa-ban forbidden] - B-->D(fa:fa-spinner) - B-->E(A fa:fa-camera-retro perhaps?) + block-beta + A + style A fill#f9f; ``` -Mermaid is compatible with Font Awesome up to verion 5, Free icons only. Check that the icons you use are from the [supported set of icons](https://fontawesome.com/v5/search?o=r&m=free). - -## Graph declarations with spaces between vertices and link and without semicolon - -- In graph declarations, the statements also can now end without a semicolon. After release 0.2.16, ending a graph statement with semicolon is just optional. So the below graph declaration is also valid along with the old declarations of the graph. - -- A single space is allowed between vertices and the link. However there should not be any space between a vertex and its text and a link and its text. The old syntax of graph declaration will also work and hence this new feature is optional and is introduced to improve readability. - -Below is the new declaration of the graph edges which is also valid along with the old declaration of the graph edges. +**Correction:** +Correct the syntax by ensuring proper separation of style properties with commas and using the correct CSS property format: ```mermaid-example block-beta - A[Hard edge] -->|Link text| B(Round edge) - B --> C{Decision} - C -->|One| D[Result one] - C -->|Two| E[Result two] -``` - -## Configuration + A + style A fill:#f9f,stroke:#333; -### Renderer +``` -The layout of the diagram is done with the renderer. The default renderer is dagre. +### Tips for Complex Diagram Structures -Starting with Mermaid version 9.4, you can use an alternate renderer named elk. The elk renderer is better for larger and/or more complex diagrams. +Managing complexity in Mermaid diagrams involves planning and employing best practices. -The _elk_ renderer is an experimenal feature. -You can change the renderer to elk by adding this directive: +#### Modular Design -``` -%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%% -``` +Break down complex diagrams into smaller, more manageable components. This approach not only makes the diagram easier to understand but also simplifies the creation and maintenance process. -```note -Note that the site needs to use mermaid version 9.4+ for this to work and have this featured enabled in the lazy-loading configuration. -``` +#### Consistent Styling -### Width +Use classes to maintain consistent styling across similar elements. This not only saves time but also ensures a cohesive and professional appearance. -It is possible to adjust the width of the rendered flowchart. +#### Comments and Documentation -This is done by defining **mermaid.flowchartConfig** or by the CLI to use a JSON file with the configuration. How to use the CLI is described in the mermaidCLI page. -mermaid.flowchartConfig can be set to a JSON string with config parameters or the corresponding object. +Use comments within the Mermaid syntax to document the purpose of various parts of the diagram. This practice is invaluable for maintaining clarity, especially when working in teams or returning to a diagram after some time. -```javascript -mermaid.flowchartConfig = { - width: 100% -} -``` +With these troubleshooting tips and best practices, you can effectively manage and resolve common issues in Mermaid block diagrams. The final section, 'Conclusion', will summarize the key points covered in this documentation and invite user feedback for continuous improvement. diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts index aa5c1edeb9..a4686be573 100644 --- a/packages/mermaid/src/mermaidAPI.ts +++ b/packages/mermaid/src/mermaidAPI.ts @@ -204,8 +204,6 @@ export const createCssStyles = ( cssStyles += `\n:root { --mermaid-alt-font-family: ${config.altFontFamily}}`; } - console.log('expr check', !isEmpty(classDefs), classDefs); - // classDefs defined in the diagram text if (!isEmpty(classDefs) && CLASSDEF_DIAGRAMS.includes(graphType)) { const htmlLabels = config.htmlLabels || config.flowchart?.htmlLabels; // TODO why specifically check the Flowchart diagram config? From 1230da7fc79e27476c5dd403a786ea86e79b5ab4 Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Thu, 18 Jan 2024 15:31:14 +0100 Subject: [PATCH 38/97] #3358 Some cleanup --- cypress/integration/rendering/block.spec.ts | 60 ++++++++- cypress/platform/knsv2.html | 9 +- .../mermaid/src/diagrams/block/blockDB.ts | 9 +- .../mermaid/src/diagrams/block/blockTypes.ts | 1 + .../src/diagrams/block/parser/block.jison | 2 +- .../src/diagrams/block/parser/block.spec.ts | 115 ++++++++++++------ .../src/diagrams/block/renderHelpers.ts | 9 +- packages/mermaid/src/utils.ts | 1 + 8 files changed, 149 insertions(+), 57 deletions(-) diff --git a/cypress/integration/rendering/block.spec.ts b/cypress/integration/rendering/block.spec.ts index 7856f534d7..51d78444fc 100644 --- a/cypress/integration/rendering/block.spec.ts +++ b/cypress/integration/rendering/block.spec.ts @@ -313,7 +313,7 @@ describe('Block diagram', () => { ); }); - it('BL23: sizing - it should be possieble to make a composite block wider', () => { + it('BL23: sizing - it should be possible to make a composite block wider', () => { imgSnapshotTest( `block-beta block:2 @@ -325,13 +325,61 @@ describe('Block diagram', () => { ); }); - it('BL23: sizing - it should be possieble to make a composite block wider', () => { + it('BL24: block in the middle with space on each side', () => { imgSnapshotTest( `block-beta - block:2 - A - end - B + columns 3 + space + middle["In the middle"] + space + `, + {} + ); + }); + it('BL25: space and an edge', () => { + imgSnapshotTest( + `block-beta + columns 5 + A space B + A --x B + `, + {} + ); + }); + it('BL26: block sizes for regular blocks', () => { + imgSnapshotTest( + `block-beta + columns 3 + a["A wide one"] b:2 c:2 d + `, + {} + ); + }); + it('BL27: composite block with a set width - f should use the available space', () => { + imgSnapshotTest( + `block-beta + columns 3 + a:3 + block:e:3 + f + end + g + `, + {} + ); + }); + it('BL23: composite block with a set width - f and g should split the available space', () => { + imgSnapshotTest( + `block-beta + columns 3 + a:3 + block:e:3 + f + g + end + h + i + j `, {} ); diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index b2af1f5f9b..67776fe1bd 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -65,10 +65,9 @@
     block-beta
    -        columns 3
    -        block1["Block 1"]
    -        blockArrow<["   "]>(right)
    -        block2["Block 2"]
    +columns 1
    +    B["A wide one in the middle"]
    +  style B fill:#f9F,stroke:#333,stroke-width:4px
         
     block-beta
    @@ -96,7 +95,7 @@
       end
       g
         
    -
    +    
     block-beta
       columns 3
       a:3
    diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts
    index 7e7bd7528f..34d2b5d10b 100644
    --- a/packages/mermaid/src/diagrams/block/blockDB.ts
    +++ b/packages/mermaid/src/diagrams/block/blockDB.ts
    @@ -136,8 +136,11 @@ const populateBlockDatabase = (_blockList: Block[], parent: Block): void => {
           continue;
         }
         if (block.type === 'applyStyles') {
    -      addStyle2Node(block.id, block?.styles);
    -      continue;
    +      console.log('applyStyles', block.stylesStr);
    +      if (block?.stylesStr) {
    +        addStyle2Node(block.id, block?.stylesStr);
    +        continue;
    +      }
         }
         if (block.type === 'column-setting') {
           parent.columns = block.columns || -1;
    @@ -289,7 +292,7 @@ export const generateId = () => {
     
     type ISetHierarchy = (block: Block[]) => void;
     const setHierarchy = (block: Block[]): void => {
    -  log.debug('The document from parsing', JSON.stringify(block, null, 2));
    +  console.log('The document from parsing', JSON.stringify(block, null, 2));
       rootBlock.children = block;
       populateBlockDatabase(block, rootBlock);
       // log.debug('abc95 The document after popuplation', JSON.stringify(rootBlock, null, 2));
    diff --git a/packages/mermaid/src/diagrams/block/blockTypes.ts b/packages/mermaid/src/diagrams/block/blockTypes.ts
    index d2fd8d1222..7bbba93b86 100644
    --- a/packages/mermaid/src/diagrams/block/blockTypes.ts
    +++ b/packages/mermaid/src/diagrams/block/blockTypes.ts
    @@ -59,6 +59,7 @@ export interface Block {
       css?: string;
       styleClass?: string;
       styles?: string[];
    +  stylesStr?: string;
       w?: number;
     }
     
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.jison b/packages/mermaid/src/diagrams/block/parser/block.jison
    index 066b7be0fc..751f8381be 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.jison
    +++ b/packages/mermaid/src/diagrams/block/parser/block.jison
    @@ -288,7 +288,7 @@ cssClassStatement
     
     styleStatement
         : style STYLE_ENTITY_IDS STYLE_DEFINITION_DATA {
    -        $$={ type: 'applyStyles', id: $2.trim(), styles: $3.trim() };
    +        $$={ type: 'applyStyles', id: $2.trim(), stylesStr: $3.trim() };
             }
         ;
     
    diff --git a/packages/mermaid/src/diagrams/block/parser/block.spec.ts b/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    index 367edb8426..3028a6c3ca 100644
    --- a/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    +++ b/packages/mermaid/src/diagrams/block/parser/block.spec.ts
    @@ -4,6 +4,7 @@ import db from '../blockDB.js';
     import { cleanupComments } from '../../../diagram-api/comments.js';
     import { prepareTextForParsing } from '../blockUtils.js';
     import { setConfig } from '../../../config.js';
    +import getStyles from '../../../../dist/diagrams/pie/styles';
     
     describe('Block diagram', function () {
       describe('when parsing an block diagram graph it should handle > ', function () {
    @@ -88,12 +89,34 @@ describe('Block diagram', function () {
           expect(blocks[1].label).toBe('id2');
           expect(blocks[1].type).toBe('na');
         });
    -    it('a diagram with multiple nodes with edges', async () => {
    +    it('a diagram with multiple nodes with edges abc123', async () => {
           const str = `block-beta
               id1["first"]  -->   id2["second"]
           `;
     
           block.parse(str);
    +      const blocks = db.getBlocks();
    +      const edges = db.getEdges();
    +      expect(blocks.length).toBe(2);
    +      expect(edges.length).toBe(1);
    +      expect(edges[0].start).toBe('id1');
    +      expect(edges[0].end).toBe('id2');
    +      expect(edges[0].arrowTypeEnd).toBe('arrow_point');
    +    });
    +    it('a diagram with multiple nodes with edges abc123', async () => {
    +      const str = `block-beta
    +          id1["first"]  -- "a label" -->   id2["second"]
    +      `;
    +
    +      block.parse(str);
    +      const blocks = db.getBlocks();
    +      const edges = db.getEdges();
    +      expect(blocks.length).toBe(2);
    +      expect(edges.length).toBe(1);
    +      expect(edges[0].start).toBe('id1');
    +      expect(edges[0].end).toBe('id2');
    +      expect(edges[0].arrowTypeEnd).toBe('arrow_point');
    +      expect(edges[0].label).toBe('a label');
         });
         it('a diagram with column statements', async () => {
           const str = `block-beta
    @@ -103,7 +126,8 @@ describe('Block diagram', function () {
     
           block.parse(str);
           expect(db.getColumns('root')).toBe(2);
    -      // Todo: DB check that the we have one block and that the root block has one column
    +      const blocks = db.getBlocks();
    +      expect(blocks.length).toBe(1);
         });
         it('a diagram withput column statements', async () => {
           const str = `block-beta
    @@ -112,7 +136,8 @@ describe('Block diagram', function () {
     
           block.parse(str);
           expect(db.getColumns('root')).toBe(-1);
    -      // Todo: DB check that the we have one block and that the root block has one column
    +      const blocks = db.getBlocks();
    +      expect(blocks.length).toBe(1);
         });
         it('a diagram with auto column statements', async () => {
           const str = `block-beta
    @@ -122,7 +147,8 @@ describe('Block diagram', function () {
     
           block.parse(str);
           expect(db.getColumns('root')).toBe(-1);
    -      // Todo: DB check that the we have one block and that the root block has one column
    +      const blocks = db.getBlocks();
    +      expect(blocks.length).toBe(1);
         });
     
         it('blocks next to each other', async () => {
    @@ -134,7 +160,9 @@ describe('Block diagram', function () {
     
           block.parse(str);
     
    -      // Todo: DB check that the we have two blocks and that the root block has two columns
    +      const blocks = db.getBlocks();
    +      expect(db.getColumns('root')).toBe(2);
    +      expect(blocks.length).toBe(2);
         });
     
         it('blocks on top of each other', async () => {
    @@ -146,7 +174,9 @@ describe('Block diagram', function () {
     
           block.parse(str);
     
    -      // Todo: DB check that the we have two blocks and that the root block has one column
    +      const blocks = db.getBlocks();
    +      expect(db.getColumns('root')).toBe(1);
    +      expect(blocks.length).toBe(2);
         });
     
         it('compound blocks 2', async () => {
    @@ -287,12 +317,13 @@ describe('Block diagram', function () {
           expect(block2.type).toBe('square');
           expect(blockArrow.type).toBe('block_arrow');
           console.log('blockArrow', blockArrow);
    +      expect(blockArrow.directions).toContain('right');
         });
    -    it.skip('Arrow blocks with multiple points', async () => {
    +    it('Arrow blocks with multiple points', async () => {
           const str = `block-beta
             columns 1
             A
    -        blockArrow(1,3)
    +        blockArrow<["   "]>(up, down)
             block
               columns 3
                 B
    @@ -301,6 +332,16 @@ describe('Block diagram', function () {
             end`;
     
           block.parse(str);
    +
    +      const blocks = db.getBlocks();
    +      expect(blocks.length).toBe(3);
    +
    +      const blockArrow = blocks[1];
    +      expect(blockArrow.type).toBe('block_arrow');
    +      console.log('blockArrow', blockArrow);
    +      expect(blockArrow.directions).toContain('up');
    +      expect(blockArrow.directions).toContain('down');
    +      expect(blockArrow.directions).not.toContain('right');
         });
         it('blocks with different widths', async () => {
           const str = `block-beta
    @@ -315,7 +356,7 @@ describe('Block diagram', function () {
           expect(blocks.length).toBe(2);
           const one = blocks[0];
           const two = blocks[1];
    -      console.log('Obe and Two', one, two);
    +      console.log('One and Two', one, two);
           expect(two.w).toBe(2);
         });
         it('empty blocks', async () => {
    @@ -323,46 +364,52 @@ describe('Block diagram', function () {
             columns 3
             space
             middle["In the middle"]
    +        space
             `;
     
           block.parse(str);
    +
    +      const blocks = db.getBlocks();
    +      expect(blocks.length).toBe(3);
    +      const sp1 = blocks[0];
    +      const middle = blocks[1];
    +      const sp2 = blocks[2];
    +      expect(sp1.type).toBe('space');
    +      expect(sp2.type).toBe('space');
    +      expect(middle.label).toBe('In the middle');
         });
    -    it.skip('classDef statements applied to a block', async () => {
    +    it('classDef statements applied to a block', async () => {
           const str = `block-beta
             classDef black color:#ffffff, fill:#000000;
     
    -        mc["Memcache"]:::black
    +        mc["Memcache"]
    +        class mc black
             `;
     
           block.parse(str);
    +      const blocks = db.getBlocks();
    +      expect(blocks.length).toBe(1);
    +      const mc = blocks[0];
    +      expect(mc.classes).toContain('black');
    +      const classes = db.getClasses();
    +      console.log(classes);
    +      const black = classes.black;
    +      expect(black.id).toBe('black');
    +      expect(black.styles[0]).toEqual('color:#ffffff');
         });
    -    it.skip('classDef statements applied to a block with a width', async () => {
    +    it('style statements applied to a block', async () => {
           const str = `block-beta
    -        classDef black color:#ffffff, fill:#000000;
    -        columns 2
    -        mc["Memcache"]:2::black
    +columns 1
    +    B["A wide one in the middle"]
    +  style B fill:#f9F,stroke:#333,stroke-width:4px
             `;
    -      const apa = 'apan hopar i träden';
    -      block.parse(str);
    -    });
    -
    -    it.skip('classDef statements', async () => {
    -      const str = `block-beta
    -        classDef black color:#ffffff, fill:#000000;
    -
    -        block DataServices["Data Services"]
    -          columns H
    -          block Relational
    -            mssql["Microsoft SQL
    Server"] - end - block Tabular - columns 3 - gds["Google Data Store"]:1 - mc["Memcache"]:2:::black - end - end`; block.parse(str); + const blocks = db.getBlocks(); + expect(blocks.length).toBe(1); + const B = blocks[0]; + console.log(B); + expect(B.styles).toContain('fill:#f9F'); }); }); }); diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts index 757bbadb9b..34f249315f 100644 --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts @@ -98,7 +98,7 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) { _shape = 'rect'; } - const styles = getStylesFromArray(vertex?.styles || ''); + const styles = getStylesFromArray(vertex?.styles || []); // const styles = getStylesFromArray([]); // Use vertex id as text in the box if no text is provided by the graph definition @@ -117,13 +117,6 @@ function getNodeFromBlock(block: Block, db: BlockDB, positioned = false) { style: styles.style, // + 'fill:#9f9;stroke:#333;stroke-width:4px;', id: vertex.id, directions: vertex.directions, - // link: vertex.link, - // linkTarget: vertex.linkTarget, - // tooltip: diagObj.db.getTooltip(vertex.id) || '', - // domId: diagObj.db.lookUpDomId(vertex.id), - // haveCallback: vertex.haveCallback, - // width: vertex.type === 'group' ? 500 : undefined, - // dir: vertex.dir, width: bounds.width, height: bounds.height, x: bounds.x, diff --git a/packages/mermaid/src/utils.ts b/packages/mermaid/src/utils.ts index e48b49fcda..6ea93aaa24 100644 --- a/packages/mermaid/src/utils.ts +++ b/packages/mermaid/src/utils.ts @@ -492,6 +492,7 @@ export function getStylesFromArray(arr: string[]): { style: string; labelStyle: } } } + console.log(arr, style, labelStyle); return { style: style, labelStyle: labelStyle }; } From 8e147206d8a02daa68b0d42d3b60f6e92d71d8ae Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Thu, 18 Jan 2024 15:44:16 +0100 Subject: [PATCH 39/97] #3358 Removed logging som type fixes --- .../mermaid/src/diagrams/block/blockDB.ts | 58 ++++--------------- packages/mermaid/src/diagrams/block/layout.ts | 9 +-- .../src/diagrams/block/parser/block.spec.ts | 6 -- 3 files changed, 13 insertions(+), 60 deletions(-) diff --git a/packages/mermaid/src/diagrams/block/blockDB.ts b/packages/mermaid/src/diagrams/block/blockDB.ts index 34d2b5d10b..2ba5e80a0b 100644 --- a/packages/mermaid/src/diagrams/block/blockDB.ts +++ b/packages/mermaid/src/diagrams/block/blockDB.ts @@ -31,8 +31,8 @@ let classes = {} as Record; * Called when the parser comes across a (style) class definition * @example classDef my-style fill:#f96; * - * @param {string} id - the id of this (style) class - * @param {string | null} styleAttributes - the string with 1 or more style attributes (each separated by a comma) + * @param id - the id of this (style) class + * @param styleAttributes - the string with 1 or more style attributes (each separated by a comma) */ export const addStyleClass = function (id: string, styleAttributes = '') { // create a new style class object with this id @@ -60,11 +60,11 @@ export const addStyleClass = function (id: string, styleAttributes = '') { * Called when the parser comes across a (style) class definition * @example classDef my-style fill:#f96; * - * @param {string} id - the id of this (style) class - * @param {string | null} styles - the string with 1 or more style attributes (each separated by a comma) + * @param id - the id of this (style) class + * @param styles - the string with 1 or more style attributes (each separated by a comma) */ export const addStyle2Node = function (id: string, styles = '') { - let foundBlock = blockDatabase[id]; + const foundBlock = blockDatabase[id]; if (styles !== undefined && styles !== null) { foundBlock.styles = styles.split(STYLECLASS_SEP); } @@ -75,8 +75,8 @@ export const addStyle2Node = function (id: string, styles = '') { * If the state isn't already in the list of known states, add it. * Might be called by parser when a style class or CSS class should be applied to a state * - * @param {string | string[]} itemIds The id or a list of ids of the item(s) to apply the css class to - * @param {string} cssClassName CSS class name + * @param itemIds - The id or a list of ids of the item(s) to apply the css class to + * @param cssClassName - CSS class name */ export const setCssClass = function (itemIds: string, cssClassName: string) { itemIds.split(',').forEach(function (id: string) { @@ -93,36 +93,6 @@ export const setCssClass = function (itemIds: string, cssClassName: string) { }); }; -// /** -// * Add a style to a state with the given id. -// * @example style stateId fill:#f9f,stroke:#333,stroke-width:4px -// * where 'style' is the keyword -// * stateId is the id of a state -// * the rest of the string is the styleText (all of the attributes to be applied to the state) -// * -// * @param itemId The id of item to apply the style to -// * @param styleText - the text of the attributes for the style -// */ -// export const setStyle = function (itemId, styleText) { -// const item = getState(itemId); -// if (item !== undefined) { -// item.textStyles.push(styleText); -// } -// }; - -// /** -// * Add a text style to a state with the given id -// * -// * @param itemId The id of item to apply the css class to -// * @param cssClassName CSS class name -// */ -// export const setTextStyle = function (itemId, cssClassName) { -// const item = getState(itemId); -// if (item !== undefined) { -// item.textStyles.push(cssClassName); -// } -// }; - const populateBlockDatabase = (_blockList: Block[], parent: Block): void => { const blockList = _blockList.flat(); const children = []; @@ -135,12 +105,9 @@ const populateBlockDatabase = (_blockList: Block[], parent: Block): void => { setCssClass(block.id, block?.styleClass || ''); continue; } - if (block.type === 'applyStyles') { - console.log('applyStyles', block.stylesStr); - if (block?.stylesStr) { - addStyle2Node(block.id, block?.stylesStr); - continue; - } + if (block.type === 'applyStyles' && block?.stylesStr) { + addStyle2Node(block.id, block?.stylesStr); + continue; } if (block.type === 'column-setting') { parent.columns = block.columns || -1; @@ -292,10 +259,8 @@ export const generateId = () => { type ISetHierarchy = (block: Block[]) => void; const setHierarchy = (block: Block[]): void => { - console.log('The document from parsing', JSON.stringify(block, null, 2)); rootBlock.children = block; populateBlockDatabase(block, rootBlock); - // log.debug('abc95 The document after popuplation', JSON.stringify(rootBlock, null, 2)); blocks = rootBlock.children; }; @@ -335,7 +300,7 @@ const getBlocksFlat: IGetBlocks = () => { return result; }; /** - * Returns the the hirarchy of blocks + * Returns the the hierarchy of blocks * @returns */ const getBlocks: IGetBlocks = () => { @@ -363,7 +328,6 @@ const getLogger: IGetLogger = () => console; type IGetClasses = () => Record; /** * Return all of the style classes - * @returns {{} | any | classes} */ export const getClasses = function () { return classes; diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts index e06d6ff10d..b5dc63b343 100644 --- a/packages/mermaid/src/diagrams/block/layout.ts +++ b/packages/mermaid/src/diagrams/block/layout.ts @@ -68,12 +68,7 @@ const getMaxChildSize = (block: Block) => { return { width: maxWidth, height: maxHeight }; }; -function setBlockSizes( - block: Block, - db: BlockDB, - sieblingWidth: number = 0, - sieblingHeight: number = 0 -) { +function setBlockSizes(block: Block, db: BlockDB, sieblingWidth = 0, sieblingHeight = 0) { log.debug( 'setBlockSizes abc95 (start)', block.id, @@ -118,7 +113,7 @@ function setBlockSizes( maxHeight, child.size ); - child.size.width = maxWidth * child.w + padding * (child.w - 1); + child.size.width = maxWidth * (child.w || 1) + padding * ((child.w || 1) - 1); child.size.height = maxHeight; child.size.x = 0; child.size.y = 0; diff --git a/packages/mermaid/src/diagrams/block/parser/block.spec.ts b/packages/mermaid/src/diagrams/block/parser/block.spec.ts index 3028a6c3ca..aec14cc08d 100644 --- a/packages/mermaid/src/diagrams/block/parser/block.spec.ts +++ b/packages/mermaid/src/diagrams/block/parser/block.spec.ts @@ -4,7 +4,6 @@ import db from '../blockDB.js'; import { cleanupComments } from '../../../diagram-api/comments.js'; import { prepareTextForParsing } from '../blockUtils.js'; import { setConfig } from '../../../config.js'; -import getStyles from '../../../../dist/diagrams/pie/styles'; describe('Block diagram', function () { describe('when parsing an block diagram graph it should handle > ', function () { @@ -316,7 +315,6 @@ describe('Block diagram', function () { expect(block2.label).toBe('Block 2'); expect(block2.type).toBe('square'); expect(blockArrow.type).toBe('block_arrow'); - console.log('blockArrow', blockArrow); expect(blockArrow.directions).toContain('right'); }); it('Arrow blocks with multiple points', async () => { @@ -338,7 +336,6 @@ describe('Block diagram', function () { const blockArrow = blocks[1]; expect(blockArrow.type).toBe('block_arrow'); - console.log('blockArrow', blockArrow); expect(blockArrow.directions).toContain('up'); expect(blockArrow.directions).toContain('down'); expect(blockArrow.directions).not.toContain('right'); @@ -356,7 +353,6 @@ describe('Block diagram', function () { expect(blocks.length).toBe(2); const one = blocks[0]; const two = blocks[1]; - console.log('One and Two', one, two); expect(two.w).toBe(2); }); it('empty blocks', async () => { @@ -392,7 +388,6 @@ describe('Block diagram', function () { const mc = blocks[0]; expect(mc.classes).toContain('black'); const classes = db.getClasses(); - console.log(classes); const black = classes.black; expect(black.id).toBe('black'); expect(black.styles[0]).toEqual('color:#ffffff'); @@ -408,7 +403,6 @@ columns 1 const blocks = db.getBlocks(); expect(blocks.length).toBe(1); const B = blocks[0]; - console.log(B); expect(B.styles).toContain('fill:#f9F'); }); }); From 173ba2ecf5db8c9e29bf84e98496bcc77be95adb Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Thu, 18 Jan 2024 15:48:40 +0100 Subject: [PATCH 40/97] Final console.log removed --- packages/mermaid/src/utils.ts | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/mermaid/src/utils.ts b/packages/mermaid/src/utils.ts index 6ea93aaa24..35d01a60e7 100644 --- a/packages/mermaid/src/utils.ts +++ b/packages/mermaid/src/utils.ts @@ -492,8 +492,6 @@ export function getStylesFromArray(arr: string[]): { style: string; labelStyle: } } } - console.log(arr, style, labelStyle); - return { style: style, labelStyle: labelStyle }; } From 5553cbbb228ba499568dd2a08c34917b2f53ff72 Mon Sep 17 00:00:00 2001 From: knsv Date: Thu, 18 Jan 2024 16:10:57 +0000 Subject: [PATCH 41/97] Update docs --- docs/config/setup/modules/defaultConfig.md | 2 +- docs/config/setup/modules/mermaidAPI.md | 2 +- docs/intro/examples.md | 247 --------------------- 3 files changed, 2 insertions(+), 249 deletions(-) delete mode 100644 docs/intro/examples.md diff --git a/docs/config/setup/modules/defaultConfig.md b/docs/config/setup/modules/defaultConfig.md index 7a9b891c43..3d94055bea 100644 --- a/docs/config/setup/modules/defaultConfig.md +++ b/docs/config/setup/modules/defaultConfig.md @@ -14,7 +14,7 @@ #### Defined in -[defaultConfig.ts:272](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L272) +[defaultConfig.ts:278](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L278) --- diff --git a/docs/config/setup/modules/mermaidAPI.md b/docs/config/setup/modules/mermaidAPI.md index a1992c2254..9516d2b460 100644 --- a/docs/config/setup/modules/mermaidAPI.md +++ b/docs/config/setup/modules/mermaidAPI.md @@ -96,7 +96,7 @@ mermaid.initialize(config); #### Defined in -[mermaidAPI.ts:608](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L608) +[mermaidAPI.ts:607](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L607) ## Functions diff --git a/docs/intro/examples.md b/docs/intro/examples.md deleted file mode 100644 index a7089ea9df..0000000000 --- a/docs/intro/examples.md +++ /dev/null @@ -1,247 +0,0 @@ -> **Warning** -> -> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT. -> -> ## Please edit the corresponding file in [/packages/mermaid/src/docs/intro/examples.md](../../packages/mermaid/src/docs/intro/examples.md). - -## Diagram Types - -### [Flowchart](../syntax/flowchart.md?id=flowcharts-basic-syntax) - -```mermaid-example -graph TD; - A-->B; - A-->C; - B-->D; - C-->D; -``` - -```mermaid -graph TD; - A-->B; - A-->C; - B-->D; - C-->D; -``` - -### [Sequence diagram](../syntax/sequenceDiagram.md) - -```mermaid-example -sequenceDiagram - participant Alice - participant Bob - Alice->>John: Hello John, how are you? - loop Healthcheck - John->>John: Fight against hypochondria - end - Note right of John: Rational thoughts
    prevail! - John-->>Alice: Great! - John->>Bob: How about you? - Bob-->>John: Jolly good! -``` - -```mermaid -sequenceDiagram - participant Alice - participant Bob - Alice->>John: Hello John, how are you? - loop Healthcheck - John->>John: Fight against hypochondria - end - Note right of John: Rational thoughts
    prevail! - John-->>Alice: Great! - John->>Bob: How about you? - Bob-->>John: Jolly good! -``` - -### [Gantt diagram](../syntax/gantt.md) - -```mermaid-example -gantt -dateFormat YYYY-MM-DD -title Adding GANTT diagram to mermaid -excludes weekdays 2014-01-10 - -section A section -Completed task :done, des1, 2014-01-06,2014-01-08 -Active task :active, des2, 2014-01-09, 3d -Future task : des3, after des2, 5d -Future task2 : des4, after des3, 5d -``` - -```mermaid -gantt -dateFormat YYYY-MM-DD -title Adding GANTT diagram to mermaid -excludes weekdays 2014-01-10 - -section A section -Completed task :done, des1, 2014-01-06,2014-01-08 -Active task :active, des2, 2014-01-09, 3d -Future task : des3, after des2, 5d -Future task2 : des4, after des3, 5d -``` - -### [Class diagram](../syntax/classDiagram.md) - -```mermaid-example -classDiagram -Class01 <|-- AveryLongClass : Cool -Class03 *-- Class04 -Class05 o-- Class06 -Class07 .. Class08 -Class09 --> C2 : Where am i? -Class09 --* C3 -Class09 --|> Class07 -Class07 : equals() -Class07 : Object[] elementData -Class01 : size() -Class01 : int chimp -Class01 : int gorilla -Class08 <--> C2: Cool label -``` - -```mermaid -classDiagram -Class01 <|-- AveryLongClass : Cool -Class03 *-- Class04 -Class05 o-- Class06 -Class07 .. Class08 -Class09 --> C2 : Where am i? -Class09 --* C3 -Class09 --|> Class07 -Class07 : equals() -Class07 : Object[] elementData -Class01 : size() -Class01 : int chimp -Class01 : int gorilla -Class08 <--> C2: Cool label -``` - -### [Git graph](../syntax/gitgraph.md) - -```mermaid-example - gitGraph - commit - commit - branch develop - commit - commit - commit - checkout main - commit - commit -``` - -```mermaid - gitGraph - commit - commit - branch develop - commit - commit - commit - checkout main - commit - commit -``` - -### [Entity Relationship Diagram - :exclamation: experimental](../syntax/entityRelationshipDiagram.md) - -```mermaid-example -erDiagram - CUSTOMER ||--o{ ORDER : places - ORDER ||--|{ LINE-ITEM : contains - CUSTOMER }|..|{ DELIVERY-ADDRESS : uses - -``` - -```mermaid -erDiagram - CUSTOMER ||--o{ ORDER : places - ORDER ||--|{ LINE-ITEM : contains - CUSTOMER }|..|{ DELIVERY-ADDRESS : uses - -``` - -### [User Journey Diagram](../syntax/userJourney.md) - -```mermaid-example -journey - title My working day - section Go to work - Make tea: 5: Me - Go upstairs: 3: Me - Do work: 1: Me, Cat - section Go home - Go downstairs: 5: Me - Sit down: 5: Me -``` - -```mermaid -journey - title My working day - section Go to work - Make tea: 5: Me - Go upstairs: 3: Me - Do work: 1: Me, Cat - section Go home - Go downstairs: 5: Me - Sit down: 5: Me -``` - -### [Quadrant Chart](../syntax/quadrantChart.md) - -```mermaid-example -quadrantChart - title Reach and engagement of campaigns - x-axis Low Reach --> High Reach - y-axis Low Engagement --> High Engagement - quadrant-1 We should expand - quadrant-2 Need to promote - quadrant-3 Re-evaluate - quadrant-4 May be improved - Campaign A: [0.3, 0.6] - Campaign B: [0.45, 0.23] - Campaign C: [0.57, 0.69] - Campaign D: [0.78, 0.34] - Campaign E: [0.40, 0.34] - Campaign F: [0.35, 0.78] -``` - -```mermaid -quadrantChart - title Reach and engagement of campaigns - x-axis Low Reach --> High Reach - y-axis Low Engagement --> High Engagement - quadrant-1 We should expand - quadrant-2 Need to promote - quadrant-3 Re-evaluate - quadrant-4 May be improved - Campaign A: [0.3, 0.6] - Campaign B: [0.45, 0.23] - Campaign C: [0.57, 0.69] - Campaign D: [0.78, 0.34] - Campaign E: [0.40, 0.34] - Campaign F: [0.35, 0.78] -``` - -### [XY Chart](../syntax/xyChart.md) - -```mermaid-example -xychart-beta - title "Sales Revenue" - x-axis [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] - line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] -``` - -```mermaid -xychart-beta - title "Sales Revenue" - x-axis [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] - line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] -``` From d07576676055064960c407d5eb135a7184ae6df2 Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Thu, 18 Jan 2024 18:03:37 +0100 Subject: [PATCH 42/97] #3358 Doc updates after viewing the page --- cypress/platform/knsv2.html | 9 +- docs/config/setup/modules/defaultConfig.md | 2 +- docs/config/setup/modules/mermaidAPI.md | 2 +- docs/intro/examples.md | 247 ------------------ docs/syntax/block.md | 232 ++++++++-------- .../flowchart/swimlane/swimlaneRenderer.js | 3 + packages/mermaid/src/docs/syntax/block.md | 121 +++++---- pnpm-lock.yaml | 199 ++++++-------- ....timestamp-1696335530501-05072b5e79635.mjs | 10 + 9 files changed, 297 insertions(+), 528 deletions(-) delete mode 100644 docs/intro/examples.md diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index 1127a492f6..f8722e580e 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -65,9 +65,12 @@
     block-beta
    -columns 1
    -    B["A wide one in the middle"]
    -  style B fill:#f9F,stroke:#333,stroke-width:4px
    +  A space:2 B
    +  A-- "X" -->B
    +    
    +
    +flowchart LR
    +  A-- "X" -->B
         
     block-beta
    diff --git a/docs/config/setup/modules/defaultConfig.md b/docs/config/setup/modules/defaultConfig.md
    index 7a9b891c43..3d94055bea 100644
    --- a/docs/config/setup/modules/defaultConfig.md
    +++ b/docs/config/setup/modules/defaultConfig.md
    @@ -14,7 +14,7 @@
     
     #### Defined in
     
    -[defaultConfig.ts:272](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L272)
    +[defaultConfig.ts:278](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L278)
     
     ---
     
    diff --git a/docs/config/setup/modules/mermaidAPI.md b/docs/config/setup/modules/mermaidAPI.md
    index a1992c2254..9516d2b460 100644
    --- a/docs/config/setup/modules/mermaidAPI.md
    +++ b/docs/config/setup/modules/mermaidAPI.md
    @@ -96,7 +96,7 @@ mermaid.initialize(config);
     
     #### Defined in
     
    -[mermaidAPI.ts:608](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L608)
    +[mermaidAPI.ts:607](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/mermaidAPI.ts#L607)
     
     ## Functions
     
    diff --git a/docs/intro/examples.md b/docs/intro/examples.md
    deleted file mode 100644
    index a7089ea9df..0000000000
    --- a/docs/intro/examples.md
    +++ /dev/null
    @@ -1,247 +0,0 @@
    -> **Warning**
    ->
    -> ## THIS IS AN AUTOGENERATED FILE. DO NOT EDIT.
    ->
    -> ## Please edit the corresponding file in [/packages/mermaid/src/docs/intro/examples.md](../../packages/mermaid/src/docs/intro/examples.md).
    -
    -## Diagram Types
    -
    -### [Flowchart](../syntax/flowchart.md?id=flowcharts-basic-syntax)
    -
    -```mermaid-example
    -graph TD;
    -    A-->B;
    -    A-->C;
    -    B-->D;
    -    C-->D;
    -```
    -
    -```mermaid
    -graph TD;
    -    A-->B;
    -    A-->C;
    -    B-->D;
    -    C-->D;
    -```
    -
    -### [Sequence diagram](../syntax/sequenceDiagram.md)
    -
    -```mermaid-example
    -sequenceDiagram
    -    participant Alice
    -    participant Bob
    -    Alice->>John: Hello John, how are you?
    -    loop Healthcheck
    -        John->>John: Fight against hypochondria
    -    end
    -    Note right of John: Rational thoughts 
    prevail! - John-->>Alice: Great! - John->>Bob: How about you? - Bob-->>John: Jolly good! -``` - -```mermaid -sequenceDiagram - participant Alice - participant Bob - Alice->>John: Hello John, how are you? - loop Healthcheck - John->>John: Fight against hypochondria - end - Note right of John: Rational thoughts
    prevail! - John-->>Alice: Great! - John->>Bob: How about you? - Bob-->>John: Jolly good! -``` - -### [Gantt diagram](../syntax/gantt.md) - -```mermaid-example -gantt -dateFormat YYYY-MM-DD -title Adding GANTT diagram to mermaid -excludes weekdays 2014-01-10 - -section A section -Completed task :done, des1, 2014-01-06,2014-01-08 -Active task :active, des2, 2014-01-09, 3d -Future task : des3, after des2, 5d -Future task2 : des4, after des3, 5d -``` - -```mermaid -gantt -dateFormat YYYY-MM-DD -title Adding GANTT diagram to mermaid -excludes weekdays 2014-01-10 - -section A section -Completed task :done, des1, 2014-01-06,2014-01-08 -Active task :active, des2, 2014-01-09, 3d -Future task : des3, after des2, 5d -Future task2 : des4, after des3, 5d -``` - -### [Class diagram](../syntax/classDiagram.md) - -```mermaid-example -classDiagram -Class01 <|-- AveryLongClass : Cool -Class03 *-- Class04 -Class05 o-- Class06 -Class07 .. Class08 -Class09 --> C2 : Where am i? -Class09 --* C3 -Class09 --|> Class07 -Class07 : equals() -Class07 : Object[] elementData -Class01 : size() -Class01 : int chimp -Class01 : int gorilla -Class08 <--> C2: Cool label -``` - -```mermaid -classDiagram -Class01 <|-- AveryLongClass : Cool -Class03 *-- Class04 -Class05 o-- Class06 -Class07 .. Class08 -Class09 --> C2 : Where am i? -Class09 --* C3 -Class09 --|> Class07 -Class07 : equals() -Class07 : Object[] elementData -Class01 : size() -Class01 : int chimp -Class01 : int gorilla -Class08 <--> C2: Cool label -``` - -### [Git graph](../syntax/gitgraph.md) - -```mermaid-example - gitGraph - commit - commit - branch develop - commit - commit - commit - checkout main - commit - commit -``` - -```mermaid - gitGraph - commit - commit - branch develop - commit - commit - commit - checkout main - commit - commit -``` - -### [Entity Relationship Diagram - :exclamation: experimental](../syntax/entityRelationshipDiagram.md) - -```mermaid-example -erDiagram - CUSTOMER ||--o{ ORDER : places - ORDER ||--|{ LINE-ITEM : contains - CUSTOMER }|..|{ DELIVERY-ADDRESS : uses - -``` - -```mermaid -erDiagram - CUSTOMER ||--o{ ORDER : places - ORDER ||--|{ LINE-ITEM : contains - CUSTOMER }|..|{ DELIVERY-ADDRESS : uses - -``` - -### [User Journey Diagram](../syntax/userJourney.md) - -```mermaid-example -journey - title My working day - section Go to work - Make tea: 5: Me - Go upstairs: 3: Me - Do work: 1: Me, Cat - section Go home - Go downstairs: 5: Me - Sit down: 5: Me -``` - -```mermaid -journey - title My working day - section Go to work - Make tea: 5: Me - Go upstairs: 3: Me - Do work: 1: Me, Cat - section Go home - Go downstairs: 5: Me - Sit down: 5: Me -``` - -### [Quadrant Chart](../syntax/quadrantChart.md) - -```mermaid-example -quadrantChart - title Reach and engagement of campaigns - x-axis Low Reach --> High Reach - y-axis Low Engagement --> High Engagement - quadrant-1 We should expand - quadrant-2 Need to promote - quadrant-3 Re-evaluate - quadrant-4 May be improved - Campaign A: [0.3, 0.6] - Campaign B: [0.45, 0.23] - Campaign C: [0.57, 0.69] - Campaign D: [0.78, 0.34] - Campaign E: [0.40, 0.34] - Campaign F: [0.35, 0.78] -``` - -```mermaid -quadrantChart - title Reach and engagement of campaigns - x-axis Low Reach --> High Reach - y-axis Low Engagement --> High Engagement - quadrant-1 We should expand - quadrant-2 Need to promote - quadrant-3 Re-evaluate - quadrant-4 May be improved - Campaign A: [0.3, 0.6] - Campaign B: [0.45, 0.23] - Campaign C: [0.57, 0.69] - Campaign D: [0.78, 0.34] - Campaign E: [0.40, 0.34] - Campaign F: [0.35, 0.78] -``` - -### [XY Chart](../syntax/xyChart.md) - -```mermaid-example -xychart-beta - title "Sales Revenue" - x-axis [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] - line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] -``` - -```mermaid -xychart-beta - title "Sales Revenue" - x-axis [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] - line [5000, 6000, 7500, 8200, 9500, 10500, 11000, 10200, 9200, 8500, 7000, 6000] -``` diff --git a/docs/syntax/block.md b/docs/syntax/block.md index 29c5d7674a..c33f31301d 100644 --- a/docs/syntax/block.md +++ b/docs/syntax/block.md @@ -6,7 +6,41 @@ # Block Diagrams Documentation -## 1. Introduction to Block Diagrams +## Introduction to Block Diagrams + +```mermaid-example +block-beta +columns 1 + db(("DB")) + blockArrowId6<["   "]>(down) + block:ID + A + B["A wide one in the middle"] + C + end + space + D + ID --> D + C --> D + style B fill:#969,stroke:#333,stroke-width:4px +``` + +```mermaid +block-beta +columns 1 + db(("DB")) + blockArrowId6<["   "]>(down) + block:ID + A + B["A wide one in the middle"] + C + end + space + D + ID --> D + C --> D + style B fill:#969,stroke:#333,stroke-width:4px +``` ### Definition and Purpose @@ -14,6 +48,8 @@ Block diagrams are an intuitive and efficient way to represent complex systems, The primary purpose of block diagrams is to provide a high-level view of a system, allowing for easy understanding and analysis without delving into the intricate details of each component. This makes them particularly useful for simplifying complex systems and for explaining the overall structure and interaction of components within a system. +Many people use mermaid flowcharts for this purpose. A side-effect of this is that the automatic layout sometimes move shapes to positions that the diagram maker does not want. Block diagrams use a different approach. In this diagram we give the author full control over where the shapes are positioned. + ### General Use Cases Block diagrams have a wide range of applications across various industries and disciplines. Some of the key use cases include: @@ -181,12 +217,12 @@ To create a block with round edges, which can be used to represent a softer or m ```mermaid-example block-beta - id1(This is the text in the box) + id1("This is the text in the box") ``` ```mermaid block-beta - id1(This is the text in the box) + id1("This is the text in the box") ``` #### Example - Stadium-Shaped Block @@ -195,12 +231,12 @@ A stadium-shaped block, resembling an elongated circle, can be used for componen ```mermaid-example block-beta - id1([This is the text in the box]) + id1(["This is the text in the box"]) ``` ```mermaid block-beta - id1([This is the text in the box]) + id1(["This is the text in the box"]) ``` #### Example - Subroutine Shape @@ -209,12 +245,12 @@ For representing subroutines or contained processes, a block with double vertica ```mermaid-example block-beta - id1[[This is the text in the box]] + id1[["This is the text in the box"]] ``` ```mermaid block-beta - id1[[This is the text in the box]] + id1[["This is the text in the box"]] ``` #### Example - Cylindrical Shape @@ -223,12 +259,12 @@ The cylindrical shape is ideal for representing databases or storage components: ```mermaid-example block-beta - id1[(Database)] + id1[("Database")] ``` ```mermaid block-beta - id1[(Database)] + id1[("Database")] ``` #### Example - Circle Shape @@ -237,12 +273,12 @@ A circle can be used for centralized or pivotal components: ```mermaid-example block-beta - id1((This is the text in the circle)) + id1(("This is the text in the circle")) ``` ```mermaid block-beta - id1((This is the text in the circle)) + id1(("This is the text in the circle")) ``` #### Example - Asymmetric, Rhombus, and Hexagon Shapes @@ -253,36 +289,36 @@ For decision points, use a rhombus, and for unique or specialized processes, asy ```mermaid-example block-beta - id1>This is the text in the box] + id1>"This is the text in the box"] ``` ```mermaid block-beta - id1>This is the text in the box] + id1>"This is the text in the box"] ``` **Rhombus** ```mermaid-example block-beta - id1{This is the text in the box} + id1{"This is the text in the box"} ``` ```mermaid block-beta - id1{This is the text in the box} + id1{"This is the text in the box"} ``` **Hexagon** ```mermaid-example block-beta - id1{{This is the text in the box}} + id1{{"This is the text in the box"}} ``` ```mermaid block-beta - id1{{This is the text in the box}} + id1{{"This is the text in the box"}} ``` #### Example - Parallelogram and Trapezoid Shapes @@ -291,18 +327,18 @@ Parallelogram and trapezoid shapes are perfect for inputs/outputs and transition ```mermaid-example flowchart TD - id1[/This is the text in the box/] - id2[\This is the text in the box\] - A[/Christmas\] - B[\Go shopping/] + id1[/"This is the text in the box"/] + id2[\"This is the text in the box"\] + A[/"Christmas"\] + B[\"Go shopping"/] ``` ```mermaid flowchart TD - id1[/This is the text in the box/] - id2[\This is the text in the box\] - A[/Christmas\] - B[\Go shopping/] + id1[/"This is the text in the box"/] + id2[\"This is the text in the box"\] + A[/"Christmas"\] + B[\"Go shopping"/] ``` #### Example - Double Circle @@ -311,12 +347,12 @@ For highlighting critical or high-priority components, a double circle can be ef ```mermaid-example flowchart TD - id1(((This is the text in the circle))) + id1((("This is the text in the circle"))) ``` ```mermaid flowchart TD - id1(((This is the text in the circle))) + id1((("This is the text in the circle"))) ``` ### Block Arrows and Space Blocks @@ -387,11 +423,13 @@ A simple link with an arrow can be created to show direction or flow from one bl ```mermaid-example block-beta + A space B A-->B ``` ```mermaid block-beta + A space B A-->B ``` @@ -402,11 +440,13 @@ For connections that are less direct or to represent a different type of relatio ```mermaid-example block-beta + A space B A --- B ``` ```mermaid block-beta + A space B A --- B ``` @@ -421,12 +461,14 @@ To add text to a link, the syntax includes the text within the link definition: ```mermaid-example block-beta - A-- This is the text! ---B + A space:2 B + A-- "X" -->B ``` ```mermaid block-beta - A-- This is the text! ---B + A space:2 B + A-- "X" -->B ``` This example show how to add descriptive text to the links, enhancing the information conveyed by the diagram. @@ -440,26 +482,16 @@ A dotted link can be used to represent a weaker or less formal relationship: ```mermaid-example block-beta + A space:2 B A-.->B ``` ```mermaid block-beta + A space:2 B A-.->B ``` -For a more pronounced connection, a thick link can be used: - -```mermaid-example -block-beta - A==>B -``` - -```mermaid -block-beta - A==>B -``` - Example - Edges and Styles: ```mermaid-example @@ -476,7 +508,7 @@ columns 1 D ID --> D C --> D - style B fill:#f9F,stroke:#333,stroke-width:4px + style B fill:#939,stroke:#333,stroke-width:4px ``` ```mermaid @@ -493,7 +525,7 @@ columns 1 D ID --> D C --> D - style B fill:#f9F,stroke:#333,stroke-width:4px + style B fill:#939,stroke:#333,stroke-width:4px ``` ## 6. Styling and Customization @@ -510,15 +542,17 @@ To apply custom styles to a block, you can use the `style` keyword followed by t ```mermaid-example block-beta - id1(Start)-->id2(Stop) - style id1 fill:#f9f,stroke:#333,stroke-width:4px + id1 space id2 + id1("Start")-->id2("Stop") + style id1 fill:#636,stroke:#333,stroke-width:4px style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 ``` ```mermaid block-beta - id1(Start)-->id2(Stop) - style id1 fill:#f9f,stroke:#333,stroke-width:4px + id1 space id2 + id1("Start")-->id2("Stop") + style id1 fill:#636,stroke:#333,stroke-width:4px style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 ``` @@ -540,24 +574,28 @@ Illustrating a simple software system architecture with interconnected component ```mermaid-example block-beta - columns 2 - Frontend Backend - Frontend-->Backend - Database[(Database)] - Backend-->Database - class Frontend,Backend fill:#f96,stroke:#333; - class Database fill:#9f9,stroke:#333; + columns 3 + Frontend blockArrowId6<["  "]>(right) Backend + space:2 down<["  "]>(down) + Disk left<["  "]>(left) Database[("Database")] + + classDef front fill:#696,stroke:#333; + classDef back fill:#969,stroke:#333; + class Frontend front + class Backend,Database back ``` ```mermaid block-beta - columns 2 - Frontend Backend - Frontend-->Backend - Database[(Database)] - Backend-->Database - class Frontend,Backend fill:#f96,stroke:#333; - class Database fill:#9f9,stroke:#333; + columns 3 + Frontend blockArrowId6<["  "]>(right) Backend + space:2 down<["  "]>(down) + Disk left<["  "]>(left) Database[("Database")] + + classDef front fill:#696,stroke:#333; + classDef back fill:#969,stroke:#333; + class Frontend front + class Backend,Database back ``` This example shows a basic architecture with a frontend, backend, and database. The blocks are styled to differentiate between types of components. @@ -568,41 +606,35 @@ Representing a business process flow with decision points and multiple stages: ```mermaid-example block-beta - Start{Start} - Decision{Make Decision} - Process1[Process A] - Process2[Process B] - End((End)) - Start --> Decision - Decision -- Yes --> Process1 - Decision -- No --> Process2 - Process1 --> End - Process2 --> End - style Start fill:#f9f; - style End fill:#bbf; + columns 3 + Start(("Start")) space:2 + down<["  "]>(down) space:2 + Decision{{"Make Decision"}} right<["Yes"]>(right) Process1["Process A"] + downAgain<["No"]>(down) space r3<["Done"]>(down) + Process2["Process B"] r2<["Done"]>(right) End(("End")) + + style Start fill:#969; + style End fill:#696; ``` ```mermaid block-beta - Start{Start} - Decision{Make Decision} - Process1[Process A] - Process2[Process B] - End((End)) - Start --> Decision - Decision -- Yes --> Process1 - Decision -- No --> Process2 - Process1 --> End - Process2 --> End - style Start fill:#f9f; - style End fill:#bbf; + columns 3 + Start(("Start")) space:2 + down<["  "]>(down) space:2 + Decision{{"Make Decision"}} right<["Yes"]>(right) Process1["Process A"] + downAgain<["No"]>(down) space r3<["Done"]>(down) + Process2["Process B"] r2<["Done"]>(right) End(("End")) + + style Start fill:#969; + style End fill:#696; ``` This diagram depicts a simple decision-making process with two possible paths leading to an endpoint, demonstrating the use of different shapes and directional arrows. -### Real works Application Scenarios +### Real world Scenarios Block diagrams can be employed in a variety of real-world scenarios. Here are a few examples: @@ -614,22 +646,6 @@ These practical examples and scenarios underscore the utility of Mermaid block d The next section, 'Troubleshooting and Common Issues', will provide insights into resolving common challenges encountered when working with Mermaid block diagrams, ensuring a smooth diagramming experience. -```mermaid-example - -``` - -```mermaid - -``` - -```mermaid-example - -``` - -```mermaid - -``` - ## 8. Troubleshooting and Common Issues Working with Mermaid block diagrams can sometimes present challenges, especially as the complexity of the diagrams increases. This section aims to provide guidance on resolving common issues and offers tips for managing more intricate diagram structures. @@ -646,15 +662,17 @@ A common mistake is incorrect linking syntax, which can lead to unexpected resul A - B **Correction**: -Ensure that links between blocks are correctly specified with arrows (--> or ---) to define the direction and type of connection: +Ensure that links between blocks are correctly specified with arrows (--> or ---) to define the direction and type of connection. Also rememeber that one of the fundaments for block diagram is to give the author full control of where the boxes are positioned so in the example you need to add a space between the boxes: ```mermaid-example block-beta + A space B A --> B ``` ```mermaid block-beta + A space B A --> B ``` @@ -665,13 +683,13 @@ Applying styles in the wrong context or with incorrect syntax can lead to blocks ```mermaid-example block-beta A - style A fill#f9f; + style A fill#969; ``` ```mermaid block-beta A - style A fill#f9f; + style A fill#969; ``` **Correction:** @@ -680,14 +698,14 @@ Correct the syntax by ensuring proper separation of style properties with commas ```mermaid-example block-beta A - style A fill:#f9f,stroke:#333; + style A fill:#969,stroke:#333; ``` ```mermaid block-beta A - style A fill:#f9f,stroke:#333; + style A fill:#969,stroke:#333; ``` diff --git a/packages/mermaid/src/diagrams/flowchart/swimlane/swimlaneRenderer.js b/packages/mermaid/src/diagrams/flowchart/swimlane/swimlaneRenderer.js index c49c30f4ec..a34ba02dd7 100644 --- a/packages/mermaid/src/diagrams/flowchart/swimlane/swimlaneRenderer.js +++ b/packages/mermaid/src/diagrams/flowchart/swimlane/swimlaneRenderer.js @@ -27,7 +27,10 @@ export const setConf = function (cnf) { * @param element * @param graph * @param layout + * @param vert * @param elem + * @param g + * @param id * @param conf */ async function swimlaneRender(layout, vert, elem, g, id, conf) { diff --git a/packages/mermaid/src/docs/syntax/block.md b/packages/mermaid/src/docs/syntax/block.md index b1067d5b36..9186d68c6a 100644 --- a/packages/mermaid/src/docs/syntax/block.md +++ b/packages/mermaid/src/docs/syntax/block.md @@ -5,7 +5,24 @@ outline: 'deep' # shows all h3 headings in outline in Vitepress # Block Diagrams Documentation -## 1. Introduction to Block Diagrams +## Introduction to Block Diagrams + +```mermaid +block-beta +columns 1 + db(("DB")) + blockArrowId6<["   "]>(down) + block:ID + A + B["A wide one in the middle"] + C + end + space + D + ID --> D + C --> D + style B fill:#969,stroke:#333,stroke-width:4px +``` ### Definition and Purpose @@ -13,6 +30,8 @@ Block diagrams are an intuitive and efficient way to represent complex systems, The primary purpose of block diagrams is to provide a high-level view of a system, allowing for easy understanding and analysis without delving into the intricate details of each component. This makes them particularly useful for simplifying complex systems and for explaining the overall structure and interaction of components within a system. +Many people use mermaid flowcharts for this purpose. A side-effect of this is that the automatic layout sometimes move shapes to positions that the diagram maker does not want. Block diagrams use a different approach. In this diagram we give the author full control over where the shapes are positioned. + ### General Use Cases Block diagrams have a wide range of applications across various industries and disciplines. Some of the key use cases include: @@ -145,7 +164,7 @@ To create a block with round edges, which can be used to represent a softer or m ```mermaid-example block-beta - id1(This is the text in the box) + id1("This is the text in the box") ``` #### Example - Stadium-Shaped Block @@ -154,7 +173,7 @@ A stadium-shaped block, resembling an elongated circle, can be used for componen ```mermaid-example block-beta - id1([This is the text in the box]) + id1(["This is the text in the box"]) ``` #### Example - Subroutine Shape @@ -163,7 +182,7 @@ For representing subroutines or contained processes, a block with double vertica ```mermaid-example block-beta - id1[[This is the text in the box]] + id1[["This is the text in the box"]] ``` #### Example - Cylindrical Shape @@ -172,7 +191,7 @@ The cylindrical shape is ideal for representing databases or storage components: ```mermaid-example block-beta - id1[(Database)] + id1[("Database")] ``` #### Example - Circle Shape @@ -181,7 +200,7 @@ A circle can be used for centralized or pivotal components: ```mermaid-example block-beta - id1((This is the text in the circle)) + id1(("This is the text in the circle")) ``` #### Example - Asymmetric, Rhombus, and Hexagon Shapes @@ -192,21 +211,21 @@ For decision points, use a rhombus, and for unique or specialized processes, asy ```mermaid-example block-beta - id1>This is the text in the box] + id1>"This is the text in the box"] ``` **Rhombus** ```mermaid-example block-beta - id1{This is the text in the box} + id1{"This is the text in the box"} ``` **Hexagon** ```mermaid-example block-beta - id1{{This is the text in the box}} + id1{{"This is the text in the box"}} ``` #### Example - Parallelogram and Trapezoid Shapes @@ -215,10 +234,10 @@ Parallelogram and trapezoid shapes are perfect for inputs/outputs and transition ```mermaid-example flowchart TD - id1[/This is the text in the box/] - id2[\This is the text in the box\] - A[/Christmas\] - B[\Go shopping/] + id1[/"This is the text in the box"/] + id2[\"This is the text in the box"\] + A[/"Christmas"\] + B[\"Go shopping"/] ``` #### Example - Double Circle @@ -227,7 +246,7 @@ For highlighting critical or high-priority components, a double circle can be ef ```mermaid-example flowchart TD - id1(((This is the text in the circle))) + id1((("This is the text in the circle"))) ``` ### Block Arrows and Space Blocks @@ -281,6 +300,7 @@ A simple link with an arrow can be created to show direction or flow from one bl ```mermaid-example block-beta + A space B A-->B ``` @@ -291,6 +311,7 @@ For connections that are less direct or to represent a different type of relatio ```mermaid-example block-beta + A space B A --- B ``` @@ -305,7 +326,8 @@ To add text to a link, the syntax includes the text within the link definition: ```mermaid-example block-beta - A-- This is the text! ---B + A space:2 B + A-- "X" -->B ``` This example show how to add descriptive text to the links, enhancing the information conveyed by the diagram. @@ -319,16 +341,10 @@ A dotted link can be used to represent a weaker or less formal relationship: ```mermaid-example block-beta + A space:2 B A-.->B ``` -For a more pronounced connection, a thick link can be used: - -```mermaid-example -block-beta - A==>B -``` - Example - Edges and Styles: ```mermaid-example @@ -345,7 +361,7 @@ columns 1 D ID --> D C --> D - style B fill:#f9F,stroke:#333,stroke-width:4px + style B fill:#939,stroke:#333,stroke-width:4px ``` ## 6. Styling and Customization @@ -362,8 +378,9 @@ To apply custom styles to a block, you can use the `style` keyword followed by t ```mermaid-example block-beta - id1(Start)-->id2(Stop) - style id1 fill:#f9f,stroke:#333,stroke-width:4px + id1 space id2 + id1("Start")-->id2("Stop") + style id1 fill:#636,stroke:#333,stroke-width:4px style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 ``` @@ -385,13 +402,15 @@ Illustrating a simple software system architecture with interconnected component ```mermaid block-beta - columns 2 - Frontend Backend - Frontend-->Backend - Database[(Database)] - Backend-->Database - class Frontend,Backend fill:#f96,stroke:#333; - class Database fill:#9f9,stroke:#333; + columns 3 + Frontend blockArrowId6<["  "]>(right) Backend + space:2 down<["  "]>(down) + Disk left<["  "]>(left) Database[("Database")] + + classDef front fill:#696,stroke:#333; + classDef back fill:#969,stroke:#333; + class Frontend front + class Backend,Database back ``` This example shows a basic architecture with a frontend, backend, and database. The blocks are styled to differentiate between types of components. @@ -402,24 +421,21 @@ Representing a business process flow with decision points and multiple stages: ```mermaid-example block-beta - Start{Start} - Decision{Make Decision} - Process1[Process A] - Process2[Process B] - End((End)) - Start --> Decision - Decision -- Yes --> Process1 - Decision -- No --> Process2 - Process1 --> End - Process2 --> End - style Start fill:#f9f; - style End fill:#bbf; + columns 3 + Start(("Start")) space:2 + down<["  "]>(down) space:2 + Decision{{"Make Decision"}} right<["Yes"]>(right) Process1["Process A"] + downAgain<["No"]>(down) space r3<["Done"]>(down) + Process2["Process B"] r2<["Done"]>(right) End(("End")) + + style Start fill:#969; + style End fill:#696; ``` This diagram depicts a simple decision-making process with two possible paths leading to an endpoint, demonstrating the use of different shapes and directional arrows. -### Real works Application Scenarios +### Real world Scenarios Block diagrams can be employed in a variety of real-world scenarios. Here are a few examples: @@ -431,14 +447,6 @@ These practical examples and scenarios underscore the utility of Mermaid block d The next section, 'Troubleshooting and Common Issues', will provide insights into resolving common challenges encountered when working with Mermaid block diagrams, ensuring a smooth diagramming experience. -```mermaid-example - -``` - -```mermaid-example - -``` - ## 8. Troubleshooting and Common Issues Working with Mermaid block diagrams can sometimes present challenges, especially as the complexity of the diagrams increases. This section aims to provide guidance on resolving common issues and offers tips for managing more intricate diagram structures. @@ -457,10 +465,11 @@ block-beta ``` **Correction**: -Ensure that links between blocks are correctly specified with arrows (--> or ---) to define the direction and type of connection: +Ensure that links between blocks are correctly specified with arrows (--> or ---) to define the direction and type of connection. Also rememeber that one of the fundaments for block diagram is to give the author full control of where the boxes are positioned so in the example you need to add a space between the boxes: ```mermaid-example block-beta + A space B A --> B ``` @@ -471,7 +480,7 @@ Applying styles in the wrong context or with incorrect syntax can lead to blocks ```mermaid-example block-beta A - style A fill#f9f; + style A fill#969; ``` **Correction:** @@ -480,7 +489,7 @@ Correct the syntax by ensuring proper separation of style properties with commas ```mermaid-example block-beta A - style A fill:#f9f,stroke:#333; + style A fill:#969,stroke:#333; ``` diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index f6f1897f66..e39424af00 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -374,7 +374,7 @@ importers: version: 4.1.2 vitepress: specifier: ^1.0.0-alpha.72 - version: 1.0.0-alpha.72(@algolia/client-search@4.19.1)(@types/node@18.17.5)(search-insights@2.7.0) + version: 1.0.0-alpha.72(@algolia/client-search@4.19.1)(@types/node@18.17.5)(search-insights@2.7.0)(typescript@5.0.4) vitepress-plugin-search: specifier: ^1.0.4-alpha.20 version: 1.0.4-alpha.20(flexsearch@0.7.31)(vitepress@1.0.0-alpha.72)(vue@3.3.8) @@ -420,7 +420,7 @@ importers: dependencies: '@zenuml/core': specifier: ^3.0.6 - version: 3.0.6(ts-node@10.9.1) + version: 3.0.6(ts-node@10.9.1)(typescript@5.1.6) devDependencies: mermaid: specifier: workspace:^ @@ -481,6 +481,61 @@ importers: specifier: ^7.0.0 version: 7.0.0 + packages/mermaid/src/vitepress: + dependencies: + '@vueuse/core': + specifier: ^10.1.0 + version: 10.1.0(vue@3.3.4) + jiti: + specifier: ^1.18.2 + version: 1.18.2 + mermaid: + specifier: workspace:^ + version: link:../.. + vue: + specifier: ^3.3 + version: 3.3.4 + devDependencies: + '@iconify-json/carbon': + specifier: ^1.1.16 + version: 1.1.16 + '@unocss/reset': + specifier: ^0.58.0 + version: 0.58.0 + '@vite-pwa/vitepress': + specifier: ^0.3.0 + version: 0.3.0(vite-plugin-pwa@0.17.0) + '@vitejs/plugin-vue': + specifier: ^4.2.1 + version: 4.2.1(vite@4.5.0)(vue@3.3.4) + fast-glob: + specifier: ^3.2.12 + version: 3.2.12 + https-localhost: + specifier: ^4.7.1 + version: 4.7.1 + pathe: + specifier: ^1.1.0 + version: 1.1.0 + unocss: + specifier: ^0.58.0 + version: 0.58.0(postcss@8.4.31)(rollup@2.79.1)(vite@4.5.0) + unplugin-vue-components: + specifier: ^0.26.0 + version: 0.26.0(rollup@2.79.1)(vue@3.3.4) + vite: + specifier: ^4.4.12 + version: 4.5.0(@types/node@18.17.5) + vite-plugin-pwa: + specifier: ^0.17.0 + version: 0.17.0(vite@4.5.0)(workbox-build@7.0.0)(workbox-window@7.0.0) + vitepress: + specifier: 1.0.0-rc.31 + version: 1.0.0-rc.31(@algolia/client-search@4.19.1)(@types/node@18.17.5)(postcss@8.4.31)(search-insights@2.7.0)(typescript@5.1.6) + workbox-window: + specifier: ^7.0.0 + version: 7.0.0 + tests/webpack: dependencies: '@mermaid-js/mermaid-example-diagram': @@ -1372,7 +1427,6 @@ packages: /@babel/helper-string-parser@7.23.4: resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} engines: {node: '>=6.9.0'} - dev: true /@babel/helper-validator-identifier@7.22.20: resolution: {integrity: sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A==} @@ -1455,7 +1509,6 @@ packages: hasBin: true dependencies: '@babel/types': 7.23.5 - dev: true /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.22.5(@babel/core@7.23.5): resolution: {integrity: sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==} @@ -2547,7 +2600,6 @@ packages: '@babel/helper-string-parser': 7.23.4 '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 - dev: true /@bcherny/json-schema-ref-parser@9.0.9: resolution: {integrity: sha512-vmEmnJCfpkLdas++9OYg6riIezTYqTHpqUTODJzHLzs5UnXujbOJW9VwcVCnyo1mVRt32FRr23iXBx/sX8YbeQ==} @@ -4397,21 +4449,6 @@ packages: picomatch: 2.3.1 dev: true - /@rollup/pluginutils@5.0.5(rollup@2.79.1): - resolution: {integrity: sha512-6aEYR910NyP73oHiJglti74iRyOwgFU4x3meH/H8OJx6Ry0j6cOVZ5X/wTvub7G7Ao6qaHBEaNsV3GLJkSsF+Q==} - engines: {node: '>=14.0.0'} - peerDependencies: - rollup: ^1.20.0||^2.0.0||^3.0.0||^4.0.0 - peerDependenciesMeta: - rollup: - optional: true - dependencies: - '@types/estree': 1.0.1 - estree-walker: 2.0.2 - picomatch: 2.3.1 - rollup: 2.79.1 - dev: true - /@rollup/pluginutils@5.1.0(rollup@2.79.1): resolution: {integrity: sha512-XTIWOPPcpvyKI6L1NHo0lFlCyznUEyPmPY1mc3KpPVDYulHSTvyeLNVW00QTLIAFNhR3kYnJTQHeGqU4M3n09g==} engines: {node: '>=14.0.0'} @@ -5199,10 +5236,6 @@ packages: resolution: {integrity: sha512-oh8q2Zc32S6gd/j50GowEjKLoOVOwHP/bWVjKJInBwQqdOYMdPrf1oVlelTlyfFK3CKxL1uahMDAr+vy8T7yMQ==} dev: false - /@types/web-bluetooth@0.0.17: - resolution: {integrity: sha512-4p9vcSmxAayx72yn70joFoL44c9MO/0+iVEBIQXe3v2h2SiAsEIo/G5v6ObFWvNKRFjbrVadNf9LqEEZeQPzdA==} - dev: true - /@types/web-bluetooth@0.0.20: resolution: {integrity: sha512-g9gZnnXVq7gM7v3tJCWV/qw7w+KeOlSHAhgF9RytFyifW6AF61hdT2ucrYhPq9hLs5JIryeupHV3qGk95dH9ow==} dev: true @@ -5791,15 +5824,15 @@ packages: vue: 3.3.4 dev: true - /@vitejs/plugin-vue@4.2.3(vite@4.5.0)(vue@3.3.4): - resolution: {integrity: sha512-R6JDUfiZbJA9cMiguQ7jxALsgiprjBeHL5ikpXfJCH62pPHtI+JdJ5xWj6Ev73yXSlYl86+blXn1kZHQ7uElxw==} + /@vitejs/plugin-vue@4.5.0(vite@4.5.0)(vue@3.3.8): + resolution: {integrity: sha512-a2WSpP8X8HTEww/U00bU4mX1QpLINNuz/2KMNpLsdu3BzOpak3AGI1CJYBTXcc4SPhaD0eNRUp7IyQK405L5dQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: - vite: ^4.0.0 + vite: ^4.0.0 || ^5.0.0 vue: ^3.2.25 dependencies: vite: 4.5.0(@types/node@18.17.5) - vue: 3.3.4 + vue: 3.3.8(typescript@5.0.4) dev: true /@vitejs/plugin-vue@4.5.0(vite@5.0.2)(vue@3.3.8): @@ -5887,7 +5920,7 @@ packages: pretty-format: 29.6.2 dev: true - /@vue/compat@3.3.4(vue@3.3.4): + /@vue/compat@3.3.4(vue@3.3.8): resolution: {integrity: sha512-VwAsPqUqRJVxeLQPUC03Sa5d+T8UG2Qv4VItq74KmNvtQlRXICpa/sqq12BcyBB4Tz1U5paOEZxWCUoXkrZ9QQ==} peerDependencies: vue: 3.3.4 @@ -5895,7 +5928,7 @@ packages: '@babel/parser': 7.23.0 estree-walker: 2.0.2 source-map-js: 1.0.2 - vue: 3.3.4 + vue: 3.3.8(typescript@5.1.6) dev: false /@vue/compiler-core@3.3.4: @@ -5909,11 +5942,10 @@ packages: /@vue/compiler-core@3.3.8: resolution: {integrity: sha512-hN/NNBUECw8SusQvDSqqcVv6gWq8L6iAktUR0UF3vGu2OhzRqcOiAno0FmBJWwxhYEXRlQJT5XnoKsVq1WZx4g==} dependencies: - '@babel/parser': 7.23.0 + '@babel/parser': 7.23.5 '@vue/shared': 3.3.8 estree-walker: 2.0.2 source-map-js: 1.0.2 - dev: true /@vue/compiler-dom@3.3.4: resolution: {integrity: sha512-wyM+OjOVpuUukIq6p5+nwHYtj9cFroz9cwkfmP9O1nzH68BenTTv0u7/ndggT8cIQlnBeOo6sUT/gvHcIkLA5w==} @@ -5926,12 +5958,11 @@ packages: dependencies: '@vue/compiler-core': 3.3.8 '@vue/shared': 3.3.8 - dev: true /@vue/compiler-sfc@3.3.4: resolution: {integrity: sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==} dependencies: - '@babel/parser': 7.23.0 + '@babel/parser': 7.23.5 '@vue/compiler-core': 3.3.4 '@vue/compiler-dom': 3.3.4 '@vue/compiler-ssr': 3.3.4 @@ -5945,7 +5976,7 @@ packages: /@vue/compiler-sfc@3.3.8: resolution: {integrity: sha512-WMzbUrlTjfYF8joyT84HfwwXo+8WPALuPxhy+BZ6R4Aafls+jDBnSz8PDz60uFhuqFbl3HxRfxvDzrUf3THwpA==} dependencies: - '@babel/parser': 7.23.0 + '@babel/parser': 7.23.5 '@vue/compiler-core': 3.3.8 '@vue/compiler-dom': 3.3.8 '@vue/compiler-ssr': 3.3.8 @@ -5955,7 +5986,6 @@ packages: magic-string: 0.30.5 postcss: 8.4.31 source-map-js: 1.0.2 - dev: true /@vue/compiler-ssr@3.3.4: resolution: {integrity: sha512-m0v6oKpup2nMSehwA6Uuu+j+wEwcy7QmwMkVNVfrV9P2qE5KshC6RwOCq8fjGS/Eak/uNb8AaWekfiXxbBB6gQ==} @@ -5968,7 +5998,6 @@ packages: dependencies: '@vue/compiler-dom': 3.3.8 '@vue/shared': 3.3.8 - dev: true /@vue/devtools-api@6.5.0: resolution: {integrity: sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==} @@ -5994,7 +6023,6 @@ packages: '@vue/shared': 3.3.8 estree-walker: 2.0.2 magic-string: 0.30.5 - dev: true /@vue/reactivity@3.3.4: resolution: {integrity: sha512-kLTDLwd0B1jG08NBF3R5rqULtv/f8x3rOFByTDz4J53ttIQEDmALqKqXY0J+XQeN0aV2FBxY8nJDf88yvOPAqQ==} @@ -6005,7 +6033,6 @@ packages: resolution: {integrity: sha512-ctLWitmFBu6mtddPyOKpHg8+5ahouoTCRtmAHZAXmolDtuZXfjL2T3OJ6DL6ezBPQB1SmMnpzjiWjCiMYmpIuw==} dependencies: '@vue/shared': 3.3.8 - dev: true /@vue/runtime-core@3.3.4: resolution: {integrity: sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==} @@ -6018,7 +6045,6 @@ packages: dependencies: '@vue/reactivity': 3.3.8 '@vue/shared': 3.3.8 - dev: true /@vue/runtime-dom@3.3.4: resolution: {integrity: sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==} @@ -6033,7 +6059,6 @@ packages: '@vue/runtime-core': 3.3.8 '@vue/shared': 3.3.8 csstype: 3.1.2 - dev: true /@vue/server-renderer@3.3.4(vue@3.3.4): resolution: {integrity: sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==} @@ -6051,15 +6076,13 @@ packages: dependencies: '@vue/compiler-ssr': 3.3.8 '@vue/shared': 3.3.8 - vue: 3.3.8(typescript@5.0.4) - dev: true + vue: 3.3.8(typescript@5.1.6) /@vue/shared@3.3.4: resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} /@vue/shared@3.3.8: resolution: {integrity: sha512-8PGwybFwM4x8pcfgqEQFy70NaQxASvOC5DJwLQfpArw1UDfUXrJkdxD3BhVTMS+0Lef/TU7YO0Jvr0jJY8T+mw==} - dev: true /@vueuse/core@10.1.0(vue@3.3.4): resolution: {integrity: sha512-3Znoa5m5RO+z4/C9w6DRaKTR3wCVJvD5rav8HTDGsr+7rOZRHtcgFJ8NcCs0ZvIpmev2kExTa311ns5j2RbzDQ==} @@ -6067,23 +6090,11 @@ packages: '@types/web-bluetooth': 0.0.16 '@vueuse/metadata': 10.1.0 '@vueuse/shared': 10.1.0(vue@3.3.4) - vue-demi: 0.14.5(vue@3.3.4) - transitivePeerDependencies: - - '@vue/composition-api' - - vue - dev: false - - /@vueuse/core@10.3.0(vue@3.3.4): - resolution: {integrity: sha512-BEM5yxcFKb5btFjTSAFjTu5jmwoW66fyV9uJIP4wUXXU8aR5Hl44gndaaXp7dC5HSObmgbnR2RN+Un1p68Mf5Q==} - dependencies: - '@types/web-bluetooth': 0.0.17 - '@vueuse/metadata': 10.3.0 - '@vueuse/shared': 10.3.0(vue@3.3.4) vue-demi: 0.14.6(vue@3.3.4) transitivePeerDependencies: - '@vue/composition-api' - vue - dev: true + dev: false /@vueuse/core@10.6.1(vue@3.3.8): resolution: {integrity: sha512-Pc26IJbqgC9VG1u6VY/xrXXfxD33hnvxBnKrLlA2LJlyHII+BSrRoTPJgGYq7qZOu61itITFUnm6QbacwZ4H8Q==} @@ -6151,31 +6162,18 @@ packages: resolution: {integrity: sha512-cM28HjDEw5FIrPE9rgSPFZvQ0ZYnOLAOr8hl1XM6tFl80U3WAR5ROdnAqiYybniwP5gt9MKKAJAqd/ab2aHkqg==} dev: false - /@vueuse/metadata@10.3.0: - resolution: {integrity: sha512-Ema3YhNOa4swDsV0V7CEY5JXvK19JI/o1szFO1iWxdFg3vhdFtCtSTP26PCvbUpnUtNHBY2wx5y3WDXND5Pvnw==} - dev: true - /@vueuse/metadata@10.6.1: resolution: {integrity: sha512-qhdwPI65Bgcj23e5lpGfQsxcy0bMjCAsUGoXkJ7DsoeDUdasbZ2DBa4dinFCOER3lF4gwUv+UD2AlA11zdzMFw==} dev: true /@vueuse/shared@10.1.0(vue@3.3.4): resolution: {integrity: sha512-2X52ogu12i9DkKOQ01yeb/BKg9UO87RNnpm5sXkQvyORlbq8ONS5l39MYkjkeVWWjdT0teJru7a2S41dmHmqjQ==} - dependencies: - vue-demi: 0.14.5(vue@3.3.4) - transitivePeerDependencies: - - '@vue/composition-api' - - vue - dev: false - - /@vueuse/shared@10.3.0(vue@3.3.4): - resolution: {integrity: sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==} dependencies: vue-demi: 0.14.6(vue@3.3.4) transitivePeerDependencies: - '@vue/composition-api' - vue - dev: true + dev: false /@vueuse/shared@10.6.1(vue@3.3.8): resolution: {integrity: sha512-TECVDTIedFlL0NUfHWncf3zF9Gc4VfdxfQc8JFwoVZQmxpONhLxFrlm0eHQeidHj4rdTPL3KXJa0TZCk1wnc5Q==} @@ -6390,13 +6388,13 @@ packages: resolution: {integrity: sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==} dev: true - /@zenuml/core@3.0.6(ts-node@10.9.1): + /@zenuml/core@3.0.6(ts-node@10.9.1)(typescript@5.1.6): resolution: {integrity: sha512-azEBVrl+ClCPhII92TbzBUFcWhIjlOPdEHVzF6eZXs5Oy4JlrfldS5pAZBHCFL4riOBsjZ5sHHmQLQg9V07T4Q==} engines: {node: '>=12.0.0'} dependencies: '@types/assert': 1.5.6 '@types/ramda': 0.28.25 - '@vue/compat': 3.3.4(vue@3.3.4) + '@vue/compat': 3.3.4(vue@3.3.8) antlr4: 4.11.0 color-string: 1.9.1 dom-to-image-more: 2.16.0 @@ -6409,10 +6407,11 @@ packages: postcss: 8.4.27 ramda: 0.28.0 tailwindcss: 3.3.3(ts-node@10.9.1) - vue: 3.3.4 - vuex: 4.1.0(vue@3.3.4) + vue: 3.3.8(typescript@5.1.6) + vuex: 4.1.0(vue@3.3.8) transitivePeerDependencies: - ts-node + - typescript dev: false /JSONSelect@0.4.0: @@ -8085,7 +8084,7 @@ packages: cspell-glob: 6.31.1 cspell-io: 6.31.1 cspell-lib: 6.31.1 - fast-glob: 3.3.1 + fast-glob: 3.3.2 fast-json-stable-stringify: 2.1.0 file-entry-cache: 6.0.1 get-stdin: 8.0.0 @@ -9821,17 +9820,6 @@ packages: micromatch: 4.0.5 dev: true - /fast-glob@3.3.1: - resolution: {integrity: sha512-kNFPyjhh5cKjrUltxs+wFx+ZkbRaxxmZ+X0ZU31SOsxCEtP9VPgtq2teZw1DebupL5GmDaNQ6yKMMVcM41iqDg==} - engines: {node: '>=8.6.0'} - dependencies: - '@nodelib/fs.stat': 2.0.5 - '@nodelib/fs.walk': 1.2.8 - glob-parent: 5.1.2 - merge2: 1.4.1 - micromatch: 4.0.5 - dev: true - /fast-glob@3.3.2: resolution: {integrity: sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==} engines: {node: '>=8.6.0'} @@ -10489,7 +10477,7 @@ packages: engines: {node: ^12.20.0 || ^14.13.1 || >=16.0.0} dependencies: dir-glob: 3.0.1 - fast-glob: 3.3.1 + fast-glob: 3.3.2 ignore: 5.2.4 merge2: 1.4.1 slash: 4.0.0 @@ -16353,7 +16341,7 @@ packages: optional: true dependencies: '@antfu/utils': 0.7.6 - '@rollup/pluginutils': 5.0.5(rollup@2.79.1) + '@rollup/pluginutils': 5.1.0(rollup@2.79.1) chokidar: 3.5.3 debug: 4.3.4(supports-color@8.1.1) fast-glob: 3.3.2 @@ -16685,25 +16673,25 @@ packages: flexsearch: 0.7.31 glob-to-regexp: 0.4.1 markdown-it: 13.0.1 - vitepress: 1.0.0-alpha.72(@algolia/client-search@4.19.1)(@types/node@18.17.5)(search-insights@2.7.0) + vitepress: 1.0.0-alpha.72(@algolia/client-search@4.19.1)(@types/node@18.17.5)(search-insights@2.7.0)(typescript@5.0.4) vue: 3.3.8(typescript@5.0.4) dev: true - /vitepress@1.0.0-alpha.72(@algolia/client-search@4.19.1)(@types/node@18.17.5)(search-insights@2.7.0): + /vitepress@1.0.0-alpha.72(@algolia/client-search@4.19.1)(@types/node@18.17.5)(search-insights@2.7.0)(typescript@5.0.4): resolution: {integrity: sha512-Ou7fNE/OVYLrKGQMHSTVG6AcNsdv7tm4ACrdhx93SPMzEDj8UgIb4RFa5CTTowaYf3jeDGi2EAJlzXVC+IE3dg==} hasBin: true dependencies: '@docsearch/css': 3.5.1 '@docsearch/js': 3.5.1(@algolia/client-search@4.19.1)(search-insights@2.7.0) - '@vitejs/plugin-vue': 4.2.3(vite@4.5.0)(vue@3.3.4) + '@vitejs/plugin-vue': 4.5.0(vite@4.5.0)(vue@3.3.8) '@vue/devtools-api': 6.5.0 - '@vueuse/core': 10.3.0(vue@3.3.4) + '@vueuse/core': 10.6.1(vue@3.3.8) body-scroll-lock: 4.0.0-beta.0 mark.js: 8.11.1 minisearch: 6.1.0 shiki: 0.14.3 vite: 4.5.0(@types/node@18.17.5) - vue: 3.3.4 + vue: 3.3.8(typescript@5.0.4) transitivePeerDependencies: - '@algolia/client-search' - '@types/node' @@ -16718,6 +16706,7 @@ packages: - stylus - sugarss - terser + - typescript dev: true /vitepress@1.0.0-rc.31(@algolia/client-search@4.19.1)(@types/node@18.17.5)(postcss@8.4.31)(search-insights@2.7.0)(typescript@5.1.6): @@ -16877,21 +16866,6 @@ packages: resolution: {integrity: sha512-eOpPHogvorZRobNqJGhapa0JdwaxpjVvyBp0QIUMRMSf8ZAlqOdEquKuRmw9Qwu0qXtJIWqFtMkmvJjUZmMjVA==} dev: true - /vue-demi@0.14.5(vue@3.3.4): - resolution: {integrity: sha512-o9NUVpl/YlsGJ7t+xuqJKx8EBGf1quRhCiT6D/J0pfwmk9zUwYkC7yrF4SZCe6fETvSM3UNL2edcbYrSyc4QHA==} - engines: {node: '>=12'} - hasBin: true - requiresBuild: true - peerDependencies: - '@vue/composition-api': ^1.0.0-rc.1 - vue: ^3.0.0-0 || ^2.6.0 - peerDependenciesMeta: - '@vue/composition-api': - optional: true - dependencies: - vue: 3.3.4 - dev: false - /vue-demi@0.14.6(vue@3.3.4): resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==} engines: {node: '>=12'} @@ -16905,7 +16879,7 @@ packages: optional: true dependencies: vue: 3.3.4 - dev: true + dev: false /vue-demi@0.14.6(vue@3.3.8): resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==} @@ -16961,15 +16935,14 @@ packages: '@vue/server-renderer': 3.3.8(vue@3.3.8) '@vue/shared': 3.3.8 typescript: 5.1.6 - dev: true - /vuex@4.1.0(vue@3.3.4): + /vuex@4.1.0(vue@3.3.8): resolution: {integrity: sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==} peerDependencies: vue: ^3.2.0 dependencies: '@vue/devtools-api': 6.5.1 - vue: 3.3.4 + vue: 3.3.8(typescript@5.1.6) dev: false /w3c-hr-time@1.0.2: diff --git a/vite.config.ts.timestamp-1696335530501-05072b5e79635.mjs b/vite.config.ts.timestamp-1696335530501-05072b5e79635.mjs index a08d96e7f1..7896fdd2c0 100644 --- a/vite.config.ts.timestamp-1696335530501-05072b5e79635.mjs +++ b/vite.config.ts.timestamp-1696335530501-05072b5e79635.mjs @@ -16,6 +16,9 @@ var transformJison = (src) => { // .vite/jisonPlugin.ts var fileRegex = /\.(jison)$/; +/** + * + */ function jison2() { return { name: 'jison', @@ -55,6 +58,10 @@ var MERMAID_CONFIG_DIAGRAM_KEYS = [ 'c4', 'sankey', ]; +/** + * + * @param mermaidConfigSchema + */ function generateDefaults(mermaidConfigSchema) { const ajv = new Ajv2019({ useDefaults: true, @@ -113,6 +120,9 @@ function generateDefaults(mermaidConfigSchema) { } return mermaidDefaultConfig; } +/** + * + */ function jsonSchemaPlugin() { return { name: 'json-schema-plugin', From d96425d19e7dc4a493b0eaf45670949e3a26091d Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Fri, 19 Jan 2024 14:57:45 +0100 Subject: [PATCH 43/97] #3358 Reviving arrow heads after merging develop --- cypress/platform/knsv2.html | 6 +++--- packages/mermaid/src/dagre-wrapper/edges.js | 6 +++--- .../mermaid/src/diagrams/block/blockRenderer.ts | 5 +++-- .../mermaid/src/diagrams/block/renderHelpers.ts | 14 +++++++++++--- 4 files changed, 20 insertions(+), 11 deletions(-) diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index f8722e580e..22820680db 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -65,12 +65,12 @@
     block-beta
    -  A space:2 B
    -  A-- "X" -->B
    +  a space:2 c
    +  a-- "b" --> c
         
     flowchart LR
    -  A-- "X" -->B
    +  X-- "y" -->z
         
     block-beta
    diff --git a/packages/mermaid/src/dagre-wrapper/edges.js b/packages/mermaid/src/dagre-wrapper/edges.js
    index ef96a3269c..36a4e25538 100644
    --- a/packages/mermaid/src/dagre-wrapper/edges.js
    +++ b/packages/mermaid/src/dagre-wrapper/edges.js
    @@ -134,7 +134,7 @@ function setTerminalWidth(fo, value) {
     }
     
     export const positionEdgeLabel = (edge, paths) => {
    -  log.info('Moving label abc78 ', edge.id, edge.label, edgeLabels[edge.id]);
    +  log.info('Moving label abc88 ', edge.id, edge.label, edgeLabels[edge.id], paths);
       let path = paths.updatedPath ? paths.updatedPath : paths.originalPath;
       if (edge.label) {
         const el = edgeLabels[edge.id];
    @@ -152,7 +152,7 @@ export const positionEdgeLabel = (edge, paths) => {
             pos.x,
             ',',
             pos.y,
    -        ') abc78'
    +        ') abc88'
           );
           if (paths.updatedPath) {
             x = pos.x;
    @@ -376,7 +376,7 @@ export const insertEdge = function (elem, e, edge, clusterDb, diagramType, graph
       let pointsHasChanged = false;
       const tail = graph.node(e.v);
       var head = graph.node(e.w);
    -  log.info('abc88 InsertEdge (head & tail): ', e.v, head, ' --- ', e.w, tail);
    +  log.info('abc88 InsertEdge (head & tail) fin: ', e.v, head, ' --- ', e.w, tail);
     
       if (head?.intersect && tail?.intersect) {
         points = points.slice(1, edge.points.length - 1);
    diff --git a/packages/mermaid/src/diagrams/block/blockRenderer.ts b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    index c47671b88b..31790de6e9 100644
    --- a/packages/mermaid/src/diagrams/block/blockRenderer.ts
    +++ b/packages/mermaid/src/diagrams/block/blockRenderer.ts
    @@ -58,7 +58,8 @@ export const draw = async function (
     
       // Add the marker definitions to the svg as marker tags
       // insertMarkers(svg, markers, diagObj.type, diagObj.arrowMarkerAbsolute);
    -  insertMarkers(svg, markers, diagObj.type, true);
    +  // insertMarkers(svg, markers, diagObj.type, true);
    +  insertMarkers(svg, markers, diagObj.type, id);
     
       const bl = db.getBlocks();
       const blArr = db.getBlocksFlat();
    @@ -69,7 +70,7 @@ export const draw = async function (
       const bounds = layout(db);
       // log.debug('Here be blocks', bl);
       await insertBlocks(nodes, bl, db);
    -  await insertEdges(nodes, edges, blArr, db);
    +  await insertEdges(nodes, edges, blArr, db, id);
     
       // log.debug('Here', bl);
     
    diff --git a/packages/mermaid/src/diagrams/block/renderHelpers.ts b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    index 588bca786f..2215e9e3ec 100644
    --- a/packages/mermaid/src/diagrams/block/renderHelpers.ts
    +++ b/packages/mermaid/src/diagrams/block/renderHelpers.ts
    @@ -1,6 +1,6 @@
     import { getStylesFromArray } from '../../utils.js';
     import { insertNode, positionNode } from '../../dagre-wrapper/nodes.js';
    -import { insertEdge, insertEdgeLabel } from '../../dagre-wrapper/edges.js';
    +import { insertEdge, insertEdgeLabel, positionEdgeLabel } from '../../dagre-wrapper/edges.js';
     import * as graphlib from 'dagre-d3-es/src/graphlib/index.js';
     import { getConfig } from '../../config.js';
     import type { ContainerElement } from 'd3';
    @@ -185,7 +185,8 @@ export async function insertEdges(
       elem: ContainerElement,
       edges: Block[],
       blocks: Block[],
    -  db: BlockDB
    +  db: BlockDB,
    +  id: string
     ) {
       const g = new graphlib.Graph({
         multigraph: true,
    @@ -238,7 +239,8 @@ export async function insertEdges(
               },
               undefined,
               'block',
    -          g
    +          g,
    +          id
             );
             if (edge.label) {
               await insertEdgeLabel(elem, {
    @@ -250,6 +252,12 @@ export async function insertEdges(
                 points,
                 classes: 'edge-thickness-normal edge-pattern-solid flowchart-link LS-a1 LE-b1',
               });
    +          await positionEdgeLabel(
    +            { ...edge, x: points[1].x, y: points[1].y },
    +            {
    +              originalPath: points,
    +            }
    +          );
             }
           }
         }
    
    From fe89b9510da2267e80f71028cf8fd5b705813e87 Mon Sep 17 00:00:00 2001
    From: Knut Sveidqvist 
    Date: Mon, 22 Jan 2024 14:14:54 +0100
    Subject: [PATCH 44/97] #3358 Adjusting docs and a bug fix for nested blocks
    
    ---
     cypress/platform/knsv2.html                   | 41 +++++++-
     docs/syntax/block.md                          | 98 ++++++++-----------
     packages/mermaid/src/diagrams/block/layout.ts |  7 +-
     .../mermaid/src/docs/.vitepress/config.ts     | 11 ++-
     packages/mermaid/src/docs/syntax/block.md     | 55 ++++-------
     5 files changed, 110 insertions(+), 102 deletions(-)
    
    diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html
    index 22820680db..8c6bf8a63b 100644
    --- a/cypress/platform/knsv2.html
    +++ b/cypress/platform/knsv2.html
    @@ -65,10 +65,47 @@
       
         
     block-beta
    -  a space:2 c
    -  a-- "b" --> c
    +columns 3
    +a:3
    +block:e:3
    +f
    +end
    +g
    +
    +    
    +
    +block-beta
    +  block:e:4
    +    columns 2
    +      f
    +      g
    +  end
    +
         
    +block-beta
    +  block:e:4
    +    columns 2
    +      f
    +      g
    +      h
    +  end
    +
    +    
    +
    +block-beta
    +  columns 4
    +  a b c d
    +  block:e:4
    +    columns 2
    +      f
    +      g
    +      h
    +  end
    +  i:4
    +
    +    
    +
     flowchart LR
       X-- "y" -->z
         
    diff --git a/docs/syntax/block.md b/docs/syntax/block.md index c33f31301d..638aa34b68 100644 --- a/docs/syntax/block.md +++ b/docs/syntax/block.md @@ -181,22 +181,22 @@ In diagrams with varying block sizes, Mermaid automatically adjusts the column w ```mermaid-example block-beta -columns 3 -a:3 -block:e:3 -f -end -g + columns 3 + a:3 + block:e:3 + f + end + g ``` ```mermaid block-beta -columns 3 -a:3 -block:e:3 -f -end -g + columns 3 + a:3 + block:e:3 + f + end + g ``` This example demonstrates how Mermaid dynamically adjusts the width of the columns to accommodate the widest block, in this case, 'a' and the composite block 'e'. This dynamic adjustment is essential for creating visually balanced and easy-to-understand diagrams. @@ -326,7 +326,7 @@ block-beta Parallelogram and trapezoid shapes are perfect for inputs/outputs and transitional processes: ```mermaid-example -flowchart TD +block-beta id1[/"This is the text in the box"/] id2[\"This is the text in the box"\] A[/"Christmas"\] @@ -334,7 +334,7 @@ flowchart TD ``` ```mermaid -flowchart TD +block-beta id1[/"This is the text in the box"/] id2[\"This is the text in the box"\] A[/"Christmas"\] @@ -346,12 +346,12 @@ flowchart TD For highlighting critical or high-priority components, a double circle can be effective: ```mermaid-example -flowchart TD +block-beta id1((("This is the text in the circle"))) ``` ```mermaid -flowchart TD +block-beta id1((("This is the text in the circle"))) ``` @@ -389,6 +389,22 @@ block-beta Space blocks can be used to create intentional empty spaces in the diagram, which is useful for layout and readability: +```mermaid-example +block-beta + columns 3 + a space b + c d e +``` + +```mermaid +block-beta + columns 3 + a space b + c d e +``` + +or + ```mermaid-example block-beta space:3 @@ -435,21 +451,6 @@ block-beta This example illustrates a direct connection from block 'A' to block 'B', using a straightforward arrow. -**Example - Open Link:** -For connections that are less direct or to represent a different type of relationship, an open link (without an arrowhead) can be used: - -```mermaid-example -block-beta - A space B - A --- B -``` - -```mermaid -block-beta - A space B - A --- B -``` - This syntax creates a line connecting 'A' and 'B', implying a relationship or connection without indicating a specific direction. ### Text on Links @@ -473,25 +474,6 @@ block-beta This example show how to add descriptive text to the links, enhancing the information conveyed by the diagram. -### Advanced Link Types - -Mermaid also supports various advanced link types, such as dotted lines, thick links, and different arrowheads, to represent different kinds of relationships or interactions. - -**Example - Dotted and Thick Links** -A dotted link can be used to represent a weaker or less formal relationship: - -```mermaid-example -block-beta - A space:2 B - A-.->B -``` - -```mermaid -block-beta - A space:2 B - A-.->B -``` - Example - Edges and Styles: ```mermaid-example @@ -575,9 +557,9 @@ Illustrating a simple software system architecture with interconnected component ```mermaid-example block-beta columns 3 - Frontend blockArrowId6<["  "]>(right) Backend - space:2 down<["  "]>(down) - Disk left<["  "]>(left) Database[("Database")] + Frontend blockArrowId6<[" "]>(right) Backend + space:2 down<[" "]>(down) + Disk left<[" "]>(left) Database[("Database")] classDef front fill:#696,stroke:#333; classDef back fill:#969,stroke:#333; @@ -588,9 +570,9 @@ block-beta ```mermaid block-beta columns 3 - Frontend blockArrowId6<["  "]>(right) Backend - space:2 down<["  "]>(down) - Disk left<["  "]>(left) Database[("Database")] + Frontend blockArrowId6<[" "]>(right) Backend + space:2 down<[" "]>(down) + Disk left<[" "]>(left) Database[("Database")] classDef front fill:#696,stroke:#333; classDef back fill:#969,stroke:#333; @@ -608,7 +590,7 @@ Representing a business process flow with decision points and multiple stages: block-beta columns 3 Start(("Start")) space:2 - down<["  "]>(down) space:2 + down<[" "]>(down) space:2 Decision{{"Make Decision"}} right<["Yes"]>(right) Process1["Process A"] downAgain<["No"]>(down) space r3<["Done"]>(down) Process2["Process B"] r2<["Done"]>(right) End(("End")) @@ -622,7 +604,7 @@ block-beta block-beta columns 3 Start(("Start")) space:2 - down<["  "]>(down) space:2 + down<[" "]>(down) space:2 Decision{{"Make Decision"}} right<["Yes"]>(right) Process1["Process A"] downAgain<["No"]>(down) space r3<["Done"]>(down) Process2["Process B"] r2<["Done"]>(right) End(("End")) diff --git a/packages/mermaid/src/diagrams/block/layout.ts b/packages/mermaid/src/diagrams/block/layout.ts index f3ecd02549..629d87083b 100644 --- a/packages/mermaid/src/diagrams/block/layout.ts +++ b/packages/mermaid/src/diagrams/block/layout.ts @@ -198,10 +198,10 @@ function setBlockSizes(block: Block, db: BlockDB, sieblingWidth = 0, sieblingHei width = block?.size?.width || 0; // Grow children to fit - const num = block.children.length; + const num = columns > 0 ? Math.min(block.children.length, columns) : block.children.length; if (num > 0) { const childWidth = (width - num * padding - padding) / num; - // log.debug('abc95 (finale calc) width', block.id, width, block.size?.width, childWidth); + log.debug('abc95 (growing to fit) width', block.id, width, block.size?.width, childWidth); for (const child of block.children) { if (child.size) { child.size.width = childWidth; @@ -264,7 +264,8 @@ function layoutBlocks(block: Block, db: BlockDB) { const { px, py } = calculateBlockPosition(columns, columnPos); if (py != rowPos) { rowPos = py; - startingPosX = block?.size?.x || -padding; + startingPosX = block?.size?.x ? block?.size?.x + (-block?.size?.width / 2 || 0) : -padding; + log.debug('New row in layout for block', block.id, ' and child ', child.id, rowPos); } log.debug( 'abc89 layout blocks (child) id:', diff --git a/packages/mermaid/src/docs/.vitepress/config.ts b/packages/mermaid/src/docs/.vitepress/config.ts index f5647e3c37..4a383b68d8 100644 --- a/packages/mermaid/src/docs/.vitepress/config.ts +++ b/packages/mermaid/src/docs/.vitepress/config.ts @@ -147,13 +147,14 @@ function sidebarSyntax() { { text: 'Pie Chart', link: '/syntax/pie' }, { text: 'Quadrant Chart', link: '/syntax/quadrantChart' }, { text: 'Requirement Diagram', link: '/syntax/requirementDiagram' }, - { text: 'Gitgraph (Git) Diagram 🔥', link: '/syntax/gitgraph' }, + { text: 'Gitgraph (Git) Diagram', link: '/syntax/gitgraph' }, { text: 'C4 Diagram 🦺⚠️', link: '/syntax/c4' }, - { text: 'Mindmaps 🔥', link: '/syntax/mindmap' }, - { text: 'Timeline 🔥', link: '/syntax/timeline' }, - { text: 'Zenuml 🔥', link: '/syntax/zenuml' }, - { text: 'Sankey 🔥', link: '/syntax/sankey' }, + { text: 'Mindmaps', link: '/syntax/mindmap' }, + { text: 'Timeline', link: '/syntax/timeline' }, + { text: 'Zenuml', link: '/syntax/zenuml' }, + { text: 'Sankey', link: '/syntax/sankey' }, { text: 'XYChart 🔥', link: '/syntax/xyChart' }, + { text: 'Block Diagram 🔥', link: '/syntax/block' }, { text: 'Other Examples', link: '/syntax/examples' }, ], }, diff --git a/packages/mermaid/src/docs/syntax/block.md b/packages/mermaid/src/docs/syntax/block.md index 9186d68c6a..c80492a2fd 100644 --- a/packages/mermaid/src/docs/syntax/block.md +++ b/packages/mermaid/src/docs/syntax/block.md @@ -138,12 +138,12 @@ In diagrams with varying block sizes, Mermaid automatically adjusts the column w ```mermaid-example block-beta -columns 3 -a:3 -block:e:3 -f -end -g + columns 3 + a:3 + block:e:3 + f + end + g ``` This example demonstrates how Mermaid dynamically adjusts the width of the columns to accommodate the widest block, in this case, 'a' and the composite block 'e'. This dynamic adjustment is essential for creating visually balanced and easy-to-understand diagrams. @@ -233,7 +233,7 @@ block-beta Parallelogram and trapezoid shapes are perfect for inputs/outputs and transitional processes: ```mermaid-example -flowchart TD +block-beta id1[/"This is the text in the box"/] id2[\"This is the text in the box"\] A[/"Christmas"\] @@ -245,7 +245,7 @@ flowchart TD For highlighting critical or high-priority components, a double circle can be effective: ```mermaid-example -flowchart TD +block-beta id1((("This is the text in the circle"))) ``` @@ -272,6 +272,15 @@ block-beta Space blocks can be used to create intentional empty spaces in the diagram, which is useful for layout and readability: +```mermaid-example +block-beta + columns 3 + a space b + c d e +``` + +or + ```mermaid-example block-beta space:3 @@ -306,15 +315,6 @@ block-beta This example illustrates a direct connection from block 'A' to block 'B', using a straightforward arrow. -**Example - Open Link:** -For connections that are less direct or to represent a different type of relationship, an open link (without an arrowhead) can be used: - -```mermaid-example -block-beta - A space B - A --- B -``` - This syntax creates a line connecting 'A' and 'B', implying a relationship or connection without indicating a specific direction. ### Text on Links @@ -332,19 +332,6 @@ block-beta This example show how to add descriptive text to the links, enhancing the information conveyed by the diagram. -### Advanced Link Types - -Mermaid also supports various advanced link types, such as dotted lines, thick links, and different arrowheads, to represent different kinds of relationships or interactions. - -**Example - Dotted and Thick Links** -A dotted link can be used to represent a weaker or less formal relationship: - -```mermaid-example -block-beta - A space:2 B - A-.->B -``` - Example - Edges and Styles: ```mermaid-example @@ -403,9 +390,9 @@ Illustrating a simple software system architecture with interconnected component ```mermaid block-beta columns 3 - Frontend blockArrowId6<["  "]>(right) Backend - space:2 down<["  "]>(down) - Disk left<["  "]>(left) Database[("Database")] + Frontend blockArrowId6<[" "]>(right) Backend + space:2 down<[" "]>(down) + Disk left<[" "]>(left) Database[("Database")] classDef front fill:#696,stroke:#333; classDef back fill:#969,stroke:#333; @@ -423,7 +410,7 @@ Representing a business process flow with decision points and multiple stages: block-beta columns 3 Start(("Start")) space:2 - down<["  "]>(down) space:2 + down<[" "]>(down) space:2 Decision{{"Make Decision"}} right<["Yes"]>(right) Process1["Process A"] downAgain<["No"]>(down) space r3<["Done"]>(down) Process2["Process B"] r2<["Done"]>(right) End(("End")) From 1629a91a25a075cbb0e2ee1ddd06173843a6604a Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Mon, 22 Jan 2024 14:52:02 +0100 Subject: [PATCH 45/97] Updated lockfile --- pnpm-lock.yaml | 756 +++++++++++++++++++++++++------------------------ 1 file changed, 387 insertions(+), 369 deletions(-) diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index d09113a2ca..8daca235a9 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -519,7 +519,7 @@ importers: version: 1.1.0 unocss: specifier: ^0.58.0 - version: 0.58.0(postcss@8.4.31)(rollup@2.79.1)(vite@4.5.0) + version: 0.58.0(postcss@8.4.33)(rollup@2.79.1)(vite@4.5.0) unplugin-vue-components: specifier: ^0.26.0 version: 0.26.0(rollup@2.79.1)(vue@3.3.4) @@ -531,7 +531,7 @@ importers: version: 0.17.0(vite@4.5.0)(workbox-build@7.0.0)(workbox-window@7.0.0) vitepress: specifier: 1.0.0-rc.31 - version: 1.0.0-rc.31(@algolia/client-search@4.19.1)(@types/node@18.17.5)(postcss@8.4.31)(search-insights@2.7.0)(typescript@5.1.6) + version: 1.0.0-rc.31(@algolia/client-search@4.19.1)(@types/node@18.17.5)(postcss@8.4.33)(search-insights@2.7.0)(typescript@5.1.6) workbox-window: specifier: ^7.0.0 version: 7.0.0 @@ -1108,22 +1108,6 @@ packages: engines: {node: '>=4'} dev: true - /@babel/code-frame@7.22.10: - resolution: {integrity: sha512-/KKIMG4UEL35WmI9OlvMhurwtytjvXoFcGNrOvyG9zIzA8YmPjVtIZUf7b05+TPO7G7/GEmLHDaoCgACHl9hhA==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.22.20 - chalk: 2.4.2 - dev: true - - /@babel/code-frame@7.22.13: - resolution: {integrity: sha512-XktuhWlJ5g+3TJXc5upd9Ks1HutSArik6jf2eAjYFyIOf4ej3RN+184cZbzDvbPnuTJIUhPKKJE3cIsYTiAT3w==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/highlight': 7.22.20 - chalk: 2.4.2 - dev: true - /@babel/code-frame@7.23.5: resolution: {integrity: sha512-CgH3s1a96LipHCmSUmYFPwY7MNx8C3avkq7i4Wl3cfa662ldtUe4VM1TPXX70pfmrlWTb6jLqTYrZyT2ZTJBgA==} engines: {node: '>=6.9.0'} @@ -1137,29 +1121,6 @@ packages: engines: {node: '>=6.9.0'} dev: true - /@babel/core@7.22.10: - resolution: {integrity: sha512-fTmqbbUBAwCcre6zPzNngvsI0aNrPZe77AeqvDxWM9Nm+04RrJ3CAmGHA9f7lJQY6ZMhRztNemy4uslDxTX4Qw==} - engines: {node: '>=6.9.0'} - dependencies: - '@ampproject/remapping': 2.2.1 - '@babel/code-frame': 7.22.10 - '@babel/generator': 7.22.10 - '@babel/helper-compilation-targets': 7.22.10 - '@babel/helper-module-transforms': 7.22.9(@babel/core@7.22.10) - '@babel/helpers': 7.22.10 - '@babel/parser': 7.23.5 - '@babel/template': 7.22.5 - '@babel/traverse': 7.23.2 - '@babel/types': 7.23.5 - convert-source-map: 1.9.0 - debug: 4.3.4(supports-color@8.1.1) - gensync: 1.0.0-beta.2 - json5: 2.2.3 - semver: 6.3.1 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/core@7.23.5: resolution: {integrity: sha512-Cwc2XjUrG4ilcfOw4wBAK+enbdgwAcAJCfGUItPBKR7Mjw4aEfAFYrLxeRp4jWgtNIKn3n2AlBOfwwafl+42/g==} engines: {node: '>=6.9.0'} @@ -1170,7 +1131,7 @@ packages: '@babel/helper-compilation-targets': 7.22.15 '@babel/helper-module-transforms': 7.23.3(@babel/core@7.23.5) '@babel/helpers': 7.23.5 - '@babel/parser': 7.23.5 + '@babel/parser': 7.23.6 '@babel/template': 7.22.15 '@babel/traverse': 7.23.5 '@babel/types': 7.23.5 @@ -1183,26 +1144,6 @@ packages: - supports-color dev: true - /@babel/generator@7.22.10: - resolution: {integrity: sha512-79KIf7YiWjjdZ81JnLujDRApWtl7BxTqWD88+FFdQEIOG8LJ0etDOM7CXuIgGJa55sGOwZVwuEsaLEm0PJ5/+A==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.5 - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.19 - jsesc: 2.5.2 - dev: true - - /@babel/generator@7.23.0: - resolution: {integrity: sha512-lN85QRR+5IbYrMWM6Y4pE/noaQtg4pNiqeNGX60eqOfo6gtEj6uw/JagelB8vVztSd7R6M5n1+PQkDbHbBRU4g==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.5 - '@jridgewell/gen-mapping': 0.3.3 - '@jridgewell/trace-mapping': 0.3.19 - jsesc: 2.5.2 - dev: true - /@babel/generator@7.23.5: resolution: {integrity: sha512-BPssCHrBD+0YrxviOa3QzpqwhNIXKEtOa2jQrm4FlmkC2apYgRnQcmPWiGZDlGxiNtltnUFolMe8497Esry+jA==} engines: {node: '>=6.9.0'} @@ -1227,17 +1168,6 @@ packages: '@babel/types': 7.23.5 dev: true - /@babel/helper-compilation-targets@7.22.10: - resolution: {integrity: sha512-JMSwHD4J7SLod0idLq5PKgI+6g/hLD/iuWBq08ZX49xE14VpVEojJ5rHWptpirV2j020MvypRLAXAO50igCJ5Q==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/compat-data': 7.22.9 - '@babel/helper-validator-option': 7.22.5 - browserslist: 4.21.10 - lru-cache: 5.1.1 - semver: 6.3.1 - dev: true - /@babel/helper-compilation-targets@7.22.15: resolution: {integrity: sha512-y6EEzULok0Qvz8yyLkCvVX+02ic+By2UdOhylwUOvOn9dvYc9mKICJuuU1n1XBI02YWsNsnrY1kc6DVbjcXbtw==} engines: {node: '>=6.9.0'} @@ -1328,27 +1258,6 @@ packages: '@babel/types': 7.23.5 dev: true - /@babel/helper-module-imports@7.22.5: - resolution: {integrity: sha512-8Dl6+HD/cKifutF5qGd/8ZJi84QeAKh+CEe1sBzz8UayBBGg1dAIJrdHOcOM5b2MpzWL2yuotJTtGjETq0qjXg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/types': 7.23.5 - dev: true - - /@babel/helper-module-transforms@7.22.9(@babel/core@7.22.10): - resolution: {integrity: sha512-t+WA2Xn5K+rTeGtC8jCsdAH52bjggG5TKRuRrAGNM/mjIbO4GxvlLMFOEz9wXY5I2XQ60PMFsAG2WIcG82dQMQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0 - dependencies: - '@babel/core': 7.22.10 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-module-imports': 7.22.5 - '@babel/helper-simple-access': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/helper-validator-identifier': 7.22.20 - dev: true - /@babel/helper-module-transforms@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==} engines: {node: '>=6.9.0'} @@ -1420,10 +1329,6 @@ packages: '@babel/types': 7.23.5 dev: true - /@babel/helper-string-parser@7.22.5: - resolution: {integrity: sha512-mM4COjgZox8U+JcXQwPijIZLElkgEpO5rsERVDJTc2qfCDfERyob6k5WegS14SX18IIjv+XD+GrqNumY5JRCDw==} - engines: {node: '>=6.9.0'} - /@babel/helper-string-parser@7.23.4: resolution: {integrity: sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ==} engines: {node: '>=6.9.0'} @@ -1437,11 +1342,6 @@ packages: engines: {node: '>=6.9.0'} dev: true - /@babel/helper-validator-option@7.22.5: - resolution: {integrity: sha512-R3oB6xlIVKUnxNUxbmgq7pKjxpru24zlimpE8WK47fACIlM0II/Hm1RS8IaOI7NgCr6LNS+jl5l75m20npAziw==} - engines: {node: '>=6.9.0'} - dev: true - /@babel/helper-validator-option@7.23.5: resolution: {integrity: sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==} engines: {node: '>=6.9.0'} @@ -1456,17 +1356,6 @@ packages: '@babel/types': 7.23.5 dev: true - /@babel/helpers@7.22.10: - resolution: {integrity: sha512-a41J4NW8HyZa1I1vAndrraTlPZ/eZoga2ZgS7fEr0tZJGVU4xqdE80CEm0CcNjha5EZ8fTBYLKHF0kqDUuAwQw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/template': 7.22.15 - '@babel/traverse': 7.23.2 - '@babel/types': 7.23.5 - transitivePeerDependencies: - - supports-color - dev: true - /@babel/helpers@7.23.5: resolution: {integrity: sha512-oO7us8FzTEsG3U6ag9MfdF1iA/7Z6dz+MtFhifZk8C8o453rGJFFWUP1t+ULM9TUIAzC9uxXEiXjOiVMyd7QPg==} engines: {node: '>=6.9.0'} @@ -1478,15 +1367,6 @@ packages: - supports-color dev: true - /@babel/highlight@7.22.20: - resolution: {integrity: sha512-dkdMCN3py0+ksCgYmGG8jKeGA/8Tk+gJwSYYlFGxG5lmhfKNoAy004YpLxpS1W2J8m/EK2Ew+yOs9pVRwO89mg==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/helper-validator-identifier': 7.22.20 - chalk: 2.4.2 - js-tokens: 4.0.0 - dev: true - /@babel/highlight@7.23.4: resolution: {integrity: sha512-acGdbYSfp2WheJoJm/EBBBLh/ID8KDc64ISZ9DYtBmC8/Q204PZJLHyzeB5qMzJ5trcOkybd78M4x2KWsUq++A==} engines: {node: '>=6.9.0'} @@ -1501,7 +1381,7 @@ packages: engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.23.0 + '@babel/types': 7.23.5 /@babel/parser@7.23.5: resolution: {integrity: sha512-hOOqoiNXrmGdFbhgCzu6GiURxUgM27Xwd/aPuu8RfHEZPBzL1Z54okAHAQjXfcQNwvrlkAmAp4SlRTZ45vlthQ==} @@ -1515,8 +1395,7 @@ packages: engines: {node: '>=6.0.0'} hasBin: true dependencies: - '@babel/types': 7.23.5 - dev: true + '@babel/types': 7.23.0 /@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression@7.22.5(@babel/core@7.23.5): resolution: {integrity: sha512-NP1M5Rf+u2Gw9qfSO4ihjcTGW5zXTi36ITLd4/EoAcEhIZ0yjMqmftDNl3QC19CX7olhrjpyU454g/2W7X0jvQ==} @@ -1549,15 +1428,6 @@ packages: '@babel/core': 7.23.5 dev: true - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.22.10): - resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-async-generators@7.8.4(@babel/core@7.23.5): resolution: {integrity: sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==} peerDependencies: @@ -1567,21 +1437,12 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.22.10): + /@babel/plugin-syntax-bigint@7.8.3(@babel/core@7.23.5): resolution: {integrity: sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==} peerDependencies: '@babel/core': ^7.0.0-0 dependencies: - '@babel/core': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - - /@babel/plugin-syntax-class-properties@7.12.13(@babel/core@7.22.10): - resolution: {integrity: sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.10 + '@babel/core': 7.23.5 '@babel/helper-plugin-utils': 7.22.5 dev: true @@ -1642,15 +1503,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.22.10): - resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-import-meta@7.10.4(@babel/core@7.23.5): resolution: {integrity: sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==} peerDependencies: @@ -1660,15 +1512,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.22.10): - resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-json-strings@7.8.3(@babel/core@7.23.5): resolution: {integrity: sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==} peerDependencies: @@ -1678,16 +1521,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-jsx@7.22.5(@babel/core@7.22.10): - resolution: {integrity: sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-jsx@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-EB2MELswq55OHUoRZLGg/zC7QWUKfNLpE57m/S2yr1uEneIgsTgrSzXP3NXEsMkVn76OlaVVnzN+ugObuYGwhg==} engines: {node: '>=6.9.0'} @@ -1698,15 +1531,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.22.10): - resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-logical-assignment-operators@7.10.4(@babel/core@7.23.5): resolution: {integrity: sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==} peerDependencies: @@ -1716,15 +1540,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.22.10): - resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-nullish-coalescing-operator@7.8.3(@babel/core@7.23.5): resolution: {integrity: sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==} peerDependencies: @@ -1734,15 +1549,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.22.10): - resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-numeric-separator@7.10.4(@babel/core@7.23.5): resolution: {integrity: sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==} peerDependencies: @@ -1752,15 +1558,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.22.10): - resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-object-rest-spread@7.8.3(@babel/core@7.23.5): resolution: {integrity: sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==} peerDependencies: @@ -1770,15 +1567,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.22.10): - resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-optional-catch-binding@7.8.3(@babel/core@7.23.5): resolution: {integrity: sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==} peerDependencies: @@ -1788,15 +1576,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.22.10): - resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-optional-chaining@7.8.3(@babel/core@7.23.5): resolution: {integrity: sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==} peerDependencies: @@ -1816,16 +1595,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.22.10): - resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-top-level-await@7.14.5(@babel/core@7.23.5): resolution: {integrity: sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==} engines: {node: '>=6.9.0'} @@ -1836,16 +1605,6 @@ packages: '@babel/helper-plugin-utils': 7.22.5 dev: true - /@babel/plugin-syntax-typescript@7.22.5(@babel/core@7.22.10): - resolution: {integrity: sha512-1mS2o03i7t1c6VzH6fdQ3OA8tcEIxwG18zIPRp+UY1Ihv6W+XZzBCVxExF9upussPXJ0xE9XRHwMoNs1ep/nRQ==} - engines: {node: '>=6.9.0'} - peerDependencies: - '@babel/core': ^7.0.0-0 - dependencies: - '@babel/core': 7.22.10 - '@babel/helper-plugin-utils': 7.22.5 - dev: true - /@babel/plugin-syntax-typescript@7.23.3(@babel/core@7.23.5): resolution: {integrity: sha512-9EiNjVJOMwCO+43TqoTrgQ8jMwcAd0sWyXi9RPfIsLTj4R2MADDDQXELhffaUx/uJv2AYcxBgPwH6j4TIA4ytQ==} engines: {node: '>=6.9.0'} @@ -2544,35 +2303,8 @@ packages: engines: {node: '>=6.9.0'} dependencies: '@babel/code-frame': 7.23.5 - '@babel/parser': 7.23.5 - '@babel/types': 7.23.5 - dev: true - - /@babel/template@7.22.5: - resolution: {integrity: sha512-X7yV7eiwAxdj9k94NEylvbVHLiVG1nvzCV2EAowhxLTwODV1jl9UzZ48leOC0sH7OnuHrIkllaBgneUykIcZaw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.22.13 - '@babel/parser': 7.23.5 - '@babel/types': 7.23.5 - dev: true - - /@babel/traverse@7.23.2: - resolution: {integrity: sha512-azpe59SQ48qG6nu2CzcMLbxUudtN+dOM9kDbUqGq3HXUJRlo7i8fvPoxQUzYgLZ4cMVmuZgm8vvBpNeRhd6XSw==} - engines: {node: '>=6.9.0'} - dependencies: - '@babel/code-frame': 7.22.13 - '@babel/generator': 7.23.0 - '@babel/helper-environment-visitor': 7.22.20 - '@babel/helper-function-name': 7.23.0 - '@babel/helper-hoist-variables': 7.22.5 - '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.23.5 + '@babel/parser': 7.23.6 '@babel/types': 7.23.5 - debug: 4.3.4(supports-color@8.1.1) - globals: 11.12.0 - transitivePeerDependencies: - - supports-color dev: true /@babel/traverse@7.23.5: @@ -2585,7 +2317,7 @@ packages: '@babel/helper-function-name': 7.23.0 '@babel/helper-hoist-variables': 7.22.5 '@babel/helper-split-export-declaration': 7.22.6 - '@babel/parser': 7.23.5 + '@babel/parser': 7.23.6 '@babel/types': 7.23.5 debug: 4.3.4(supports-color@8.1.1) globals: 11.12.0 @@ -2597,7 +2329,7 @@ packages: resolution: {integrity: sha512-0oIyUfKoI3mSqMvsxBdclDwxXKXAUA8v/apZbc+iSyARYou1o8ZGDxbUYyLFoW2arqS2jDGqJuZvv1d/io1axg==} engines: {node: '>=6.9.0'} dependencies: - '@babel/helper-string-parser': 7.22.5 + '@babel/helper-string-parser': 7.23.4 '@babel/helper-validator-identifier': 7.22.20 to-fast-properties: 2.0.0 @@ -4236,7 +3968,7 @@ packages: resolution: {integrity: sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@babel/core': 7.22.10 + '@babel/core': 7.23.5 '@jest/types': 29.6.1 '@jridgewell/trace-mapping': 0.3.19 babel-plugin-istanbul: 6.1.1 @@ -4643,7 +4375,7 @@ packages: /@types/babel__core@7.20.1: resolution: {integrity: sha512-aACu/U/omhdk15O4Nfb+fHgH/z3QsfQzpnvRZhYhThms83ZnAOZz7zZAWO7mn2yyNQaA4xTO8GLK3uqFU4bYYw==} dependencies: - '@babel/parser': 7.23.5 + '@babel/parser': 7.23.6 '@babel/types': 7.23.5 '@types/babel__generator': 7.6.4 '@types/babel__template': 7.4.1 @@ -4659,7 +4391,7 @@ packages: /@types/babel__template@7.4.1: resolution: {integrity: sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==} dependencies: - '@babel/parser': 7.23.5 + '@babel/parser': 7.23.6 '@babel/types': 7.23.5 dev: true @@ -4992,6 +4724,12 @@ packages: '@types/node': 18.17.5 dev: true + /@types/hast@3.0.3: + resolution: {integrity: sha512-2fYGlaDy/qyLlhidX42wAH0KBi2TCjKMH8CHmBXgRlJ3Y+OXTiqsPQ6IWarZKwF1JoUcAJdPogv1d4b0COTpmQ==} + dependencies: + '@types/unist': 3.0.2 + dev: true + /@types/http-cache-semantics@4.0.1: resolution: {integrity: sha512-SZs7ekbP8CN0txVG2xVRH6EgKmEm31BOxA07vkFaETzZz1xh+cbt8BcI0slpymvwhx5dlFnQG2rTlPVQn+iRPQ==} dev: true @@ -5077,6 +4815,12 @@ packages: dependencies: '@types/unist': 2.0.7 + /@types/mdast@4.0.3: + resolution: {integrity: sha512-LsjtqsyF+d2/yFOYaN22dHZI1Cpwkrj+g06G8+qtUKlhovPW89YhqSnfKtMbkgmEtYpH2gydRNULd6y8mciAFg==} + dependencies: + '@types/unist': 3.0.2 + dev: true + /@types/mdurl@1.0.2: resolution: {integrity: sha512-eC4U9MlIcu2q0KQmXszyn5Akca/0jrQmwDRgpAMJai7qBWq4amIQhZyNau4VYGtCeALvW1/NtjzJJ567aZxfKA==} dev: true @@ -5220,6 +4964,10 @@ packages: /@types/unist@2.0.7: resolution: {integrity: sha512-cputDpIbFgLUaGQn6Vqg3/YsJwxUwHLO13v3i5ouxT4lat0khip9AEWxtERujXV9wxIB1EyF97BSJFt6vpdI8g==} + /@types/unist@3.0.2: + resolution: {integrity: sha512-dqId9J8K/vGi5Zr7oo212BGii5m3q5Hxlkwy3WpYuKPklmBEvsbMYYyLxAQpSffdLl/gdW0XUpKWFvYmyoWCoQ==} + dev: true + /@types/uuid@9.0.1: resolution: {integrity: sha512-rFT3ak0/2trgvp4yYZo5iKFEPsET7vKydKF+VRCxlQ9bpheehyAJH89dAkaLEq/j/RZXJIqcgsmPJKUP1Z28HA==} dev: true @@ -5579,6 +5327,10 @@ packages: eslint-visitor-keys: 3.4.3 dev: true + /@ungap/structured-clone@1.2.0: + resolution: {integrity: sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ==} + dev: true + /@unocss/astro@0.58.0(rollup@2.79.1)(vite@4.5.0): resolution: {integrity: sha512-df+tEFO5eKXjQOwSWQhS9IdjD0sfLHLtn8U09sEKR2Nmh5CvpwyBxmvLQgOCilPou7ehmyKfsyGRLZg7IMp+Ew==} peerDependencies: @@ -5812,7 +5564,7 @@ packages: vue: 3.3.4 dev: true - /@vitejs/plugin-vue@4.5.0(vite@4.5.0)(vue@3.3.8): + /@vitejs/plugin-vue@4.5.0(vite@4.5.0)(vue@3.4.15): resolution: {integrity: sha512-a2WSpP8X8HTEww/U00bU4mX1QpLINNuz/2KMNpLsdu3BzOpak3AGI1CJYBTXcc4SPhaD0eNRUp7IyQK405L5dQ==} engines: {node: ^14.18.0 || >=16.0.0} peerDependencies: @@ -5820,7 +5572,18 @@ packages: vue: ^3.2.25 dependencies: vite: 4.5.0(@types/node@18.17.5) - vue: 3.3.8(typescript@5.0.4) + vue: 3.4.15(typescript@5.0.4) + dev: true + + /@vitejs/plugin-vue@4.5.0(vite@5.0.11)(vue@3.4.15): + resolution: {integrity: sha512-a2WSpP8X8HTEww/U00bU4mX1QpLINNuz/2KMNpLsdu3BzOpak3AGI1CJYBTXcc4SPhaD0eNRUp7IyQK405L5dQ==} + engines: {node: ^14.18.0 || >=16.0.0} + peerDependencies: + vite: ^4.0.0 || ^5.0.0 + vue: ^3.2.25 + dependencies: + vite: 5.0.11(@types/node@18.17.5) + vue: 3.4.15(typescript@5.1.6) dev: true /@vitejs/plugin-vue@5.0.3(vite@5.0.11)(vue@3.4.15): @@ -5908,7 +5671,7 @@ packages: pretty-format: 29.6.2 dev: true - /@vue/compat@3.3.4(vue@3.3.8): + /@vue/compat@3.3.4(vue@3.4.15): resolution: {integrity: sha512-VwAsPqUqRJVxeLQPUC03Sa5d+T8UG2Qv4VItq74KmNvtQlRXICpa/sqq12BcyBB4Tz1U5paOEZxWCUoXkrZ9QQ==} peerDependencies: vue: 3.3.4 @@ -5916,7 +5679,7 @@ packages: '@babel/parser': 7.23.0 estree-walker: 2.0.2 source-map-js: 1.0.2 - vue: 3.3.8(typescript@5.1.6) + vue: 3.4.15(typescript@5.1.6) dev: false /@vue/compiler-core@3.3.4: @@ -5947,7 +5710,6 @@ packages: dependencies: '@vue/compiler-core': 3.4.15 '@vue/shared': 3.4.15 - dev: true /@vue/compiler-sfc@3.3.4: resolution: {integrity: sha512-6y/d8uw+5TkCuzBkgLS0v3lSM3hJDntFEiUORM11pQ/hKvkhSKZrXW6i69UyXlJQisJxuUEJKAWEqWbWsLeNKQ==} @@ -5987,7 +5749,6 @@ packages: dependencies: '@vue/compiler-dom': 3.4.15 '@vue/shared': 3.4.15 - dev: true /@vue/devtools-api@6.5.0: resolution: {integrity: sha512-o9KfBeaBmCKl10usN4crU53fYtC1r7jJwdGKjPT24t348rHxgfpZ0xL3Xm/gLUYnc0oTp8LAmrxOeLyu6tbk2Q==} @@ -5999,7 +5760,7 @@ packages: /@vue/reactivity-transform@3.3.4: resolution: {integrity: sha512-MXgwjako4nu5WFLAjpBnCj/ieqcjE2aJBINUNQzkZQfzIZA4xn+0fV1tIYBJvvva3N3OvKGofRLvQIwEQPpaXw==} dependencies: - '@babel/parser': 7.23.5 + '@babel/parser': 7.23.6 '@vue/compiler-core': 3.3.4 '@vue/shared': 3.3.4 estree-walker: 2.0.2 @@ -6014,7 +5775,6 @@ packages: resolution: {integrity: sha512-55yJh2bsff20K5O84MxSvXKPHHt17I2EomHznvFiJCAZpJTNW8IuLj1xZWMLELRhBK3kkFV/1ErZGHJfah7i7w==} dependencies: '@vue/shared': 3.4.15 - dev: true /@vue/runtime-core@3.3.4: resolution: {integrity: sha512-R+bqxMN6pWO7zGI4OMlmvePOdP2c93GsHFM/siJI7O2nxFRzj55pLwkpCedEY+bTMgp5miZ8CxfIZo3S+gFqvA==} @@ -6027,7 +5787,6 @@ packages: dependencies: '@vue/reactivity': 3.4.15 '@vue/shared': 3.4.15 - dev: true /@vue/runtime-dom@3.3.4: resolution: {integrity: sha512-Aj5bTJ3u5sFsUckRghsNjVTtxZQ1OyMWCr5dZRAPijF/0Vy4xEoRCwLyHXcj4D0UFbJ4lbx3gPTgg06K/GnPnQ==} @@ -6042,7 +5801,6 @@ packages: '@vue/runtime-core': 3.4.15 '@vue/shared': 3.4.15 csstype: 3.1.3 - dev: true /@vue/server-renderer@3.3.4(vue@3.3.4): resolution: {integrity: sha512-Q6jDDzR23ViIb67v+vM1Dqntu+HUexQcsWKhhQa4ARVzxOY2HbC7QRW/ggkDBd5BU+uM1sV6XOAP0b216o34JQ==} @@ -6061,14 +5819,12 @@ packages: '@vue/compiler-ssr': 3.4.15 '@vue/shared': 3.4.15 vue: 3.4.15(typescript@5.0.4) - dev: true /@vue/shared@3.3.4: resolution: {integrity: sha512-7OjdcV8vQ74eiz1TZLzZP4JwqM5fA94K6yntPS5Z25r9HDuGNzaGdgvwKYq6S+MxwF0TFRwe50fIR/MYnakdkQ==} /@vue/shared@3.4.15: resolution: {integrity: sha512-KzfPTxVaWfB+eGcGdbSf4CWdaXcGDqckoeXUh7SB3fZdEtzPCK2Vq9B/lRRL3yutax/LWITz+SwvgyOxz5V75g==} - dev: true /@vueuse/core@10.1.0(vue@3.3.4): resolution: {integrity: sha512-3Znoa5m5RO+z4/C9w6DRaKTR3wCVJvD5rav8HTDGsr+7rOZRHtcgFJ8NcCs0ZvIpmev2kExTa311ns5j2RbzDQ==} @@ -6082,18 +5838,6 @@ packages: - vue dev: false - /@vueuse/core@10.3.0(vue@3.3.4): - resolution: {integrity: sha512-BEM5yxcFKb5btFjTSAFjTu5jmwoW66fyV9uJIP4wUXXU8aR5Hl44gndaaXp7dC5HSObmgbnR2RN+Un1p68Mf5Q==} - dependencies: - '@types/web-bluetooth': 0.0.17 - '@vueuse/metadata': 10.3.0 - '@vueuse/shared': 10.3.0(vue@3.3.4) - vue-demi: 0.14.6(vue@3.3.4) - transitivePeerDependencies: - - '@vue/composition-api' - - vue - dev: true - /@vueuse/core@10.7.2(vue@3.4.15): resolution: {integrity: sha512-AOyAL2rK0By62Hm+iqQn6Rbu8bfmbgaIMXcE3TSr7BdQ42wnSFlwIdPjInO62onYsEMK/yDMU8C6oGfDAtZ2qQ==} dependencies: @@ -6160,10 +5904,6 @@ packages: resolution: {integrity: sha512-cM28HjDEw5FIrPE9rgSPFZvQ0ZYnOLAOr8hl1XM6tFl80U3WAR5ROdnAqiYybniwP5gt9MKKAJAqd/ab2aHkqg==} dev: false - /@vueuse/metadata@10.3.0: - resolution: {integrity: sha512-Ema3YhNOa4swDsV0V7CEY5JXvK19JI/o1szFO1iWxdFg3vhdFtCtSTP26PCvbUpnUtNHBY2wx5y3WDXND5Pvnw==} - dev: true - /@vueuse/metadata@10.7.2: resolution: {integrity: sha512-kCWPb4J2KGrwLtn1eJwaJD742u1k5h6v/St5wFe8Quih90+k2a0JP8BS4Zp34XUuJqS2AxFYMb1wjUL8HfhWsQ==} dev: true @@ -6177,15 +5917,6 @@ packages: - vue dev: false - /@vueuse/shared@10.3.0(vue@3.3.4): - resolution: {integrity: sha512-kGqCTEuFPMK4+fNWy6dUOiYmxGcUbtznMwBZLC1PubidF4VZY05B+Oht7Jh7/6x4VOWGpvu3R37WHi81cKpiqg==} - dependencies: - vue-demi: 0.14.6(vue@3.3.4) - transitivePeerDependencies: - - '@vue/composition-api' - - vue - dev: true - /@vueuse/shared@10.7.2(vue@3.4.15): resolution: {integrity: sha512-qFbXoxS44pi2FkgFjPvF4h7c9oMDutpyBdcJdMYIMg9XyXli2meFMuaKn+UMgsClo//Th6+beeCgqweT/79BVA==} dependencies: @@ -6405,7 +6136,7 @@ packages: dependencies: '@types/assert': 1.5.6 '@types/ramda': 0.28.25 - '@vue/compat': 3.3.4(vue@3.3.8) + '@vue/compat': 3.3.4(vue@3.4.15) antlr4: 4.11.0 color-string: 1.9.1 dom-to-image-more: 2.16.0 @@ -6418,8 +6149,8 @@ packages: postcss: 8.4.27 ramda: 0.28.0 tailwindcss: 3.3.3(ts-node@10.9.1) - vue: 3.3.8(typescript@5.1.6) - vuex: 4.1.0(vue@3.3.8) + vue: 3.4.15(typescript@5.1.6) + vuex: 4.1.0(vue@3.4.15) transitivePeerDependencies: - ts-node - typescript @@ -6867,17 +6598,17 @@ packages: - debug dev: true - /babel-jest@29.6.2(@babel/core@7.22.10): + /babel-jest@29.6.2(@babel/core@7.23.5): resolution: {integrity: sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: '@babel/core': ^7.8.0 dependencies: - '@babel/core': 7.22.10 + '@babel/core': 7.23.5 '@jest/transform': 29.6.2 '@types/babel__core': 7.20.1 babel-plugin-istanbul: 6.1.1 - babel-preset-jest: 29.5.0(@babel/core@7.22.10) + babel-preset-jest: 29.5.0(@babel/core@7.23.5) chalk: 4.1.2 graceful-fs: 4.2.11 slash: 3.0.0 @@ -6957,35 +6688,35 @@ packages: - supports-color dev: true - /babel-preset-current-node-syntax@1.0.1(@babel/core@7.22.10): + /babel-preset-current-node-syntax@1.0.1(@babel/core@7.23.5): resolution: {integrity: sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.22.10 - '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.22.10) - '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.22.10) - '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.22.10) - '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.22.10) - '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.22.10) - '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.22.10) - '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.22.10) - '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.22.10) - '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.22.10) - '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.22.10) - '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.22.10) - '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.22.10) - dev: true - - /babel-preset-jest@29.5.0(@babel/core@7.22.10): + '@babel/core': 7.23.5 + '@babel/plugin-syntax-async-generators': 7.8.4(@babel/core@7.23.5) + '@babel/plugin-syntax-bigint': 7.8.3(@babel/core@7.23.5) + '@babel/plugin-syntax-class-properties': 7.12.13(@babel/core@7.23.5) + '@babel/plugin-syntax-import-meta': 7.10.4(@babel/core@7.23.5) + '@babel/plugin-syntax-json-strings': 7.8.3(@babel/core@7.23.5) + '@babel/plugin-syntax-logical-assignment-operators': 7.10.4(@babel/core@7.23.5) + '@babel/plugin-syntax-nullish-coalescing-operator': 7.8.3(@babel/core@7.23.5) + '@babel/plugin-syntax-numeric-separator': 7.10.4(@babel/core@7.23.5) + '@babel/plugin-syntax-object-rest-spread': 7.8.3(@babel/core@7.23.5) + '@babel/plugin-syntax-optional-catch-binding': 7.8.3(@babel/core@7.23.5) + '@babel/plugin-syntax-optional-chaining': 7.8.3(@babel/core@7.23.5) + '@babel/plugin-syntax-top-level-await': 7.14.5(@babel/core@7.23.5) + dev: true + + /babel-preset-jest@29.5.0(@babel/core@7.23.5): resolution: {integrity: sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} peerDependencies: '@babel/core': ^7.0.0 dependencies: - '@babel/core': 7.22.10 + '@babel/core': 7.23.5 babel-plugin-jest-hoist: 29.5.0 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.10) + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.23.5) dev: true /bail@2.0.2: @@ -7359,10 +7090,18 @@ packages: engines: {node: '>=10'} dev: true + /character-entities-html4@2.1.0: + resolution: {integrity: sha512-1v7fgQRj6hnSwFpq1Eu0ynr/CDEw0rXo2B61qXrLNdHZmPKgb7fqS1a2JwF0rISo9q77jDI8VMEHoApn8qDoZA==} + dev: true + /character-entities-legacy@1.1.4: resolution: {integrity: sha512-3Xnr+7ZFS1uxeiUDvV02wQ+QDbc55o97tIV5zHScSPJpcLm/r0DFPcoY3tYRp+VZukxuMeKgXYmsXQHO05zQeA==} dev: true + /character-entities-legacy@3.0.0: + resolution: {integrity: sha512-RpPp0asT/6ufRm//AJVwpViZbGM/MkjQFxJccQRHmISF/22NBtsHqAWmL+/pmkPWoIUJdWyeVleTl1wydHATVQ==} + dev: true + /character-entities@1.2.4: resolution: {integrity: sha512-iBMyeEHxfVnIakwOuDXpVkc54HijNgCyQB2w0VfGQThle6NXn50zU6V/u+LDhxHcDUPojn6Kpga3PTAD8W1bQw==} dev: true @@ -7584,6 +7323,10 @@ packages: delayed-stream: 1.0.0 dev: true + /comma-separated-tokens@2.0.3: + resolution: {integrity: sha512-Fu4hJdvzeylCfQPp9SGWidpzrMs7tTrlu6Vb8XGaRGck8QSNZJJp538Wrb60Lax4fPwR64ViY468OIUTbRlGZg==} + dev: true + /commander@10.0.1: resolution: {integrity: sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==} engines: {node: '>=14'} @@ -8146,7 +7889,6 @@ packages: /csstype@3.1.3: resolution: {integrity: sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==} - dev: true /cuint@0.2.2: resolution: {integrity: sha512-d4ZVpCW31eWwCMe1YT3ur7mUDnTXbgwyzaL320DrcRT45rfjYxkt5QWLrmOJ+/UEAI2+fQgKe/fCjR8l4TpRgw==} @@ -8867,6 +8609,12 @@ packages: resolution: {integrity: sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==} dev: true + /devlop@1.1.0: + resolution: {integrity: sha512-RWmIqhcFf1lRYBvNmr7qTNuyCt/7/ns2jbpp1+PalgE/rDQcBT0fioSMUpJ93irlUhC5hrg4cYqe6U+0ImW0rA==} + dependencies: + dequal: 2.0.3 + dev: true + /didyoumean@1.2.2: resolution: {integrity: sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==} dev: false @@ -9060,7 +8808,6 @@ packages: /entities@4.5.0: resolution: {integrity: sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==} engines: {node: '>=0.12'} - dev: true /envinfo@7.10.0: resolution: {integrity: sha512-ZtUjZO6l5mwTHvc1L9+1q5p/R3wTopcfqMW8r5t8SJSKqeVI/LtajORwRFEKpEFuekjD0VBjwu1HMxL4UalIRw==} @@ -10631,6 +10378,88 @@ packages: type-fest: 0.8.1 dev: true + /hast-util-from-parse5@8.0.1: + resolution: {integrity: sha512-Er/Iixbc7IEa7r/XLtuG52zoqn/b3Xng/w6aZQ0xGVxzhw5xUFxcRqdPzP6yFi/4HBYRaifaI5fQ1RH8n0ZeOQ==} + dependencies: + '@types/hast': 3.0.3 + '@types/unist': 3.0.2 + devlop: 1.1.0 + hastscript: 8.0.0 + property-information: 6.4.0 + vfile: 6.0.1 + vfile-location: 5.0.2 + web-namespaces: 2.0.1 + dev: true + + /hast-util-parse-selector@4.0.0: + resolution: {integrity: sha512-wkQCkSYoOGCRKERFWcxMVMOcYE2K1AaNLU8DXS9arxnLOUEWbOXKXiJUNzEpqZ3JOKpnha3jkFrumEjVliDe7A==} + dependencies: + '@types/hast': 3.0.3 + dev: true + + /hast-util-raw@9.0.2: + resolution: {integrity: sha512-PldBy71wO9Uq1kyaMch9AHIghtQvIwxBUkv823pKmkTM3oV1JxtsTNYdevMxvUHqcnOAuO65JKU2+0NOxc2ksA==} + dependencies: + '@types/hast': 3.0.3 + '@types/unist': 3.0.2 + '@ungap/structured-clone': 1.2.0 + hast-util-from-parse5: 8.0.1 + hast-util-to-parse5: 8.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.1.0 + parse5: 7.1.2 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.1 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + dev: true + + /hast-util-to-html@9.0.0: + resolution: {integrity: sha512-IVGhNgg7vANuUA2XKrT6sOIIPgaYZnmLx3l/CCOAK0PtgfoHrZwX7jCSYyFxHTrGmC6S9q8aQQekjp4JPZF+cw==} + dependencies: + '@types/hast': 3.0.3 + '@types/unist': 3.0.2 + ccount: 2.0.1 + comma-separated-tokens: 2.0.3 + hast-util-raw: 9.0.2 + hast-util-whitespace: 3.0.0 + html-void-elements: 3.0.0 + mdast-util-to-hast: 13.1.0 + property-information: 6.4.0 + space-separated-tokens: 2.0.2 + stringify-entities: 4.0.3 + zwitch: 2.0.4 + dev: true + + /hast-util-to-parse5@8.0.0: + resolution: {integrity: sha512-3KKrV5ZVI8if87DVSi1vDeByYrkGzg4mEfeu4alwgmmIeARiBLKCZS2uw5Gb6nU9x9Yufyj3iudm6i7nl52PFw==} + dependencies: + '@types/hast': 3.0.3 + comma-separated-tokens: 2.0.3 + devlop: 1.1.0 + property-information: 6.4.0 + space-separated-tokens: 2.0.2 + web-namespaces: 2.0.1 + zwitch: 2.0.4 + dev: true + + /hast-util-whitespace@3.0.0: + resolution: {integrity: sha512-88JUN06ipLwsnv+dVn+OIYOvAuvBMy/Qoi6O7mQHxdPXpjy+Cd6xRkWwux7DKO+4sYILtLBRIKgsdpS2gQc7qw==} + dependencies: + '@types/hast': 3.0.3 + dev: true + + /hastscript@8.0.0: + resolution: {integrity: sha512-dMOtzCEd3ABUeSIISmrETiKuyydk1w0pa+gE/uormcTpSYuaNJPbX1NU3JLyscSLjwAQM8bWMhhIlnCqnRvDTw==} + dependencies: + '@types/hast': 3.0.3 + comma-separated-tokens: 2.0.3 + hast-util-parse-selector: 4.0.0 + property-information: 6.4.0 + space-separated-tokens: 2.0.2 + dev: true + /heap@0.2.7: resolution: {integrity: sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg==} dev: false @@ -10678,6 +10507,10 @@ packages: resolution: {integrity: sha512-9gux8QhvjRO/erSnDPv28noDZcPZmYE7e1vFsBLKLlRlKDSqNJYebj6Qz1TGd5lsRV+X+xYyjCKjuZdABinWjA==} dev: false + /html-void-elements@3.0.0: + resolution: {integrity: sha512-bEqo66MRXsUGxWHV5IP0PUiAWwoEjba4VCzg0LjFJBpchPaTfyfCKTG6bc5F8ucKec3q5y6qOdGyYTSBEvhCrg==} + dev: true + /htmlparser2@8.0.2: resolution: {integrity: sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==} dependencies: @@ -11289,7 +11122,7 @@ packages: resolution: {integrity: sha512-BXgQl9kf4WTCPCCpmFGoJkz/+uhvm7h7PFKUYxh7qarQd3ER33vHG//qaE8eN25l07YqZPpHXU9I09l/RD5aGQ==} engines: {node: '>=8'} dependencies: - '@babel/core': 7.22.10 + '@babel/core': 7.23.5 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.0 semver: 6.3.1 @@ -11301,8 +11134,8 @@ packages: resolution: {integrity: sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==} engines: {node: '>=8'} dependencies: - '@babel/core': 7.22.10 - '@babel/parser': 7.23.0 + '@babel/core': 7.23.5 + '@babel/parser': 7.23.6 '@istanbuljs/schema': 0.1.3 istanbul-lib-coverage: 3.2.0 semver: 6.3.1 @@ -11456,11 +11289,11 @@ packages: ts-node: optional: true dependencies: - '@babel/core': 7.22.10 + '@babel/core': 7.23.5 '@jest/test-sequencer': 29.6.2 '@jest/types': 29.6.1 '@types/node': 18.17.5 - babel-jest: 29.6.2(@babel/core@7.22.10) + babel-jest: 29.6.2(@babel/core@7.23.5) chalk: 4.1.2 ci-info: 3.8.0 deepmerge: 4.3.1 @@ -11589,7 +11422,7 @@ packages: resolution: {integrity: sha512-vnIGYEjoPSuRqV8W9t+Wow95SDp6KPX2Uf7EoeG9G99J2OVh7OSwpS4B6J0NfpEIpfkBNHlBZpA2rblEuEFhZQ==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@babel/code-frame': 7.22.13 + '@babel/code-frame': 7.23.5 '@jest/types': 29.6.1 '@types/stack-utils': 2.0.1 chalk: 4.1.2 @@ -11714,15 +11547,15 @@ packages: resolution: {integrity: sha512-1OdjqvqmRdGNvWXr/YZHuyhh5DeaLp1p/F8Tht/MrMw4Kr1Uu/j4lRG+iKl1DAqUJDWxtQBMk41Lnf/JETYBRA==} engines: {node: ^14.15.0 || ^16.10.0 || >=18.0.0} dependencies: - '@babel/core': 7.22.10 - '@babel/generator': 7.23.0 - '@babel/plugin-syntax-jsx': 7.22.5(@babel/core@7.22.10) - '@babel/plugin-syntax-typescript': 7.22.5(@babel/core@7.22.10) + '@babel/core': 7.23.5 + '@babel/generator': 7.23.5 + '@babel/plugin-syntax-jsx': 7.23.3(@babel/core@7.23.5) + '@babel/plugin-syntax-typescript': 7.23.3(@babel/core@7.23.5) '@babel/types': 7.23.5 '@jest/expect-utils': 29.6.2 '@jest/transform': 29.6.2 '@jest/types': 29.6.1 - babel-preset-current-node-syntax: 1.0.1(@babel/core@7.22.10) + babel-preset-current-node-syntax: 1.0.1(@babel/core@7.23.5) chalk: 4.1.2 expect: 29.6.2 graceful-fs: 4.2.11 @@ -12653,6 +12486,20 @@ packages: unist-util-is: 5.2.1 dev: true + /mdast-util-to-hast@13.1.0: + resolution: {integrity: sha512-/e2l/6+OdGp/FB+ctrJ9Avz71AN/GRH3oi/3KAx/kMnoUsD6q0woXlDT8lLEeViVKE7oZxE7RXzvO3T8kF2/sA==} + dependencies: + '@types/hast': 3.0.3 + '@types/mdast': 4.0.3 + '@ungap/structured-clone': 1.2.0 + devlop: 1.1.0 + micromark-util-sanitize-uri: 2.0.0 + trim-lines: 3.0.1 + unist-util-position: 5.0.0 + unist-util-visit: 5.0.0 + vfile: 6.0.1 + dev: true + /mdast-util-to-markdown@1.5.0: resolution: {integrity: sha512-bbv7TPv/WC49thZPg3jXuqzuvI45IL2EVAr/KxF0BSdHsU0ceFHOmwQn6evxAh1GaoK/6GQ1wp4R4oW2+LFL/A==} dependencies: @@ -12908,6 +12755,13 @@ packages: micromark-util-symbol: 1.1.0 micromark-util-types: 1.1.0 + /micromark-util-character@2.0.1: + resolution: {integrity: sha512-3wgnrmEAJ4T+mGXAUfMvMAbxU9RDG43XmGce4j6CwPtVxB3vfwXSZ6KhFwDzZ3mZHhmPimMAXg71veiBGzeAZw==} + dependencies: + micromark-util-symbol: 2.0.0 + micromark-util-types: 2.0.0 + dev: true + /micromark-util-chunked@1.1.0: resolution: {integrity: sha512-Ye01HXpkZPNcV6FiyoW2fGZDUw4Yc7vT0E9Sad83+bEDiCJ1uXu0S3mr8WLpsz3HaG3x2q0HM6CTuPdcZcluFQ==} dependencies: @@ -12942,6 +12796,10 @@ packages: /micromark-util-encode@1.1.0: resolution: {integrity: sha512-EuEzTWSTAj9PA5GOAs992GzNh2dGQO52UvAbtSOMvXTxv3Criqb6IOzJUBCmEqrrXSblJIJBbFFv6zPxpreiJw==} + /micromark-util-encode@2.0.0: + resolution: {integrity: sha512-pS+ROfCXAGLWCOc8egcBvT0kf27GoWMqtdarNfDcjb6YLuV5cM3ioG45Ys2qOVqeqSbjaKg72vU+Wby3eddPsA==} + dev: true + /micromark-util-html-tag-name@1.2.0: resolution: {integrity: sha512-VTQzcuQgFUD7yYztuQFKXT49KghjtETQ+Wv/zUjGSGBioZnkA4P1XXZPT1FHeJA6RwRXSF47yvJ1tsJdoxwO+Q==} @@ -12962,6 +12820,14 @@ packages: micromark-util-encode: 1.1.0 micromark-util-symbol: 1.1.0 + /micromark-util-sanitize-uri@2.0.0: + resolution: {integrity: sha512-WhYv5UEcZrbAtlsnPuChHUAsu/iBPOVaEVsntLBIdpibO0ddy8OzavZz3iL2xVvBZOpolujSliP65Kq0/7KIYw==} + dependencies: + micromark-util-character: 2.0.1 + micromark-util-encode: 2.0.0 + micromark-util-symbol: 2.0.0 + dev: true + /micromark-util-subtokenize@1.1.0: resolution: {integrity: sha512-kUQHyzRoxvZO2PuLzMt2P/dwVsTiivCK8icYTeR+3WgbuPqfHgPPy7nFKbeqRivBvn/3N3GBiNC+JRTMSxEC7A==} dependencies: @@ -12973,9 +12839,17 @@ packages: /micromark-util-symbol@1.1.0: resolution: {integrity: sha512-uEjpEYY6KMs1g7QfJ2eX1SQEV+ZT4rUD3UcF6l57acZvLNK7PBZL+ty82Z1qhK1/yXIY4bdx04FKMgR0g4IAag==} + /micromark-util-symbol@2.0.0: + resolution: {integrity: sha512-8JZt9ElZ5kyTnO94muPxIGS8oyElRJaiJO8EzV6ZSyGQ1Is8xwl4Q45qU5UOg+bGH4AikWziz0iN4sFLWs8PGw==} + dev: true + /micromark-util-types@1.1.0: resolution: {integrity: sha512-ukRBgie8TIAcacscVHSiddHjO4k/q3pnedmzMQ4iwDcK0FtFCohKOlFbaOL/mPgfnPsL3C1ZyxJa4sbWrBl3jg==} + /micromark-util-types@2.0.0: + resolution: {integrity: sha512-oNh6S2WMHWRZrmutsRmDDfkzKtxF+bc2VxLC9dvtrDIRFln627VsFP6fLMgTryGDljgLPjkrzQSDcPrjPyDJ5w==} + dev: true + /micromark@2.11.4: resolution: {integrity: sha512-+WoovN/ppKolQOFIAajxi7Lu9kInbPxFuTBVEavFcL8eAfVstoc5MocPmqBeAdBOJV00uaVjegzH4+MA0DN/uA==} dependencies: @@ -13168,12 +13042,12 @@ packages: resolution: {integrity: sha512-BGcqMMJuToF7i1rt+2PWSNVnWIkGCU78jBG3RxO/bZlnZPK2Cmi2QaffxGO/2RvWi9sL+FAiRiXMgsyxQ1DIDA==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true + dev: false /nanoid@3.3.7: resolution: {integrity: sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==} engines: {node: ^10 || ^12 || ^13.7 || ^14 || >=15.0.1} hasBin: true - dev: true /natural-compare-lite@1.4.0: resolution: {integrity: sha512-Tj+HTDSJJKaZnfiuw+iaF9skdPpTo2GtEly5JHnWV/hfv2Qj/9RKsGISQtLh2ox3l5EAGw487hnBee0sIJ6v2g==} @@ -13648,7 +13522,7 @@ packages: resolution: {integrity: sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==} engines: {node: '>=8'} dependencies: - '@babel/code-frame': 7.22.10 + '@babel/code-frame': 7.23.5 error-ex: 1.3.2 json-parse-even-better-errors: 2.3.1 lines-and-columns: 1.2.4 @@ -13982,7 +13856,7 @@ packages: resolution: {integrity: sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==} engines: {node: ^10 || ^12 || >=14} dependencies: - nanoid: 3.3.6 + nanoid: 3.3.7 picocolors: 1.0.0 source-map-js: 1.0.2 @@ -13993,7 +13867,6 @@ packages: nanoid: 3.3.7 picocolors: 1.0.0 source-map-js: 1.0.2 - dev: true /preact@10.16.0: resolution: {integrity: sha512-XTSj3dJ4roKIC93pald6rWuB2qQJO9gO2iLLyTe87MrjQN+HklueLsmskbywEWqCHlclgz3/M4YLL2iBr9UmMA==} @@ -14075,6 +13948,10 @@ packages: sisteransi: 1.0.5 dev: true + /property-information@6.4.0: + resolution: {integrity: sha512-9t5qARVofg2xQqKtytzt+lZ4d1Qvj8t5B8fEwXK6qOfgRLgH/b13QlgEyDh033NOS31nXeFbYv7CLUDG1CeifQ==} + dev: true + /proxy-addr@2.0.7: resolution: {integrity: sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==} engines: {node: '>= 0.10'} @@ -14911,12 +14788,24 @@ packages: resolution: {integrity: sha512-AFJu/vcNT21t0e6YrfadZ+9q86gvPum6iywRyt1OtIPjPFe25RQnYJyxHQPMLKCCWA992TPxmEmbNcOZCAJclw==} dev: true + /shikiji-transformers@0.7.6: + resolution: {integrity: sha512-yTp+7JMD/aXbV9ndn14eo9IK/UNt8iDsLNyqlOmCtcldlkqWE9T2YKAlOHOTVaeDfYWUWZa2EgSXb/CBfepBrw==} + dependencies: + shikiji: 0.7.6 + dev: true + /shikiji-transformers@0.9.19: resolution: {integrity: sha512-lGLI7Z8frQrIBbhZ74/eiJtxMoCQRbpaHEB+gcfvdIy+ZFaAtXncJGnc52932/UET+Y4GyKtwwC/vjWUCp+c/Q==} dependencies: shikiji: 0.9.19 dev: true + /shikiji@0.7.6: + resolution: {integrity: sha512-KzEtvSGQtBvfwVIB70kOmIfl/5rz1LC8j+tvlHXsJKAIdONNQvG1at7ivUUq3xUctqgO6fsO3AGomUSh0F+wsQ==} + dependencies: + hast-util-to-html: 9.0.0 + dev: true + /shikiji@0.9.19: resolution: {integrity: sha512-Kw2NHWktdcdypCj1GkKpXH4o6Vxz8B8TykPlPuLHOGSV8VkhoCLcFOH4k19K4LXAQYRQmxg+0X/eM+m2sLhAkg==} dependencies: @@ -15069,6 +14958,10 @@ packages: deprecated: Please use @jridgewell/sourcemap-codec instead dev: true + /space-separated-tokens@2.0.2: + resolution: {integrity: sha512-PEGlAwrG8yXGXRjW32fGbg66JAlOAwbObuqVoJpv/mRgoWDQfgH1wDPvtzWyUSNAXBGSk8h755YDbbcEy3SH2Q==} + dev: true + /spawn-command@0.0.2-1: resolution: {integrity: sha512-n98l9E2RMSJ9ON1AKisHzz7V42VDiBQGY6PB1BwRglz99wpVsSuGzQ+jOi6lFXBGVTCrRpltvjm+/XA+tpeJrg==} dev: true @@ -15307,6 +15200,13 @@ packages: dependencies: safe-buffer: 5.2.1 + /stringify-entities@4.0.3: + resolution: {integrity: sha512-BP9nNHMhhfcMbiuQKCqMjhDP5yBCAxsPu4pHFFzJ6Alo9dZgY4VLDPutXqIjpRiMoKdp7Av85Gr73Q5uH9k7+g==} + dependencies: + character-entities-html4: 2.1.0 + character-entities-legacy: 3.0.0 + dev: true + /stringify-object@3.3.0: resolution: {integrity: sha512-rHqiFh1elqCQ9WPLIC8I0Q/g/wj5J1eMkyoiD6eoQApWHP0FtlK7rqnhmabL5VUY9JQCcqwwvlOaSuutekgyrw==} engines: {node: '>=4'} @@ -15719,6 +15619,10 @@ packages: hasBin: true dev: true + /trim-lines@3.0.1: + resolution: {integrity: sha512-kRj8B+YHZCc9kQYdWfJB2/oUl9rA99qbowYYBtr4ui4mZyAQ2JpvVBd/6U2YloATfqBhBTSMhTpgBHtU0Mf3Rg==} + dev: true + /trim-newlines@3.0.1: resolution: {integrity: sha512-c1PTsA3tYrIsLGkJkzHF+w9F2EyxfXGo4UyJc4pFL++FMjnq0HJS69T3M7d//gKrFKwy429bouPescbjecU+Zw==} engines: {node: '>=8'} @@ -15989,7 +15893,6 @@ packages: resolution: {integrity: sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==} engines: {node: '>=12.20'} hasBin: true - dev: true /typescript@5.1.6: resolution: {integrity: sha512-zaWCozRZ6DLEWAWFrVDz1H6FVXzUSfTy5FUMWsQlU8Ym5JP9eO4xkTIROFCQvhQf61z6O/G6ugw3SgAnvvm+HA==} @@ -16090,6 +15993,18 @@ packages: '@types/unist': 2.0.7 dev: true + /unist-util-is@6.0.0: + resolution: {integrity: sha512-2qCTHimwdxLfz+YzdGfkqNlH0tLi9xjTnHddPmJwtIG9MGsdbutfTc4P+haPD7l7Cjxf/WZj+we5qfVPvvxfYw==} + dependencies: + '@types/unist': 3.0.2 + dev: true + + /unist-util-position@5.0.0: + resolution: {integrity: sha512-fucsC7HjXvkB5R3kTCO7kUjRdrS0BJt3M/FPxmHMBOm8JQi2BsHAHFsy27E0EolP8rp0NzXsJ+jNPyDWvOJZPA==} + dependencies: + '@types/unist': 3.0.2 + dev: true + /unist-util-stringify-position@2.0.3: resolution: {integrity: sha512-3faScn5I+hy9VleOq/qNbAd6pAx7iH5jYBMS9I1HgQVijz/4mv5Bvw5iw1sC/90CODiKo81G/ps8AJrISn687g==} dependencies: @@ -16101,6 +16016,12 @@ packages: dependencies: '@types/unist': 2.0.7 + /unist-util-stringify-position@4.0.0: + resolution: {integrity: sha512-0ASV06AAoKCDkS2+xw5RXJywruurpbC4JZSm7nr7MOt1ojAzvyyaO+UxZf18j8FCF6kmzCZKcAgN/yu2gm2XgQ==} + dependencies: + '@types/unist': 3.0.2 + dev: true + /unist-util-visit-parents@5.1.3: resolution: {integrity: sha512-x6+y8g7wWMyQhL1iZfhIPhDAs7Xwbn9nRosDXl7qoPTSCy0yNxnKc+hWokFifWQIDGi154rdUqKvbCa4+1kLhg==} dependencies: @@ -16108,6 +16029,13 @@ packages: unist-util-is: 5.2.1 dev: true + /unist-util-visit-parents@6.0.1: + resolution: {integrity: sha512-L/PqWzfTP9lzzEa6CKs0k2nARxTdZduw3zyh8d2NVBnsyvHjSX4TWse388YrrQKbvI8w20fGjGlhgT96WwKykw==} + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + dev: true + /unist-util-visit@4.1.2: resolution: {integrity: sha512-MSd8OUGISqHdVvfY9TPhyK2VdUrPgxkUtWSuMHF6XAAFuL4LokseigBnZtPnJMu+FbynTkFNnFlyjxpVKujMRg==} dependencies: @@ -16116,6 +16044,14 @@ packages: unist-util-visit-parents: 5.1.3 dev: true + /unist-util-visit@5.0.0: + resolution: {integrity: sha512-MR04uvD+07cwl/yhVuVWAtw+3GOR/knlL55Nd/wAdblk27GCVt3lqpTivy/tkJcZoNPzTwS1Y+KMojlLDhoTzg==} + dependencies: + '@types/unist': 3.0.2 + unist-util-is: 6.0.0 + unist-util-visit-parents: 6.0.1 + dev: true + /universalify@0.1.2: resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==} engines: {node: '>= 4.0.0'} @@ -16308,6 +16244,13 @@ packages: extsprintf: 1.3.0 dev: true + /vfile-location@5.0.2: + resolution: {integrity: sha512-NXPYyxyBSH7zB5U6+3uDdd6Nybz6o6/od9rk8bp9H8GR3L+cm/fC0uUTbqBmUTnMCUDslAGBOIKNfvvb+gGlDg==} + dependencies: + '@types/unist': 3.0.2 + vfile: 6.0.1 + dev: true + /vfile-message@3.1.4: resolution: {integrity: sha512-fa0Z6P8HUrQN4BZaX05SIVXic+7kE3b05PWAtPuYP9QLHsLKYR7/AlLW3NtOrpXRLeawpDLMsVkmk5DG0NXgWw==} dependencies: @@ -16315,6 +16258,13 @@ packages: unist-util-stringify-position: 3.0.3 dev: true + /vfile-message@4.0.2: + resolution: {integrity: sha512-jRDZ1IMLttGj41KcZvlrYAaI3CfqpLpfpf+Mfig13viT6NKvRzWZ+lXz0Y5D60w6uJIBAOGq9mSHf0gktF0duw==} + dependencies: + '@types/unist': 3.0.2 + unist-util-stringify-position: 4.0.0 + dev: true + /vfile@5.3.7: resolution: {integrity: sha512-r7qlzkgErKjobAmyNIkkSpizsFPYiUPuJb5pNW1RB4JcYVZhs4lIbVqk8XPk033CV/1z8ss5pkax8SuhGpcG8g==} dependencies: @@ -16324,6 +16274,14 @@ packages: vfile-message: 3.1.4 dev: true + /vfile@6.0.1: + resolution: {integrity: sha512-1bYqc7pt6NIADBJ98UiG0Bn/CHIVOoZ/IyEkqIruLg0mE1BKzkOXY2D6CSqQIcKqgadppE5lrxgWXJmXd7zZJw==} + dependencies: + '@types/unist': 3.0.2 + unist-util-stringify-position: 4.0.0 + vfile-message: 4.0.2 + dev: true + /vite-node@0.34.0(@types/node@18.17.5): resolution: {integrity: sha512-rGZMvpb052rjUwJA/a17xMfOibzNF7byMdRSTcN2Lw8uxX08s5EfjWW5mBkm3MSFTPctMSVtT2yC+8ShrZbT5g==} engines: {node: '>=v14.18.0'} @@ -16499,7 +16457,7 @@ packages: flexsearch: 0.7.31 glob-to-regexp: 0.4.1 markdown-it: 13.0.1 - vitepress: 1.0.0-alpha.72(@algolia/client-search@4.19.1)(@types/node@18.17.5)(search-insights@2.7.0) + vitepress: 1.0.0-alpha.72(@algolia/client-search@4.19.1)(@types/node@18.17.5)(search-insights@2.7.0)(typescript@5.0.4) vue: 3.4.15(typescript@5.0.4) dev: true @@ -16509,30 +16467,86 @@ packages: dependencies: '@docsearch/css': 3.5.1 '@docsearch/js': 3.5.1(@algolia/client-search@4.19.1)(search-insights@2.7.0) - '@vitejs/plugin-vue': 4.5.0(vite@4.5.0)(vue@3.3.8) + '@vitejs/plugin-vue': 4.5.0(vite@4.5.0)(vue@3.4.15) '@vue/devtools-api': 6.5.0 - '@vueuse/core': 10.6.1(vue@3.3.8) + '@vueuse/core': 10.7.2(vue@3.4.15) body-scroll-lock: 4.0.0-beta.0 mark.js: 8.11.1 minisearch: 6.1.0 shiki: 0.14.3 vite: 4.5.0(@types/node@18.17.5) - vue: 3.3.8(typescript@5.0.4) + vue: 3.4.15(typescript@5.0.4) + transitivePeerDependencies: + - '@algolia/client-search' + - '@types/node' + - '@types/react' + - '@vue/composition-api' + - less + - lightningcss + - react + - react-dom + - sass + - search-insights + - stylus + - sugarss + - terser + - typescript + dev: true + + /vitepress@1.0.0-rc.31(@algolia/client-search@4.19.1)(@types/node@18.17.5)(postcss@8.4.33)(search-insights@2.7.0)(typescript@5.1.6): + resolution: {integrity: sha512-ikH9pIjOOAbyoYAGBVfTz8TzuXp+UoWaIRMU4bw/oiTg8R65SbAaGKY84xx6TuL+f4VqUJ8lhzW82YyxSLvstA==} + hasBin: true + peerDependencies: + markdown-it-mathjax3: ^4.3.2 + postcss: ^8.4.31 + peerDependenciesMeta: + markdown-it-mathjax3: + optional: true + postcss: + optional: true + dependencies: + '@docsearch/css': 3.5.2 + '@docsearch/js': 3.5.2(@algolia/client-search@4.19.1)(search-insights@2.7.0) + '@types/markdown-it': 13.0.7 + '@vitejs/plugin-vue': 4.5.0(vite@5.0.11)(vue@3.4.15) + '@vue/devtools-api': 6.5.1 + '@vueuse/core': 10.7.2(vue@3.4.15) + '@vueuse/integrations': 10.7.2(focus-trap@7.5.4)(vue@3.4.15) + focus-trap: 7.5.4 + mark.js: 8.11.1 + minisearch: 6.3.0 + mrmime: 1.0.1 + postcss: 8.4.33 + shikiji: 0.7.6 + shikiji-transformers: 0.7.6 + vite: 5.0.11(@types/node@18.17.5) + vue: 3.4.15(typescript@5.1.6) transitivePeerDependencies: - '@algolia/client-search' - '@types/node' - '@types/react' - '@vue/composition-api' + - async-validator + - axios + - change-case + - drauu + - fuse.js + - idb-keyval + - jwt-decode - less - lightningcss + - nprogress + - qrcode - react - react-dom - sass - search-insights + - sortablejs - stylus - sugarss - terser - typescript + - universal-cookie dev: true /vitepress@1.0.0-rc.39(@algolia/client-search@4.19.1)(@types/node@18.17.5)(postcss@8.4.33)(search-insights@2.7.0)(typescript@5.1.6): @@ -16705,6 +16719,7 @@ packages: optional: true dependencies: vue: 3.3.4 + dev: false /vue-demi@0.14.6(vue@3.4.15): resolution: {integrity: sha512-8QA7wrYSHKaYgUxDA5ZC24w+eHm3sYCbp0EzcDwKqN3p6HqtTCGR/GVsPyZW92unff4UlcSh++lmqDWN3ZIq4w==} @@ -16718,7 +16733,7 @@ packages: '@vue/composition-api': optional: true dependencies: - vue: 3.4.15(typescript@5.1.6) + vue: 3.4.15(typescript@5.0.4) dev: true /vue@3.3.4: @@ -16744,7 +16759,6 @@ packages: '@vue/server-renderer': 3.4.15(vue@3.4.15) '@vue/shared': 3.4.15 typescript: 5.0.4 - dev: true /vue@3.4.15(typescript@5.1.6): resolution: {integrity: sha512-jC0GH4KkWLWJOEQjOpkqU1bQsBwf4R1rsFtw5GQJbjHVKWDzO6P0nWWBTmjp1xSemAioDFj1jdaK1qa3DnMQoQ==} @@ -16761,13 +16775,13 @@ packages: '@vue/shared': 3.4.15 typescript: 5.1.6 - /vuex@4.1.0(vue@3.3.8): + /vuex@4.1.0(vue@3.4.15): resolution: {integrity: sha512-hmV6UerDrPcgbSy9ORAtNXDr9M4wlNP4pEFKye4ujJF8oqgFFuxDCdOLS3eNoRTtq5O3hoBDh9Doj1bQMYHRbQ==} peerDependencies: vue: ^3.2.0 dependencies: '@vue/devtools-api': 6.5.1 - vue: 3.3.8(typescript@5.1.6) + vue: 3.4.15(typescript@5.1.6) dev: false /w3c-hr-time@1.0.2: @@ -16825,6 +16839,10 @@ packages: minimalistic-assert: 1.0.1 dev: true + /web-namespaces@2.0.1: + resolution: {integrity: sha512-bKr1DkiNa2krS7qxNtdrtHAmzuYGFQLiQ13TsorsdT6ULTkPLKuu5+GsFpDlg6JFjUTwX2DyhMPG2be8uPrqsQ==} + dev: true + /web-streams-polyfill@3.2.1: resolution: {integrity: sha512-e0MO3wdXWKrLbL0DgGnUV7WHVuw9OUvL4hjgnPkIeEvESk74gAITi5G606JtZPp39cd8HA9VQzCIvA49LpPN5Q==} engines: {node: '>= 8'} From 12dc3d8373259f2caaacb7cea7c300c2c7ee8599 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Sun, 28 Jan 2024 15:52:37 +0530 Subject: [PATCH 46/97] Rename files to TS --- .../src/diagrams/mindmap/{mindmap.spec.js => mindmap.spec.ts} | 0 .../mermaid/src/diagrams/mindmap/{mindmapDb.js => mindmapDb.ts} | 0 .../diagrams/mindmap/{mindmapRenderer.js => mindmapRenderer.ts} | 0 3 files changed, 0 insertions(+), 0 deletions(-) rename packages/mermaid/src/diagrams/mindmap/{mindmap.spec.js => mindmap.spec.ts} (100%) rename packages/mermaid/src/diagrams/mindmap/{mindmapDb.js => mindmapDb.ts} (100%) rename packages/mermaid/src/diagrams/mindmap/{mindmapRenderer.js => mindmapRenderer.ts} (100%) diff --git a/packages/mermaid/src/diagrams/mindmap/mindmap.spec.js b/packages/mermaid/src/diagrams/mindmap/mindmap.spec.ts similarity index 100% rename from packages/mermaid/src/diagrams/mindmap/mindmap.spec.js rename to packages/mermaid/src/diagrams/mindmap/mindmap.spec.ts diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapDb.js b/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts similarity index 100% rename from packages/mermaid/src/diagrams/mindmap/mindmapDb.js rename to packages/mermaid/src/diagrams/mindmap/mindmapDb.ts diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.js b/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts similarity index 100% rename from packages/mermaid/src/diagrams/mindmap/mindmapRenderer.js rename to packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts From e046da10c2913938435c05370bc4729e69184726 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Sun, 28 Jan 2024 15:55:22 +0530 Subject: [PATCH 47/97] Convert mindmap.spec.js --- .../src/diagrams/mindmap/mindmap.spec.ts | 78 ++++++++----------- 1 file changed, 33 insertions(+), 45 deletions(-) diff --git a/packages/mermaid/src/diagrams/mindmap/mindmap.spec.ts b/packages/mermaid/src/diagrams/mindmap/mindmap.spec.ts index c0b72060d9..f6cc4304f8 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmap.spec.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmap.spec.ts @@ -1,3 +1,4 @@ +// @ts-expect-error No types available for JISON import { parser as mindmap } from './parser/mindmap.jison'; import * as mindmapDB from './mindmapDb.js'; // Todo fix utils functions for tests @@ -11,7 +12,7 @@ describe('when parsing a mindmap ', function () { }); describe('hiearchy', function () { it('MMP-1 should handle a simple root definition abc122', function () { - let str = `mindmap + const str = `mindmap root`; mindmap.parse(str); @@ -19,7 +20,7 @@ describe('when parsing a mindmap ', function () { expect(mindmap.yy.getMindmap().descr).toEqual('root'); }); it('MMP-2 should handle a hierachial mindmap definition', function () { - let str = `mindmap + const str = `mindmap root child1 child2 @@ -34,7 +35,7 @@ describe('when parsing a mindmap ', function () { }); it('3 should handle a simple root definition with a shape and without an id abc123', function () { - let str = `mindmap + const str = `mindmap (root)`; mindmap.parse(str); @@ -43,7 +44,7 @@ describe('when parsing a mindmap ', function () { }); it('MMP-4 should handle a deeper hierachial mindmap definition', function () { - let str = `mindmap + const str = `mindmap root child1 leaf1 @@ -58,40 +59,27 @@ describe('when parsing a mindmap ', function () { expect(mm.children[1].descr).toEqual('child2'); }); it('5 Multiple roots are illegal', function () { - let str = `mindmap + const str = `mindmap root fakeRoot`; - try { - mindmap.parse(str); - // Fail test if above expression doesn't throw anything. - expect(true).toBe(false); - } catch (e) { - expect(e.message).toBe( - 'There can be only one root. No parent could be found for ("fakeRoot")' - ); - } + expect(() => mindmap.parse(str)).toThrow( + 'There can be only one root. No parent could be found for ("fakeRoot")' + ); }); it('MMP-6 real root in wrong place', function () { - let str = `mindmap + const str = `mindmap root fakeRoot realRootWrongPlace`; - - try { - mindmap.parse(str); - // Fail test if above expression doesn't throw anything. - expect(true).toBe(false); - } catch (e) { - expect(e.message).toBe( - 'There can be only one root. No parent could be found for ("fakeRoot")' - ); - } + expect(() => mindmap.parse(str)).toThrow( + 'There can be only one root. No parent could be found for ("fakeRoot")' + ); }); }); describe('nodes', function () { it('MMP-7 should handle an id and type for a node definition', function () { - let str = `mindmap + const str = `mindmap root[The root] `; @@ -102,7 +90,7 @@ describe('when parsing a mindmap ', function () { expect(mm.type).toEqual(mindmap.yy.nodeType.RECT); }); it('MMP-8 should handle an id and type for a node definition', function () { - let str = `mindmap + const str = `mindmap root theId(child1)`; @@ -116,7 +104,7 @@ describe('when parsing a mindmap ', function () { expect(child.type).toEqual(mindmap.yy.nodeType.ROUNDED_RECT); }); it('MMP-9 should handle an id and type for a node definition', function () { - let str = `mindmap + const str = `mindmap root theId(child1)`; @@ -130,7 +118,7 @@ root expect(child.type).toEqual(mindmap.yy.nodeType.ROUNDED_RECT); }); it('MMP-10 multiple types (circle)', function () { - let str = `mindmap + const str = `mindmap root((the root)) `; @@ -142,7 +130,7 @@ root }); it('MMP-11 multiple types (cloud)', function () { - let str = `mindmap + const str = `mindmap root)the root( `; @@ -153,7 +141,7 @@ root expect(mm.type).toEqual(mindmap.yy.nodeType.CLOUD); }); it('MMP-12 multiple types (bang)', function () { - let str = `mindmap + const str = `mindmap root))the root(( `; @@ -165,7 +153,7 @@ root }); it('MMP-12-a multiple types (hexagon)', function () { - let str = `mindmap + const str = `mindmap root{{the root}} `; @@ -178,7 +166,7 @@ root }); describe('decorations', function () { it('MMP-13 should be possible to set an icon for the node', function () { - let str = `mindmap + const str = `mindmap root[The root] ::icon(bomb) `; @@ -192,7 +180,7 @@ root expect(mm.icon).toEqual('bomb'); }); it('MMP-14 should be possible to set classes for the node', function () { - let str = `mindmap + const str = `mindmap root[The root] :::m-4 p-8 `; @@ -206,7 +194,7 @@ root expect(mm.class).toEqual('m-4 p-8'); }); it('MMP-15 should be possible to set both classes and icon for the node', function () { - let str = `mindmap + const str = `mindmap root[The root] :::m-4 p-8 ::icon(bomb) @@ -222,7 +210,7 @@ root expect(mm.icon).toEqual('bomb'); }); it('MMP-16 should be possible to set both classes and icon for the node', function () { - let str = `mindmap + const str = `mindmap root[The root] ::icon(bomb) :::m-4 p-8 @@ -240,7 +228,7 @@ root }); describe('descriptions', function () { it('MMP-17 should be possible to use node syntax in the descriptions', function () { - let str = `mindmap + const str = `mindmap root["String containing []"] `; mindmap.parse(str); @@ -249,7 +237,7 @@ root expect(mm.descr).toEqual('String containing []'); }); it('MMP-18 should be possible to use node syntax in the descriptions in children', function () { - let str = `mindmap + const str = `mindmap root["String containing []"] child1["String containing ()"] `; @@ -261,7 +249,7 @@ root expect(mm.children[0].descr).toEqual('String containing ()'); }); it('MMP-19 should be possible to have a child after a class assignment', function () { - let str = `mindmap + const str = `mindmap root(Root) Child(Child) :::hot @@ -281,7 +269,7 @@ root }); }); it('MMP-20 should be possible to have meaningless empty rows in a mindmap abc124', function () { - let str = `mindmap + const str = `mindmap root(Root) Child(Child) a(a) @@ -300,7 +288,7 @@ root expect(child.children[1].nodeId).toEqual('b'); }); it('MMP-21 should be possible to have comments in a mindmap', function () { - let str = `mindmap + const str = `mindmap root(Root) Child(Child) a(a) @@ -321,7 +309,7 @@ root }); it('MMP-22 should be possible to have comments at the end of a line', function () { - let str = `mindmap + const str = `mindmap root(Root) Child(Child) a(a) %% This is a comment @@ -339,7 +327,7 @@ root expect(child.children[1].nodeId).toEqual('b'); }); it('MMP-23 Rows with only spaces should not interfere', function () { - let str = 'mindmap\nroot\n A\n \n\n B'; + const str = 'mindmap\nroot\n A\n \n\n B'; mindmap.parse(str); const mm = mindmap.yy.getMindmap(); expect(mm.nodeId).toEqual('root'); @@ -351,7 +339,7 @@ root expect(child2.nodeId).toEqual('B'); }); it('MMP-24 Handle rows above the mindmap declarations', function () { - let str = '\n \nmindmap\nroot\n A\n \n\n B'; + const str = '\n \nmindmap\nroot\n A\n \n\n B'; mindmap.parse(str); const mm = mindmap.yy.getMindmap(); expect(mm.nodeId).toEqual('root'); @@ -363,7 +351,7 @@ root expect(child2.nodeId).toEqual('B'); }); it('MMP-25 Handle rows above the mindmap declarations, no space', function () { - let str = '\n\n\nmindmap\nroot\n A\n \n\n B'; + const str = '\n\n\nmindmap\nroot\n A\n \n\n B'; mindmap.parse(str); const mm = mindmap.yy.getMindmap(); expect(mm.nodeId).toEqual('root'); From b71f4c7e5446b0512a56455f695349779e9123f3 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Sun, 28 Jan 2024 15:56:30 +0530 Subject: [PATCH 48/97] Add MindmapDB type --- packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts | 3 ++- packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts | 3 +++ 2 files changed, 5 insertions(+), 1 deletion(-) create mode 100644 packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts diff --git a/packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts b/packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts index b352144359..c5c7303c30 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts @@ -3,8 +3,9 @@ import mindmapParser from './parser/mindmap.jison'; import * as mindmapDb from './mindmapDb.js'; import mindmapRenderer from './mindmapRenderer.js'; import mindmapStyles from './styles.js'; +import type { DiagramDefinition } from '../../diagram-api/types.js'; -export const diagram = { +export const diagram: DiagramDefinition = { db: mindmapDb, renderer: mindmapRenderer, parser: mindmapParser, diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts b/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts new file mode 100644 index 0000000000..caec37d2c0 --- /dev/null +++ b/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts @@ -0,0 +1,3 @@ +import type * as mindmapDb from './mindmapDb.js'; + +export type MindmapDB = typeof mindmapDb; From f30c26485e02cbd697e2c8ac21967a57cece768d Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Sun, 28 Jan 2024 15:58:07 +0530 Subject: [PATCH 49/97] Cleanup svgDraw.js --- .../mermaid/src/diagrams/mindmap/svgDraw.js | 51 ------------------- 1 file changed, 51 deletions(-) diff --git a/packages/mermaid/src/diagrams/mindmap/svgDraw.js b/packages/mermaid/src/diagrams/mindmap/svgDraw.js index 2a4fc4b671..b065e8010f 100644 --- a/packages/mermaid/src/diagrams/mindmap/svgDraw.js +++ b/packages/mermaid/src/diagrams/mindmap/svgDraw.js @@ -1,54 +1,7 @@ -import { select } from 'd3'; import * as db from './mindmapDb.js'; import { createText } from '../../rendering-util/createText.js'; const MAX_SECTIONS = 12; -/** - * @param {string} text The text to be wrapped - * @param {number} width The max width of the text - */ -function wrap(text, width) { - text.each(function () { - var text = select(this), - words = text - .text() - .split(/(\s+|)/) - .reverse(), - word, - line = [], - lineHeight = 1.1, // ems - y = text.attr('y'), - dy = parseFloat(text.attr('dy')), - tspan = text - .text(null) - .append('tspan') - .attr('x', 0) - .attr('y', y) - .attr('dy', dy + 'em'); - for (let j = 0; j < words.length; j++) { - word = words[words.length - 1 - j]; - line.push(word); - tspan.text(line.join(' ').trim()); - if (tspan.node().getComputedTextLength() > width || word === '
    ') { - line.pop(); - tspan.text(line.join(' ').trim()); - if (word === '
    ') { - line = ['']; - } else { - line = [word]; - } - - tspan = text - .append('tspan') - .attr('x', 0) - .attr('y', y) - .attr('dy', lineHeight + 'em') - .text(word); - } - } - }); -} - const defaultBkg = function (elem, node, section) { const rd = 5; elem @@ -317,10 +270,6 @@ export const drawNode = function (elem, node, fullSection, conf) { break; } - // Position the node to its coordinate - // if (typeof node.x !== 'undefined' && typeof node.y !== 'undefined') { - // nodeElem.attr('transform', 'translate(' + node.x + ',' + node.y + ')'); - // } db.setElementForId(node.id, nodeElem); return node.height; }; From ba0bddf4178e1d48de5cc3c73ac52db5a23f05e8 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Sun, 28 Jan 2024 16:02:28 +0530 Subject: [PATCH 50/97] Add MermaidConfigWithDefaults --- packages/mermaid/src/config.ts | 4 ++-- packages/mermaid/src/config.type.ts | 5 +++++ packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts | 1 - 3 files changed, 7 insertions(+), 3 deletions(-) diff --git a/packages/mermaid/src/config.ts b/packages/mermaid/src/config.ts index ede3a568df..f1dccd251d 100644 --- a/packages/mermaid/src/config.ts +++ b/packages/mermaid/src/config.ts @@ -2,7 +2,7 @@ import assignWithDepth from './assignWithDepth.js'; import { log } from './logger.js'; import theme from './themes/index.js'; import config from './defaultConfig.js'; -import type { MermaidConfig } from './config.type.js'; +import type { MermaidConfig, MermaidConfigWithDefaults } from './config.type.js'; import { sanitizeDirective } from './utils/sanitizeDirective.js'; export const defaultConfig: MermaidConfig = Object.freeze(config); @@ -128,7 +128,7 @@ export const setConfig = (conf: MermaidConfig): MermaidConfig => { * * @returns The currentConfig */ -export const getConfig = (): MermaidConfig => { +export const getConfig = (): MermaidConfigWithDefaults => { return assignWithDepth({}, currentConfig); }; /** diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index 575f428ddd..7ca4b89d67 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -5,6 +5,8 @@ * and run json-schema-to-typescript to regenerate this file. */ +import { RequiredDeep } from 'type-fest'; + /** * Configuration options to pass to the `dompurify` library. */ @@ -165,6 +167,9 @@ export interface MermaidConfig { wrap?: boolean; fontSize?: number; } + +// I'd prefer this to be named MermaidConfig, so all the functions can use the shorter name. +export type MermaidConfigWithDefaults = RequiredDeep; /** * This interface was referenced by `MermaidConfig`'s JSON-Schema * via the `definition` "BaseDiagramConfig". diff --git a/packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts b/packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts index 7433f2b9ce..51f808ff44 100644 --- a/packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts +++ b/packages/mermaid/src/diagrams/sankey/sankeyRenderer.ts @@ -1,6 +1,5 @@ import type { Diagram } from '../../Diagram.js'; import { getConfig, defaultConfig } from '../../diagram-api/diagramAPI.js'; - import { select as d3select, scaleOrdinal as d3scaleOrdinal, From f069de54878637762a99bb4e787220e287e23940 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Sun, 28 Jan 2024 16:03:20 +0530 Subject: [PATCH 51/97] Convert MindmapDB.ts --- .../mermaid/src/diagrams/mindmap/mindmapDb.ts | 99 ++++++++++--------- 1 file changed, 52 insertions(+), 47 deletions(-) diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts b/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts index 4206a4a260..72c9968b62 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts @@ -1,19 +1,36 @@ import { getConfig } from '../../diagram-api/diagramAPI.js'; -import { sanitizeText as _sanitizeText } from '../../diagrams/common/common.js'; +import { sanitizeText } from '../../diagrams/common/common.js'; import { log } from '../../logger.js'; +import type { D3Element } from '../../mermaidAPI.js'; -export const sanitizeText = (text) => _sanitizeText(text, getConfig()); +export interface MindMapNode { + id: number; + nodeId: string; + level: number; + descr: string; + type: number; + children: MindMapNode[]; + width: number; + padding: number; + section?: number; + height?: number; + class?: string; + icon?: string; + x?: number; + y?: number; +} -let nodes = []; +let nodes: MindMapNode[] = []; let cnt = 0; -let elements = {}; +let elements: Record = {}; + export const clear = () => { nodes = []; cnt = 0; elements = {}; }; -const getParent = function (level) { +const getParent = function (level: number) { for (let i = nodes.length - 1; i >= 0; i--) { if (nodes[i].level < level) { return nodes[i]; @@ -26,31 +43,29 @@ const getParent = function (level) { export const getMindmap = () => { return nodes.length > 0 ? nodes[0] : null; }; -export const addNode = (level, id, descr, type) => { + +export const addNode = (level: number, id: string, descr: string, type: number) => { log.info('addNode', level, id, descr, type); const conf = getConfig(); + let padding: number = conf.mindmap?.padding ?? 10; + switch (type) { + case nodeType.ROUNDED_RECT: + case nodeType.RECT: + case nodeType.HEXAGON: + padding *= 2; + } + const node = { id: cnt++, - nodeId: sanitizeText(id), + nodeId: sanitizeText(id, conf), level, - descr: sanitizeText(descr), + descr: sanitizeText(descr, conf), type, children: [], - width: getConfig().mindmap.maxNodeWidth, - }; - switch (node.type) { - case nodeType.ROUNDED_RECT: - node.padding = 2 * conf.mindmap.padding; - break; - case nodeType.RECT: - node.padding = 2 * conf.mindmap.padding; - break; - case nodeType.HEXAGON: - node.padding = 2 * conf.mindmap.padding; - break; - default: - node.padding = conf.mindmap.padding; - } + width: conf.mindmap?.maxNodeWidth ?? 200, + padding, + } satisfies MindMapNode; + const parent = getParent(level); if (parent) { parent.children.push(node); @@ -62,16 +77,9 @@ export const addNode = (level, id, descr, type) => { nodes.push(node); } else { // Syntax error ... there can only bee one root - let error = new Error( + const error = new Error( 'There can be only one root. No parent could be found for ("' + node.descr + '")' ); - error.hash = { - text: 'branch ' + name, - token: 'branch ' + name, - line: '1', - loc: { first_line: 1, last_line: 1, first_column: 1, last_column: 1 }, - expected: ['"checkout ' + name + '"'], - }; throw error; } } @@ -88,7 +96,7 @@ export const nodeType = { HEXAGON: 6, }; -export const getType = (startStr, endStr) => { +export const getType = (startStr: string, endStr: string): number => { log.debug('In get type', startStr, endStr); switch (startStr) { case '[': @@ -108,21 +116,25 @@ export const getType = (startStr, endStr) => { } }; -export const setElementForId = (id, element) => { +export const setElementForId = (id: string, element: D3Element) => { elements[id] = element; }; -export const decorateNode = (decoration) => { +export const decorateNode = (decoration?: { class?: string; icon?: string }) => { + if (!decoration) { + return; + } + const config = getConfig(); const node = nodes[nodes.length - 1]; - if (decoration && decoration.icon) { - node.icon = sanitizeText(decoration.icon); + if (decoration.icon) { + node.icon = sanitizeText(decoration.icon, config); } - if (decoration && decoration.class) { - node.class = sanitizeText(decoration.class); + if (decoration.class) { + node.class = sanitizeText(decoration.class, config); } }; -export const type2Str = (type) => { +export const type2Str = (type: number) => { switch (type) { case nodeType.DEFAULT: return 'no-border'; @@ -143,13 +155,6 @@ export const type2Str = (type) => { } }; -export let parseError; -export const setErrorHandler = (handler) => { - parseError = handler; -}; - // Expose logger to grammar export const getLogger = () => log; - -export const getNodeById = (id) => nodes[id]; -export const getElementById = (id) => elements[id]; +export const getElementById = (id: string) => elements[id]; From d346a77e3c72e36a441bf271700744a0e381bedf Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Sun, 28 Jan 2024 16:03:37 +0530 Subject: [PATCH 52/97] Convert MindmapRenderer.ts --- .../src/diagrams/mindmap/mindmapRenderer.ts | 104 ++++++++---------- 1 file changed, 48 insertions(+), 56 deletions(-) diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts b/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts index 3fe9e1d510..6d0dc6067e 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts @@ -1,23 +1,21 @@ -/** Created by knut on 14-12-11. */ import { select } from 'd3'; import { log } from '../../logger.js'; import { getConfig } from '../../diagram-api/diagramAPI.js'; import { setupGraphViewbox } from '../../setupGraphViewbox.js'; import svgDraw from './svgDraw.js'; -import cytoscape from 'cytoscape/dist/cytoscape.umd.js'; +import cytoscape from 'cytoscape'; +// @ts-expect-error No types available import coseBilkent from 'cytoscape-cose-bilkent'; import * as db from './mindmapDb.js'; +import type { MermaidConfig, MermaidConfigWithDefaults } from '../../config.type.js'; +import type { Diagram } from '../../Diagram.js'; +import type { MindmapDB } from './mindmapTypes.js'; +import type { D3Element } from '../../mermaidAPI.js'; // Inject the layout algorithm into cytoscape cytoscape.use(coseBilkent); -/** - * @param {any} svg The svg element to draw the diagram onto - * @param {object} mindmap The mindmap data and hierarchy - * @param section - * @param {object} conf The configuration object - */ -function drawNodes(svg, mindmap, section, conf) { +function drawNodes(svg: D3Element, mindmap: db.MindMapNode, section: number, conf: MermaidConfig) { svgDraw.drawNode(svg, mindmap, section, conf); if (mindmap.children) { mindmap.children.forEach((child, index) => { @@ -26,11 +24,23 @@ function drawNodes(svg, mindmap, section, conf) { } } -/** - * @param edgesEl - * @param cy - */ -function drawEdges(edgesEl, cy) { +declare module 'cytoscape' { + interface EdgeSingular { + _private: { + bodyBounds: unknown; + rscratch: { + startX: number; + startY: number; + midX: number; + midY: number; + endX: number; + endY: number; + }; + }; + } +} + +function drawEdges(edgesEl: D3Element, cy: cytoscape.Core) { cy.edges().map((edge, id) => { const data = edge.data(); if (edge[0]._private.bodyBounds) { @@ -47,17 +57,11 @@ function drawEdges(edgesEl, cy) { }); } -/** - * @param mindmap The mindmap data and hierarchy - * @param cy - * @param conf The configuration object - * @param level - */ -function addNodes(mindmap, cy, conf, level) { +function addNodes(mindmap: db.MindMapNode, cy: cytoscape.Core, conf: MermaidConfig, level: number) { cy.add({ group: 'nodes', data: { - id: mindmap.id, + id: mindmap.id.toString(), labelText: mindmap.descr, height: mindmap.height, width: mindmap.width, @@ -67,8 +71,8 @@ function addNodes(mindmap, cy, conf, level) { type: mindmap.type, }, position: { - x: mindmap.x, - y: mindmap.y, + x: mindmap.x!, + y: mindmap.y!, }, }); if (mindmap.children) { @@ -88,12 +92,10 @@ function addNodes(mindmap, cy, conf, level) { } } -/** - * @param node - * @param conf - * @param cy - */ -function layoutMindmap(node, conf) { +function layoutMindmap( + node: db.MindMapNode, + conf: MermaidConfigWithDefaults +): Promise { return new Promise((resolve) => { // Add temporary render element const renderEl = select('body').append('div').attr('id', 'cy').attr('style', 'display:none'); @@ -122,8 +124,8 @@ function layoutMindmap(node, conf) { cy.layout({ name: 'cose-bilkent', + // @ts-ignore Types for cose-bilkent are not correct? quality: 'proof', - // headless: true, styleEnabled: false, animate: false, }).run(); @@ -133,13 +135,8 @@ function layoutMindmap(node, conf) { }); }); } -/** - * @param node - * @param cy - * @param positionedMindmap - * @param conf - */ -function positionNodes(cy) { + +function positionNodes(cy: cytoscape.Core) { cy.nodes().map((node, id) => { const data = node.data(); data.x = node.position().x; @@ -155,38 +152,33 @@ function positionNodes(cy) { }); } -/** - * Draws a an info picture in the tag with id: id based on the graph definition in text. - * - * @param {any} text - * @param {any} id - * @param {any} version - * @param diagObj - */ - -export const draw = async (text, id, version, diagObj) => { +export const draw = async (text: string, id: string, version: string, diagObj: Diagram) => { const conf = getConfig(); conf.htmlLabels = false; log.debug('Rendering mindmap diagram\n' + text, diagObj.parser); - const securityLevel = getConfig().securityLevel; + const securityLevel = conf.securityLevel; // Handle root and Document for when rendering in sandbox mode - let sandboxElement; + // eslint-disable-next-line @typescript-eslint/no-explicit-any + let sandboxElement: any; if (securityLevel === 'sandbox') { sandboxElement = select('#i' + id); } - const root = + // eslint-disable-next-line @typescript-eslint/no-explicit-any + const root: any = securityLevel === 'sandbox' ? select(sandboxElement.nodes()[0].contentDocument.body) : select('body'); - // Parse the graph definition const svg = root.select('#' + id); svg.append('g'); - const mm = diagObj.db.getMindmap(); + const mm = (diagObj.db as MindmapDB).getMindmap(); + if (!mm) { + return; + } // Draw the graph and start with drawing the nodes without proper position // this gives us the size of the nodes and we can set the positions later @@ -201,9 +193,9 @@ export const draw = async (text, id, version, diagObj) => { const cy = await layoutMindmap(mm, conf); - // // After this we can draw, first the edges and the then nodes with the correct position - drawEdges(edgesElem, cy, conf); - positionNodes(cy, conf); + // After this we can draw, first the edges and the then nodes with the correct position + drawEdges(edgesElem, cy); + positionNodes(cy); // Setup the view box and size of the svg element setupGraphViewbox(undefined, svg, conf.mindmap.padding, conf.mindmap.useMaxWidth); From e1a23f10df548a13844c600540d4ae9d0e9df7d5 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Sun, 28 Jan 2024 21:43:03 +0530 Subject: [PATCH 53/97] chore: Fix config type --- docs/config/setup/modules/config.md | 36 ++++++++++++------- docs/config/setup/modules/mermaidAPI.md | 2 +- packages/mermaid/src/config.ts | 6 +++- packages/mermaid/src/config.type.ts | 5 --- .../src/diagrams/mindmap/mindmapRenderer.ts | 3 +- 5 files changed, 31 insertions(+), 21 deletions(-) diff --git a/docs/config/setup/modules/config.md b/docs/config/setup/modules/config.md index f1de64e2df..afe0af4567 100644 --- a/docs/config/setup/modules/config.md +++ b/docs/config/setup/modules/config.md @@ -6,6 +6,16 @@ # Module: config +## Type Aliases + +### MermaidConfigWithDefaults + +Ƭ **MermaidConfigWithDefaults**: `RequiredDeep`<`MermaidConfig`> + +#### Defined in + +[config.ts:10](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L10) + ## Variables ### defaultConfig @@ -14,7 +24,7 @@ #### Defined in -[config.ts:8](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L8) +[config.ts:12](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L12) ## Functions @@ -36,13 +46,13 @@ Pushes in a directive to the configuration #### Defined in -[config.ts:188](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L188) +[config.ts:192](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L192) --- ### getConfig -▸ **getConfig**(): `MermaidConfig` +▸ **getConfig**(): `RequiredObjectDeep`<`MermaidConfig`> ## getConfig @@ -54,13 +64,13 @@ Pushes in a directive to the configuration #### Returns -`MermaidConfig` +`RequiredObjectDeep`<`MermaidConfig`> The currentConfig #### Defined in -[config.ts:131](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L131) +[config.ts:135](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L135) --- @@ -84,7 +94,7 @@ The siteConfig #### Defined in -[config.ts:96](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L96) +[config.ts:100](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L100) --- @@ -118,7 +128,7 @@ The siteConfig #### Defined in -[config.ts:218](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L218) +[config.ts:222](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L222) --- @@ -147,7 +157,7 @@ options in-place #### Defined in -[config.ts:146](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L146) +[config.ts:150](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L150) --- @@ -167,7 +177,7 @@ options in-place #### Defined in -[config.ts:75](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L75) +[config.ts:79](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L79) --- @@ -199,7 +209,7 @@ The currentConfig merged with the sanitized conf #### Defined in -[config.ts:113](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L113) +[config.ts:117](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L117) --- @@ -232,7 +242,7 @@ The new siteConfig #### Defined in -[config.ts:61](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L61) +[config.ts:65](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L65) --- @@ -253,7 +263,7 @@ The new siteConfig #### Defined in -[config.ts:15](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L15) +[config.ts:19](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L19) --- @@ -273,4 +283,4 @@ The new siteConfig #### Defined in -[config.ts:79](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L79) +[config.ts:83](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/config.ts#L83) diff --git a/docs/config/setup/modules/mermaidAPI.md b/docs/config/setup/modules/mermaidAPI.md index a1992c2254..0fa7dec02c 100644 --- a/docs/config/setup/modules/mermaidAPI.md +++ b/docs/config/setup/modules/mermaidAPI.md @@ -31,7 +31,7 @@ Renames and re-exports [mermaidAPI](mermaidAPI.md#mermaidapi) ### mermaidAPI -• `Const` **mermaidAPI**: `Readonly`<{ `defaultConfig`: `MermaidConfig` = configApi.defaultConfig; `getConfig`: () => `MermaidConfig` = configApi.getConfig; `getDiagramFromText`: (`text`: `string`, `metadata`: `Pick`<`DiagramMetadata`, `"title"`>) => `Promise`<`Diagram`> ; `getSiteConfig`: () => `MermaidConfig` = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`options`: `MermaidConfig`) => `void` ; `parse`: (`text`: `string`, `parseOptions?`: [`ParseOptions`](../interfaces/mermaidAPI.ParseOptions.md)) => `Promise`<`boolean`> ; `render`: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`) => `Promise`<[`RenderResult`](../interfaces/mermaidAPI.RenderResult.md)> ; `reset`: () => `void` ; `setConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.setConfig; `updateSiteConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.updateSiteConfig }> +• `Const` **mermaidAPI**: `Readonly`<{ `defaultConfig`: `MermaidConfig` = configApi.defaultConfig; `getConfig`: () => `RequiredObjectDeep`<`MermaidConfig`> = configApi.getConfig; `getDiagramFromText`: (`text`: `string`, `metadata`: `Pick`<`DiagramMetadata`, `"title"`>) => `Promise`<`Diagram`> ; `getSiteConfig`: () => `MermaidConfig` = configApi.getSiteConfig; `globalReset`: () => `void` ; `initialize`: (`options`: `MermaidConfig`) => `void` ; `parse`: (`text`: `string`, `parseOptions?`: [`ParseOptions`](../interfaces/mermaidAPI.ParseOptions.md)) => `Promise`<`boolean`> ; `render`: (`id`: `string`, `text`: `string`, `svgContainingElement?`: `Element`) => `Promise`<[`RenderResult`](../interfaces/mermaidAPI.RenderResult.md)> ; `reset`: () => `void` ; `setConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.setConfig; `updateSiteConfig`: (`conf`: `MermaidConfig`) => `MermaidConfig` = configApi.updateSiteConfig }> ## mermaidAPI configuration defaults diff --git a/packages/mermaid/src/config.ts b/packages/mermaid/src/config.ts index f1dccd251d..f117881265 100644 --- a/packages/mermaid/src/config.ts +++ b/packages/mermaid/src/config.ts @@ -2,8 +2,12 @@ import assignWithDepth from './assignWithDepth.js'; import { log } from './logger.js'; import theme from './themes/index.js'; import config from './defaultConfig.js'; -import type { MermaidConfig, MermaidConfigWithDefaults } from './config.type.js'; +import type { MermaidConfig } from './config.type.js'; import { sanitizeDirective } from './utils/sanitizeDirective.js'; +import type { RequiredDeep } from 'type-fest'; + +// I'd prefer this to be named MermaidConfig, so all the functions can use the shorter name. +export type MermaidConfigWithDefaults = RequiredDeep; export const defaultConfig: MermaidConfig = Object.freeze(config); diff --git a/packages/mermaid/src/config.type.ts b/packages/mermaid/src/config.type.ts index 7ca4b89d67..575f428ddd 100644 --- a/packages/mermaid/src/config.type.ts +++ b/packages/mermaid/src/config.type.ts @@ -5,8 +5,6 @@ * and run json-schema-to-typescript to regenerate this file. */ -import { RequiredDeep } from 'type-fest'; - /** * Configuration options to pass to the `dompurify` library. */ @@ -167,9 +165,6 @@ export interface MermaidConfig { wrap?: boolean; fontSize?: number; } - -// I'd prefer this to be named MermaidConfig, so all the functions can use the shorter name. -export type MermaidConfigWithDefaults = RequiredDeep; /** * This interface was referenced by `MermaidConfig`'s JSON-Schema * via the `definition` "BaseDiagramConfig". diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts b/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts index 6d0dc6067e..2a8fabd4f3 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts @@ -7,10 +7,11 @@ import cytoscape from 'cytoscape'; // @ts-expect-error No types available import coseBilkent from 'cytoscape-cose-bilkent'; import * as db from './mindmapDb.js'; -import type { MermaidConfig, MermaidConfigWithDefaults } from '../../config.type.js'; +import type { MermaidConfig } from '../../config.type.js'; import type { Diagram } from '../../Diagram.js'; import type { MindmapDB } from './mindmapTypes.js'; import type { D3Element } from '../../mermaidAPI.js'; +import type { MermaidConfigWithDefaults } from '../../config.js'; // Inject the layout algorithm into cytoscape cytoscape.use(coseBilkent); From 9651d0c2da4799713fbbded20e34550cc9f2af44 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Mon, 29 Jan 2024 10:45:47 +0530 Subject: [PATCH 54/97] refactor: Fix types and imports --- package.json | 5 ++ packages/mermaid-example-diagram/package.json | 7 +-- packages/mermaid/package.json | 3 +- .../diagrams/mindmap/mindmap-definition.ts | 16 +++--- .../src/diagrams/mindmap/mindmap.spec.ts | 2 +- .../mermaid/src/diagrams/mindmap/mindmapDb.ts | 32 +++++------ .../src/diagrams/mindmap/mindmapRenderer.ts | 17 +++--- .../src/diagrams/mindmap/mindmapTypes.ts | 19 ++++++- patches/cytoscape@3.28.1.patch | 20 +++++++ pnpm-lock.yaml | 57 +++++-------------- 10 files changed, 90 insertions(+), 88 deletions(-) create mode 100644 patches/cytoscape@3.28.1.patch diff --git a/package.json b/package.json index 441484218d..4a5a56aaef 100644 --- a/package.json +++ b/package.json @@ -127,5 +127,10 @@ }, "nyc": { "report-dir": "coverage/cypress" + }, + "pnpm": { + "patchedDependencies": { + "cytoscape@3.28.1": "patches/cytoscape@3.28.1.patch" + } } } diff --git a/packages/mermaid-example-diagram/package.json b/packages/mermaid-example-diagram/package.json index dc468a6c73..63e8aadea9 100644 --- a/packages/mermaid-example-diagram/package.json +++ b/packages/mermaid-example-diagram/package.json @@ -39,15 +39,10 @@ }, "dependencies": { "@braintree/sanitize-url": "^6.0.1", - "cytoscape": "^3.23.0", - "cytoscape-cose-bilkent": "^4.1.0", - "cytoscape-fcose": "^2.1.0", "d3": "^7.0.0", - "khroma": "^2.0.0", - "non-layered-tidy-tree-layout": "^2.0.2" + "khroma": "^2.0.0" }, "devDependencies": { - "@types/cytoscape": "^3.19.9", "concurrently": "^8.0.0", "rimraf": "^5.0.0", "mermaid": "workspace:*" diff --git a/packages/mermaid/package.json b/packages/mermaid/package.json index 4557506afd..471a11fd32 100644 --- a/packages/mermaid/package.json +++ b/packages/mermaid/package.json @@ -62,9 +62,8 @@ "@braintree/sanitize-url": "^6.0.1", "@types/d3-scale": "^4.0.3", "@types/d3-scale-chromatic": "^3.0.0", - "cytoscape": "^3.23.0", + "cytoscape": "^3.28.1", "cytoscape-cose-bilkent": "^4.1.0", - "cytoscape-fcose": "^2.1.0", "d3": "^7.4.0", "d3-sankey": "^0.12.3", "dagre-d3-es": "7.0.10", diff --git a/packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts b/packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts index c5c7303c30..66b44b4f9f 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts @@ -1,13 +1,13 @@ // @ts-ignore: JISON doesn't support types -import mindmapParser from './parser/mindmap.jison'; -import * as mindmapDb from './mindmapDb.js'; -import mindmapRenderer from './mindmapRenderer.js'; -import mindmapStyles from './styles.js'; +import parser from './parser/mindmap.jison'; +import db from './mindmapDb.js'; +import renderer from './mindmapRenderer.js'; +import styles from './styles.js'; import type { DiagramDefinition } from '../../diagram-api/types.js'; export const diagram: DiagramDefinition = { - db: mindmapDb, - renderer: mindmapRenderer, - parser: mindmapParser, - styles: mindmapStyles, + db, + renderer, + parser, + styles, }; diff --git a/packages/mermaid/src/diagrams/mindmap/mindmap.spec.ts b/packages/mermaid/src/diagrams/mindmap/mindmap.spec.ts index f6cc4304f8..2d67fc600a 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmap.spec.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmap.spec.ts @@ -1,6 +1,6 @@ // @ts-expect-error No types available for JISON import { parser as mindmap } from './parser/mindmap.jison'; -import * as mindmapDB from './mindmapDb.js'; +import mindmapDB from './mindmapDb.js'; // Todo fix utils functions for tests import { setLogLevel } from '../../diagram-api/diagramAPI.js'; diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts b/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts index 72c9968b62..eceabc52b9 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts @@ -2,23 +2,7 @@ import { getConfig } from '../../diagram-api/diagramAPI.js'; import { sanitizeText } from '../../diagrams/common/common.js'; import { log } from '../../logger.js'; import type { D3Element } from '../../mermaidAPI.js'; - -export interface MindMapNode { - id: number; - nodeId: string; - level: number; - descr: string; - type: number; - children: MindMapNode[]; - width: number; - padding: number; - section?: number; - height?: number; - class?: string; - icon?: string; - x?: number; - y?: number; -} +import type { MindMapNode } from './mindmapTypes.js'; let nodes: MindMapNode[] = []; let cnt = 0; @@ -158,3 +142,17 @@ export const type2Str = (type: number) => { // Expose logger to grammar export const getLogger = () => log; export const getElementById = (id: string) => elements[id]; + +const db = { + clear, + addNode, + getMindmap, + nodeType, + setElementForId, + decorateNode, + type2Str, + getLogger, + getElementById, +} as const; + +export default db; diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts b/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts index 2a8fabd4f3..f4471b01da 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts @@ -6,17 +6,16 @@ import svgDraw from './svgDraw.js'; import cytoscape from 'cytoscape'; // @ts-expect-error No types available import coseBilkent from 'cytoscape-cose-bilkent'; -import * as db from './mindmapDb.js'; +import type { MindMapNode, MindmapDB } from './mindmapTypes.js'; import type { MermaidConfig } from '../../config.type.js'; import type { Diagram } from '../../Diagram.js'; -import type { MindmapDB } from './mindmapTypes.js'; import type { D3Element } from '../../mermaidAPI.js'; import type { MermaidConfigWithDefaults } from '../../config.js'; // Inject the layout algorithm into cytoscape cytoscape.use(coseBilkent); -function drawNodes(svg: D3Element, mindmap: db.MindMapNode, section: number, conf: MermaidConfig) { +function drawNodes(svg: D3Element, mindmap: MindMapNode, section: number, conf: MermaidConfig) { svgDraw.drawNode(svg, mindmap, section, conf); if (mindmap.children) { mindmap.children.forEach((child, index) => { @@ -58,7 +57,7 @@ function drawEdges(edgesEl: D3Element, cy: cytoscape.Core) { }); } -function addNodes(mindmap: db.MindMapNode, cy: cytoscape.Core, conf: MermaidConfig, level: number) { +function addNodes(mindmap: MindMapNode, cy: cytoscape.Core, conf: MermaidConfig, level: number) { cy.add({ group: 'nodes', data: { @@ -94,7 +93,7 @@ function addNodes(mindmap: db.MindMapNode, cy: cytoscape.Core, conf: MermaidConf } function layoutMindmap( - node: db.MindMapNode, + node: MindMapNode, conf: MermaidConfigWithDefaults ): Promise { return new Promise((resolve) => { @@ -137,7 +136,7 @@ function layoutMindmap( }); } -function positionNodes(cy: cytoscape.Core) { +function positionNodes(db: MindmapDB, cy: cytoscape.Core) { cy.nodes().map((node, id) => { const data = node.data(); data.x = node.position().x; @@ -155,7 +154,7 @@ function positionNodes(cy: cytoscape.Core) { export const draw = async (text: string, id: string, version: string, diagObj: Diagram) => { const conf = getConfig(); - + const db = diagObj.db as MindmapDB; conf.htmlLabels = false; log.debug('Rendering mindmap diagram\n' + text, diagObj.parser); @@ -176,7 +175,7 @@ export const draw = async (text: string, id: string, version: string, diagObj: D const svg = root.select('#' + id); svg.append('g'); - const mm = (diagObj.db as MindmapDB).getMindmap(); + const mm = db.getMindmap(); if (!mm) { return; } @@ -196,7 +195,7 @@ export const draw = async (text: string, id: string, version: string, diagObj: D // After this we can draw, first the edges and the then nodes with the correct position drawEdges(edgesElem, cy); - positionNodes(cy); + positionNodes(db, cy); // Setup the view box and size of the svg element setupGraphViewbox(undefined, svg, conf.mindmap.padding, conf.mindmap.useMaxWidth); diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts b/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts index caec37d2c0..28ec37c391 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts @@ -1,3 +1,20 @@ -import type * as mindmapDb from './mindmapDb.js'; +import type mindmapDb from './mindmapDb.js'; + +export interface MindMapNode { + id: number; + nodeId: string; + level: number; + descr: string; + type: number; + children: MindMapNode[]; + width: number; + padding: number; + section?: number; + height?: number; + class?: string; + icon?: string; + x?: number; + y?: number; +} export type MindmapDB = typeof mindmapDb; diff --git a/patches/cytoscape@3.28.1.patch b/patches/cytoscape@3.28.1.patch new file mode 100644 index 0000000000..d92163a318 --- /dev/null +++ b/patches/cytoscape@3.28.1.patch @@ -0,0 +1,20 @@ +diff --git a/package.json b/package.json +index f2f77fa79c99382b079f4051ed51eafe8d2379c8..0bfddf55394e86f3a386eb7ab681369d410bae07 100644 +--- a/package.json ++++ b/package.json +@@ -30,7 +30,15 @@ + "engines": { + "node": ">=0.10" + }, ++ "exports": { ++ ".": { ++ "import": "./dist/cytoscape.umd.js", ++ "default": "./dist/cytoscape.cjs.js" ++ }, ++ "./*": "./*" ++ }, + "main": "dist/cytoscape.cjs.js", ++ "module": "dist/cytoscape.umd.js", + "unpkg": "dist/cytoscape.min.js", + "jsdelivr": "dist/cytoscape.min.js", + "scripts": { diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 5d950edefc..1312ff7c52 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -4,6 +4,11 @@ settings: autoInstallPeers: true excludeLinksFromLockfile: false +patchedDependencies: + cytoscape@3.28.1: + hash: claipxynndhyqyu2csninuoh5e + path: patches/cytoscape@3.28.1.patch + importers: .: @@ -201,14 +206,11 @@ importers: specifier: ^3.0.0 version: 3.0.0 cytoscape: - specifier: ^3.23.0 - version: 3.23.0 + specifier: ^3.28.1 + version: 3.28.1(patch_hash=claipxynndhyqyu2csninuoh5e) cytoscape-cose-bilkent: specifier: ^4.1.0 - version: 4.1.0(cytoscape@3.23.0) - cytoscape-fcose: - specifier: ^2.1.0 - version: 2.1.0(cytoscape@3.23.0) + version: 4.1.0(cytoscape@3.28.1) d3: specifier: ^7.4.0 version: 7.4.0 @@ -384,28 +386,13 @@ importers: '@braintree/sanitize-url': specifier: ^6.0.1 version: 6.0.2 - cytoscape: - specifier: ^3.23.0 - version: 3.23.0 - cytoscape-cose-bilkent: - specifier: ^4.1.0 - version: 4.1.0(cytoscape@3.23.0) - cytoscape-fcose: - specifier: ^2.1.0 - version: 2.1.0(cytoscape@3.23.0) d3: specifier: ^7.0.0 version: 7.0.0 khroma: specifier: ^2.0.0 version: 2.0.0 - non-layered-tidy-tree-layout: - specifier: ^2.0.2 - version: 2.0.2 devDependencies: - '@types/cytoscape': - specifier: ^3.19.9 - version: 3.19.9 concurrently: specifier: ^8.0.0 version: 8.0.0 @@ -7739,12 +7726,6 @@ packages: layout-base: 1.0.2 dev: false - /cose-base@2.2.0: - resolution: {integrity: sha512-AzlgcsCbUMymkADOJtQm3wO9S3ltPfYOFD5033keQn9NJzIbtnZj+UdBJe7DYml/8TdbtHJW3j58SOnKhWY/5g==} - dependencies: - layout-base: 2.0.1 - dev: false - /cosmiconfig-typescript-loader@4.4.0(@types/node@20.4.7)(cosmiconfig@8.2.0)(ts-node@10.9.1)(typescript@5.1.6): resolution: {integrity: sha512-BabizFdC3wBHhbI4kJh0VkQP9GkBfoHPydD0COMce1nJ1kJAB3F2TmJ/I7diULBKtmEWSwEbuN/KDtgnmUUVmw==} engines: {node: '>=v14.21.3'} @@ -8135,31 +8116,23 @@ packages: yauzl: 2.10.0 dev: true - /cytoscape-cose-bilkent@4.1.0(cytoscape@3.23.0): + /cytoscape-cose-bilkent@4.1.0(cytoscape@3.28.1): resolution: {integrity: sha512-wgQlVIUJF13Quxiv5e1gstZ08rnZj2XaLHGoFMYXz7SkNfCDOOteKBE6SYRfA9WxxI/iBc3ajfDoc6hb/MRAHQ==} peerDependencies: cytoscape: ^3.2.0 dependencies: cose-base: 1.0.3 - cytoscape: 3.23.0 - dev: false - - /cytoscape-fcose@2.1.0(cytoscape@3.23.0): - resolution: {integrity: sha512-Q3apPl66jf8/2sMsrCjNP247nbDkyIPjA9g5iPMMWNLZgP3/mn9aryF7EFY/oRPEpv7bKJ4jYmCoU5r5/qAc1Q==} - peerDependencies: - cytoscape: ^3.2.0 - dependencies: - cose-base: 2.2.0 - cytoscape: 3.23.0 + cytoscape: 3.28.1(patch_hash=claipxynndhyqyu2csninuoh5e) dev: false - /cytoscape@3.23.0: - resolution: {integrity: sha512-gRZqJj/1kiAVPkrVFvz/GccxsXhF3Qwpptl32gKKypO4IlqnKBjTOu+HbXtEggSGzC5KCaHp3/F7GgENrtsFkA==} + /cytoscape@3.28.1(patch_hash=claipxynndhyqyu2csninuoh5e): + resolution: {integrity: sha512-xyItz4O/4zp9/239wCcH8ZcFuuZooEeF8KHRmzjDfGdXsj3OG9MFSMA0pJE0uX3uCN/ygof6hHf4L7lst+JaDg==} engines: {node: '>=0.10'} dependencies: heap: 0.2.7 lodash: 4.17.21 dev: false + patched: true /d3-array@2.12.1: resolution: {integrity: sha512-B0ErZK/66mHtEsR1TkPEEkwdy+WDesimkM5gpZr5Dsg54BiTA5RXtYW5qTLIAcekaS9xfZrzBLF/OAkB3Qn1YQ==} @@ -12000,10 +11973,6 @@ packages: resolution: {integrity: sha512-8h2oVEZNktL4BH2JCOI90iD1yXwL6iNW7KcCKT2QZgQJR2vbqDsldCTPRU9NifTCqHZci57XvQQ15YTu+sTYPg==} dev: false - /layout-base@2.0.1: - resolution: {integrity: sha512-dp3s92+uNI1hWIpPGH3jK2kxE2lMjdXdr+DH8ynZHpd6PUlH6x6cbuXnoMmiNumznqaNO31xu9e79F0uuZ0JFg==} - dev: false - /lazy-ass@1.6.0: resolution: {integrity: sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==} engines: {node: '> 0.8'} From cffac848ead7cc3250db2f79cd09bce7a99739c1 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Mon, 29 Jan 2024 10:52:58 +0530 Subject: [PATCH 55/97] chore: Fix mindmapDb exports --- .../mermaid/src/diagrams/mindmap/mindmapDb.ts | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts b/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts index eceabc52b9..f5303ac29c 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts @@ -8,7 +8,7 @@ let nodes: MindMapNode[] = []; let cnt = 0; let elements: Record = {}; -export const clear = () => { +const clear = () => { nodes = []; cnt = 0; elements = {}; @@ -24,11 +24,11 @@ const getParent = function (level: number) { return null; }; -export const getMindmap = () => { +const getMindmap = () => { return nodes.length > 0 ? nodes[0] : null; }; -export const addNode = (level: number, id: string, descr: string, type: number) => { +const addNode = (level: number, id: string, descr: string, type: number) => { log.info('addNode', level, id, descr, type); const conf = getConfig(); let padding: number = conf.mindmap?.padding ?? 10; @@ -69,7 +69,7 @@ export const addNode = (level: number, id: string, descr: string, type: number) } }; -export const nodeType = { +const nodeType = { DEFAULT: 0, NO_BORDER: 0, ROUNDED_RECT: 1, @@ -80,7 +80,7 @@ export const nodeType = { HEXAGON: 6, }; -export const getType = (startStr: string, endStr: string): number => { +const getType = (startStr: string, endStr: string): number => { log.debug('In get type', startStr, endStr); switch (startStr) { case '[': @@ -100,11 +100,11 @@ export const getType = (startStr: string, endStr: string): number => { } }; -export const setElementForId = (id: string, element: D3Element) => { +const setElementForId = (id: string, element: D3Element) => { elements[id] = element; }; -export const decorateNode = (decoration?: { class?: string; icon?: string }) => { +const decorateNode = (decoration?: { class?: string; icon?: string }) => { if (!decoration) { return; } @@ -118,7 +118,7 @@ export const decorateNode = (decoration?: { class?: string; icon?: string }) => } }; -export const type2Str = (type: number) => { +const type2Str = (type: number) => { switch (type) { case nodeType.DEFAULT: return 'no-border'; @@ -140,14 +140,15 @@ export const type2Str = (type: number) => { }; // Expose logger to grammar -export const getLogger = () => log; -export const getElementById = (id: string) => elements[id]; +const getLogger = () => log; +const getElementById = (id: string) => elements[id]; const db = { clear, addNode, getMindmap, nodeType, + getType, setElementForId, decorateNode, type2Str, From 23d843b6d381aa42caf1ebb7f5f908e2c187608d Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Mon, 29 Jan 2024 11:21:12 +0530 Subject: [PATCH 56/97] refactor: Remove db import from svgDraw --- .../src/diagrams/mindmap/mindmapRenderer.ts | 18 ++++-- .../mermaid/src/diagrams/mindmap/svgDraw.js | 58 ++++++------------- 2 files changed, 29 insertions(+), 47 deletions(-) diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts b/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts index f4471b01da..04eed6b5a1 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts @@ -2,7 +2,7 @@ import { select } from 'd3'; import { log } from '../../logger.js'; import { getConfig } from '../../diagram-api/diagramAPI.js'; import { setupGraphViewbox } from '../../setupGraphViewbox.js'; -import svgDraw from './svgDraw.js'; +import { drawNode, positionNode } from './svgDraw.js'; import cytoscape from 'cytoscape'; // @ts-expect-error No types available import coseBilkent from 'cytoscape-cose-bilkent'; @@ -15,11 +15,17 @@ import type { MermaidConfigWithDefaults } from '../../config.js'; // Inject the layout algorithm into cytoscape cytoscape.use(coseBilkent); -function drawNodes(svg: D3Element, mindmap: MindMapNode, section: number, conf: MermaidConfig) { - svgDraw.drawNode(svg, mindmap, section, conf); +function drawNodes( + db: MindmapDB, + svg: D3Element, + mindmap: MindMapNode, + section: number, + conf: MermaidConfig +) { + drawNode(db, svg, mindmap, section, conf); if (mindmap.children) { mindmap.children.forEach((child, index) => { - drawNodes(svg, child, section < 0 ? index : section, conf); + drawNodes(db, svg, child, section < 0 ? index : section, conf); }); } } @@ -141,7 +147,7 @@ function positionNodes(db: MindmapDB, cy: cytoscape.Core) { const data = node.data(); data.x = node.position().x; data.y = node.position().y; - svgDraw.positionNode(data); + positionNode(db, data); const el = db.getElementById(data.nodeId); log.info('Id:', id, 'Position: (', node.position().x, ', ', node.position().y, ')', data); el.attr( @@ -187,7 +193,7 @@ export const draw = async (text: string, id: string, version: string, diagObj: D edgesElem.attr('class', 'mindmap-edges'); const nodesElem = svg.append('g'); nodesElem.attr('class', 'mindmap-nodes'); - drawNodes(nodesElem, mm, -1, conf); + drawNodes(db, nodesElem, mm, -1, conf); // Next step is to layout the mindmap, giving each node a position diff --git a/packages/mermaid/src/diagrams/mindmap/svgDraw.js b/packages/mermaid/src/diagrams/mindmap/svgDraw.js index b065e8010f..8d3340c6e6 100644 --- a/packages/mermaid/src/diagrams/mindmap/svgDraw.js +++ b/packages/mermaid/src/diagrams/mindmap/svgDraw.js @@ -1,8 +1,7 @@ -import * as db from './mindmapDb.js'; import { createText } from '../../rendering-util/createText.js'; const MAX_SECTIONS = 12; -const defaultBkg = function (elem, node, section) { +const defaultBkg = function (db, elem, node, section) { const rd = 5; elem .append('path') @@ -24,7 +23,7 @@ const defaultBkg = function (elem, node, section) { .attr('y2', node.height); }; -const rectBkg = function (elem, node) { +const rectBkg = function (db, elem, node) { elem .append('rect') .attr('id', 'node-' + node.id) @@ -33,7 +32,7 @@ const rectBkg = function (elem, node) { .attr('width', node.width); }; -const cloudBkg = function (elem, node) { +const cloudBkg = function (db, elem, node) { const w = node.width; const h = node.height; const r1 = 0.15 * w; @@ -64,7 +63,7 @@ const cloudBkg = function (elem, node) { ); }; -const bangBkg = function (elem, node) { +const bangBkg = function (db, elem, node) { const w = node.width; const h = node.height; const r = 0.15 * w; @@ -96,7 +95,7 @@ const bangBkg = function (elem, node) { ); }; -const circleBkg = function (elem, node) { +const circleBkg = function (db, elem, node) { elem .append('circle') .attr('id', 'node-' + node.id) @@ -126,7 +125,7 @@ function insertPolygonShape(parent, w, h, points, node) { .attr('transform', 'translate(' + (node.width - w) / 2 + ', ' + h + ')'); } -const hexagonBkg = function (elem, node) { +const hexagonBkg = function (db, elem, node) { const h = node.height; const f = 4; const m = h / f; @@ -142,7 +141,7 @@ const hexagonBkg = function (elem, node) { const shapeSvg = insertPolygonShape(elem, w, h, points, node); }; -const roundedRectBkg = function (elem, node) { +const roundedRectBkg = function (db, elem, node) { elem .append('rect') .attr('id', 'node-' + node.id) @@ -154,13 +153,14 @@ const roundedRectBkg = function (elem, node) { }; /** + * @param {import('./mindmapTypes.js').MindmapDB} db The database * @param {object} elem The D3 dom element in which the node is to be added * @param {object} node The node to be added * @param fullSection * @param {object} conf The configuration object * @returns {number} The height nodes dom element */ -export const drawNode = function (elem, node, fullSection, conf) { +export const drawNode = function (db, elem, node, fullSection, conf) { const htmlLabels = conf.htmlLabels; const section = fullSection % (MAX_SECTIONS - 1); const nodeElem = elem.append('g'); @@ -247,26 +247,26 @@ export const drawNode = function (elem, node, fullSection, conf) { switch (node.type) { case db.nodeType.DEFAULT: - defaultBkg(bkgElem, node, section, conf); + defaultBkg(db, bkgElem, node, section, conf); break; case db.nodeType.ROUNDED_RECT: - roundedRectBkg(bkgElem, node, section, conf); + roundedRectBkg(db, bkgElem, node, section, conf); break; case db.nodeType.RECT: - rectBkg(bkgElem, node, section, conf); + rectBkg(db, bkgElem, node, section, conf); break; case db.nodeType.CIRCLE: bkgElem.attr('transform', 'translate(' + node.width / 2 + ', ' + +node.height / 2 + ')'); - circleBkg(bkgElem, node, section, conf); + circleBkg(db, bkgElem, node, section, conf); break; case db.nodeType.CLOUD: - cloudBkg(bkgElem, node, section, conf); + cloudBkg(db, bkgElem, node, section, conf); break; case db.nodeType.BANG: - bangBkg(bkgElem, node, section, conf); + bangBkg(db, bkgElem, node, section, conf); break; case db.nodeType.HEXAGON: - hexagonBkg(bkgElem, node, section, conf); + hexagonBkg(db, bkgElem, node, section, conf); break; } @@ -274,29 +274,7 @@ export const drawNode = function (elem, node, fullSection, conf) { return node.height; }; -export const drawEdge = function drawEdge(edgesElem, mindmap, parent, depth, fullSection) { - const section = fullSection % (MAX_SECTIONS - 1); - const sx = parent.x + parent.width / 2; - const sy = parent.y + parent.height / 2; - const ex = mindmap.x + mindmap.width / 2; - const ey = mindmap.y + mindmap.height / 2; - const mx = ex > sx ? sx + Math.abs(sx - ex) / 2 : sx - Math.abs(sx - ex) / 2; - const my = ey > sy ? sy + Math.abs(sy - ey) / 2 : sy - Math.abs(sy - ey) / 2; - const qx = ex > sx ? Math.abs(sx - mx) / 2 + sx : -Math.abs(sx - mx) / 2 + sx; - const qy = ey > sy ? Math.abs(sy - my) / 2 + sy : -Math.abs(sy - my) / 2 + sy; - - edgesElem - .append('path') - .attr( - 'd', - parent.direction === 'TB' || parent.direction === 'BT' - ? `M${sx},${sy} Q${sx},${qy} ${mx},${my} T${ex},${ey}` - : `M${sx},${sy} Q${qx},${sy} ${mx},${my} T${ex},${ey}` - ) - .attr('class', 'edge section-edge-' + section + ' edge-depth-' + depth); -}; - -export const positionNode = function (node) { +export const positionNode = function (db, node) { const nodeElem = db.getElementById(node.id); const x = node.x || 0; @@ -304,5 +282,3 @@ export const positionNode = function (node) { // Position the node to its coordinate nodeElem.attr('transform', 'translate(' + x + ',' + y + ')'); }; - -export default { drawNode, positionNode, drawEdge }; From bde6a9ff4f3fc636d2ad0df7e9076b6b1b7eedc5 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Mon, 29 Jan 2024 11:21:42 +0530 Subject: [PATCH 57/97] Rename styles.js --- packages/mermaid/src/diagrams/mindmap/{styles.js => styles.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/mermaid/src/diagrams/mindmap/{styles.js => styles.ts} (100%) diff --git a/packages/mermaid/src/diagrams/mindmap/styles.js b/packages/mermaid/src/diagrams/mindmap/styles.ts similarity index 100% rename from packages/mermaid/src/diagrams/mindmap/styles.js rename to packages/mermaid/src/diagrams/mindmap/styles.ts From 13e052ff8175bb8a10899b77e6b246846f0f9284 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Mon, 29 Jan 2024 11:26:10 +0530 Subject: [PATCH 58/97] Fix styles.ts --- packages/mermaid/src/diagrams/mindmap/styles.ts | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/packages/mermaid/src/diagrams/mindmap/styles.ts b/packages/mermaid/src/diagrams/mindmap/styles.ts index 863522fdf7..cf435a721a 100644 --- a/packages/mermaid/src/diagrams/mindmap/styles.ts +++ b/packages/mermaid/src/diagrams/mindmap/styles.ts @@ -1,6 +1,7 @@ +// @ts-expect-error Incorrect khroma types import { darken, lighten, isDark } from 'khroma'; -const genSections = (options) => { +const genSections = (options: any) => { let sections = ''; for (let i = 0; i < options.THEME_COLOR_LIMIT; i++) { @@ -49,7 +50,8 @@ const genSections = (options) => { return sections; }; -const getStyles = (options) => +// TODO: These options seem incorrect. +const getStyles = (options: any) => ` .edge { stroke-width: 3; From 75ec719257b58f930b7ae33138fff94501608638 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Mon, 29 Jan 2024 11:31:22 +0530 Subject: [PATCH 59/97] Rename svgDraw.js --- packages/mermaid/src/diagrams/mindmap/{svgDraw.js => svgDraw.ts} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename packages/mermaid/src/diagrams/mindmap/{svgDraw.js => svgDraw.ts} (100%) diff --git a/packages/mermaid/src/diagrams/mindmap/svgDraw.js b/packages/mermaid/src/diagrams/mindmap/svgDraw.ts similarity index 100% rename from packages/mermaid/src/diagrams/mindmap/svgDraw.js rename to packages/mermaid/src/diagrams/mindmap/svgDraw.ts From b51d8ff7ba4cf9714903a60d8c703b10b0f6ca59 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Mon, 29 Jan 2024 12:16:21 +0530 Subject: [PATCH 60/97] Convert svgDraw.ts --- .../mermaid/src/diagrams/mindmap/mindmapDb.ts | 16 ++--- .../src/diagrams/mindmap/mindmapRenderer.ts | 12 ++-- .../src/diagrams/mindmap/mindmapTypes.ts | 6 +- .../mermaid/src/diagrams/mindmap/svgDraw.ts | 60 ++++++++++--------- 4 files changed, 51 insertions(+), 43 deletions(-) diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts b/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts index f5303ac29c..c0fdd12574 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts @@ -1,12 +1,12 @@ import { getConfig } from '../../diagram-api/diagramAPI.js'; +import type { D3Element } from '../../mermaidAPI.js'; import { sanitizeText } from '../../diagrams/common/common.js'; import { log } from '../../logger.js'; -import type { D3Element } from '../../mermaidAPI.js'; -import type { MindMapNode } from './mindmapTypes.js'; +import type { MindmapNode } from './mindmapTypes.js'; -let nodes: MindMapNode[] = []; +let nodes: MindmapNode[] = []; let cnt = 0; -let elements: Record = {}; +let elements: Record = {}; const clear = () => { nodes = []; @@ -14,7 +14,7 @@ const clear = () => { elements = {}; }; -const getParent = function (level: number) { +const getParent = function(level: number) { for (let i = nodes.length - 1; i >= 0; i--) { if (nodes[i].level < level) { return nodes[i]; @@ -48,7 +48,7 @@ const addNode = (level: number, id: string, descr: string, type: number) => { children: [], width: conf.mindmap?.maxNodeWidth ?? 200, padding, - } satisfies MindMapNode; + } satisfies MindmapNode; const parent = getParent(level); if (parent) { @@ -100,7 +100,7 @@ const getType = (startStr: string, endStr: string): number => { } }; -const setElementForId = (id: string, element: D3Element) => { +const setElementForId = (id: number, element: D3Element) => { elements[id] = element; }; @@ -141,7 +141,7 @@ const type2Str = (type: number) => { // Expose logger to grammar const getLogger = () => log; -const getElementById = (id: string) => elements[id]; +const getElementById = (id: number) => elements[id]; const db = { clear, diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts b/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts index 04eed6b5a1..6b98715675 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts @@ -6,7 +6,7 @@ import { drawNode, positionNode } from './svgDraw.js'; import cytoscape from 'cytoscape'; // @ts-expect-error No types available import coseBilkent from 'cytoscape-cose-bilkent'; -import type { MindMapNode, MindmapDB } from './mindmapTypes.js'; +import type { MindmapNode, MindmapDB, FilledMindMapNode } from './mindmapTypes.js'; import type { MermaidConfig } from '../../config.type.js'; import type { Diagram } from '../../Diagram.js'; import type { D3Element } from '../../mermaidAPI.js'; @@ -18,9 +18,9 @@ cytoscape.use(coseBilkent); function drawNodes( db: MindmapDB, svg: D3Element, - mindmap: MindMapNode, + mindmap: FilledMindMapNode, section: number, - conf: MermaidConfig + conf: MermaidConfigWithDefaults ) { drawNode(db, svg, mindmap, section, conf); if (mindmap.children) { @@ -63,7 +63,7 @@ function drawEdges(edgesEl: D3Element, cy: cytoscape.Core) { }); } -function addNodes(mindmap: MindMapNode, cy: cytoscape.Core, conf: MermaidConfig, level: number) { +function addNodes(mindmap: MindmapNode, cy: cytoscape.Core, conf: MermaidConfig, level: number) { cy.add({ group: 'nodes', data: { @@ -99,7 +99,7 @@ function addNodes(mindmap: MindMapNode, cy: cytoscape.Core, conf: MermaidConfig, } function layoutMindmap( - node: MindMapNode, + node: MindmapNode, conf: MermaidConfigWithDefaults ): Promise { return new Promise((resolve) => { @@ -193,7 +193,7 @@ export const draw = async (text: string, id: string, version: string, diagObj: D edgesElem.attr('class', 'mindmap-edges'); const nodesElem = svg.append('g'); nodesElem.attr('class', 'mindmap-nodes'); - drawNodes(db, nodesElem, mm, -1, conf); + drawNodes(db, nodesElem, mm as FilledMindMapNode, -1, conf); // Next step is to layout the mindmap, giving each node a position diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts b/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts index 28ec37c391..ced93ecacb 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts @@ -1,12 +1,13 @@ +import { RequiredDeep } from 'type-fest'; import type mindmapDb from './mindmapDb.js'; -export interface MindMapNode { +export interface MindmapNode { id: number; nodeId: string; level: number; descr: string; type: number; - children: MindMapNode[]; + children: MindmapNode[]; width: number; padding: number; section?: number; @@ -17,4 +18,5 @@ export interface MindMapNode { y?: number; } +export type FilledMindMapNode = RequiredDeep; export type MindmapDB = typeof mindmapDb; diff --git a/packages/mermaid/src/diagrams/mindmap/svgDraw.ts b/packages/mermaid/src/diagrams/mindmap/svgDraw.ts index 8d3340c6e6..5670a8f6c5 100644 --- a/packages/mermaid/src/diagrams/mindmap/svgDraw.ts +++ b/packages/mermaid/src/diagrams/mindmap/svgDraw.ts @@ -1,7 +1,13 @@ +import type { D3Element } from '../../mermaidAPI.js'; import { createText } from '../../rendering-util/createText.js'; +import type { FilledMindMapNode, MindmapDB } from './mindmapTypes.js'; +import { MermaidConfigWithDefaults } from '../../config.js'; +import { Point } from '../../types.js'; const MAX_SECTIONS = 12; -const defaultBkg = function (db, elem, node, section) { +type ShapeFunction = (db: MindmapDB, elem: D3Element, node: FilledMindMapNode, section?: number) => void; + +const defaultBkg: ShapeFunction = function(db, elem, node, section) { const rd = 5; elem .append('path') @@ -9,8 +15,7 @@ const defaultBkg = function (db, elem, node, section) { .attr('class', 'node-bkg node-' + db.type2Str(node.type)) .attr( 'd', - `M0 ${node.height - rd} v${-node.height + 2 * rd} q0,-5 5,-5 h${ - node.width - 2 * rd + `M0 ${node.height - rd} v${-node.height + 2 * rd} q0,-5 5,-5 h${node.width - 2 * rd } q5,0 5,5 v${node.height - rd} H0 Z` ); @@ -23,7 +28,7 @@ const defaultBkg = function (db, elem, node, section) { .attr('y2', node.height); }; -const rectBkg = function (db, elem, node) { +const rectBkg: ShapeFunction = function(db, elem, node) { elem .append('rect') .attr('id', 'node-' + node.id) @@ -32,7 +37,7 @@ const rectBkg = function (db, elem, node) { .attr('width', node.width); }; -const cloudBkg = function (db, elem, node) { +const cloudBkg: ShapeFunction = function(db, elem, node) { const w = node.width; const h = node.height; const r1 = 0.15 * w; @@ -63,7 +68,7 @@ const cloudBkg = function (db, elem, node) { ); }; -const bangBkg = function (db, elem, node) { +const bangBkg: ShapeFunction = function(db, elem, node) { const w = node.width; const h = node.height; const r = 0.15 * w; @@ -95,7 +100,7 @@ const bangBkg = function (db, elem, node) { ); }; -const circleBkg = function (db, elem, node) { +const circleBkg: ShapeFunction = function(db, elem, node) { elem .append('circle') .attr('id', 'node-' + node.id) @@ -111,13 +116,13 @@ const circleBkg = function (db, elem, node) { * @param points * @param node */ -function insertPolygonShape(parent, w, h, points, node) { +function insertPolygonShape(parent: D3Element, w: number, h: number, points: Point[], node: FilledMindMapNode) { return parent .insert('polygon', ':first-child') .attr( 'points', points - .map(function (d) { + .map(function(d) { return d.x + ',' + d.y; }) .join(' ') @@ -125,12 +130,12 @@ function insertPolygonShape(parent, w, h, points, node) { .attr('transform', 'translate(' + (node.width - w) / 2 + ', ' + h + ')'); } -const hexagonBkg = function (db, elem, node) { +const hexagonBkg: ShapeFunction = function(_db: MindmapDB, elem: D3Element, node: FilledMindMapNode) { const h = node.height; const f = 4; const m = h / f; const w = node.width - node.padding + 2 * m; - const points = [ + const points: Point[] = [ { x: m, y: 0 }, { x: w - m, y: 0 }, { x: w, y: -h / 2 }, @@ -138,10 +143,10 @@ const hexagonBkg = function (db, elem, node) { { x: m, y: -h }, { x: 0, y: -h / 2 }, ]; - const shapeSvg = insertPolygonShape(elem, w, h, points, node); + insertPolygonShape(elem, w, h, points, node); }; -const roundedRectBkg = function (db, elem, node) { +const roundedRectBkg: ShapeFunction = function(db, elem, node) { elem .append('rect') .attr('id', 'node-' + node.id) @@ -153,14 +158,14 @@ const roundedRectBkg = function (db, elem, node) { }; /** - * @param {import('./mindmapTypes.js').MindmapDB} db The database - * @param {object} elem The D3 dom element in which the node is to be added - * @param {object} node The node to be added + * @param db The database + * @param elem The D3 dom element in which the node is to be added + * @param node The node to be added * @param fullSection - * @param {object} conf The configuration object - * @returns {number} The height nodes dom element + * @param conf The configuration object + * @returns The height nodes dom element */ -export const drawNode = function (db, elem, node, fullSection, conf) { +export const drawNode = function(db: MindmapDB, elem: D3Element, node: FilledMindMapNode, fullSection: number, conf: MermaidConfigWithDefaults): number { const htmlLabels = conf.htmlLabels; const section = fullSection % (MAX_SECTIONS - 1); const nodeElem = elem.append('g'); @@ -190,6 +195,7 @@ export const drawNode = function (db, elem, node, fullSection, conf) { } // .call(wrap, node.width); const bbox = textElem.node().getBBox(); + // @ts-expect-error TODO: Check if fontSize can be string? const fontSize = conf.fontSize.replace ? conf.fontSize.replace('px', '') : conf.fontSize; node.height = bbox.height + fontSize * 1.1 * 0.5 + node.padding; node.width = bbox.width + 2 * node.padding; @@ -247,26 +253,26 @@ export const drawNode = function (db, elem, node, fullSection, conf) { switch (node.type) { case db.nodeType.DEFAULT: - defaultBkg(db, bkgElem, node, section, conf); + defaultBkg(db, bkgElem, node, section); break; case db.nodeType.ROUNDED_RECT: - roundedRectBkg(db, bkgElem, node, section, conf); + roundedRectBkg(db, bkgElem, node, section); break; case db.nodeType.RECT: - rectBkg(db, bkgElem, node, section, conf); + rectBkg(db, bkgElem, node, section); break; case db.nodeType.CIRCLE: bkgElem.attr('transform', 'translate(' + node.width / 2 + ', ' + +node.height / 2 + ')'); - circleBkg(db, bkgElem, node, section, conf); + circleBkg(db, bkgElem, node, section); break; case db.nodeType.CLOUD: - cloudBkg(db, bkgElem, node, section, conf); + cloudBkg(db, bkgElem, node, section); break; case db.nodeType.BANG: - bangBkg(db, bkgElem, node, section, conf); + bangBkg(db, bkgElem, node, section); break; case db.nodeType.HEXAGON: - hexagonBkg(db, bkgElem, node, section, conf); + hexagonBkg(db, bkgElem, node, section); break; } @@ -274,7 +280,7 @@ export const drawNode = function (db, elem, node, fullSection, conf) { return node.height; }; -export const positionNode = function (db, node) { +export const positionNode = function(db: MindmapDB, node: FilledMindMapNode) { const nodeElem = db.getElementById(node.id); const x = node.x || 0; From d21461fba03dcd01ec82d7b152b2bb1ac786d4b4 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Mon, 29 Jan 2024 12:27:17 +0530 Subject: [PATCH 61/97] Lint --- .../mermaid/src/diagrams/mindmap/mindmapDb.ts | 2 +- .../mermaid/src/diagrams/mindmap/svgDraw.ts | 48 ++++++++++++++----- 2 files changed, 36 insertions(+), 14 deletions(-) diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts b/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts index c0fdd12574..e2b453a0d5 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmapDb.ts @@ -14,7 +14,7 @@ const clear = () => { elements = {}; }; -const getParent = function(level: number) { +const getParent = function (level: number) { for (let i = nodes.length - 1; i >= 0; i--) { if (nodes[i].level < level) { return nodes[i]; diff --git a/packages/mermaid/src/diagrams/mindmap/svgDraw.ts b/packages/mermaid/src/diagrams/mindmap/svgDraw.ts index 5670a8f6c5..8fe47468b0 100644 --- a/packages/mermaid/src/diagrams/mindmap/svgDraw.ts +++ b/packages/mermaid/src/diagrams/mindmap/svgDraw.ts @@ -5,9 +5,14 @@ import { MermaidConfigWithDefaults } from '../../config.js'; import { Point } from '../../types.js'; const MAX_SECTIONS = 12; -type ShapeFunction = (db: MindmapDB, elem: D3Element, node: FilledMindMapNode, section?: number) => void; +type ShapeFunction = ( + db: MindmapDB, + elem: D3Element, + node: FilledMindMapNode, + section?: number +) => void; -const defaultBkg: ShapeFunction = function(db, elem, node, section) { +const defaultBkg: ShapeFunction = function (db, elem, node, section) { const rd = 5; elem .append('path') @@ -15,7 +20,8 @@ const defaultBkg: ShapeFunction = function(db, elem, node, section) { .attr('class', 'node-bkg node-' + db.type2Str(node.type)) .attr( 'd', - `M0 ${node.height - rd} v${-node.height + 2 * rd} q0,-5 5,-5 h${node.width - 2 * rd + `M0 ${node.height - rd} v${-node.height + 2 * rd} q0,-5 5,-5 h${ + node.width - 2 * rd } q5,0 5,5 v${node.height - rd} H0 Z` ); @@ -28,7 +34,7 @@ const defaultBkg: ShapeFunction = function(db, elem, node, section) { .attr('y2', node.height); }; -const rectBkg: ShapeFunction = function(db, elem, node) { +const rectBkg: ShapeFunction = function (db, elem, node) { elem .append('rect') .attr('id', 'node-' + node.id) @@ -37,7 +43,7 @@ const rectBkg: ShapeFunction = function(db, elem, node) { .attr('width', node.width); }; -const cloudBkg: ShapeFunction = function(db, elem, node) { +const cloudBkg: ShapeFunction = function (db, elem, node) { const w = node.width; const h = node.height; const r1 = 0.15 * w; @@ -68,7 +74,7 @@ const cloudBkg: ShapeFunction = function(db, elem, node) { ); }; -const bangBkg: ShapeFunction = function(db, elem, node) { +const bangBkg: ShapeFunction = function (db, elem, node) { const w = node.width; const h = node.height; const r = 0.15 * w; @@ -100,7 +106,7 @@ const bangBkg: ShapeFunction = function(db, elem, node) { ); }; -const circleBkg: ShapeFunction = function(db, elem, node) { +const circleBkg: ShapeFunction = function (db, elem, node) { elem .append('circle') .attr('id', 'node-' + node.id) @@ -116,13 +122,19 @@ const circleBkg: ShapeFunction = function(db, elem, node) { * @param points * @param node */ -function insertPolygonShape(parent: D3Element, w: number, h: number, points: Point[], node: FilledMindMapNode) { +function insertPolygonShape( + parent: D3Element, + w: number, + h: number, + points: Point[], + node: FilledMindMapNode +) { return parent .insert('polygon', ':first-child') .attr( 'points', points - .map(function(d) { + .map(function (d) { return d.x + ',' + d.y; }) .join(' ') @@ -130,7 +142,11 @@ function insertPolygonShape(parent: D3Element, w: number, h: number, points: Poi .attr('transform', 'translate(' + (node.width - w) / 2 + ', ' + h + ')'); } -const hexagonBkg: ShapeFunction = function(_db: MindmapDB, elem: D3Element, node: FilledMindMapNode) { +const hexagonBkg: ShapeFunction = function ( + _db: MindmapDB, + elem: D3Element, + node: FilledMindMapNode +) { const h = node.height; const f = 4; const m = h / f; @@ -146,7 +162,7 @@ const hexagonBkg: ShapeFunction = function(_db: MindmapDB, elem: D3Element, node insertPolygonShape(elem, w, h, points, node); }; -const roundedRectBkg: ShapeFunction = function(db, elem, node) { +const roundedRectBkg: ShapeFunction = function (db, elem, node) { elem .append('rect') .attr('id', 'node-' + node.id) @@ -165,7 +181,13 @@ const roundedRectBkg: ShapeFunction = function(db, elem, node) { * @param conf The configuration object * @returns The height nodes dom element */ -export const drawNode = function(db: MindmapDB, elem: D3Element, node: FilledMindMapNode, fullSection: number, conf: MermaidConfigWithDefaults): number { +export const drawNode = function ( + db: MindmapDB, + elem: D3Element, + node: FilledMindMapNode, + fullSection: number, + conf: MermaidConfigWithDefaults +): number { const htmlLabels = conf.htmlLabels; const section = fullSection % (MAX_SECTIONS - 1); const nodeElem = elem.append('g'); @@ -280,7 +302,7 @@ export const drawNode = function(db: MindmapDB, elem: D3Element, node: FilledMin return node.height; }; -export const positionNode = function(db: MindmapDB, node: FilledMindMapNode) { +export const positionNode = function (db: MindmapDB, node: FilledMindMapNode) { const nodeElem = db.getElementById(node.id); const x = node.x || 0; From 4c551b2acacff1648c1cf982b79edc7d72bc589e Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Mon, 29 Jan 2024 12:35:39 +0530 Subject: [PATCH 62/97] Lint --- .../src/diagrams/mindmap/mindmapTypes.ts | 2 +- .../mermaid/src/diagrams/mindmap/svgDraw.ts | 22 ++++++------------- 2 files changed, 8 insertions(+), 16 deletions(-) diff --git a/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts b/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts index ced93ecacb..e8350477a9 100644 --- a/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts +++ b/packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts @@ -1,4 +1,4 @@ -import { RequiredDeep } from 'type-fest'; +import type { RequiredDeep } from 'type-fest'; import type mindmapDb from './mindmapDb.js'; export interface MindmapNode { diff --git a/packages/mermaid/src/diagrams/mindmap/svgDraw.ts b/packages/mermaid/src/diagrams/mindmap/svgDraw.ts index 8fe47468b0..797a3fd990 100644 --- a/packages/mermaid/src/diagrams/mindmap/svgDraw.ts +++ b/packages/mermaid/src/diagrams/mindmap/svgDraw.ts @@ -1,8 +1,8 @@ import type { D3Element } from '../../mermaidAPI.js'; import { createText } from '../../rendering-util/createText.js'; import type { FilledMindMapNode, MindmapDB } from './mindmapTypes.js'; -import { MermaidConfigWithDefaults } from '../../config.js'; -import { Point } from '../../types.js'; +import type { MermaidConfigWithDefaults } from '../../config.js'; +import type { Point } from '../../types.js'; const MAX_SECTIONS = 12; type ShapeFunction = ( @@ -114,14 +114,6 @@ const circleBkg: ShapeFunction = function (db, elem, node) { .attr('r', node.width / 2); }; -/** - * - * @param parent - * @param w - * @param h - * @param points - * @param node - */ function insertPolygonShape( parent: D3Element, w: number, @@ -174,11 +166,11 @@ const roundedRectBkg: ShapeFunction = function (db, elem, node) { }; /** - * @param db The database - * @param elem The D3 dom element in which the node is to be added - * @param node The node to be added - * @param fullSection - * @param conf The configuration object + * @param db - The database + * @param elem - The D3 dom element in which the node is to be added + * @param node - The node to be added + * @param fullSection - ? + * @param conf - The configuration object * @returns The height nodes dom element */ export const drawNode = function ( From 1965f69a10f8c41863065e22e5fb1551762024ad Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Mon, 29 Jan 2024 15:29:26 +0100 Subject: [PATCH 63/97] Update packages/mermaid/src/schemas/config.schema.yaml Co-authored-by: Alois Klink --- packages/mermaid/src/schemas/config.schema.yaml | 2 -- 1 file changed, 2 deletions(-) diff --git a/packages/mermaid/src/schemas/config.schema.yaml b/packages/mermaid/src/schemas/config.schema.yaml index 7278d5a796..b7925d042f 100644 --- a/packages/mermaid/src/schemas/config.schema.yaml +++ b/packages/mermaid/src/schemas/config.schema.yaml @@ -2034,8 +2034,6 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file) type: object unevaluatedProperties: false properties: - useMaxWidth: - default: false padding: default: 8 From 37d7c7e2ddbc61d7473f2870f321e28df8513dbd Mon Sep 17 00:00:00 2001 From: Knut Sveidqvist Date: Mon, 29 Jan 2024 16:22:48 +0100 Subject: [PATCH 64/97] #3358 Second set of changes after review --- cypress/platform/knsv2.html | 16 +- demos/block.html | 126 +++++- docs/syntax/block.md | 44 +- .../src/dagre-wrapper/blockArrowHelper.js | 288 +++++++------ packages/mermaid/src/dagre-wrapper/edges.js | 95 +---- packages/mermaid/src/dagre-wrapper/nodes.js | 23 +- .../mermaid/src/dagre-wrapper/shapes/util.js | 4 +- .../mermaid/src/diagrams/block/blockDB.ts | 110 ++--- packages/mermaid/src/docs/syntax/block.md | 29 +- pnpm-lock.yaml | 398 +----------------- 10 files changed, 377 insertions(+), 756 deletions(-) diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index 8c6bf8a63b..847a8bf242 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -64,14 +64,14 @@
    -block-beta
    -columns 3
    -a:3
    -block:e:3
    -f
    -end
    -g
    -
    +      block-beta
    +  blockArrowId<["Label"]>(right)
    +  blockArrowId2<["Label"]>(left)
    +  blockArrowId3<["Label"]>(up)
    +  blockArrowId4<["Label"]>(down)
    +  blockArrowId5<["Label"]>(x)
    +  blockArrowId6<["Label"]>(y)
    +  blockArrowId6<["Label"]>(x, down)
         
     block-beta
    diff --git a/demos/block.html b/demos/block.html
    index 406350611a..03db61fad0 100644
    --- a/demos/block.html
    +++ b/demos/block.html
    @@ -3,23 +3,125 @@
       
         
         
    -    States Mermaid Quick Test Page
    +    Mermaid Block diagram demo page
         
    -    
       
     
       
         

    Block diagram demos

    -

    TCI IP

    -
    -  block-beta
    -      A>"rect_left_inv_arrow"]
    -      B{"diamond"}
    -      C{{"hexagon"}}
    +    
    +block-beta
    +columns 1
    +  db(("DB"))
    +  blockArrowId6<["   "]>(down)
    +  block:ID
    +    A
    +    B["A wide one in the middle"]
    +    C
    +  end
    +  space
    +  D
    +  ID --> D
    +  C --> D
    +  style B fill:#f9F,stroke:#333,stroke-width:4px
    +    
    +
    +block-beta
    +    A1["square"]
    +    B1("rounded")
    +    C1(("circle"))
    +    A2>"rect_left_inv_arrow"]
    +    B2{"diamond"}
    +    C2{{"hexagon"}}
    +    
    + +
    +block-beta
    +    A1(["stadium"])
    +    A2[["subroutine"]]
    +    B1[("cylinder")]
    +    C1>"surprise"]
    +    A3[/"lean right"/]
    +    B2[\"lean left"\]
    +    C2[/"trapezoid"\]
    +    D2[\"trapezoid"/]
    +    
    + +
    +block-beta
    +  block:e:4
    +    columns 2
    +      f
    +      g
    +  end
    +
    +    
    +
    +block-beta
    +  block:e:4
    +    columns 2
    +      f
    +      g
    +      h
    +  end
    +
    +    
    +
    +block-beta
    +  columns 3
    +  a:3
    +  block:e:3
    +      f
    +      g
    +  end
    +  h
    +  i
    +  j
    +
    +    
    +
    +block-beta
    +  columns 4
    +  a b c d
    +  block:e:4
    +    columns 2
    +      f
    +      g
    +      h
    +  end
    +  i:4
    +
    +    
    +
    +flowchart LR
    +  X-- "a label" -->z
    +    
    +
    +block-beta
    +columns 5
    +   A space B
    +   A --x B
    +    
    +
    +block-beta
    +columns 3
    +  a["A wide one"] b:2 c:2 d
    +    
    + +
    +block-beta
    +columns 3
    +  a b c
    +  e:3
    +  f g h
    +    
    + +
    +block-beta
    +
    +  A1:3
    +  A2:1
    +  A3