diff --git a/cypress/integration/rendering/newShapes.spec.js b/cypress/integration/rendering/newShapes.spec.js deleted file mode 100644 index 5c33bb571..000000000 --- a/cypress/integration/rendering/newShapes.spec.js +++ /dev/null @@ -1,106 +0,0 @@ -import { imgSnapshotTest, renderGraph } from '../../helpers/util.ts'; - -describe('newShapes', () => { - it('1: should render new triangle shape', () => { - imgSnapshotTest( - `flowchart - BTF --> ADT@{ shape: triangle, label:"This is Sample Label" }@ - ` - ); - }); - - it('2: should render new slopedRect shape', () => { - imgSnapshotTest( - `flowchart - GS --> AQ@{ shape: slopedRect, label:"This is Final Label" }@ - RE --> AQ - `, - {} - ); - }); - it('3: should render new tiltedCylinder shape', () => { - imgSnapshotTest( - `flowchart - KS --> AC@{ shape: tiltedCylinder, label:"This is Final Label" }@ - RE --> AC - `, - {} - ); - }); - it('4: should render new flippedTriangle shape', () => { - imgSnapshotTest( - `flowchart - FS --> AD@{ shape: flippedTriangle, label:"This is Final Label" }@ - FE --> AD - `, - {} - ); - }); - it('5: should render new hourGlass shape', () => { - imgSnapshotTest( - `flowchart - MS --> AE@{ shape: hourglass, label:"This is Final Label" }@ - ME --> AE - `, - {} - ); - }); - it('6: should render new taggedRect shape', () => { - imgSnapshotTest( - `flowchart - KS --> AC@{ shape: taggedRect, label:"This is Final Label" }@ - RE --> AC - `, - {} - ); - }); - it('7: should render new multiRect shape', () => { - imgSnapshotTest( - `flowchart - DS --> AF@{ shape: multiRect, label:"This is Final Label" }@ - DE --> AF - `, - {} - ); - }); - it('8: should render new FlowChart for New Shapes', () => { - renderGraph( - ` - flowchart - A@{ shape: stateStart }@ - B@{ shape: crossedCircle, label: "Start Defining Test Case" }@ - C@{ shape: tiltedCylinder, label: "write your Test Case"}@ - D@{ shape: flippedTriangle, label: "new Test Case"}@ - E@{ shape: waveRectangle, label: "Execute Test Case" }@ - F@{ shape: hourglass , label: "add test case"}@ - G@{ shape: taggedRect, label: "execute new test case"}@ - H@{ shape: slopedRect, label: "Test Passed?" }@ - I@{ shape: bowTieRect, label: "Pass" }@ - J@{ shape: dividedRect, label: "Log Defect" }@ - K@{ shape: curvedTrapezoid, label: "End" }@ - L@{ shape: multiRect, label: "coming soon"}@ - - A --> B - B --> C - C --> D - D --> E - E --> F - F -->|Yes| G - G -->|No| H - H --> I - I --> J - J --> K - K --> L - `, - { flowchart: { useMaxWidth: true } } - ); - cy.get('svg').should((svg) => { - const style = svg.attr('style'); - expect(svg).to.have.attr('width', '100%'); - // use within because the absolute value can be slightly different depending on the environment ±5% - expect(style).to.match(/^max-width: [\d.]+px;$/); - const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); - expect(maxWidthValue).to.be.within(250 * 0.95 - 1, 250 * 1.05); - }); - }); -}); diff --git a/cypress/integration/rendering/newShapes.spec.ts b/cypress/integration/rendering/newShapes.spec.ts new file mode 100644 index 000000000..e993b010b --- /dev/null +++ b/cypress/integration/rendering/newShapes.spec.ts @@ -0,0 +1,208 @@ +import { imgSnapshotTest } from '../../helpers/util.ts'; + +// Define the looks and shape sets using readonly tuples to ensure type safety +const looks = ['classic', 'handDrawn'] as const; +const directions = ['TB', 'BT', 'LR', 'RL'] as const; +const newShapesSet1 = [ + 'triangle', + 'slopedRect', + 'tiltedCylinder', + 'flippedTriangle', + 'hourglass', +] as const; +const newShapesSet2 = ['taggedRect', 'multiRect'] as const; + +// Aggregate all shape sets into a single array +const newShapesSets = [newShapesSet1, newShapesSet2] as const; + +looks.forEach((look) => { + directions.forEach((direction) => { + newShapesSets.forEach((newShapesSet) => { + describe(`Test ${newShapesSet.join(', ')} in ${look} look and dir ${direction}`, () => { + it(`without label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + newShapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape} }@\n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + newShapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a label' }@\n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with very long label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + newShapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is a very very very very very long long long label' }@\n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with markdown htmlLabels:true`, () => { + let flowchartCode = `flowchart ${direction}\n`; + newShapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold**
and strong' }@\n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with markdown htmlLabels:false`, () => { + let flowchartCode = `flowchart ${direction}\n`; + newShapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'This is **bold**
and strong' }@\n`; + }); + imgSnapshotTest(flowchartCode, { look, htmlLabels: false }); + }); + + it.skip(`with styles`, () => { + let flowchartCode = `flowchart ${direction}\n`; + newShapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new shape' }@\n`; + flowchartCode += ` style n${index}${index} fill:#f9f,stroke:#333,stroke-width:4px \n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with classDef`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5\n`; + newShapesSet.forEach((newShape, index) => { + flowchartCode += ` n${index} --> n${index}${index}@{ shape: ${newShape}, label: 'new shape' }@\n`; + flowchartCode += ` n${index}${index}:::customClazz\n`; + }); + imgSnapshotTest(flowchartCode, { look }); + }); + }); + }); + }); +}); + +// describe('Test for new shape set 1', () => { +// it('1: should render new shape', () => { +// imgSnapshotTest( +// `flowchart +// A --> A1@{ shape: triangle, label:"This is Sample Label" }@ +// ` +// ); +// }); + +// it('2: should render new slopedRect shape', () => { +// imgSnapshotTest( +// `flowchart +// GS --> AQ@{ shape: slopedRect, label:"This is Final Label" }@ +// RE --> AQ +// `, +// {} +// ); +// }); +// }); + +// describe('newShapes', () => { +// it('1: should render new triangle shape', () => { +// imgSnapshotTest( +// `flowchart +// BTF --> ADT@{ shape: triangle, label:"This is Sample Label" }@ +// ` +// ); +// }); + +// it('2: should render new slopedRect shape', () => { +// imgSnapshotTest( +// `flowchart +// GS --> AQ@{ shape: slopedRect, label:"This is Final Label" }@ +// RE --> AQ +// `, +// {} +// ); +// }); +// it('3: should render new tiltedCylinder shape', () => { +// imgSnapshotTest( +// `flowchart +// KS --> AC@{ shape: tiltedCylinder, label:"This is Final Label" }@ +// RE --> AC +// `, +// {} +// ); +// }); +// it('4: should render new flippedTriangle shape', () => { +// imgSnapshotTest( +// `flowchart +// FS --> AD@{ shape: flippedTriangle, label:"This is Final Label" }@ +// FE --> AD +// `, +// {} +// ); +// }); +// it('5: should render new hourGlass shape', () => { +// imgSnapshotTest( +// `flowchart +// MS --> AE@{ shape: hourglass, label:"This is Final Label" }@ +// ME --> AE +// `, +// {} +// ); +// }); +// it('6: should render new taggedRect shape', () => { +// imgSnapshotTest( +// `flowchart +// KS --> AC@{ shape: taggedRect, label:"This is Final Label" }@ +// RE --> AC +// `, +// {} +// ); +// }); +// it('7: should render new multiRect shape', () => { +// imgSnapshotTest( +// `flowchart +// DS --> AF@{ shape: multiRect, label:"This is Final Label" }@ +// DE --> AF +// `, +// {} +// ); +// }); +// it('8: should render new FlowChart for New Shapes', () => { +// renderGraph( +// ` +// flowchart +// A@{ shape: stateStart }@ +// B@{ shape: crossedCircle, label: "Start Defining Test Case" }@ +// C@{ shape: tiltedCylinder, label: "write your Test Case"}@ +// D@{ shape: flippedTriangle, label: "new Test Case"}@ +// E@{ shape: waveRectangle, label: "Execute Test Case" }@ +// F@{ shape: hourglass , label: "add test case"}@ +// G@{ shape: taggedRect, label: "execute new test case"}@ +// H@{ shape: slopedRect, label: "Test Passed?" }@ +// I@{ shape: bowTieRect, label: "Pass" }@ +// J@{ shape: dividedRect, label: "Log Defect" }@ +// K@{ shape: curvedTrapezoid, label: "End" }@ +// L@{ shape: multiRect, label: "coming soon"}@ + +// A --> B +// B --> C +// C --> D +// D --> E +// E --> F +// F -->|Yes| G +// G -->|No| H +// H --> I +// I --> J +// J --> K +// K --> L +// `, +// { flowchart: { useMaxWidth: true } } +// ); +// cy.get('svg').should((svg) => { +// const style = svg.attr('style'); +// expect(svg).to.have.attr('width', '100%'); +// // use within because the absolute value can be slightly different depending on the environment ±5% +// expect(style).to.match(/^max-width: [\d.]+px;$/); +// const maxWidthValue = parseFloat(style.match(/[\d.]+/g).join('')); +// expect(maxWidthValue).to.be.within(250 * 0.95 - 1, 250 * 1.05); +// }); +// }); +// }); diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index 00632ca51..7fd7ad157 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -62,10 +62,54 @@
+  flowchart TB
+       %% ['triangle', 'slopedRect', 'tiltedCylinder', 'flippedTriangle', 'hourglass'];
+        node_0
+        noed_00 --> node_1@{ shape: triangle, label: "This is **bold** 
and strong" }@ + style node_1 fill:#f9f,stroke:#333,stroke-width:4px + + node_2@{ shape: slopedRect }@ + node_3@{ shape: tiltedCylinder }@ + style node_0 fill:#f9f,stroke:#333,stroke-width:4px + style node_3 fill:#f9f,stroke:#333,stroke-width:4px + classDef customClazz fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 + node_2:::customClazz + node_00:::customClazz + + +
+
+    flowchart RL
+    n0 --> n00@{ shape: taggedRect, label: 'new shape' }@
+    style n00 fill:#f9f,stroke:#333,stroke-width:4px
+    n1 --> n11@{ shape: multiRect, label: 'new shape' }@
+    style n11 fill:#f9f,stroke:#333,stroke-width:4px"
+  
+
 flowchart
      
+      %% without shape or label
+      node_0
+      %% with shape but no label
       node_3@{ shape: triangle }@
+
+      %% with shape and label
+      node_1@{ shape: triangle, label: "This is a label" }@
+
+      %% with shape and long label
+      node_2@{ shape: triangle, label: "This is a long long long long long long label" }@
      
+      %% with shape and label && htmlLabel true
+      node_4@{ shape: triangle, label: "This is a label", htmlLabel: true }@
+
+      %% with shape and label && htmlLabel false
+      node_5@{ shape: triangle, label: "This is a label", htmlLabel: false }@
+
+      %% with shape and label handDrawn look ON
+      node_6@{ shape: triangle, label: "This is a label", handDrawn: true }@
+
+
       
   
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/nodes.js b/packages/mermaid/src/rendering-util/rendering-elements/nodes.js index a9c69d2cc..218551aac 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/nodes.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/nodes.js @@ -34,7 +34,7 @@ import { bowTieRect } from './shapes/bowTieRect.js'; import { dividedRect } from './shapes/dividedRect.js'; import { crossedCircle } from './shapes/crossedCircle.js'; import { waveRectangle } from './shapes/waveRectangle.js'; -import { titledCylinder } from './shapes/tiltedCylinder.js'; +import { tiltedCylinder } from './shapes/tiltedCylinder.js'; import { trapezoidalPentagon } from './shapes/trapezoidalPentagon.js'; import { flippedTriangle } from './shapes/flippedTriangle.js'; import { hourglass } from './shapes/hourglass.js'; @@ -79,7 +79,7 @@ const shapes = { dividedRect, crossedCircle, waveRectangle, - titledCylinder, + tiltedCylinder, trapezoidalPentagon, flippedTriangle, hourglass, diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/tiltedCylinder.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/tiltedCylinder.ts index b0ae92308..9a52c9681 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/tiltedCylinder.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/tiltedCylinder.ts @@ -16,7 +16,7 @@ function createCylinderPathD(rx: number, ry: number, w: number, h: number) { A ${rx} ${ry} 0 0 0 ${w / 2} ${h / 2}`; } -export const titledCylinder = async (parent: SVGAElement, node: Node) => { +export const tiltedCylinder = async (parent: SVGAElement, node: Node) => { const { labelStyles, nodeStyles } = styles2String(node); node.labelStyle = labelStyles; const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node)); @@ -38,20 +38,20 @@ export const titledCylinder = async (parent: SVGAElement, node: Node) => { const cylinderPath = createCylinderPathD(rx, ry, w, h); const cylinderNode = rc.path(cylinderPath, options); - const titledCylinder = shapeSvg.insert('g', ':first-child'); - titledCylinder.insert(() => cylinderNode, ':first-child'); + const tiltedCylinder = shapeSvg.insert('g', ':first-child'); + tiltedCylinder.insert(() => cylinderNode, ':first-child'); - titledCylinder.attr('class', 'basic label-container'); + tiltedCylinder.attr('class', 'basic label-container'); if (cssStyles) { - titledCylinder.attr('style', cssStyles); + tiltedCylinder.attr('style', cssStyles); } if (nodeStyles) { - titledCylinder.attr('style', nodeStyles); + tiltedCylinder.attr('style', nodeStyles); } - updateNodeBounds(node, titledCylinder); + updateNodeBounds(node, tiltedCylinder); node.intersect = function (point) { const pos = intersect.rect(node, point);