diff --git a/cypress/platform/flowchart-sate.html b/cypress/platform/flowchart-sate.html index 83e46363a..61c3c167d 100644 --- a/cypress/platform/flowchart-sate.html +++ b/cypress/platform/flowchart-sate.html @@ -91,10 +91,8 @@ - - - - + + - + - +
DagreDagre with roughELKELK with roughState roughFlowchart rough
@@ -111,7 +109,7 @@
 %%{init: {"look": "handdrawn"} }%%
-stateDiagram-v2 
+stateDiagram-v2
     stateA
 
       
@@ -120,14 +118,14 @@ stateDiagram-v2
 %%{init: {"look": "handdrawn"} }%%
 flowchart LR
-    id1([This is the text in the box])
+    id1[[This is the text in the box]]
 
 
       
diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/circle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/circle.ts index 0574ab6cb..48054cce3 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/circle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/circle.ts @@ -1,19 +1,15 @@ import { log } from '$root/logger.js'; -import { labelHelper, updateNodeBounds } from './util.js'; +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import { getConfig } from '$root/diagram-api/diagramAPI.js'; import type { Node } from '$root/rendering-util/types.d.ts'; import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js'; import rough from 'roughjs'; export const circle = async (parent: SVGAElement, node: Node): Promise => { - const { themeVariables, handdrawnSeed } = getConfig(); - const { nodeBorder, mainBkg } = themeVariables; - const { shapeSvg, bbox, halfPadding } = await labelHelper( parent, node, - 'node ' + node.cssClasses, + getNodeClasses(node), true ); @@ -22,17 +18,9 @@ export const circle = async (parent: SVGAElement, node: Node): Promise roughNode, ':first-child'); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/cylinder.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/cylinder.ts index cd12792c6..f8e849382 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/cylinder.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/cylinder.ts @@ -1,7 +1,6 @@ import { log } from '$root/logger.js'; -import { labelHelper, updateNodeBounds } from './util.js'; +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import { getConfig } from '$root/diagram-api/diagramAPI.js'; import type { Node } from '$root/rendering-util/types.d.ts'; import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js'; import rough from 'roughjs'; @@ -33,17 +32,35 @@ export const createCylinderPathD = ( `l0,${-height}`, ].join(' '); }; - +export const createOuterCylinderPathD = ( + x: number, + y: number, + width: number, + height: number, + rx: number, + ry: number +): string => { + return [ + `M${x},${y + ry}`, + `M${x + width},${y + ry}`, + `a${rx},${ry} 0,0,0 ${-width},0`, + `l0,${height}`, + `a${rx},${ry} 0,0,0 ${width},0`, + `l0,${-height}`, + ].join(' '); +}; +export const createInnerCylinderPathD = ( + x: number, + y: number, + width: number, + height: number, + rx: number, + ry: number +): string => { + return [`M${x - width / 2},${-height / 2}`, `a${rx},${ry} 0,0,0 ${width},0`].join(' '); +}; export const cylinder = async (parent: SVGAElement, node: Node) => { - const { themeVariables, handdrawnSeed } = getConfig(); - const { nodeBorder, mainBkg } = themeVariables; - - const { shapeSvg, bbox, halfPadding } = await labelHelper( - parent, - node, - 'node ' + node.cssClasses, // + ' ' + node.class, - true - ); + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node), true); const w = bbox.width + node.padding; const rx = w / 2; @@ -54,21 +71,15 @@ export const cylinder = async (parent: SVGAElement, node: Node) => { const { cssStyles, useRough } = node; if (useRough) { - console.log('Cylinder: Inside use useRough'); + // @ts-ignore const rc = rough.svg(shapeSvg); - const options = userNodeOverrides(node, { - roughness: 0.7, - fill: mainBkg, - fillStyle: 'hachure', - fillWeight: 1.5, - stroke: nodeBorder, - seed: handdrawnSeed, - strokeWidth: 1, - }); - const pathData = createCylinderPathD(0, 0, w, h, rx, ry); - const roughNode = rc.path(pathData, options); + const outerPathData = createOuterCylinderPathD(0, 0, w, h, rx, ry); + const innerPathData = createInnerCylinderPathD(0, ry, w, h, rx, ry); + const outerNode = rc.path(outerPathData, userNodeOverrides(node, {})); + const innerLine = rc.path(innerPathData, userNodeOverrides(node, { fill: 'none' })); - cylinder = shapeSvg.insert(() => roughNode, ':first-child'); + cylinder = shapeSvg.insert(() => innerLine, ':first-child'); + cylinder = shapeSvg.insert(() => outerNode, ':first-child'); cylinder.attr('class', 'basic label-container'); if (cssStyles) { cylinder.attr('style', cssStyles); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/doubleCircle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/doubleCircle.ts index 49e4051c3..b32420cc0 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/doubleCircle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/doubleCircle.ts @@ -1,5 +1,5 @@ import { log } from '$root/logger.js'; -import { labelHelper, updateNodeBounds } from './util.js'; +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; import { getConfig } from '$root/diagram-api/diagramAPI.js'; import type { Node } from '$root/rendering-util/types.d.ts'; @@ -8,8 +8,8 @@ import rough from 'roughjs'; //import d3 from 'd3'; export const doublecircle = async (parent: SVGAElement, node: Node): Promise => { - const { themeVariables, handdrawnSeed } = getConfig(); - const { nodeBorder, mainBkg } = themeVariables; + const { themeVariables } = getConfig(); + const { mainBkg } = themeVariables; const { shapeSvg, bbox, halfPadding } = await labelHelper( parent, @@ -25,17 +25,9 @@ export const doublecircle = async (parent: SVGAElement, node: Node): Promise, -// borders: string | undefined, -// totalWidth: number, -// totalHeight: number -// ) { -// if (!borders) { -// return; -// } -// const strokeDashArray: number[] = []; -// const addBorder = (length: number) => { -// strokeDashArray.push(length, 0); -// }; -// const skipBorder = (length: number) => { -// strokeDashArray.push(0, length); -// }; -// if (borders.includes('t')) { -// log.debug('add top border'); -// addBorder(totalWidth); -// } else { -// skipBorder(totalWidth); -// } -// if (borders.includes('r')) { -// log.debug('add right border'); -// addBorder(totalHeight); -// } else { -// skipBorder(totalHeight); -// } -// if (borders.includes('b')) { -// log.debug('add bottom border'); -// addBorder(totalWidth); -// } else { -// skipBorder(totalWidth); -// } -// if (borders.includes('l')) { -// log.debug('add left border'); -// addBorder(totalHeight); -// } else { -// skipBorder(totalHeight); -// } - -// rect.attr('stroke-dasharray', strokeDashArray.join(' ')); -// } - export const drawRect = async (parent: SVGAElement, node: Node, options: RectOptions) => { - const { themeVariables, handdrawnSeed } = getConfig(); - const { nodeBorder, mainBkg } = themeVariables; - const { shapeSvg, bbox, halfPadding } = await labelHelper( parent, node, - 'node ' + node.cssClasses, // + ' ' + node.class, + getNodeClasses(node), true ); @@ -79,15 +31,7 @@ export const drawRect = async (parent: SVGAElement, node: Node, options: RectOpt if (useRough) { // @ts-ignore TODO: Fix rough typings const rc = rough.svg(shapeSvg); - const options = userNodeOverrides(node, { - roughness: 0.7, - fill: mainBkg, - // fillStyle: 'solid', // solid fill' - fillStyle: 'hachure', // solid fill' - fillWeight: 3.5, - stroke: nodeBorder, - seed: handdrawnSeed, - }); + const options = userNodeOverrides(node, {}); console.log('rect options: ', options); const roughNode = diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/handdrawnStyles.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/handdrawnStyles.ts index 462ce9f3d..21e8f2835 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/handdrawnStyles.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/handdrawnStyles.ts @@ -18,8 +18,25 @@ export const solidStateFill = (color: string) => { // Striped fill like start or fork nodes in state diagrams // TODO remove any export const userNodeOverrides = (node: Node, options: any) => { - const result = Object.assign({}, options); - result.fill = node.backgroundColor || options.fill; - result.stroke = node.borderColor || options.stroke; + const { themeVariables, handdrawnSeed } = getConfig(); + const { nodeBorder, mainBkg } = themeVariables; + const result = Object.assign( + { + roughness: 0.7, + fill: mainBkg, + fillStyle: 'hachure', // solid fill + fillWeight: 3.5, + stroke: nodeBorder, + seed: handdrawnSeed, + strokeWidth: 1, + }, + options + ); + if (node.backgroundColor) { + result.fill = node.backgroundColor; + } + if (node.borderColor) { + result.stroke = node.borderColor; + } return result; }; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/hexagon.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/hexagon.ts index e9070d8d3..0678e6013 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/hexagon.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/hexagon.ts @@ -1,7 +1,6 @@ import { log } from '$root/logger.js'; -import { labelHelper, updateNodeBounds } from './util.js'; +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import { getConfig } from '$root/diagram-api/diagramAPI.js'; import type { Node } from '$root/rendering-util/types.d.ts'; import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js'; import rough from 'roughjs'; @@ -36,13 +35,10 @@ export const createHexagonPathD = ( }; export const hexagon = async (parent: SVGAElement, node: Node): Promise => { - const { themeVariables, handdrawnSeed } = getConfig(); - const { nodeBorder, mainBkg } = themeVariables; - const { shapeSvg, bbox, halfPadding } = await labelHelper( parent, node, - 'node ' + node.cssClasses, + getNodeClasses(node), true ); @@ -63,17 +59,9 @@ export const hexagon = async (parent: SVGAElement, node: Node): Promise => { - const { themeVariables, handdrawnSeed } = getConfig(); - const { nodeBorder, mainBkg } = themeVariables; - - const { shapeSvg, bbox, halfPadding } = await labelHelper( - parent, - node, - 'node ' + node.cssClasses, - true - ); + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node), true); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -54,17 +46,9 @@ export const inv_trapezoid = async (parent: SVGAElement, node: Node): Promise => { - const { themeVariables, handdrawnSeed } = getConfig(); - const { nodeBorder, mainBkg } = themeVariables; - - const { shapeSvg, bbox, halfPadding } = await labelHelper( - parent, - node, - 'node ' + node.cssClasses, - true - ); + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node), true); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -54,17 +45,9 @@ export const lean_left = async (parent: SVGAElement, node: Node): Promise => { - const { themeVariables, handdrawnSeed } = getConfig(); - const { nodeBorder, mainBkg } = themeVariables; - - const { shapeSvg, bbox, halfPadding } = await labelHelper( - parent, - node, - 'node ' + node.cssClasses, - true - ); + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node), true); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -54,17 +45,9 @@ export const lean_right = async (parent: SVGAElement, node: Node): Promise => { - const { themeVariables, handdrawnSeed } = getConfig(); - const { nodeBorder, mainBkg } = themeVariables; - - const { shapeSvg, bbox, halfPadding } = await labelHelper( - parent, - node, - 'node ' + node.cssClasses, - true - ); + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node), true); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -50,17 +41,9 @@ export const question = async (parent: SVGAElement, node: Node): Promise => { - const { themeVariables, handdrawnSeed } = getConfig(); - const { nodeBorder, mainBkg } = themeVariables; - - const { shapeSvg, bbox, halfPadding } = await labelHelper( - parent, - node, - 'node ' + node.cssClasses, - true - ); + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node), true); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -54,17 +45,9 @@ export const rect_left_inv_arrow = async ( const { cssStyles, useRough } = node; if (useRough) { - console.log('Polygon: Inside use useRough'); + // @ts-ignore const rc = rough.svg(shapeSvg); - const options = userNodeOverrides(node, { - roughness: 0.7, - fill: mainBkg, - fillStyle: 'hachure', - fillWeight: 1.5, - stroke: nodeBorder, - seed: handdrawnSeed, - strokeWidth: 1, - }); + const options = userNodeOverrides(node, {}); const pathData = createPolygonPathD(0, 0, w, h); const roughNode = rc.path(pathData, options); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stadium.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stadium.ts index 423f2392a..102e49069 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stadium.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stadium.ts @@ -1,7 +1,6 @@ import { log } from '$root/logger.js'; -import { labelHelper, updateNodeBounds } from './util.js'; +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import { getConfig } from '$root/diagram-api/diagramAPI.js'; import type { Node } from '$root/rendering-util/types.d.ts'; import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js'; import rough from 'roughjs'; @@ -53,15 +52,7 @@ export const createStadiumPathD = ( }; export const stadium = async (parent: SVGAElement, node: Node) => { - const { themeVariables, handdrawnSeed } = getConfig(); - const { nodeBorder, mainBkg } = themeVariables; - - const { shapeSvg, bbox, halfPadding } = await labelHelper( - parent, - node, - 'node ' + node.cssClasses, // + ' ' + node.class, - true - ); + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node), true); const h = bbox.height + node.padding; const w = bbox.width + h / 4 + node.padding; @@ -69,20 +60,11 @@ export const stadium = async (parent: SVGAElement, node: Node) => { let rect; const { cssStyles, useRough } = node; if (useRough) { - console.log('Stadium:Inside use useRough'); + // @ts-ignore const rc = rough.svg(shapeSvg); - const options = userNodeOverrides(node, { - roughness: 0.7, - fill: mainBkg, - fillStyle: 'hachure', // solid fill - fillWeight: 3.5, - stroke: nodeBorder, - seed: handdrawnSeed, - // strokeWidth: 1, - }); + const options = userNodeOverrides(node, {}); - console.log('Stadium options: ', options); - const pathData = createRoundedRectPathD(-w / 2, -h / 2, w, h, h / 3); + const pathData = createRoundedRectPathD(-w / 2, -h / 2, w, h, h / 2); const roughNode = rc.path(pathData, options); rect = shapeSvg.insert(() => roughNode, ':first-child'); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/subroutine.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/subroutine.ts index eacd53e27..4046cfcc9 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/subroutine.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/subroutine.ts @@ -1,7 +1,6 @@ import { log } from '$root/logger.js'; -import { labelHelper, updateNodeBounds } from './util.js'; +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import { getConfig } from '$root/diagram-api/diagramAPI.js'; import type { Node } from '$root/rendering-util/types.d.ts'; import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js'; import rough from 'roughjs'; @@ -34,39 +33,14 @@ export const createSubroutinePathD = ( }; export const subroutine = async (parent: SVGAElement, node: Node) => { - const { themeVariables, handdrawnSeed } = getConfig(); - const { nodeBorder, mainBkg } = themeVariables; - - const { shapeSvg, bbox, halfPadding } = await labelHelper( - parent, - node, - 'node ' + node.cssClasses, // + ' ' + node.class, - true - ); - + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node), true); + const halfPadding = (node?.padding || 0) / 2; const w = bbox.width + node.padding; const h = bbox.height + node.padding; - + const x = -bbox.width / 2 - halfPadding; + const y = -bbox.height / 2 - halfPadding; let rect; const { cssStyles, useRough } = node; - if (useRough) { - const rc = rough.svg(shapeSvg); - const options = userNodeOverrides(node, { - roughness: 0.7, - fill: mainBkg, - fillStyle: 'hachure', - fillWeight: 1.5, - stroke: nodeBorder, - seed: handdrawnSeed, - strokeWidth: 1, - }); - const pathData = createSubroutinePathD(-w / 2, -h / 2, w, h); - const roughNode = rc.path(pathData, options); - - rect = shapeSvg.insert(() => roughNode, ':first-child'); - rect.attr('class', 'basic label-container').attr('style', cssStyles); - } - const points = [ { x: 0, y: 0 }, { x: w, y: 0 }, @@ -80,12 +54,28 @@ export const subroutine = async (parent: SVGAElement, node: Node) => { { x: -8, y: 0 }, ]; - const el = insertPolygonShape(shapeSvg, w, h, points); - if (cssStyles) { - el.attr('style', cssStyles); - } + if (useRough) { + // @ts-ignore + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + const pathData = createSubroutinePathD(-w / 2, -h / 2, w, h); - updateNodeBounds(node, el); + const roughNode = rc.rectangle(x - 8, y, w + 16, h, options); + const l1 = rc.line(x, y, x, y + h, options); + const l2 = rc.line(x + w, y, x + w, y + h, options); + + shapeSvg.insert(() => l1, ':first-child'); + shapeSvg.insert(() => l2, ':first-child'); + rect = shapeSvg.insert(() => roughNode, ':first-child'); + + rect.attr('class', 'basic label-container').attr('style', cssStyles); + } else { + const el = insertPolygonShape(shapeSvg, w, h, points); + if (cssStyles) { + el.attr('style', cssStyles); + } + updateNodeBounds(node, el); + } node.intersect = function (point) { return intersect.polygon(node, points, point); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoid.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoid.ts index 6a26f83e1..1a6a2d1c2 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoid.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoid.ts @@ -1,7 +1,6 @@ import { log } from '$root/logger.js'; -import { labelHelper, updateNodeBounds } from './util.js'; +import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import { getConfig } from '$root/diagram-api/diagramAPI.js'; import type { Node } from '$root/rendering-util/types.d.ts'; import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handdrawnStyles.js'; import rough from 'roughjs'; @@ -31,15 +30,7 @@ export const createTrapezoidPathD = ( }; export const trapezoid = async (parent: SVGAElement, node: Node): Promise => { - const { themeVariables, handdrawnSeed } = getConfig(); - const { nodeBorder, mainBkg } = themeVariables; - - const { shapeSvg, bbox, halfPadding } = await labelHelper( - parent, - node, - 'node ' + node.cssClasses, - true - ); + const { shapeSvg, bbox } = await labelHelper(parent, node, getNodeClasses(node), true); const w = bbox.width + node.padding; const h = bbox.height + node.padding; @@ -55,16 +46,9 @@ export const trapezoid = async (parent: SVGAElement, node: Node): Promise + (node.useRough ? 'rough-node' : 'node') + ' ' + node.cssClasses + ' ' + (extra || '');