diff --git a/.gitignore b/.gitignore index 009c6dfac..6a1cc85e5 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,6 @@ stats/ **/contributor-names.json .pnpm-store .nyc_output + +demos/dev/** +!/demos/dev/example.html diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 307bd038b..02733ee2e 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -26,9 +26,14 @@ Install required packages: ```bash # npx is required for first install as volta support for pnpm is not added yet. npx pnpm install -pnpm test +pnpm test # run unit tests +pnpm dev # starts a dev server ``` +Open in your browser after starting the dev server. +You can also duplicate the `example.html` file in `demos/dev`, rename it and add your own mermaid code to it. +That will be served at . + ### Docker If you are using docker and docker-compose, you have self-documented `run` bash script, which is a convenient alias for docker-compose commands: diff --git a/cypress/integration/rendering/flowchart-v2.spec.js b/cypress/integration/rendering/flowchart-v2.spec.js index 0f4b079c9..aac4a31b1 100644 --- a/cypress/integration/rendering/flowchart-v2.spec.js +++ b/cypress/integration/rendering/flowchart-v2.spec.js @@ -449,7 +449,7 @@ flowchart TD { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } ); }); - it('65: text-color from classes', () => { + it('65-1: text-color from classes', () => { imgSnapshotTest( ` flowchart LR @@ -460,6 +460,31 @@ flowchart TD { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } ); }); + it('65-2: bold text from classes', () => { + imgSnapshotTest( + ` + flowchart + classDef cat fill:#f9d5e5, stroke:#233d4d,stroke-width:2px, font-weight:bold; + CS(A long bold text to be viewed):::cat + `, + { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } + ); + }); + it('65-3: bigger font from classes', () => { + imgSnapshotTest( + ` +flowchart + Node1:::class1 --> Node2:::class2 + Node1:::class1 --> Node3:::class2 + Node3 --> Node4((I am a circle)):::larger + + classDef class1 fill:lightblue + classDef class2 fill:pink + classDef larger font-size:30px,fill:yellow + `, + { htmlLabels: true, flowchart: { htmlLabels: true }, securityLevel: 'loose' } + ); + }); it('66: More nested subgraph cases (TB)', () => { imgSnapshotTest( ` diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index 13de19ba0..f9a9f3756 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -58,12 +58,21 @@
----
-title: Simple flowchart with invisible edges
----
-flowchart TD
-A ~~~ B
-  
+
+flowchart
+Node1:::class1 --> Node2:::class2
+Node1:::class1 --> Node3:::class2
+Node3 --> Node4((I am a circle)):::larger
+
+classDef class1 fill:lightblue
+classDef class2 fill:pink
+classDef larger font-size:30px,fill:yellow
+      
 stateDiagram-v2
diff --git a/demos/dev/example.html b/demos/dev/example.html
new file mode 100644
index 000000000..482343014
--- /dev/null
+++ b/demos/dev/example.html
@@ -0,0 +1,34 @@
+
+
+
+  
+    Mermaid development page
+  
+  
+    
+graph TB
+      a --> b
+      a --> c
+      b --> d
+      c --> d
+    
+ +
+ + + + diff --git a/docs/community/development.md b/docs/community/development.md index 0634759f5..f8c8b0638 100644 --- a/docs/community/development.md +++ b/docs/community/development.md @@ -70,7 +70,21 @@ pnpm test The `test` script and others are in the top-level `package.json` file. -All tests should run successfully without any errors or failures. (You might see _lint_ or _formatting_ warnings; those are ok during this step.) +All tests should run successfully without any errors or failures. (You might see _lint_ or _formatting_ "warnings"; those are ok during this step.) + +#### 4. Make your changes + +Now you are ready to make your changes! +Edit whichever files in `src` as required. + +#### 5. See your changes + +Open in your browser, after starting the dev server. +There is a list of demos that can be used to see and test your changes. + +If you need a specific diagram, you can duplicate the `example.html` file in `/demos/dev` and add your own mermaid code to your copy. +That will be served at . +After making code changes, the dev server will rebuild the mermaid library. You will need to reload the browser page yourself to see the changes. (PRs for auto reload are welcome!) ### Docker diff --git a/packages/mermaid/package.json b/packages/mermaid/package.json index 21c0e4d12..a32bcb257 100644 --- a/packages/mermaid/package.json +++ b/packages/mermaid/package.json @@ -1,6 +1,6 @@ { "name": "mermaid", - "version": "10.3.0", + "version": "10.3.1", "description": "Markdown-ish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.", "type": "module", "module": "./dist/mermaid.core.mjs", @@ -24,6 +24,7 @@ ], "scripts": { "clean": "rimraf dist", + "dev": "pnpm -w dev", "docs:code": "typedoc src/defaultConfig.ts src/config.ts src/mermaidAPI.ts && prettier --write ./src/docs/config/setup", "docs:build": "rimraf ../../docs && pnpm docs:spellcheck && pnpm docs:code && ts-node-esm scripts/docs.cli.mts", "docs:verify": "pnpm docs:spellcheck && pnpm docs:code && ts-node-esm scripts/docs.cli.mts --verify", diff --git a/packages/mermaid/src/dagre-wrapper/nodes.js b/packages/mermaid/src/dagre-wrapper/nodes.js index 6c6733358..e7988c8b5 100644 --- a/packages/mermaid/src/dagre-wrapper/nodes.js +++ b/packages/mermaid/src/dagre-wrapper/nodes.js @@ -8,8 +8,25 @@ import note from './shapes/note.js'; import { parseMember } from '../diagrams/class/svgDraw.js'; import { evaluate } from '../diagrams/common/common.js'; +const formatClass = (str) => { + if (str) { + return ' ' + str; + } + return ''; +}; +const getClassesFromNode = (node, otherClasses) => { + return `${otherClasses ? otherClasses : 'node default'}${formatClass(node.classes)} ${formatClass( + node.class + )}`; +}; + const question = async (parent, node) => { - const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true); + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -70,7 +87,12 @@ const choice = (parent, node) => { }; const hexagon = async (parent, node) => { - const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true); + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const f = 4; const h = bbox.height + node.padding; @@ -97,7 +119,12 @@ const hexagon = async (parent, node) => { }; const rect_left_inv_arrow = async (parent, node) => { - const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true); + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -123,7 +150,7 @@ const rect_left_inv_arrow = async (parent, node) => { }; const lean_right = async (parent, node) => { - const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true); + const { shapeSvg, bbox } = await labelHelper(parent, node, getClassesFromNode(node), true); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -146,7 +173,12 @@ const lean_right = async (parent, node) => { }; const lean_left = async (parent, node) => { - const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true); + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -169,7 +201,12 @@ const lean_left = async (parent, node) => { }; const trapezoid = async (parent, node) => { - const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true); + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -192,7 +229,12 @@ const trapezoid = async (parent, node) => { }; const inv_trapezoid = async (parent, node) => { - const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true); + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -215,7 +257,12 @@ const inv_trapezoid = async (parent, node) => { }; const rect_right_inv_arrow = async (parent, node) => { - const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true); + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -239,7 +286,12 @@ const rect_right_inv_arrow = async (parent, node) => { }; const cylinder = async (parent, node) => { - const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true); + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const rx = w / 2; @@ -314,7 +366,7 @@ const rect = async (parent, node) => { const { shapeSvg, bbox, halfPadding } = await labelHelper( parent, node, - 'node ' + node.classes, + 'node ' + node.classes + ' ' + node.class, true ); @@ -360,7 +412,7 @@ const rect = async (parent, node) => { const labelRect = async (parent, node) => { const { shapeSvg } = await labelHelper(parent, node, 'label', true); - log.trace('Classes = ', node.classes); + log.trace('Classes = ', node.class); // add the rect const rect = shapeSvg.insert('rect', ':first-child'); @@ -545,7 +597,12 @@ const rectWithTitle = (parent, node) => { }; const stadium = async (parent, node) => { - const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true); + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const h = bbox.height + node.padding; const w = bbox.width + h / 4 + node.padding; @@ -571,7 +628,12 @@ const stadium = async (parent, node) => { }; const circle = async (parent, node) => { - const { shapeSvg, bbox, halfPadding } = await labelHelper(parent, node, undefined, true); + const { shapeSvg, bbox, halfPadding } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const circle = shapeSvg.insert('circle', ':first-child'); // center the circle around its coordinate @@ -596,7 +658,12 @@ const circle = async (parent, node) => { }; const doublecircle = async (parent, node) => { - const { shapeSvg, bbox, halfPadding } = await labelHelper(parent, node, undefined, true); + const { shapeSvg, bbox, halfPadding } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const gap = 5; const circleGroup = shapeSvg.insert('g', ':first-child'); const outerCircle = circleGroup.insert('circle'); @@ -634,7 +701,12 @@ const doublecircle = async (parent, node) => { }; const subroutine = async (parent, node) => { - const { shapeSvg, bbox } = await labelHelper(parent, node, undefined, true); + const { shapeSvg, bbox } = await labelHelper( + parent, + node, + getClassesFromNode(node, undefined), + true + ); const w = bbox.width + node.padding; const h = bbox.height + node.padding; diff --git a/packages/mermaid/src/dagre-wrapper/shapes/util.js b/packages/mermaid/src/dagre-wrapper/shapes/util.js index 3eaedb4b9..95b82ddc0 100644 --- a/packages/mermaid/src/dagre-wrapper/shapes/util.js +++ b/packages/mermaid/src/dagre-wrapper/shapes/util.js @@ -13,6 +13,7 @@ export const labelHelper = async (parent, node, _classes, isNode) => { } else { classes = _classes; } + // Add outer g element const shapeSvg = parent .insert('g') @@ -49,7 +50,6 @@ export const labelHelper = async (parent, node, _classes, isNode) => { ) ); } - // Get the size of the label let bbox = text.getBBox(); const halfPadding = node.padding / 2; diff --git a/packages/mermaid/src/diagrams/error/errorRenderer.ts b/packages/mermaid/src/diagrams/error/errorRenderer.ts index ebe0d0d73..a8e738e5f 100644 --- a/packages/mermaid/src/diagrams/error/errorRenderer.ts +++ b/packages/mermaid/src/diagrams/error/errorRenderer.ts @@ -14,8 +14,8 @@ export const draw = (_text: string, id: string, version: string) => { log.debug('renering svg for syntax error\n'); const svg: SVG = selectSvgElement(id); - svg.attr('viewBox', '768 0 912 512'); - configureSvgSize(svg, 100, 500, true); + svg.attr('viewBox', '0 0 2412 512'); + configureSvgSize(svg, 100, 512, true); const g: Group = svg.append('g'); g.append('path') diff --git a/packages/mermaid/src/diagrams/state/stateRenderer-v2.js b/packages/mermaid/src/diagrams/state/stateRenderer-v2.js index 990048ec7..1c9b2d1d3 100644 --- a/packages/mermaid/src/diagrams/state/stateRenderer-v2.js +++ b/packages/mermaid/src/diagrams/state/stateRenderer-v2.js @@ -84,6 +84,7 @@ export const setConf = function (cnf) { * @returns {object} ClassDef styles (a Map with keys = strings, values = ) */ export const getClasses = function (text, diagramObj) { + diagramObj.db.extract(diagramObj.db.getRootDocV2()); return diagramObj.db.getClasses(); }; diff --git a/packages/mermaid/src/docs/community/development.md b/packages/mermaid/src/docs/community/development.md index 93146f0c3..35a01e589 100644 --- a/packages/mermaid/src/docs/community/development.md +++ b/packages/mermaid/src/docs/community/development.md @@ -64,7 +64,21 @@ pnpm test The `test` script and others are in the top-level `package.json` file. -All tests should run successfully without any errors or failures. (You might see _lint_ or _formatting_ warnings; those are ok during this step.) +All tests should run successfully without any errors or failures. (You might see _lint_ or _formatting_ "warnings"; those are ok during this step.) + +#### 4. Make your changes + +Now you are ready to make your changes! +Edit whichever files in `src` as required. + +#### 5. See your changes + +Open in your browser, after starting the dev server. +There is a list of demos that can be used to see and test your changes. + +If you need a specific diagram, you can duplicate the `example.html` file in `/demos/dev` and add your own mermaid code to your copy. +That will be served at . +After making code changes, the dev server will rebuild the mermaid library. You will need to reload the browser page yourself to see the changes. (PRs for auto reload are welcome!) ### Docker