diff --git a/.changeset/rude-meals-invite.md b/.changeset/rude-meals-invite.md new file mode 100644 index 000000000..8d43692f8 --- /dev/null +++ b/.changeset/rude-meals-invite.md @@ -0,0 +1,5 @@ +--- +'mermaid': minor +--- + +New Flowchart Shapes (with new syntax) diff --git a/.changeset/slow-goats-act.md b/.changeset/slow-goats-act.md new file mode 100644 index 000000000..a21565ec3 --- /dev/null +++ b/.changeset/slow-goats-act.md @@ -0,0 +1,5 @@ +--- +'@mermaid-js/layout-elk': patch +--- + +chore: fix render types diff --git a/.github/workflows/release-preview.yml b/.github/workflows/release-preview.yml new file mode 100644 index 000000000..283c316fb --- /dev/null +++ b/.github/workflows/release-preview.yml @@ -0,0 +1,42 @@ +name: Preview release + +on: + pull_request: + branches: [develop] + +concurrency: + group: ${{ github.workflow }}-${{ github.event.number }} + cancel-in-progress: true + +permissions: + contents: read + actions: write + +jobs: + preview: + if: ${{ github.repository_owner == 'mermaid-js' }} + runs-on: ubuntu-latest + permissions: + contents: read + id-token: write + issues: write + pull-requests: write + name: Publish preview release + timeout-minutes: 5 + steps: + - name: Checkout Repo + uses: actions/checkout@f43a0e5ff2bd294095638e18286ca9a3d1956744 # v3.6.0 + + - uses: pnpm/action-setup@fe02b34f77f8bc703788d5817da081398fad5dd2 # v4.0.0 + + - name: Setup Node.js + uses: actions/setup-node@1e60f620b9541d16bece96c5465dc8ee9832be0b # v4.0.3 + with: + cache: pnpm + node-version-file: '.node-version' + + - name: Install Packages + run: pnpm install --frozen-lockfile + + - name: Publish packages + run: pnpx pkg-pr-new publish --pnpm './packages/*' diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml index 375d5fada..026ca0fb7 100644 --- a/.github/workflows/test.yml +++ b/.github/workflows/test.yml @@ -38,6 +38,10 @@ jobs: run: | pnpm exec vitest run ./packages/mermaid/src/diagrams/gantt/ganttDb.spec.ts --coverage + - name: Verify out-of-tree build with TypeScript + run: | + pnpm test:check:tsc + - name: Upload Coverage to Codecov uses: codecov/codecov-action@e28ff129e5465c2c0dcc6f003fc735cb6ae0c673 # v4.5.0 # Run step only pushes to develop and pull_requests diff --git a/Dockerfile b/Dockerfile index fa933f999..7be53d24e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -5,6 +5,9 @@ USER 0:0 RUN corepack enable \ && corepack enable pnpm +RUN apk add --no-cache git~=2.43.4 \ + && git config --add --system safe.directory /mermaid + ENV NODE_OPTIONS="--max_old_space_size=8192" EXPOSE 9000 3333 diff --git a/cypress/integration/rendering/flowchart-shape-alias.spec.ts b/cypress/integration/rendering/flowchart-shape-alias.spec.ts new file mode 100644 index 000000000..3e6d9092d --- /dev/null +++ b/cypress/integration/rendering/flowchart-shape-alias.spec.ts @@ -0,0 +1,134 @@ +import { imgSnapshotTest } from '../../helpers/util.ts'; + +const aliasSet1 = ['process', 'rect', 'proc', 'rectangle'] as const; + +const aliasSet2 = ['event', 'rounded'] as const; + +const aliasSet3 = ['stadium', 'pill', 'term'] as const; + +const aliasSet4 = ['fr', 'subproc', 'framed-rectangle', 'subroutine'] as const; + +const aliasSet5 = ['db', 'cylinder', 'cyl'] as const; + +const aliasSet6 = ['diam', 'decision', 'diamond'] as const; + +const aliasSet7 = ['hex', 'hexagon', 'prepare'] as const; + +const aliasSet8 = ['l-r', 'lean-right', 'in-out'] as const; + +const aliasSet9 = ['l-l', 'lean-left', 'out-in'] as const; + +const aliasSet10 = ['trap-b', 'trapezoid-bottom', 'priority', 'trapezoid'] as const; + +const aliasSet11 = ['trap-t', 'trapezoid-top', 'manual', 'inv-trapezoid'] as const; + +const aliasSet12 = ['dc', 'double-circle'] as const; + +const aliasSet13 = ['notched-rect', 'card', 'notch-rect'] as const; + +const aliasSet14 = ['lined-rect', 'lined-proc', 'shaded-proc'] as const; + +const aliasSet15 = ['sm-circ', 'small-circle', 'start'] as const; + +const aliasSet16 = ['framed-circle', 'stop'] as const; + +const aliasSet17 = ['fork', 'join', 'long-rect'] as const; + +const aliasSet18 = ['brace', 'comment', 'brace-l'] as const; + +const aliasSet19 = ['bolt', 'com-link', 'lightning-bolt'] as const; + +const aliasSet20 = ['we-rect', 'doc', 'wave-edge-rect', 'wave-edged-rectangle'] as const; + +const aliasSet21 = ['delay', 'half-rounded-rect'] as const; + +const aliasSet22 = ['t-cyl', 'das', 'tilted-cylinder'] as const; + +const aliasSet23 = ['l-cyl', 'disk', 'lined-cylinder'] as const; + +const aliasSet24 = ['cur-trap', 'disp', 'display', 'curved-trapezoid'] as const; + +const aliasSet25 = ['div-rect', 'div-proc', 'divided-rectangle'] as const; + +const aliasSet26 = ['sm-tri', 'extract', 'small-triangle', 'triangle'] as const; + +const aliasSet27 = ['win-pane', 'internal-storage', 'window-pane'] as const; + +const aliasSet28 = ['fc', 'junction', 'filled-circle'] as const; + +const aliasSet29 = ['lin-we-rect', 'lin-doc', 'lined-wave-edged-rect'] as const; + +const aliasSet30 = ['notch-pent', 'loop-limit', 'notched-pentagon'] as const; + +const aliasSet31 = ['flip-tri', 'manual-file', 'flipped-triangle'] as const; + +const aliasSet32 = ['sloped-rect', 'manual-input', 'sloped-rectangle'] as const; + +const aliasSet33 = ['mul-we-rect', 'mul-doc', 'multi-wave-edged-rectangle'] as const; + +const aliasSet34 = ['mul-rect', 'mul-proc', 'multi-rect'] as const; + +const aliasSet35 = ['flag', 'paper-tape'] as const; + +const aliasSet36 = ['bt-rect', 'stored-data', 'bow-tie-rect'] as const; + +const aliasSet37 = ['cross-circle', 'summary', 'crossed-circle'] as const; + +const aliasSet38 = ['tag-we-rect', 'tag-doc', 'tagged-wave-edged-rectangle'] as const; + +const aliasSet39 = ['tag-rect', 'tag-proc', 'tagged-rect'] as const; + +// Aggregate all alias sets into a single array +const aliasSets = [ + aliasSet1, + aliasSet2, + aliasSet3, + aliasSet4, + aliasSet5, + aliasSet6, + aliasSet7, + aliasSet8, + aliasSet9, + aliasSet10, + aliasSet11, + aliasSet12, + aliasSet13, + aliasSet14, + aliasSet15, + aliasSet16, + aliasSet17, + aliasSet18, + aliasSet19, + aliasSet20, + aliasSet21, + aliasSet22, + aliasSet23, + aliasSet24, + aliasSet25, + aliasSet26, + aliasSet27, + aliasSet28, + aliasSet29, + aliasSet30, + aliasSet31, + aliasSet32, + aliasSet33, + aliasSet34, + aliasSet35, + aliasSet36, + aliasSet37, + aliasSet38, + aliasSet39, +] as const; + +aliasSets.forEach((aliasSet) => { + describe(`Test ${aliasSet.join(',')} `, () => { + it(`All ${aliasSet.join(',')} should render same shape`, () => { + let flowchartCode = `flowchart \n`; + aliasSet.forEach((alias, index) => { + flowchartCode += ` n${index}@{ shape: ${alias}, label: "${alias}" }@\n`; + }); + imgSnapshotTest(flowchartCode); + }); + }); +}); diff --git a/cypress/integration/rendering/iconShape.spec.ts b/cypress/integration/rendering/iconShape.spec.ts new file mode 100644 index 000000000..9a01932fb --- /dev/null +++ b/cypress/integration/rendering/iconShape.spec.ts @@ -0,0 +1,121 @@ +import { imgSnapshotTest } from '../../helpers/util'; + +const looks = ['classic', 'handDrawn'] as const; +const directions = ['TB', 'BT', 'LR', 'RL'] as const; +const forms = [undefined, 'square', 'circle', 'rounded'] as const; +const labelPos = [undefined, 't', 'b'] as const; + +looks.forEach((look) => { + directions.forEach((direction) => { + forms.forEach((form) => { + labelPos.forEach((pos) => { + describe(`Test iconShape in ${form ? `${form} form,` : ''} ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => { + it(`without label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is a label for icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with very long label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is a very very very very very long long long label for icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with markdown htmlLabels:true`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is **bold**
and strong for icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with markdown htmlLabels:false`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'This is **bold**
and strong for icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { + look, + htmlLabels: false, + flowchart: { htmlLabels: false }, + }); + }); + + it(`with styles`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'new icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + flowchartCode += ` style nAA 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`; + flowchartCode += ` nA --> nAA@{ icon: 'fa:bell', label: 'new icon shape'`; + if (form) { + flowchartCode += `, form: '${form}'`; + } + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + flowchartCode += ` nAA:::customClazz\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + }); + }); + }); + }); +}); + +describe('Test iconShape with different h', () => { + it('with different h', () => { + let flowchartCode = `flowchart TB\n`; + const icon = 'fa:bell'; + const iconHeight = 64; + flowchartCode += ` nA --> nAA@{ icon: '${icon}', label: 'icon with different h', h: ${iconHeight} }@\n`; + imgSnapshotTest(flowchartCode); + }); +}); diff --git a/cypress/integration/rendering/imageShape.spec.ts b/cypress/integration/rendering/imageShape.spec.ts new file mode 100644 index 000000000..228ca5d4e --- /dev/null +++ b/cypress/integration/rendering/imageShape.spec.ts @@ -0,0 +1,98 @@ +import { imgSnapshotTest } from '../../helpers/util'; + +const looks = ['classic', 'handDrawn'] as const; +const directions = ['TB', 'LR'] as const; +const labelPos = [undefined, 't', 'b'] as const; + +looks.forEach((look) => { + directions.forEach((direction) => { + labelPos.forEach((pos) => { + describe(`Test imageShape in ${look} look and dir ${direction} with label position ${pos ? pos : 'not defined'}`, () => { + it(`without label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', w: '100', h: '100' }@\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a label for image shape'`; + + flowchartCode += `, w: '100', h: '200'`; + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with very long label`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is a very very very very very long long long label for image shape'`; + + flowchartCode += `, w: '100', h: '250'`; + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + + it(`with markdown htmlLabels:true`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold**
and strong for image shape'`; + + flowchartCode += `, w: '550', h: '200'`; + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { look, htmlLabels: true }); + }); + + it(`with markdown htmlLabels:false`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'This is **bold**
and strong for image shape'`; + flowchartCode += `, w: '250', h: '200'`; + + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + imgSnapshotTest(flowchartCode, { + look, + htmlLabels: false, + flowchart: { htmlLabels: false }, + }); + }); + + it(`with styles`, () => { + let flowchartCode = `flowchart ${direction}\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`; + flowchartCode += `, w: '550', h: '200'`; + + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + flowchartCode += ` style A 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:#000000,stroke-dasharray: 5 5\n`; + flowchartCode += ` nA --> A@{ img: 'https://cdn.pixabay.com/photo/2020/02/22/18/49/paper-4871356_1280.jpg', label: 'new image shape'`; + + flowchartCode += `, w: '500', h: '550'`; + if (pos) { + flowchartCode += `, pos: '${pos}'`; + } + flowchartCode += ` }@\n`; + flowchartCode += ` A:::customClazz\n`; + imgSnapshotTest(flowchartCode, { look }); + }); + }); + }); + }); +}); diff --git a/cypress/integration/rendering/newShapes.spec.ts b/cypress/integration/rendering/newShapes.spec.ts index 4e382f829..906a04da3 100644 --- a/cypress/integration/rendering/newShapes.spec.ts +++ b/cypress/integration/rendering/newShapes.spec.ts @@ -4,45 +4,53 @@ const looks = ['classic'] as const; const directions = ['TB'] as const; const newShapesSet1 = [ 'triangle', - 'slopedRect', - 'tiltedCylinder', - 'flippedTriangle', + 'sloped-rect', + 'tilted-cylinder', + 'flipped-triangle', 'hourglass', ] as const; const newShapesSet2 = [ - 'taggedRect', - 'multiRect', - 'lightningBolt', - 'filledCircle', - 'windowPane', + 'tagged-rect', + 'multi-rect', + 'lightning-bolt', + 'filled-circle', + 'window-pane', ] as const; const newShapesSet3 = [ - 'curvedTrapezoid', - 'bowTieRect', - 'waveEdgedRectangle', - 'dividedRectangle', - 'crossedCircle', + 'curved-trapezoid', + 'bow-tie-rect', + 'wave-edge-rect', + 'divided-rectangle', + 'crossed-circle', ] as const; const newShapesSet4 = [ - 'waveRectangle', - 'trapezoidalPentagon', - 'linedCylinder', - 'multiWaveEdgedRectangle', - 'halfRoundedRectangle', + 'wave-rectangle', + 'notched-pentagon', + 'lined-cylinder', + 'multi-wave-edged-rectangle', + 'half-rounded-rect', ] as const; const newShapesSet5 = [ - 'linedWaveEdgedRect', - 'taggedWaveEdgedRectangle', - 'curlyBraceLeft', - 'curvedTrapezoid', - 'waveRectangle', + 'lined-wave-edged-rect', + 'tagged-wave-edged-rectangle', + 'brace-l', + 'curved-trapezoid', + 'wave-rectangle', ] as const; +const newShapesSet6 = ['brace-r', 'braces'] as const; // Aggregate all shape sets into a single array -const newShapesSets = [newShapesSet2] as const; +const newShapesSets = [ + newShapesSet1, + newShapesSet2, + newShapesSet3, + newShapesSet4, + newShapesSet5, + newShapesSet6, +]; looks.forEach((look) => { directions.forEach((direction) => { diff --git a/cypress/platform/saurabh.html b/cypress/platform/saurabh.html index aaa2bbc71..76c635084 100644 --- a/cypress/platform/saurabh.html +++ b/cypress/platform/saurabh.html @@ -1,54 +1,40 @@ - - - - - - - - - - - - - + } + + - -
-flowchart
-A
-      B@{ shape: multiRect, label: "title aduwab whgdawhbd wajhdbawj"  }@
-      F@{ shape: multiRect, label: "title "  }@
-      G@{ shape: multiRect, label: "title \n duawd \n duawd \n duawd \n duawd"  }@
-      C
-      D 
-      E 
-      C -->B
-      B --> D
-      B --> E
-      F --> A
-      A --> F
-  
+ +
+      flowchart TD
+       B2@{ icon: "fa:bell", form: "square", label: "B2 agsyua duadu", pos: "t", h: 80 }@
+       
 
-    
-  
-
+       W --> B2
+       X --> B2
+       Y --> B2
+       Z --> B2
+       B2 --sas--> C
+
+
+    
+
+      flowchart TB
+       A --test2--> B2@{ icon: "fa:bell", form: "rounded", label: "B2 aiduaid uyawduad uaduabd uyduadb", pos: "b" }@
+       B2 --test--> C
+       D --> B2 --> E
+       style B2 fill:#f9f,stroke:#333,stroke-width:4px
+  
+
+      flowchart BT
+       A --test2--> B2@{ icon: "fa:bell", form: "square", label: "B2", pos: "t", h: 40, w: 30 }@
+       B2 --test--> C
+       D --> B2 --> E
+  
+
+      flowchart BT
+       A --test2--> B2@{ icon: "fa:bell", label: "B2 awiugdawu uydgayuiwd wuydguy", pos: "b", h: 40, w: 30 }@
+       B2 --test--> C
+  
+
+      flowchart BT
+       A --test2--> B2@{ icon: "fa:bell", label: "B2 dawuygd ayuwgd uy", pos: "t", h: 40, w: 30 }@
+       B2 --test--> C
+  
+
+      flowchart TB
+       A --> B2@{ icon: "fa:bell", form: "circle", label: "test augfuyfavf ydvaubfuac", pos: "t", w: 200, h: 100 }@ --> C
+  
+
+      flowchart TB
+       A --> B2@{ icon: "fa:bell", form: "circle", label: "test augfuyfavf ydvaubfuac", pos: "b", w: 200, h: 100 }@ --> C
+       D --> B2 --> E
+  
+ + + + \ No newline at end of file diff --git a/cypress/platform/viewer.js b/cypress/platform/viewer.js index 77da253c2..2882be130 100644 --- a/cypress/platform/viewer.js +++ b/cypress/platform/viewer.js @@ -50,6 +50,23 @@ const contentLoaded = async function () { mermaid.registerLayoutLoaders(layouts); mermaid.initialize(graphObj.mermaid); + const staticBellIconPack = { + prefix: 'fa6-regular', + icons: { + bell: { + body: '', + width: 448, + }, + }, + width: 512, + height: 512, + }; + mermaid.registerIconPacks([ + { + name: 'fa', + loader: () => staticBellIconPack, + }, + ]); await mermaid.run(); } }; diff --git a/docs/adding_new_shape/Readme.md b/docs/adding_new_shape/Readme.md index 3b92eff2d..74e0f45ba 100644 --- a/docs/adding_new_shape/Readme.md +++ b/docs/adding_new_shape/Readme.md @@ -101,7 +101,7 @@ To add a new shape: - **Example**: ```typescript - import { Node } from '$root/rendering-util/types.d.ts'; + import { Node } from '../../types.d.ts'; export const myNewShape = async (parent: SVGAElement, node: Node) => { // Create your shape here diff --git a/docs/config/setup/interfaces/mermaid.LayoutData.md b/docs/config/setup/interfaces/mermaid.LayoutData.md index 6f128f4a7..7a8a302d8 100644 --- a/docs/config/setup/interfaces/mermaid.LayoutData.md +++ b/docs/config/setup/interfaces/mermaid.LayoutData.md @@ -16,11 +16,11 @@ ### config -• **config**: `MermaidConfig` +• **config**: [`MermaidConfig`](mermaid.MermaidConfig.md) #### Defined in -[packages/mermaid/src/rendering-util/types.d.ts:118](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.d.ts#L118) +[packages/mermaid/src/rendering-util/types.ts:122](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L122) --- @@ -30,7 +30,7 @@ #### Defined in -[packages/mermaid/src/rendering-util/types.d.ts:117](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.d.ts#L117) +[packages/mermaid/src/rendering-util/types.ts:121](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L121) --- @@ -40,4 +40,4 @@ #### Defined in -[packages/mermaid/src/rendering-util/types.d.ts:116](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.d.ts#L116) +[packages/mermaid/src/rendering-util/types.ts:120](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/rendering-util/types.ts#L120) diff --git a/docs/config/setup/interfaces/mermaid.ParseOptions.md b/docs/config/setup/interfaces/mermaid.ParseOptions.md index d9b141282..528e7ec35 100644 --- a/docs/config/setup/interfaces/mermaid.ParseOptions.md +++ b/docs/config/setup/interfaces/mermaid.ParseOptions.md @@ -19,4 +19,4 @@ The `parseError` function will not be called. #### Defined in -[packages/mermaid/src/types.ts:47](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L47) +[packages/mermaid/src/types.ts:55](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L55) diff --git a/docs/config/setup/interfaces/mermaid.ParseResult.md b/docs/config/setup/interfaces/mermaid.ParseResult.md index 62b412fce..c09445909 100644 --- a/docs/config/setup/interfaces/mermaid.ParseResult.md +++ b/docs/config/setup/interfaces/mermaid.ParseResult.md @@ -10,6 +10,18 @@ ## Properties +### config + +• **config**: [`MermaidConfig`](mermaid.MermaidConfig.md) + +The config passed as YAML frontmatter or directives + +#### Defined in + +[packages/mermaid/src/types.ts:66](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L66) + +--- + ### diagramType • **diagramType**: `string` @@ -18,4 +30,4 @@ The diagram type, e.g. 'flowchart', 'sequence', etc. #### Defined in -[packages/mermaid/src/types.ts:54](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L54) +[packages/mermaid/src/types.ts:62](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L62) diff --git a/docs/config/setup/interfaces/mermaid.RenderResult.md b/docs/config/setup/interfaces/mermaid.RenderResult.md index 8b706231c..6f297848c 100644 --- a/docs/config/setup/interfaces/mermaid.RenderResult.md +++ b/docs/config/setup/interfaces/mermaid.RenderResult.md @@ -39,7 +39,7 @@ bindFunctions?.(div); // To call bindFunctions only if it's present. #### Defined in -[packages/mermaid/src/types.ts:77](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L77) +[packages/mermaid/src/types.ts:89](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L89) --- @@ -51,7 +51,7 @@ The diagram type, e.g. 'flowchart', 'sequence', etc. #### Defined in -[packages/mermaid/src/types.ts:67](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L67) +[packages/mermaid/src/types.ts:79](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L79) --- @@ -63,4 +63,4 @@ The svg code for the rendered graph. #### Defined in -[packages/mermaid/src/types.ts:63](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L63) +[packages/mermaid/src/types.ts:75](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/types.ts#L75) diff --git a/docs/ecosystem/integrations-community.md b/docs/ecosystem/integrations-community.md index a9687359b..ef51b423c 100644 --- a/docs/ecosystem/integrations-community.md +++ b/docs/ecosystem/integrations-community.md @@ -145,7 +145,7 @@ Communication tools and platforms - [Mermaid Extension](https://www.mediawiki.org/wiki/Extension:Mermaid) - [PmWiki](https://www.pmwiki.org) - [MermaidJs Cookbook recipe](https://www.pmwiki.org/wiki/Cookbook/MermaidJs) -- [Semantic Media Wiki](https://semantic-mediawiki.org) +- [Semantic Media Wiki](https://www.semantic-mediawiki.org) - [Mermaid Plugin](https://github.com/SemanticMediaWiki/Mermaid) - [TiddlyWiki](https://tiddlywiki.com/) - [mermaid-tw5: wrapper for Mermaid Live](https://github.com/efurlanm/mermaid-tw5) diff --git a/docs/news/blog.md b/docs/news/blog.md index 372247b86..4d33f67f5 100644 --- a/docs/news/blog.md +++ b/docs/news/blog.md @@ -6,6 +6,12 @@ # Blog +## [Introducing Architecture Diagrams in Mermaid](https://www.mermaidchart.com/blog/posts/mermaid-supports-architecture-diagrams/) + +2 September 2024 · 2 mins + +Discover the fresh new and unique Neo and Hand-Drawn looks for Mermaid Diagrams, while still offering the classic look you love. + ## [Mermaid v11 is out!](https://www.mermaidchart.com/blog/posts/mermaid-v11/) 23 August 2024 · 2 mins diff --git a/docs/syntax/flowchart.md b/docs/syntax/flowchart.md index 3ea1580a2..b511c7cb4 100644 --- a/docs/syntax/flowchart.md +++ b/docs/syntax/flowchart.md @@ -316,53 +316,53 @@ This syntax creates a node A as a rectangle. It renders in the same way as `A["A Below is a comprehensive list of the newly introduced shapes and their corresponding semantic meanings, short names, and aliases: -| **Semantic Name** | **Shape Name** | **Short Name** | **Description** | **Alias Supported** | -| ------------------------------------- | --------------------------- | --------------- | ------------------------------ | ---------------------------------------- | -| **Process** | Rectangle | `rect` | Standard process shape | `proc`, `process` | -| **Event** | Rounded Rectangle | `rounded` | Represents an event | `event` | -| **Terminal Point** | Stadium | `stadium` | Terminal point | `term`, `pill` | -| **Subprocess** | Framed Rectangle | `fr` | Subprocess | `subproc`, `framed-rectangle` | -| **Database** | Cylinder | `cyl` | Database storage | `db`, `cylinder` | -| **Start** | Circle | `circle` | Starting point | | -| **Odd** | Odd | `odd` | Odd shape | | -| **Decision** | Diamond | `diam` | Decision-making step | `decision`, `diamond` | -| **Prepare Conditional** | Hexagon | `hex` | Preparation or condition step | `hexagon`, `prepare` | -| **Data Input/Output** | Lean Right | `l-r` | Represents input or output | `lean-right`, `in-out` | -| **Data Input/Output** | Lean Left | `l-l` | Represents output or input | `lean-left`, `out-in` | -| **Priority Action** | Trapezoid Base Bottom | `trap-b` | Priority action | `priority`, `trapezoid-bottom` | -| **Manual Operation** | Trapezoid Base Top | `trap-t` | Represents a manual task | `manual`, `trapezoid-top` | -| **Stop** | Double Circle | `dc` | Represents a stop point | `double-circle` | -| **Text Block** | Text Block | `text` | Text block | - | -| **Card** | Notched Rectangle | `notched-rect` | Represents a card | `card`, `notch-rect` | -| **Lined/Shaded Process** | Lined Rectangle | `lined-rect` | Lined process shape | `lined-proc` | -| **Start** | Small Circle | `sm-circ` | Small starting point | `start`, `small-circle` | -| **Stop** | Framed Circle | `framed-circle` | Stop point | `stop`, `framed-circle` | -| **Fork/Join** | Long Rectangle | `fork` | Fork or join in process flow | `join`, `long-rect` | -| **Collate** | Hourglass | `hourglass` | Represents a collate operation | - | -| **Comment** | Curly Brace | `brace` | Adds a comment | `comment`, `brace-l` | -| **Comment Right** | Curly Brace | `brace-r` | Adds a comment | - | -| **Comment with braces on both sides** | Curly Braces | `braces` | Adds a comment | - | -| **Com Link** | Lightning Bolt | `bolt` | Communication link | `com-link`, `lightning-bolt` | -| **Document** | Wave-Edged Rectangle | `we-rect` | Represents a document | `doc`, `wave-edge-rect` | -| **Delay** | Half-Rounded Rectangle | `delay` | Represents a delay | `half-rounded-rect` | -| **Direct Access Storage** | Tilted Cylinder | `t-cyl` | Direct access storage | `das`, `tilted-cylinder` | -| **Disk Storage** | Lined Cylinder | `l-cyl` | Disk storage | `disk`, `lined-cylinder` | -| **Display** | Curved Trapezoid | `cur-trap` | Represents a display | `disp`, `curved-trapezoid` | -| **Divided Process** | Divided Rectangle | `div-rect` | Divided process shape | `div-proc`, `divided-rectangle` | -| **Extract** | Small Triangle | `sm-tri` | Extraction process | `extract`, `small-triangle` | -| **Internal Storage** | Window Pane | `win-pane` | Internal storage | `internal-storage`, `window-pane` | -| **Junction** | Filled Circle | `fc` | Junction point | `junction`, `filled-circle` | -| **Lined Document** | Lined Wave-Edged Rectangle | `lin-we-rect` | Lined document | `lin-doc`, `lined-wave-edged-rect` | -| **Loop Limit** | Trapezoidal Pentagon | `not-pent` | Loop limit step | `loop-limit`, `notched-pentagon` | -| **Manual File** | Flipped Triangle | `flip-tria` | Manual file operation | `manual-file`, `flipped-triangle` | -| **Manual Input** | Sloped Rectangle | `sloped-rect` | Manual input step | `manual-input`, `sloped-rectangle` | -| **Multi-Document** | Multi-Wave-Edged Rectangle | `mul-we-rect` | Multiple documents | `mul-doc`, `multi-wave-edged-rectangle` | -| **Multi-Process** | Multi-Rect | `mul-rect` | Multiple processes | `mul-proc`, `multi-rect` | -| **Paper Tape** | Flag | `flag` | Paper tape | `paper-tape`, \`\` | -| **Stored Data** | Bow Tie Rectangle | `bt-rect` | Stored data | `stored-data`, `bow-tie-rect` | -| **Summary** | Crossed Circle | `cross-circle` | Summary | `summary`, `crossed-circle` | -| **Tagged Document** | Tagged Wave-Edged Rectangle | `tag-we-rect` | Tagged document | `tag-doc`, `tagged-wave-edged-rectangle` | -| **Tagged Process** | Tagged Rectangle | `tag-rect` | Tagged process | `tag-proc`, `tagged-rect` | +| **Semantic Name** | **Shape Name** | **Short Name** | **Description** | **Alias Supported** | +| ------------------------------------- | --------------------------- | --------------- | ------------------------------ | ------------------------------------------- | +| **Process** | Rectangle | `rect` | Standard process shape | `proc`, `process`, `rectangle` | +| **Event** | Rounded Rectangle | `rounded` | Represents an event | `event` | +| **Terminal Point** | Stadium | `stadium` | Terminal point | `term`, `pill` | +| **Subprocess** | Framed Rectangle | `fr` | Subprocess | `subproc`, `framed-rectangle`, `subroutine` | +| **Database** | Cylinder | `cyl` | Database storage | `db`, `cylinder` | +| **Start** | Circle | `circle` | Starting point | | +| **Odd** | Odd | `odd` | Odd shape | | +| **Decision** | Diamond | `diam` | Decision-making step | `decision`, `diamond` | +| **Prepare Conditional** | Hexagon | `hex` | Preparation or condition step | `hexagon`, `prepare` | +| **Data Input/Output** | Lean Right | `l-r` | Represents input or output | `lean-right`, `in-out` | +| **Data Input/Output** | Lean Left | `l-l` | Represents output or input | `lean-left`, `out-in` | +| **Priority Action** | Trapezoid Base Bottom | `trap-b` | Priority action | `priority`, `trapezoid-bottom`, `trapezoid` | +| **Manual Operation** | Trapezoid Base Top | `trap-t` | Represents a manual task | `manual`, `trapezoid-top`, `inv-trapezoid` | +| **Stop** | Double Circle | `dc` | Represents a stop point | `double-circle` | +| **Text Block** | Text Block | `text` | Text block | - | +| **Card** | Notched Rectangle | `notched-rect` | Represents a card | `card`, `notch-rect`, `notched-rect` | +| **Lined/Shaded Process** | Lined Rectangle | `lined-rect` | Lined process shape | `lined-proc`, `shaded-proc` | +| **Start** | Small Circle | `sm-circ` | Small starting point | `start`, `small-circle` | +| **Stop** | Framed Circle | `framed-circle` | Stop point | `stop`, `framed-circle` | +| **Fork/Join** | Long Rectangle | `fork` | Fork or join in process flow | `join`, `long-rect` | +| **Collate** | Hourglass | `hourglass` | Represents a collate operation | - | +| **Comment** | Curly Brace | `brace` | Adds a comment | `comment`, `brace-l` | +| **Comment Right** | Curly Brace | `brace-r` | Adds a comment | - | +| **Comment with braces on both sides** | Curly Braces | `braces` | Adds a comment | - | +| **Com Link** | Lightning Bolt | `bolt` | Communication link | `com-link`, `lightning-bolt` | +| **Document** | Wave-Edged Rectangle | `we-rect` | Represents a document | `doc`, `wave-edge-rect` | +| **Delay** | Half-Rounded Rectangle | `delay` | Represents a delay | `half-rounded-rect` | +| **Direct Access Storage** | Tilted Cylinder | `t-cyl` | Direct access storage | `das`, `tilted-cylinder` | +| **Disk Storage** | Lined Cylinder | `l-cyl` | Disk storage | `disk`, `lined-cylinder` | +| **Display** | Curved Trapezoid | `cur-trap` | Represents a display | `disp`, `curved-trapezoid`, `display` | +| **Divided Process** | Divided Rectangle | `div-rect` | Divided process shape | `div-proc`, `divided-rectangle` | +| **Extract** | Small Triangle | `sm-tri` | Extraction process | `extract`, `small-triangle` | +| **Internal Storage** | Window Pane | `win-pane` | Internal storage | `internal-storage`, `window-pane` | +| **Junction** | Filled Circle | `fc` | Junction point | `junction`, `filled-circle` | +| **Lined Document** | Lined Wave-Edged Rectangle | `lin-we-rect` | Lined document | `lin-doc`, `lined-wave-edged-rect` | +| **Loop Limit** | Trapezoidal Pentagon | `notch-pent` | Loop limit step | `loop-limit`, `notched-pentagon` | +| **Manual File** | Flipped Triangle | `flip-tri` | Manual file operation | `manual-file`, `flipped-triangle` | +| **Manual Input** | Sloped Rectangle | `sloped-rect` | Manual input step | `manual-input`, `sloped-rectangle` | +| **Multi-Document** | Multi-Wave-Edged Rectangle | `mul-we-rect` | Multiple documents | `mul-doc`, `multi-wave-edged-rectangle` | +| **Multi-Process** | Multi-Rect | `mul-rect` | Multiple processes | `mul-proc`, `multi-rect` | +| **Paper Tape** | Flag | `flag` | Paper tape | `paper-tape` | +| **Stored Data** | Bow Tie Rectangle | `bt-rect` | Stored data | `stored-data`, `bow-tie-rect` | +| **Summary** | Crossed Circle | `cross-circle` | Summary | `summary`, `crossed-circle` | +| **Tagged Document** | Tagged Wave-Edged Rectangle | `tag-we-rect` | Tagged document | `tag-doc`, `tagged-wave-edged-rectangle` | +| **Tagged Process** | Tagged Rectangle | `tag-rect` | Tagged process | `tag-proc`, `tagged-rect` | ### Example Flowchart with New Shapes diff --git a/eslint.config.js b/eslint.config.js index 8b4807bc5..3278c7eb4 100644 --- a/eslint.config.js +++ b/eslint.config.js @@ -23,6 +23,7 @@ export default tseslint.config( '**/generated/', '**/coverage/', 'packages/mermaid/src/config.type.ts', + 'packages/mermaid/src/docs/.vitepress/components.d.ts', ], }, { diff --git a/package.json b/package.json index 5683b6ed9..9b592394d 100644 --- a/package.json +++ b/package.json @@ -42,6 +42,7 @@ "test": "pnpm lint && vitest run", "test:watch": "vitest --watch", "test:coverage": "vitest --coverage", + "test:check:tsc": "tsx scripts/tsc-check.ts", "prepare": "husky && pnpm build", "pre-commit": "lint-staged" }, @@ -96,7 +97,7 @@ "eslint-plugin-cypress": "^3.3.0", "eslint-plugin-html": "^8.1.1", "eslint-plugin-jest": "^28.6.0", - "eslint-plugin-jsdoc": "^48.2.9", + "eslint-plugin-jsdoc": "^50.0.0", "eslint-plugin-json": "^4.0.0", "eslint-plugin-lodash": "^8.0.0", "eslint-plugin-markdown": "^5.0.0", diff --git a/packages/mermaid-layout-elk/src/render.ts b/packages/mermaid-layout-elk/src/render.ts index c6f9c0f67..36f3d5964 100644 --- a/packages/mermaid-layout-elk/src/render.ts +++ b/packages/mermaid-layout-elk/src/render.ts @@ -1,6 +1,12 @@ import { curveLinear } from 'd3'; import ELK from 'elkjs/lib/elk.bundled.js'; -import type { InternalHelpers, LayoutData, RenderOptions, SVG, SVGGroup } from 'mermaid'; +import type { + InternalHelpers, + LayoutData, + RenderOptions, + SVG, + SVGGroup, +} from '@mermaid-chart/mermaid'; import { type TreeData, findCommonAncestor } from './find-common-ancestor.js'; export const render = async ( @@ -224,7 +230,7 @@ export const render = async ( * Add edges to graph based on parsed graph definition */ const addEdges = async function ( - dataForLayout: { edges: any; direction: string }, + dataForLayout: { edges: any; direction?: string }, graph: { id?: string; layoutOptions?: { @@ -764,12 +770,12 @@ export const render = async ( layoutOptions: { 'elk.hierarchyHandling': 'INCLUDE_CHILDREN', 'elk.algorithm': algorithm, - 'nodePlacement.strategy': data4Layout.config.elk.nodePlacementStrategy, - 'elk.layered.mergeEdges': data4Layout.config.elk.mergeEdges, + 'nodePlacement.strategy': data4Layout.config.elk?.nodePlacementStrategy, + 'elk.layered.mergeEdges': data4Layout.config.elk?.mergeEdges, 'elk.direction': 'DOWN', 'spacing.baseValue': 35, 'elk.layered.unnecessaryBendpoints': true, - 'elk.layered.cycleBreaking.strategy': data4Layout.config.elk.cycleBreakingStrategy, + 'elk.layered.cycleBreaking.strategy': data4Layout.config.elk?.cycleBreakingStrategy, // 'spacing.nodeNode': 20, // 'spacing.nodeNodeBetweenLayers': 25, // 'spacing.edgeNode': 20, @@ -852,8 +858,8 @@ export const render = async ( ...node.layoutOptions, 'elk.algorithm': algorithm, 'elk.direction': dir2ElkDirection(node.dir), - 'nodePlacement.strategy': data4Layout.config['elk.nodePlacement.strategy'], - 'elk.layered.mergeEdges': data4Layout.config['elk.mergeEdges'], + 'nodePlacement.strategy': data4Layout.config.elk?.nodePlacementStrategy, + 'elk.layered.mergeEdges': data4Layout.config.elk?.mergeEdges, 'elk.hierarchyHandling': 'SEPARATE_CHILDREN', }; } diff --git a/packages/mermaid/CHANGELOG.md b/packages/mermaid/CHANGELOG.md index d7221d232..c810d2798 100644 --- a/packages/mermaid/CHANGELOG.md +++ b/packages/mermaid/CHANGELOG.md @@ -1,5 +1,21 @@ # mermaid +## 11.2.0 + +### Minor Changes + +- [#5831](https://github.com/mermaid-js/mermaid/pull/5831) [`64abf29`](https://github.com/mermaid-js/mermaid/commit/64abf29ea870eaa47148197f95ce714f85bd7eea) Thanks [@sidharthv96](https://github.com/sidharthv96)! - feat: Return parsed config from mermaid.parse + +### Patch Changes + +- [#5838](https://github.com/mermaid-js/mermaid/pull/5838) [`5e75320`](https://github.com/mermaid-js/mermaid/commit/5e75320d49eab65aca630dcc3c04c8d620a8bbf7) Thanks [@bollwyvl](https://github.com/bollwyvl)! - fix: Replace $root with relative paths + +## 11.1.1 + +### Patch Changes + +- [#5828](https://github.com/mermaid-js/mermaid/pull/5828) [`4c43d21`](https://github.com/mermaid-js/mermaid/commit/4c43d21196f784b6f483ae635fc462329f3d176f) Thanks [@knsv](https://github.com/knsv)! - fix: Fix for issue where self-loops in the root of diagrams break the rendering + ## 11.1.0 ### Minor Changes diff --git a/packages/mermaid/src/diagrams/architecture/architectureIcons.ts b/packages/mermaid/src/diagrams/architecture/architectureIcons.ts index dd6c99f9c..fac4a7b12 100644 --- a/packages/mermaid/src/diagrams/architecture/architectureIcons.ts +++ b/packages/mermaid/src/diagrams/architecture/architectureIcons.ts @@ -1,4 +1,4 @@ -import { unknownIcon } from '$root/rendering-util/icons.js'; +import { unknownIcon } from '../../rendering-util/icons.js'; import type { IconifyJSON } from '@iconify/types'; const wrapIcon = (icon: string) => { diff --git a/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts b/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts index 3abb69b9f..af9429539 100644 --- a/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts +++ b/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts @@ -1,4 +1,4 @@ -import { registerIconPacks } from '$root/rendering-util/icons.js'; +import { registerIconPacks } from '../../rendering-util/icons.js'; import type { Position } from 'cytoscape'; import cytoscape from 'cytoscape'; import type { FcoseLayoutOptions } from 'cytoscape-fcose'; diff --git a/packages/mermaid/src/diagrams/architecture/svgDraw.ts b/packages/mermaid/src/diagrams/architecture/svgDraw.ts index 357839394..b10a451fe 100644 --- a/packages/mermaid/src/diagrams/architecture/svgDraw.ts +++ b/packages/mermaid/src/diagrams/architecture/svgDraw.ts @@ -1,4 +1,4 @@ -import { getIconSVG } from '$root/rendering-util/icons.js'; +import { getIconSVG } from '../../rendering-util/icons.js'; import type cytoscape from 'cytoscape'; import { getConfig } from '../../diagram-api/diagramAPI.js'; import { createText } from '../../rendering-util/createText.js'; @@ -170,8 +170,8 @@ export const drawEdges = async function (edgesEl: D3Element, cy: cytoscape.Core) textElem.attr( 'transform', ` - translate(${midX}, ${midY - bboxOrig.height / 2}) - translate(${(x * bboxNew.width) / 2}, ${(y * bboxNew.height) / 2}) + translate(${midX}, ${midY - bboxOrig.height / 2}) + translate(${(x * bboxNew.width) / 2}, ${(y * bboxNew.height) / 2}) rotate(${-1 * x * y * 45}, 0, ${bboxOrig.height / 2}) ` ); diff --git a/packages/mermaid/src/diagrams/flowchart/flowDb.ts b/packages/mermaid/src/diagrams/flowchart/flowDb.ts index fff6aaa21..78260e967 100644 --- a/packages/mermaid/src/diagrams/flowchart/flowDb.ts +++ b/packages/mermaid/src/diagrams/flowchart/flowDb.ts @@ -15,7 +15,7 @@ import { getDiagramTitle, } from '../common/commonDb.js'; import type { FlowVertex, FlowClass, FlowSubGraph, FlowText, FlowEdge, FlowLink } from './types.js'; -import type { NodeMetaData } from '$root/types.js'; +import type { NodeMetaData } from '../../types.js'; const MERMAID_DOM_ID_PREFIX = 'flowchart-'; let vertexCounter = 0; @@ -144,6 +144,30 @@ export const addVertex = function ( if (doc?.label) { vertex.text = doc?.label; } + if (doc?.icon) { + vertex.icon = doc?.icon; + if (!doc.label) { + vertex.text = ''; + } + } + if (doc?.form) { + vertex.form = doc?.form; + } + if (doc?.pos) { + vertex.pos = doc?.pos; + } + if (doc?.img) { + vertex.img = doc?.img; + if (!doc.label) { + vertex.text = ''; + } + } + if (doc.w) { + vertex.assetWidth = Number(doc.w); + } + if (doc.h) { + vertex.assetHeight = Number(doc.h); + } } }; @@ -792,6 +816,21 @@ export const lex = { }; const getTypeFromVertex = (vertex: FlowVertex) => { + if (vertex?.img) { + return 'imageSquare'; + } + if (vertex?.icon) { + if (vertex.form === 'circle') { + return 'iconCircle'; + } + if (vertex.form === 'square') { + return 'iconSquare'; + } + if (vertex.form === 'rounded') { + return 'iconRounded'; + } + return 'icon'; + } if (vertex.type === 'square') { return 'squareRect'; } @@ -858,6 +897,11 @@ const addNodeFromVertex = ( link: vertex.link, linkTarget: vertex.linkTarget, tooltip: getTooltip(vertex.id), + icon: vertex.icon, + pos: vertex.pos, + img: vertex.img, + assetWidth: vertex.assetWidth, + assetHeight: vertex.assetHeight, }); } }; diff --git a/packages/mermaid/src/diagrams/flowchart/styles.ts b/packages/mermaid/src/diagrams/flowchart/styles.ts index 2c0feb5bf..9be910932 100644 --- a/packages/mermaid/src/diagrams/flowchart/styles.ts +++ b/packages/mermaid/src/diagrams/flowchart/styles.ts @@ -163,6 +163,20 @@ const getStyles = (options: FlowChartStyleOptions) => fill: none; stroke-width: 0; } + + .icon-shape { + background-color: ${options.edgeLabelBackground}; + p { + background-color: ${options.edgeLabelBackground}; + padding: 2px; + } + rect { + opacity: 0.5; + background-color: ${options.edgeLabelBackground}; + fill: ${options.edgeLabelBackground}; + } + text-align: center; + } `; export default getStyles; diff --git a/packages/mermaid/src/diagrams/flowchart/types.ts b/packages/mermaid/src/diagrams/flowchart/types.ts index ee64ae56b..97dc54fa7 100644 --- a/packages/mermaid/src/diagrams/flowchart/types.ts +++ b/packages/mermaid/src/diagrams/flowchart/types.ts @@ -11,6 +11,12 @@ export interface FlowVertex { styles: string[]; text?: string; type?: string; + icon?: string; + form?: string; + pos?: 't' | 'b'; + img?: string; + assetWidth?: number; + assetHeight?: number; } export interface FlowText { diff --git a/packages/mermaid/src/docs/adding_new_shape/Readme.md b/packages/mermaid/src/docs/adding_new_shape/Readme.md index e53d7a05c..5464707af 100644 --- a/packages/mermaid/src/docs/adding_new_shape/Readme.md +++ b/packages/mermaid/src/docs/adding_new_shape/Readme.md @@ -95,7 +95,7 @@ To add a new shape: - **Example**: ```typescript - import { Node } from '$root/rendering-util/types.d.ts'; + import { Node } from '../../types.d.ts'; export const myNewShape = async (parent: SVGAElement, node: Node) => { // Create your shape here diff --git a/packages/mermaid/src/docs/ecosystem/integrations-community.md b/packages/mermaid/src/docs/ecosystem/integrations-community.md index 15f802ed5..9970d1e9c 100644 --- a/packages/mermaid/src/docs/ecosystem/integrations-community.md +++ b/packages/mermaid/src/docs/ecosystem/integrations-community.md @@ -140,7 +140,7 @@ Communication tools and platforms - [Mermaid Extension](https://www.mediawiki.org/wiki/Extension:Mermaid) - [PmWiki](https://www.pmwiki.org) - [MermaidJs Cookbook recipe](https://www.pmwiki.org/wiki/Cookbook/MermaidJs) -- [Semantic Media Wiki](https://semantic-mediawiki.org) +- [Semantic Media Wiki](https://www.semantic-mediawiki.org) - [Mermaid Plugin](https://github.com/SemanticMediaWiki/Mermaid) - [TiddlyWiki](https://tiddlywiki.com/) - [mermaid-tw5: wrapper for Mermaid Live](https://github.com/efurlanm/mermaid-tw5) diff --git a/packages/mermaid/src/docs/news/blog.md b/packages/mermaid/src/docs/news/blog.md index f7f28bf4b..36a84396d 100644 --- a/packages/mermaid/src/docs/news/blog.md +++ b/packages/mermaid/src/docs/news/blog.md @@ -1,5 +1,11 @@ # Blog +## [Introducing Architecture Diagrams in Mermaid](https://www.mermaidchart.com/blog/posts/mermaid-supports-architecture-diagrams/) + +2 September 2024 · 2 mins + +Discover the fresh new and unique Neo and Hand-Drawn looks for Mermaid Diagrams, while still offering the classic look you love. + ## [Mermaid v11 is out!](https://www.mermaidchart.com/blog/posts/mermaid-v11/) 23 August 2024 · 2 mins diff --git a/packages/mermaid/src/docs/syntax/flowchart.md b/packages/mermaid/src/docs/syntax/flowchart.md index b979958dd..046c53e65 100644 --- a/packages/mermaid/src/docs/syntax/flowchart.md +++ b/packages/mermaid/src/docs/syntax/flowchart.md @@ -212,53 +212,53 @@ This syntax creates a node A as a rectangle. It renders in the same way as `A["A Below is a comprehensive list of the newly introduced shapes and their corresponding semantic meanings, short names, and aliases: -| **Semantic Name** | **Shape Name** | **Short Name** | **Description** | **Alias Supported** | -| ------------------------------------- | --------------------------- | --------------- | ------------------------------ | ---------------------------------------- | -| **Process** | Rectangle | `rect` | Standard process shape | `proc`, `process` | -| **Event** | Rounded Rectangle | `rounded` | Represents an event | `event` | -| **Terminal Point** | Stadium | `stadium` | Terminal point | `term`, `pill` | -| **Subprocess** | Framed Rectangle | `fr` | Subprocess | `subproc`, `framed-rectangle` | -| **Database** | Cylinder | `cyl` | Database storage | `db`, `cylinder` | -| **Start** | Circle | `circle` | Starting point | | -| **Odd** | Odd | `odd` | Odd shape | | -| **Decision** | Diamond | `diam` | Decision-making step | `decision`, `diamond` | -| **Prepare Conditional** | Hexagon | `hex` | Preparation or condition step | `hexagon`, `prepare` | -| **Data Input/Output** | Lean Right | `l-r` | Represents input or output | `lean-right`, `in-out` | -| **Data Input/Output** | Lean Left | `l-l` | Represents output or input | `lean-left`, `out-in` | -| **Priority Action** | Trapezoid Base Bottom | `trap-b` | Priority action | `priority`, `trapezoid-bottom` | -| **Manual Operation** | Trapezoid Base Top | `trap-t` | Represents a manual task | `manual`, `trapezoid-top` | -| **Stop** | Double Circle | `dc` | Represents a stop point | `double-circle` | -| **Text Block** | Text Block | `text` | Text block | - | -| **Card** | Notched Rectangle | `notched-rect` | Represents a card | `card`, `notch-rect` | -| **Lined/Shaded Process** | Lined Rectangle | `lined-rect` | Lined process shape | `lined-proc` | -| **Start** | Small Circle | `sm-circ` | Small starting point | `start`, `small-circle` | -| **Stop** | Framed Circle | `framed-circle` | Stop point | `stop`, `framed-circle` | -| **Fork/Join** | Long Rectangle | `fork` | Fork or join in process flow | `join`, `long-rect` | -| **Collate** | Hourglass | `hourglass` | Represents a collate operation | - | -| **Comment** | Curly Brace | `brace` | Adds a comment | `comment`, `brace-l` | -| **Comment Right** | Curly Brace | `brace-r` | Adds a comment | - | -| **Comment with braces on both sides** | Curly Braces | `braces` | Adds a comment | - | -| **Com Link** | Lightning Bolt | `bolt` | Communication link | `com-link`, `lightning-bolt` | -| **Document** | Wave-Edged Rectangle | `we-rect` | Represents a document | `doc`, `wave-edge-rect` | -| **Delay** | Half-Rounded Rectangle | `delay` | Represents a delay | `half-rounded-rect` | -| **Direct Access Storage** | Tilted Cylinder | `t-cyl` | Direct access storage | `das`, `tilted-cylinder` | -| **Disk Storage** | Lined Cylinder | `l-cyl` | Disk storage | `disk`, `lined-cylinder` | -| **Display** | Curved Trapezoid | `cur-trap` | Represents a display | `disp`, `curved-trapezoid` | -| **Divided Process** | Divided Rectangle | `div-rect` | Divided process shape | `div-proc`, `divided-rectangle` | -| **Extract** | Small Triangle | `sm-tri` | Extraction process | `extract`, `small-triangle` | -| **Internal Storage** | Window Pane | `win-pane` | Internal storage | `internal-storage`, `window-pane` | -| **Junction** | Filled Circle | `fc` | Junction point | `junction`, `filled-circle` | -| **Lined Document** | Lined Wave-Edged Rectangle | `lin-we-rect` | Lined document | `lin-doc`, `lined-wave-edged-rect` | -| **Loop Limit** | Trapezoidal Pentagon | `not-pent` | Loop limit step | `loop-limit`, `notched-pentagon` | -| **Manual File** | Flipped Triangle | `flip-tria` | Manual file operation | `manual-file`, `flipped-triangle` | -| **Manual Input** | Sloped Rectangle | `sloped-rect` | Manual input step | `manual-input`, `sloped-rectangle` | -| **Multi-Document** | Multi-Wave-Edged Rectangle | `mul-we-rect` | Multiple documents | `mul-doc`, `multi-wave-edged-rectangle` | -| **Multi-Process** | Multi-Rect | `mul-rect` | Multiple processes | `mul-proc`, `multi-rect` | -| **Paper Tape** | Flag | `flag` | Paper tape | `paper-tape`, `` | -| **Stored Data** | Bow Tie Rectangle | `bt-rect` | Stored data | `stored-data`, `bow-tie-rect` | -| **Summary** | Crossed Circle | `cross-circle` | Summary | `summary`, `crossed-circle` | -| **Tagged Document** | Tagged Wave-Edged Rectangle | `tag-we-rect` | Tagged document | `tag-doc`, `tagged-wave-edged-rectangle` | -| **Tagged Process** | Tagged Rectangle | `tag-rect` | Tagged process | `tag-proc`, `tagged-rect` | +| **Semantic Name** | **Shape Name** | **Short Name** | **Description** | **Alias Supported** | +| ------------------------------------- | --------------------------- | --------------- | ------------------------------ | ------------------------------------------- | +| **Process** | Rectangle | `rect` | Standard process shape | `proc`, `process`, `rectangle` | +| **Event** | Rounded Rectangle | `rounded` | Represents an event | `event` | +| **Terminal Point** | Stadium | `stadium` | Terminal point | `term`, `pill` | +| **Subprocess** | Framed Rectangle | `fr` | Subprocess | `subproc`, `framed-rectangle`, `subroutine` | +| **Database** | Cylinder | `cyl` | Database storage | `db`, `cylinder` | +| **Start** | Circle | `circle` | Starting point | | +| **Odd** | Odd | `odd` | Odd shape | | +| **Decision** | Diamond | `diam` | Decision-making step | `decision`, `diamond` | +| **Prepare Conditional** | Hexagon | `hex` | Preparation or condition step | `hexagon`, `prepare` | +| **Data Input/Output** | Lean Right | `l-r` | Represents input or output | `lean-right`, `in-out` | +| **Data Input/Output** | Lean Left | `l-l` | Represents output or input | `lean-left`, `out-in` | +| **Priority Action** | Trapezoid Base Bottom | `trap-b` | Priority action | `priority`, `trapezoid-bottom`, `trapezoid` | +| **Manual Operation** | Trapezoid Base Top | `trap-t` | Represents a manual task | `manual`, `trapezoid-top`, `inv-trapezoid` | +| **Stop** | Double Circle | `dc` | Represents a stop point | `double-circle` | +| **Text Block** | Text Block | `text` | Text block | - | +| **Card** | Notched Rectangle | `notched-rect` | Represents a card | `card`, `notch-rect`, `notched-rect` | +| **Lined/Shaded Process** | Lined Rectangle | `lined-rect` | Lined process shape | `lined-proc`, `shaded-proc` | +| **Start** | Small Circle | `sm-circ` | Small starting point | `start`, `small-circle` | +| **Stop** | Framed Circle | `framed-circle` | Stop point | `stop`, `framed-circle` | +| **Fork/Join** | Long Rectangle | `fork` | Fork or join in process flow | `join`, `long-rect` | +| **Collate** | Hourglass | `hourglass` | Represents a collate operation | - | +| **Comment** | Curly Brace | `brace` | Adds a comment | `comment`, `brace-l` | +| **Comment Right** | Curly Brace | `brace-r` | Adds a comment | - | +| **Comment with braces on both sides** | Curly Braces | `braces` | Adds a comment | - | +| **Com Link** | Lightning Bolt | `bolt` | Communication link | `com-link`, `lightning-bolt` | +| **Document** | Wave-Edged Rectangle | `we-rect` | Represents a document | `doc`, `wave-edge-rect` | +| **Delay** | Half-Rounded Rectangle | `delay` | Represents a delay | `half-rounded-rect` | +| **Direct Access Storage** | Tilted Cylinder | `t-cyl` | Direct access storage | `das`, `tilted-cylinder` | +| **Disk Storage** | Lined Cylinder | `l-cyl` | Disk storage | `disk`, `lined-cylinder` | +| **Display** | Curved Trapezoid | `cur-trap` | Represents a display | `disp`, `curved-trapezoid`, `display` | +| **Divided Process** | Divided Rectangle | `div-rect` | Divided process shape | `div-proc`, `divided-rectangle` | +| **Extract** | Small Triangle | `sm-tri` | Extraction process | `extract`, `small-triangle` | +| **Internal Storage** | Window Pane | `win-pane` | Internal storage | `internal-storage`, `window-pane` | +| **Junction** | Filled Circle | `fc` | Junction point | `junction`, `filled-circle` | +| **Lined Document** | Lined Wave-Edged Rectangle | `lin-we-rect` | Lined document | `lin-doc`, `lined-wave-edged-rect` | +| **Loop Limit** | Trapezoidal Pentagon | `notch-pent` | Loop limit step | `loop-limit`, `notched-pentagon` | +| **Manual File** | Flipped Triangle | `flip-tri` | Manual file operation | `manual-file`, `flipped-triangle` | +| **Manual Input** | Sloped Rectangle | `sloped-rect` | Manual input step | `manual-input`, `sloped-rectangle` | +| **Multi-Document** | Multi-Wave-Edged Rectangle | `mul-we-rect` | Multiple documents | `mul-doc`, `multi-wave-edged-rectangle` | +| **Multi-Process** | Multi-Rect | `mul-rect` | Multiple processes | `mul-proc`, `multi-rect` | +| **Paper Tape** | Flag | `flag` | Paper tape | `paper-tape` | +| **Stored Data** | Bow Tie Rectangle | `bt-rect` | Stored data | `stored-data`, `bow-tie-rect` | +| **Summary** | Crossed Circle | `cross-circle` | Summary | `summary`, `crossed-circle` | +| **Tagged Document** | Tagged Wave-Edged Rectangle | `tag-we-rect` | Tagged document | `tag-doc`, `tagged-wave-edged-rectangle` | +| **Tagged Process** | Tagged Rectangle | `tag-rect` | Tagged process | `tag-proc`, `tagged-rect` | ### Example Flowchart with New Shapes diff --git a/packages/mermaid/src/mermaid.ts b/packages/mermaid/src/mermaid.ts index a7ea01bff..9dec7ae38 100644 --- a/packages/mermaid/src/mermaid.ts +++ b/packages/mermaid/src/mermaid.ts @@ -2,7 +2,7 @@ * Web page integration module for the mermaid framework. It uses the mermaidAPI for mermaid * functionality and to render the diagrams to svg code! */ -import { registerIconPacks } from '$root/rendering-util/icons.js'; +import { registerIconPacks } from './rendering-util/icons.js'; import { dedent } from 'ts-dedent'; import type { MermaidConfig } from './config.type.js'; import { detectType, registerLazyLoadedDiagrams } from './diagram-api/detectType.js'; @@ -321,10 +321,10 @@ const executeQueue = async () => { executionQueueRunning = false; }; -interface ConfigTuple { - defaultConfig: MermaidConfig; - config: MermaidConfig; -} +// interface ConfigTuple { +// defaultConfig: MermaidConfig; +// config: MermaidConfig; +// } /** * Parse the text and validate the syntax. * @param text - The mermaid diagram definition. @@ -347,7 +347,7 @@ interface ConfigTuple { const parse = async ( text: string, parseOptions?: ParseOptions -): Promise => { +): Promise => { return new Promise((resolve, reject) => { // This promise will resolve when the render call is done. // It will be queued first and will be executed when it is first in line @@ -355,7 +355,7 @@ const parse = async ( new Promise((res, rej) => { mermaidAPI.parse(text, parseOptions).then( (r) => { - const result = r as Diagram & ConfigTuple; + const result = r; result.defaultConfig = mermaidAPI.defaultConfig; result.config = mermaidAPI.getConfig(); // This resolves for the promise for the queue handling diff --git a/packages/mermaid/src/mermaidAPI.spec.ts b/packages/mermaid/src/mermaidAPI.spec.ts index 1d4e0c963..c62d85457 100644 --- a/packages/mermaid/src/mermaidAPI.spec.ts +++ b/packages/mermaid/src/mermaidAPI.spec.ts @@ -1,4 +1,4 @@ -import { vi, it, expect, describe, beforeEach } from 'vitest'; +import { beforeEach, describe, expect, it, vi } from 'vitest'; // ------------------------------------- // Mocks and mocking @@ -66,8 +66,8 @@ vi.mock('stylis', () => { }); import { compile, serialize } from 'stylis'; -import { decodeEntities, encodeEntities } from './utils.js'; import { Diagram } from './Diagram.js'; +import { decodeEntities, encodeEntities } from './utils.js'; import { toBase64 } from './utils/base64.js'; /** diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts index d98e77137..53d4ff8b4 100644 --- a/packages/mermaid/src/mermaidAPI.ts +++ b/packages/mermaid/src/mermaidAPI.ts @@ -7,25 +7,25 @@ import { select } from 'd3'; import { compile, serialize, stringify } from 'stylis'; // @ts-ignore: TODO Fix ts errors import DOMPurify from 'dompurify'; +import isEmpty from 'lodash-es/isEmpty.js'; import { version } from '../package.json'; +import { addSVGa11yTitleDescription, setA11yDiagramInfo } from './accessibility.js'; +import assignWithDepth from './assignWithDepth.js'; import * as configApi from './config.js'; +import type { MermaidConfig } from './config.type.js'; import { addDiagrams } from './diagram-api/diagram-orchestration.js'; +import type { DiagramMetadata, DiagramStyleClassDef, Positions } from './diagram-api/types.js'; import { Diagram } from './Diagram.js'; +import { evaluate } from './diagrams/common/common.js'; import errorRenderer from './diagrams/error/errorRenderer.js'; import { attachFunctions } from './interactionDb.js'; import { log, setLogLevel } from './logger.js'; +import { preprocessDiagram } from './preprocess.js'; import getStyles from './styles.js'; import theme from './themes/index.js'; -import type { MermaidConfig } from './config.type.js'; -import { evaluate } from './diagrams/common/common.js'; -import isEmpty from 'lodash-es/isEmpty.js'; -import { setA11yDiagramInfo, addSVGa11yTitleDescription } from './accessibility.js'; -import type { DiagramMetadata, DiagramStyleClassDef, Positions } from './diagram-api/types.js'; -import { preprocessDiagram } from './preprocess.js'; +import type { D3Element, ParseOptions, ParseResult, RenderResult } from './types.js'; import { decodeEntities } from './utils.js'; import { toBase64 } from './utils/base64.js'; -import type { D3Element, ParseOptions, RenderResult } from './types.js'; -import assignWithDepth from './assignWithDepth.js'; const MAX_TEXTLENGTH = 50_000; const MAX_TEXTLENGTH_EXCEEDED_MSG = @@ -68,14 +68,14 @@ function processAndSetConfigs(text: string) { async function parse( text: string, parseOptions: ParseOptions & { suppressErrors: true } -): Promise; -async function parse(text: string, parseOptions?: ParseOptions): Promise; -async function parse(text: string, parseOptions?: ParseOptions): Promise { +): Promise; +async function parse(text: string, parseOptions?: ParseOptions): Promise; +async function parse(text: string, parseOptions?: ParseOptions): Promise { addDiagrams(); try { - const { code } = processAndSetConfigs(text); + const { code, config } = processAndSetConfigs(text); const diagram = await getDiagramFromText(code); - return diagram; + return { diagram, config, diagramType: diagram.type }; } catch (error) { if (parseOptions?.suppressErrors) { return false; diff --git a/packages/mermaid/src/preprocess.ts b/packages/mermaid/src/preprocess.ts index 10bc0adea..a62326070 100644 --- a/packages/mermaid/src/preprocess.ts +++ b/packages/mermaid/src/preprocess.ts @@ -49,7 +49,7 @@ const processDirectives = (code: string) => { * @param code - The code to preprocess. * @returns The object containing the preprocessed code, title, and configuration. */ -export function preprocessDiagram(code: string): DiagramMetadata & { code: string } { +export function preprocessDiagram(code: string) { const cleanedCode = cleanupText(code); const frontMatterResult = processFrontmatter(cleanedCode); const directiveResult = processDirectives(frontMatterResult.text); @@ -59,5 +59,5 @@ export function preprocessDiagram(code: string): DiagramMetadata & { code: strin code, title: frontMatterResult.title, config, - }; + } satisfies DiagramMetadata & { code: string }; } diff --git a/packages/mermaid/src/rendering-util/createText.ts b/packages/mermaid/src/rendering-util/createText.ts index a6ad7fa1c..845705210 100644 --- a/packages/mermaid/src/rendering-util/createText.ts +++ b/packages/mermaid/src/rendering-util/createText.ts @@ -1,7 +1,7 @@ /* eslint-disable @typescript-eslint/no-explicit-any */ // @ts-nocheck TODO: Fix types -import { getConfig } from '$root/diagram-api/diagramAPI.js'; -import common, { hasKatex, renderKatex } from '$root/diagrams/common/common.js'; +import { getConfig } from '../diagram-api/diagramAPI.js'; +import common, { hasKatex, renderKatex } from '../diagrams/common/common.js'; import { select } from 'd3'; import type { MermaidConfig } from '../config.type.js'; import type { SVGGroup } from '../diagram-api/types.js'; diff --git a/packages/mermaid/src/rendering-util/icons.ts b/packages/mermaid/src/rendering-util/icons.ts index 27709b822..5eef3f7eb 100644 --- a/packages/mermaid/src/rendering-util/icons.ts +++ b/packages/mermaid/src/rendering-util/icons.ts @@ -1,4 +1,4 @@ -import { log } from '$root/logger.js'; +import { log } from '../logger.js'; import type { ExtendedIconifyIcon, IconifyIcon, IconifyJSON } from '@iconify/types'; import type { IconifyIconCustomisations } from '@iconify/utils'; import { getIconData, iconToHTML, iconToSVG, replaceIDs, stringToIcon } from '@iconify/utils'; diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js index 5585a7624..b1faf37b3 100644 --- a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js +++ b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/index.js @@ -23,7 +23,7 @@ import { insertEdge, clear as clearEdges, } from '../../rendering-elements/edges.js'; -import { log } from '$root/logger.js'; +import { log } from '../../../logger.js'; import { getSubGraphTitleMargins } from '../../../utils/subGraphTitleMargins.js'; import { getConfig } from '../../../diagram-api/diagramAPI.js'; diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js index 54ad5d27f..f0e5cd5ed 100644 --- a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js +++ b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.js @@ -1,5 +1,5 @@ /** Decorates with functions required by mermaids dagre-wrapper. */ -import { log } from '$root/logger.js'; +import { log } from '../../../logger.js'; import * as graphlib from 'dagre-d3-es/src/graphlib/index.js'; import * as graphlibJson from 'dagre-d3-es/src/graphlib/json.js'; diff --git a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.spec.js b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.spec.js index dd71a2f7e..11acd44eb 100644 --- a/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.spec.js +++ b/packages/mermaid/src/rendering-util/layout-algorithms/dagre/mermaid-graphlib.spec.js @@ -6,7 +6,7 @@ import { extractDescendants, sortNodesByHierarchy, } from './mermaid-graphlib.js'; -import { setLogLevel, log } from '$root/logger.js'; +import { setLogLevel, log } from '../../../logger.js'; describe('Graphlib decorations', () => { let g; diff --git a/packages/mermaid/src/rendering-util/render.ts b/packages/mermaid/src/rendering-util/render.ts index 925e45dcf..1b28b8532 100644 --- a/packages/mermaid/src/rendering-util/render.ts +++ b/packages/mermaid/src/rendering-util/render.ts @@ -1,7 +1,7 @@ -import type { Positions, SVG } from '$root/diagram-api/types.js'; -import type { InternalHelpers } from '$root/internals.js'; -import { internalHelpers } from '$root/internals.js'; -import { log } from '$root/logger.js'; +import type { Positions, SVG } from '../diagram-api/types.js'; +import { log } from '../logger.js'; +import { internalHelpers } from '../internals.js'; +import type { InternalHelpers } from '../internals.js'; import type { LayoutData } from './types.js'; export interface RenderOptions { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js index 492336323..d8bd3afa5 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/clusters.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/clusters.js @@ -1,17 +1,14 @@ -import { getConfig } from '$root/diagram-api/diagramAPI.js'; -import { evaluate } from '$root/diagrams/common/common.js'; -import { log } from '$root/logger.js'; -import { getSubGraphTitleMargins } from '$root/utils/subGraphTitleMargins.js'; +import { getConfig } from '../../diagram-api/diagramAPI.js'; +import { evaluate } from '../../diagrams/common/common.js'; +import { log } from '../../logger.js'; +import { getSubGraphTitleMargins } from '../../utils/subGraphTitleMargins.js'; import { select } from 'd3'; import rough from 'roughjs'; import { createText } from '../createText.ts'; import intersectRect from '../rendering-elements/intersect/intersect-rect.js'; import createLabel from './createLabel.js'; import { createRoundedRectPathD } from './shapes/roundedRectPath.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import { styles2String, userNodeOverrides } from './shapes/handDrawnShapeStyles.js'; const rect = async (parent, node) => { log.info('Creating subgraph rect for ', node.id, node); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/createLabel.js b/packages/mermaid/src/rendering-util/rendering-elements/createLabel.js index 0afdbb714..482dbb9f1 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/createLabel.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/createLabel.js @@ -1,8 +1,8 @@ import { select } from 'd3'; -import { log } from '$root/logger.js'; -import { getConfig } from '$root/diagram-api/diagramAPI.js'; -import common, { evaluate, renderKatex, hasKatex } from '$root/diagrams/common/common.js'; -import { decodeEntities } from '$root/utils.js'; +import { log } from '../../logger.js'; +import { getConfig } from '../../diagram-api/diagramAPI.js'; +import common, { evaluate, renderKatex, hasKatex } from '../../diagrams/common/common.js'; +import { decodeEntities } from '../../utils.js'; /** * @param dom diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edgeMarker.spec.ts b/packages/mermaid/src/rendering-util/rendering-elements/edgeMarker.spec.ts index 05c7472c9..7702782c2 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edgeMarker.spec.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/edgeMarker.spec.ts @@ -1,5 +1,5 @@ /* eslint-disable @typescript-eslint/unbound-method */ -import type { SVG } from '$root/diagram-api/types.js'; +import type { SVG } from '../../diagram-api/types.js'; import type { Mocked } from 'vitest'; import { addEdgeMarkers } from './edgeMarker.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edgeMarker.ts b/packages/mermaid/src/rendering-util/rendering-elements/edgeMarker.ts index ea748d8aa..5371ac32d 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edgeMarker.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/edgeMarker.ts @@ -1,6 +1,6 @@ -import type { SVG } from '$root/diagram-api/types.js'; -import { log } from '$root/logger.js'; -import type { EdgeData } from '$root/types.js'; +import type { SVG } from '../../diagram-api/types.js'; +import { log } from '../../logger.js'; +import type { EdgeData } from '../../types.js'; /** * Adds SVG markers to a path element based on the arrow types specified in the edge. * diff --git a/packages/mermaid/src/rendering-util/rendering-elements/edges.js b/packages/mermaid/src/rendering-util/rendering-elements/edges.js index ba7e596bd..7ebb82cd9 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/edges.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/edges.js @@ -1,11 +1,10 @@ -import { getConfig } from '$root/diagram-api/diagramAPI.js'; -import { evaluate } from '$root/diagrams/common/common.js'; -import { log } from '$root/logger.js'; -import { createText } from '$root/rendering-util/createText.ts'; -import utils from '$root/utils.js'; -import { getLineFunctionsWithOffset } from '$root/utils/lineWithOffset.js'; -import { getSubGraphTitleMargins } from '$root/utils/subGraphTitleMargins.js'; -// import { curveBasis, curveLinear, curveCardinal, line, select } from 'd3'; +import { getConfig } from '../../diagram-api/diagramAPI.js'; +import { evaluate } from '../../diagrams/common/common.js'; +import { log } from '../../logger.js'; +import { createText } from '../createText.js'; +import utils from '../../utils.js'; +import { getLineFunctionsWithOffset } from '../../utils/lineWithOffset.js'; +import { getSubGraphTitleMargins } from '../../utils/subGraphTitleMargins.js'; import { curveBasis, line, select } from 'd3'; import rough from 'roughjs'; import createLabel from './createLabel.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/markers.js b/packages/mermaid/src/rendering-util/rendering-elements/markers.js index 83b6ddd17..f9777755c 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/markers.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/markers.js @@ -1,5 +1,5 @@ /** Setup arrow head and define the marker. The result is appended to the svg. */ -import { log } from '$root/logger.js'; +import { log } from '../../logger.js'; // Only add the number of markers that the diagram needs const insertMarkers = (elem, markerArray, type, id) => { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/nodes.js b/packages/mermaid/src/rendering-util/rendering-elements/nodes.js index ae2d22daf..a09967868 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/nodes.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/nodes.js @@ -1,4 +1,4 @@ -import { log } from '$root/logger.js'; +import { log } from '../../logger.js'; import { state } from './shapes/state.ts'; import { roundedRect } from './shapes/roundedRect.ts'; import { squareRect } from './shapes/squareRect.ts'; @@ -9,7 +9,7 @@ import { choice } from './shapes/choice.ts'; import { note } from './shapes/note.ts'; import { stadium } from './shapes/stadium.js'; import { rectWithTitle } from './shapes/rectWithTitle.js'; -import { getConfig } from '$root/diagram-api/diagramAPI.js'; +import { getConfig } from '../../diagram-api/diagramAPI.js'; import { subroutine } from './shapes/subroutine.js'; import { cylinder } from './shapes/cylinder.js'; import { circle } from './shapes/circle.js'; @@ -51,9 +51,14 @@ import { taggedWaveEdgedRectangle } from './shapes/taggedWaveEdgedRectangle.js'; import { curlyBraceLeft } from './shapes/curlyBraceLeft.js'; import { curlyBraceRight } from './shapes/curlyBraceRight.js'; import { curlyBraces } from './shapes/curlyBraces.js'; +import { iconSquare } from './shapes/iconSquare.js'; +import { iconCircle } from './shapes/iconCircle.js'; +import { icon } from './shapes/icon.js'; +import { imageSquare } from './shapes/imageSquare.js'; +import { iconRounded } from './shapes/iconRounded.js'; //Use these names as the left side to render shapes. -const shapes = { +export const shapes = { // States state, stateStart, @@ -77,19 +82,15 @@ const shapes = { stadium, pill: stadium, term: stadium, - windowPane, 'window-pane': windowPane, 'win-pane': windowPane, 'internal-storage': windowPane, - dividedRectangle, 'divided-rectangle': dividedRectangle, 'div-rect': dividedRectangle, 'div-proc': dividedRectangle, - taggedRect, 'tagged-rect': taggedRect, 'tag-rect': taggedRect, 'tag-proc': taggedRect, - multiRect, 'multi-rect': multiRect, 'mul-rect': multiRect, 'mul-proc': multiRect, @@ -104,46 +105,41 @@ const shapes = { cylinder, cyl: cylinder, db: cylinder, - tiltedCylinder, 'tilted-cylinder': tiltedCylinder, 't-cyl': tiltedCylinder, das: tiltedCylinder, - linedCylinder, 'lined-cylinder': linedCylinder, 'l-cyl': linedCylinder, disk: linedCylinder, // Circles circle, - doublecircle, 'double-circle': doublecircle, dc: doublecircle, - crossedCircle, 'crossed-circle': crossedCircle, 'cross-circle': crossedCircle, summary: crossedCircle, - filledCircle, 'filled-circle': filledCircle, fc: filledCircle, junction: filledCircle, - shadedProcess, 'lined-proc': shadedProcess, 'lined-rect': shadedProcess, + 'shaded-proc': shadedProcess, // Trapezoids trapezoid, - trapezoidBaseBottom: trapezoid, 'trapezoid-bottom': trapezoid, 'trap-b': trapezoid, priority: trapezoid, inv_trapezoid, + 'inv-trapezoid': inv_trapezoid, 'trapezoid-top': inv_trapezoid, 'trap-t': inv_trapezoid, manual: inv_trapezoid, - curvedTrapezoid, 'curved-trapezoid': curvedTrapezoid, 'cur-trap': curvedTrapezoid, disp: curvedTrapezoid, + display: curvedTrapezoid, // Hexagons & Misc Geometric hexagon, @@ -153,49 +149,40 @@ const shapes = { 'small-triangle': triangle, 'sm-tri': triangle, extract: triangle, - flippedTriangle, 'flipped-triangle': flippedTriangle, - 'flip-tria': flippedTriangle, + 'flip-tri': flippedTriangle, 'manual-file': flippedTriangle, - trapezoidalPentagon, 'notched-pentagon': trapezoidalPentagon, - 'not-pent': trapezoidalPentagon, + 'notch-pent': trapezoidalPentagon, 'loop-limit': trapezoidalPentagon, //wave Edged Rectangles - waveRectangle, 'wave-rectangle': waveRectangle, 'w-rect': waveRectangle, flag: waveRectangle, 'paper-tape': waveRectangle, - waveEdgedRectangle, 'wave-edge-rect': waveEdgedRectangle, + 'wave-edged-rectangle': waveEdgedRectangle, 'wave-rect': waveEdgedRectangle, 'we-rect': waveEdgedRectangle, doc: waveEdgedRectangle, - multiWaveEdgedRectangle, 'multi-wave-edged-rectangle': multiWaveEdgedRectangle, 'mul-we-rect': multiWaveEdgedRectangle, 'mul-doc': multiWaveEdgedRectangle, - linedWaveEdgedRect, 'lined-wave-edged-rect': linedWaveEdgedRect, 'lin-we-rect': linedWaveEdgedRect, 'lin-doc': linedWaveEdgedRect, - taggedWaveEdgedRectangle, 'tagged-wave-edged-rectangle': taggedWaveEdgedRectangle, 'tag-we-rect': taggedWaveEdgedRectangle, 'tag-doc': taggedWaveEdgedRectangle, // Custom Rectangles - bowTieRect, 'bow-tie-rect': bowTieRect, 'bt-rect': bowTieRect, 'stored-data': bowTieRect, - slopedRect, 'sloped-rectangle': slopedRect, 'sloped-rect': slopedRect, 'manual-input': slopedRect, - halfRoundedRectangle, 'half-rounded-rect': halfRoundedRectangle, delay: halfRoundedRectangle, card, @@ -220,19 +207,24 @@ const shapes = { text, anchor, diamond: question, - lightningBolt, + diam: question, + decision: question, 'lightning-bolt': lightningBolt, bolt: lightningBolt, 'com-link': lightningBolt, - curlyBraceLeft, 'brace-l': curlyBraceLeft, + brace: curlyBraceLeft, comment: curlyBraceLeft, hourglass, odd: rect_left_inv_arrow, labelRect, - curlyBraceRight, 'brace-r': curlyBraceRight, braces: curlyBraces, + iconSquare, + iconCircle, + icon, + iconRounded, + imageSquare, }; const nodeElems = new Map(); @@ -241,6 +233,8 @@ export const insertNode = async (elem, node, dir) => { let newEl; let el; + // console.log("node is ", node.icon, node.shape) + //special check for rect shape (with or without rounded corners) if (node.shape === 'rect') { if (node.rx && node.ry) { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/nodes.spec.js b/packages/mermaid/src/rendering-util/rendering-elements/nodes.spec.js new file mode 100644 index 000000000..2a0e7664c --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/nodes.spec.js @@ -0,0 +1,241 @@ +import exp from 'constants'; +import { shapes } from './nodes.js'; + +describe('Test Alias for shapes', function () { + // for each shape in docs/syntax/flowchart.md, along with its semantic name, short name, and alias name, add a test case + // Process | rect | proc | rectangle + it('should support alias for rectangle shape ', function () { + expect(shapes.process).toBe(shapes.rect); + expect(shapes.proc).toBe(shapes.rect); + expect(shapes.rectangle).toBe(shapes.rect); + }); + + // event | rounded + it('should support alias for rounded shape ', function () { + expect(shapes.event).toBe(shapes.rounded); + }); + + // stadium | pill | term + it('should support alias for stadium shape ', function () { + expect(shapes.pill).toBe(shapes.stadium); + expect(shapes.term).toBe(shapes.stadium); + }); + + // fr | subproc | framed-rectangle | subroutine + it('should support alias for subroutine shape ', function () { + expect(shapes['framed-rectangle']).toBe(shapes.fr); + expect(shapes.subproc).toBe(shapes.fr); + expect(shapes.subroutine).toBe(shapes.fr); + }); + + // cyl | db | cylinder + it('should support alias for cylinder shape ', function () { + expect(shapes.db).toBe(shapes.cylinder); + expect(shapes.cyl).toBe(shapes.cylinder); + }); + + // diam | decision | diamond + it('should support alias for diamond shape ', function () { + expect(shapes.diam).toBe(shapes.decision); + expect(shapes.diamond).toBe(shapes.decision); + }); + + // hex | hexagon | prepare + it('should support alias for hexagon shape ', function () { + expect(shapes.hex).toBe(shapes.hexagon); + expect(shapes.prepare).toBe(shapes.hexagon); + }); + + // l-r | lean-right | in-out + it('should support alias for lean-right shape ', function () { + expect(shapes['l-r']).toBe(shapes['lean-right']); + expect(shapes['in-out']).toBe(shapes['lean-right']); + }); + + // l-l | lean-left | out-in + it('should support alias for lean-left shape ', function () { + expect(shapes['l-l']).toBe(shapes['lean-left']); + expect(shapes['out-in']).toBe(shapes['lean-left']); + }); + + // trap-b | trapezoid-bottom | priority | trapezoid + it('should support alias for trapezoid shape ', function () { + expect(shapes['trapezoid-bottom']).toBe(shapes['trap-b']); + expect(shapes.priority).toBe(shapes['trap-b']); + expect(shapes.trapezoid).toBe(shapes['trap-b']); + }); + + // trap-t | trapezoid-top | manual | inv-trapezoid + it('should support alias for inv_trapezoid shape ', function () { + expect(shapes['trapezoid-top']).toBe(shapes['trap-t']); + expect(shapes.manual).toBe(shapes['trap-t']); + expect(shapes['inv-trapezoid']).toBe(shapes['trap-t']); + }); + + // dc | double-circle + it('should support alias for doublecircle shape ', function () { + expect(shapes['double-circle']).toBe(shapes.dc); + }); + + // notched-rect | card | notch-rect + it('should support alias for notched-rectangle shape ', function () { + expect(shapes.card).toBe(shapes['notched-rect']); + expect(shapes['notch-rect']).toBe(shapes['notched-rect']); + }); + + // lined-rect | lined-proc | shaded-proc + it('should support alias for shadedProcess shape ', function () { + expect(shapes['lined-proc']).toBe(shapes['lined-rect']); + expect(shapes['shaded-proc']).toBe(shapes['lined-rect']); + }); + + // sm-circ | small-circle | start + it('should support alias for smallCircle shape ', function () { + expect(shapes['small-circle']).toBe(shapes['sm-circ']); + expect(shapes.start).toBe(shapes['sm-circ']); + }); + + // framed-circle | stop + it('should support alias for framed circle shape ', function () { + expect(shapes.stop).toBe(shapes['framed-circle']); + }); + + // fork | join | long-rect + it('should support alias for fork shape ', function () { + expect(shapes.join).toBe(shapes.fork); + expect(shapes['long-rect']).toBe(shapes.fork); + }); + + // brace | comment | brace-l + it('should support alias for brace shape ', function () { + expect(shapes.comment).toBe(shapes.brace); + expect(shapes['brace-l']).toBe(shapes.brace); + }); + + // bolt | com-link | lightning-bolt + it('should support alias for bolt shape ', function () { + expect(shapes['com-link']).toBe(shapes.bolt); + expect(shapes['lightning-bolt']).toBe(shapes.bolt); + }); + + // we-rect | doc | wave-edge-rect | wave-edged-rectangle + it('should support alias for waveEdgedRectangle shape ', function () { + expect(shapes.doc).toBe(shapes['we-rect']); + expect(shapes['wave-edge-rect']).toBe(shapes['we-rect']); + expect(shapes['wave-edged-rectangle']).toBe(shapes['we-rect']); + }); + + // delay | half-rounded-rect + it('should support alias for halfRoundedRectangle shape ', function () { + expect(shapes.delay).toBe(shapes['half-rounded-rect']); + }); + + // t-cyl | das | titled-cylinder + it('should support alias for tilted-cylinder shape ', function () { + expect(shapes.das).toBe(shapes['t-cyl']); + expect(shapes['tilted-cylinder']).toBe(shapes['t-cyl']); + }); + + // l-cyl | disk | lined-cylinder + it('should support alias for linedCylinder shape ', function () { + expect(shapes.disk).toBe(shapes['l-cyl']); + expect(shapes['lined-cylinder']).toBe(shapes['l-cyl']); + }); + + // cur-trap | disp | display | curved-trapezoid + it('should support alias for curvedTrapezoid shape ', function () { + expect(shapes.disp).toBe(shapes['cur-trap']); + expect(shapes['curved-trapezoid']).toBe(shapes['cur-trap']); + expect(shapes.display).toBe(shapes['cur-trap']); + }); + + // div-rect | div-proc | divided-rectangle + it('should support alias for dividedRectangle shape ', function () { + expect(shapes['div-proc']).toBe(shapes['div-rect']); + expect(shapes['divided-rectangle']).toBe(shapes['div-rect']); + }); + + // sm-tri | extract | small-triangle | triangle + it('should support alias for smallTriangle shape ', function () { + expect(shapes.extract).toBe(shapes['sm-tri']); + expect(shapes['small-triangle']).toBe(shapes['sm-tri']); + expect(shapes.triangle).toBe(shapes['sm-tri']); + }); + + // win-pane | internal-storage | window-pane + it('should support alias for windowPane shape ', function () { + expect(shapes['internal-storage']).toBe(shapes['win-pane']); + expect(shapes['window-pane']).toBe(shapes['win-pane']); + }); + + // fc | junction | filled-circle + it('should support alias for filledCircle shape ', function () { + expect(shapes.junction).toBe(shapes.fc); + expect(shapes['filled-circle']).toBe(shapes.fc); + }); + + //lin-we-rect | lin-doc | lined-wave-edged-rect + it('should support alias for linedWaveEdgedRectangle shape ', function () { + expect(shapes['lin-doc']).toBe(shapes['lin-we-rect']); + expect(shapes['lined-wave-edged-rect']).toBe(shapes['lin-we-rect']); + }); + + // notch-pent | loop-limit | notched-pentagon + it('should support alias for notchedPentagon shape ', function () { + expect(shapes['loop-limit']).toBe(shapes['notch-pent']); + expect(shapes['notched-pentagon']).toBe(shapes['notch-pent']); + }); + + // flip-tri | manual-file | flipped-triangle + it('should support alias for flippedTriangle shape ', function () { + expect(shapes['manual-file']).toBe(shapes['flip-tri']); + expect(shapes['flipped-triangle']).toBe(shapes['flip-tri']); + }); + + //sloped-rect | manual-input | sloped-rectangle + it('should support alias for slopedRectangle shape ', function () { + expect(shapes['manual-input']).toBe(shapes['sloped-rect']); + expect(shapes['sloped-rectangle']).toBe(shapes['sloped-rect']); + }); + + // mul-we-rect | mul-doc | multi-wave-edged-rectangle + it('should support alias for multiWaveEdgedRectangle shape ', function () { + expect(shapes['mul-doc']).toBe(shapes['mul-we-rect']); + expect(shapes['multi-wave-edged-rectangle']).toBe(shapes['mul-we-rect']); + }); + + // mul-rect | mul-proc | multi-rect + it('should support alias for multiRect shape ', function () { + expect(shapes['mul-proc']).toBe(shapes['mul-rect']); + expect(shapes['multi-rect']).toBe(shapes['mul-rect']); + }); + + // flag | paper-tape + it('should support alias for paperTape shape ', function () { + expect(shapes['paper-tape']).toBe(shapes.flag); + }); + + // bt-rect| stored-data | bow-tie-rect + it('should support alias for bowTieRect shape ', function () { + expect(shapes['stored-data']).toBe(shapes['bt-rect']); + expect(shapes['bow-tie-rect']).toBe(shapes['bt-rect']); + }); + + // cross-circle | summary | crossed-circle + it('should support alias for crossedCircle shape ', function () { + expect(shapes.summary).toBe(shapes['cross-circle']); + expect(shapes['crossed-circle']).toBe(shapes['cross-circle']); + }); + + // tag-we-rect | tag-doc | tagged-wave-edged-rectangle + it('should support alias for taggedWaveEdgedRectangle shape ', function () { + expect(shapes['tag-doc']).toBe(shapes['tag-we-rect']); + expect(shapes['tagged-wave-edged-rectangle']).toBe(shapes['tag-we-rect']); + }); + + // tag-rect | tag-proc | tagged-rect + it('should support alias for taggedRect shape ', function () { + expect(shapes['tag-proc']).toBe(shapes['tag-rect']); + expect(shapes['tagged-rect']).toBe(shapes['tag-rect']); + }); +}); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/anchor.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/anchor.ts index b762e1c1d..bea32c975 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/anchor.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/anchor.ts @@ -1,11 +1,8 @@ -import { log } from '$root/logger.js'; +import { log } from '../../../logger.js'; import { updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; export const anchor = (parent: SVGAElement, node: Node): Promise => { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/bowTieRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/bowTieRect.ts index b4b683287..7a0309e94 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/bowTieRect.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/bowTieRect.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; function generateArcPoints( diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/card.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/card.ts index 56fb09be9..80c17d30a 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/card.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/card.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import { insertPolygonShape } from './insertPolygonShape.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/choice.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/choice.ts index 5d2804d40..6cb747898 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/choice.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/choice.ts @@ -1,6 +1,6 @@ import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import type { SVG } from '$root/diagram-api/types.js'; +import type { Node } from '../../types.js'; +import type { SVG } from '../../../diagram-api/types.js'; // @ts-ignore TODO: Fix rough typings import rough from 'roughjs'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; 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 444d67248..135720213 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/circle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/circle.ts @@ -1,11 +1,8 @@ -import { log } from '$root/logger.js'; +import { log } from '../../../logger.js'; import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; export const circle = async (parent: SVGAElement, node: Node): Promise => { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/crossedCircle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/crossedCircle.ts index b88a90e5c..f486fb21f 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/crossedCircle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/crossedCircle.ts @@ -1,8 +1,8 @@ -import { log } from '$root/logger.js'; +import { log } from '../../../logger.js'; import { getNodeClasses, updateNodeBounds } from './util.js'; -import type { SVG } from '$root/diagram-api/types.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { SVG } from '../../../diagram-api/types.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import intersect from '../intersect/index.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraceLeft.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraceLeft.ts index cd9d7f14e..9b98c9aec 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraceLeft.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraceLeft.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; function generateCirclePoints( diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraceRight.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraceRight.ts index 87787b311..9a051e273 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraceRight.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraceRight.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; function generateCirclePoints( diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraces.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraces.ts index 384c05e8a..9512c96d2 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraces.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curlyBraces.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; function generateCirclePoints( diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/curvedTrapezoid.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curvedTrapezoid.ts index 49993a992..ad31b1c09 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/curvedTrapezoid.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/curvedTrapezoid.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; function createCurvedTrapezoidPathD( 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 1b696dd3a..068df1ab0 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/cylinder.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/cylinder.ts @@ -1,11 +1,8 @@ import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { getConfig } from '$root/diagram-api/diagramAPI.js'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import { getConfig } from '../../../config.js'; import rough from 'roughjs'; export const createCylinderPathD = ( diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/dividedRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/dividedRect.ts index 8f66eb15e..a9f80d009 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/dividedRect.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/dividedRect.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; export const dividedRectangle = async (parent: SVGAElement, node: Node) => { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/document.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/document.ts index 9d7e5445b..377e7cbe7 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/document.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/document.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; export const createCylinderPathD = ( 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 bc30f112d..4093d5b2c 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/doubleCircle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/doubleCircle.ts @@ -1,11 +1,8 @@ -import { log } from '$root/logger.js'; +import { log } from '../../../logger.js'; import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; export const doublecircle = async (parent: SVGAElement, node: Node): Promise => { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/drawRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/drawRect.ts index 71eb93e25..6a7e9c28f 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/drawRect.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/drawRect.ts @@ -1,11 +1,8 @@ import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node, RectOptions } from '$root/rendering-util/types.d.ts'; +import type { Node, RectOptions } from '../../types.js'; import { createRoundedRectPathD } from './roundedRectPath.js'; -import { - userNodeOverrides, - styles2String, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import { userNodeOverrides, styles2String } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; export const drawRect = async (parent: SVGAElement, node: Node, options: RectOptions) => { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/filledCircle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/filledCircle.ts index 78a373f7b..53f7083ab 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/filledCircle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/filledCircle.ts @@ -1,11 +1,11 @@ -import { log } from '$root/logger.js'; +import { log } from '../../../logger.js'; import { getNodeClasses, updateNodeBounds } from './util.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import type { SVG } from '$root/diagram-api/types.js'; -import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import type { SVG } from '../../../diagram-api/types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import intersect from '../intersect/index.js'; -import { getConfig } from '$root/config.js'; +import { getConfig } from '../../../config.js'; export const filledCircle = (parent: SVG, node: Node) => { node.label = ''; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/flippedTriangle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/flippedTriangle.ts index c20372cda..339453e10 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/flippedTriangle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/flippedTriangle.ts @@ -1,11 +1,8 @@ -import { log } from '$root/logger.js'; +import { log } from '../../../logger.js'; import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import { createPathFromPoints } from './util.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/forkJoin.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/forkJoin.ts index 0c5f171e8..2492412dc 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/forkJoin.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/forkJoin.ts @@ -1,7 +1,7 @@ import { getNodeClasses, updateNodeBounds } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import type { SVG } from '$root/diagram-api/types.js'; +import type { Node } from '../../types.js'; +import type { SVG } from '../../../diagram-api/types.js'; import rough from 'roughjs'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; @@ -51,6 +51,5 @@ export const forkJoin = (parent: SVG, node: Node, dir: string) => { node.intersect = function (point) { return intersect.rect(node, point); }; - return shapeSvg; }; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/halfRoundedRectangle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/halfRoundedRectangle.ts index 053b76987..ae544fa95 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/halfRoundedRectangle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/halfRoundedRectangle.ts @@ -1,11 +1,8 @@ -import { log } from '$root/logger.js'; +import { log } from '../../../logger.js'; import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; function createHalfRoundedRectShapePathD(h: number, w: number, rx: number, ry: number) { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.ts index bb6a6c210..80e2a4423 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.ts @@ -1,5 +1,5 @@ -import { getConfig } from '$root/diagram-api/diagramAPI.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; +import type { Node } from '../../types.js'; // Striped fill like start or fork nodes in state diagrams export const solidStateFill = (color: string) => { 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 f1f697d60..7c8ec0a80 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/hexagon.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/hexagon.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import { insertPolygonShape } from './insertPolygonShape.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/hourglass.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/hourglass.ts index aeeb1607c..1cf6fb330 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/hourglass.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/hourglass.ts @@ -1,8 +1,8 @@ -import { log } from '$root/logger.js'; +import { log } from '../../../logger.js'; import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; export const hourglass = async (parent: SVGAElement, node: Node) => { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/icon.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/icon.ts new file mode 100644 index 000000000..96c2df848 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/icon.ts @@ -0,0 +1,120 @@ +import { log } from '../../../logger.js'; +import { labelHelper, updateNodeBounds } from './util.js'; +import type { Node } from '../../types.d.ts'; +import type { SVG } from '../../../diagram-api/types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import intersect from '../intersect/index.js'; +import { getIconSVG } from '../../icons.js'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; + +export const icon = async (parent: SVG, node: Node) => { + const { labelStyles } = styles2String(node); + node.labelStyle = labelStyles; + const assetHeight = node.assetHeight ?? 48; + const assetWidth = node.assetWidth ?? 48; + const iconSize = Math.max(assetHeight, assetWidth); + const defaultWidth = getConfig()?.flowchart?.wrappingWidth; + node.width = Math.max(iconSize, defaultWidth ?? 0); + const { shapeSvg, bbox, label } = await labelHelper(parent, node, 'icon-shape default'); + + const topLabel = node.pos === 't'; + + const height = iconSize; + const width = Math.max(iconSize, bbox.width); + + const x = -width / 2; + const y = -height / 2; + + // @ts-ignore - rough is not typed + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, { stroke: 'none', fill: 'none' }); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const iconNode = rc.rectangle(x, y, width, height, options); + + const iconShape = shapeSvg.insert(() => iconNode, ':first-child'); + + if (node.icon) { + const iconElem = shapeSvg.append('g'); + iconElem.html( + `${await getIconSVG(node.icon, { height: iconSize, fallbackPrefix: '' })}` + ); + const iconBBox = iconElem.node().getBBox(); + const iconWidth = iconBBox.width; + const iconHeight = iconBBox.height; + iconElem.attr( + 'transform', + `translate(${-iconWidth / 2},${topLabel ? height / 2 - iconHeight + bbox.height / 2 : -height / 2 - bbox.height / 2})` + ); + } + + label.attr( + 'transform', + `translate(${-width / 2 + width / 2 - bbox.width / 2},${topLabel ? -height / 2 - 5 - bbox.height / 2 : height / 2 - bbox.height / 2})` + ); + + iconShape.attr('transform', `translate(${0},${topLabel ? bbox.height / 2 : -bbox.height / 2})`); + + updateNodeBounds(node, shapeSvg); + + node.intersect = function (point) { + log.info('iconSquare intersect', node, point); + if (!node.label) { + return intersect.rect(node, point); + } + const dx = node.x ?? 0; + const dy = node.y ?? 0; + const nodeWidth = node.width ?? 0; + const nodeHeight = node.height ?? 0; + + if (topLabel) { + const points = [ + { x: dx - nodeWidth / 2, y: dy - nodeHeight / 2 - bbox.height / 2 }, + { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 - bbox.height / 2 }, + { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2 }, + { + x: dx + nodeWidth / 2 - (bbox.width - width) / 2, + y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2, + }, + { + x: dx + nodeWidth / 2 - (bbox.width - width) / 2, + y: dy + nodeHeight / 2 - bbox.height / 2, + }, + { + x: dx + nodeWidth / 2 - (bbox.width - width) / 2 - width, + y: dy + nodeHeight / 2 - bbox.height / 2, + }, + { + x: dx + nodeWidth / 2 - (bbox.width - width) / 2 - width, + y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2, + }, + { x: dx - nodeWidth / 2, y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2 }, + ]; + const pos = intersect.polygon(node, points, point); + return pos; + } else { + const points = [ + { x: dx - nodeWidth / 2 + (bbox.width - width) / 2, y: dy - nodeHeight / 2 }, + { x: dx - nodeWidth / 2 + (bbox.width - width) / 2 + width, y: dy - nodeHeight / 2 }, + { + x: dx - nodeWidth / 2 + (bbox.width - width) / 2 + width, + y: dy - nodeHeight / 2 + height, + }, + { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 + height }, + { x: dx + nodeWidth / 2, y: dy + nodeHeight / 2 }, + { x: dx - nodeWidth / 2, y: dy + nodeHeight / 2 }, + { x: dx - nodeWidth / 2, y: dy + nodeHeight / 2 - bbox.height }, + { x: dx - nodeWidth / 2 + (bbox.width - width) / 2, y: dy + nodeHeight / 2 - bbox.height }, + ]; + const pos = intersect.polygon(node, points, point); + return pos; + } + }; + + return shapeSvg; +}; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconCircle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconCircle.ts new file mode 100644 index 000000000..ab61dd65c --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconCircle.ts @@ -0,0 +1,87 @@ +import { log } from '../../../logger.js'; +import { labelHelper, updateNodeBounds } from './util.js'; +import type { Node } from '../../types.d.ts'; +import type { SVG } from '../../../diagram-api/types.js'; +import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import intersect from '../intersect/index.js'; +import { getIconSVG } from '../../icons.js'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; + +export const iconCircle = async (parent: SVG, node: Node, dir: string) => { + const translateHorizontal = dir === 'TB' || dir === 'BT' || dir === 'TD' || dir === 'DT'; + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const assetHeight = node.assetHeight ?? 48; + const assetWidth = node.assetWidth ?? 48; + const iconSize = Math.max(assetHeight, assetWidth); + const defaultWidth = getConfig()?.flowchart?.wrappingWidth; + node.width = Math.max(iconSize, defaultWidth ?? 0); + const { shapeSvg, bbox, halfPadding, label } = await labelHelper( + parent, + node, + 'icon-shape default' + ); + const { cssStyles } = node; + + const topLabel = node.pos === 't'; + + const diameter = iconSize + halfPadding * 2; + const { themeVariables } = getConfig(); + const { mainBkg } = themeVariables; + const { stylesMap } = compileStyles(node); + + // @ts-ignore - rough is not typed + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, { stroke: stylesMap.get('fill') || mainBkg }); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const iconNode = rc.circle(0, 0, diameter, options); + + const iconShape = shapeSvg.insert(() => iconNode, ':first-child'); + + if (node.icon) { + const iconElem = shapeSvg.append('g'); + iconElem.html( + `${await getIconSVG(node.icon, { height: iconSize, fallbackPrefix: '' })}` + ); + const iconBBox = iconElem.node().getBBox(); + const iconWidth = iconBBox.width; + const iconHeight = iconBBox.height; + iconElem.attr( + 'transform', + `translate(${-iconWidth / 2},${topLabel ? diameter / 2 - iconHeight - halfPadding + (translateHorizontal ? bbox.height / 2 : 0) : -diameter / 2 + halfPadding - (translateHorizontal ? bbox.height / 2 : 0)})` + ); + } + + label.attr( + 'transform', + `translate(${-diameter / 2 + diameter / 2 - bbox.width / 2},${topLabel ? -diameter / 2 - 2.5 - (translateHorizontal ? bbox.height / 2 : bbox.height) : diameter / 2 + 5 - (translateHorizontal ? bbox.height / 2 : 0)})` + ); + + if (translateHorizontal) { + iconShape.attr('transform', `translate(${0},${topLabel ? bbox.height / 2 : -bbox.height / 2})`); + } + + if (cssStyles && node.look !== 'handDrawn') { + iconShape.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + iconShape.selectAll('path').attr('style', nodeStyles); + } + + updateNodeBounds(node, shapeSvg); + + node.intersect = function (point) { + log.info('iconSquare intersect', node, point); + const pos = intersect.rect(node, point); + return pos; + }; + + return shapeSvg; +}; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconRounded.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconRounded.ts new file mode 100644 index 000000000..958a93dc3 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconRounded.ts @@ -0,0 +1,137 @@ +import { log } from '../../../logger.js'; +import { labelHelper, updateNodeBounds } from './util.js'; +import type { Node } from '../../types.js'; +import type { SVG } from '../../../diagram-api/types.js'; +import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import intersect from '../intersect/index.js'; +import { getIconSVG } from '../../icons.js'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; +import { createRoundedRectPathD } from './roundedRectPath.js'; + +export const iconRounded = async (parent: SVG, node: Node) => { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const assetHeight = node.assetHeight ?? 48; + const assetWidth = node.assetWidth ?? 48; + const iconSize = Math.max(assetHeight, assetWidth); + const defaultWidth = getConfig()?.flowchart?.wrappingWidth; + node.width = Math.max(iconSize, defaultWidth ?? 0); + const { shapeSvg, bbox, halfPadding, label } = await labelHelper( + parent, + node, + 'icon-shape default' + ); + const { cssStyles } = node; + + const topLabel = node.pos === 't'; + + const height = iconSize + halfPadding * 2; + const width = iconSize + halfPadding * 2; + const { themeVariables } = getConfig(); + const { mainBkg } = themeVariables; + const { stylesMap } = compileStyles(node); + + const x = -width / 2; + const y = -height / 2; + + // @ts-ignore - rough is not typed + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, { stroke: stylesMap.get('fill') || mainBkg }); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const iconNode = rc.path(createRoundedRectPathD(x, y, width, height, 5), options); + + const iconShape = shapeSvg.insert(() => iconNode, ':first-child'); + + if (node.icon) { + const iconElem = shapeSvg.append('g'); + iconElem.html( + `${await getIconSVG(node.icon, { height: iconSize, fallbackPrefix: '' })}` + ); + const iconBBox = iconElem.node().getBBox(); + const iconWidth = iconBBox.width; + const iconHeight = iconBBox.height; + iconElem.attr( + 'transform', + `translate(${-iconWidth / 2},${topLabel ? height / 2 - iconHeight + bbox.height / 2 : -height / 2 - bbox.height / 2})` + ); + } + + label.attr( + 'transform', + `translate(${-width / 2 + width / 2 - bbox.width / 2},${topLabel ? -height / 2 - 5 - bbox.height / 2 : height / 2 - bbox.height / 2})` + ); + + iconShape.attr('transform', `translate(${0},${topLabel ? bbox.height / 2 : -bbox.height / 2})`); + + if (cssStyles && node.look !== 'handDrawn') { + iconShape.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + iconShape.selectAll('path').attr('style', nodeStyles); + } + + updateNodeBounds(node, shapeSvg); + + node.intersect = function (point) { + log.info('iconSquare intersect', node, point); + if (!node.label) { + return intersect.rect(node, point); + } + const dx = node.x ?? 0; + const dy = node.y ?? 0; + const nodeWidth = node.width ?? 0; + const nodeHeight = node.height ?? 0; + + if (topLabel) { + const points = [ + { x: dx - nodeWidth / 2, y: dy - nodeHeight / 2 - bbox.height / 2 }, + { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 - bbox.height / 2 }, + { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2 }, + { + x: dx + nodeWidth / 2 - (bbox.width - width) / 2, + y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2, + }, + { + x: dx + nodeWidth / 2 - (bbox.width - width) / 2, + y: dy + nodeHeight / 2 - bbox.height / 2, + }, + { + x: dx + nodeWidth / 2 - (bbox.width - width) / 2 - width, + y: dy + nodeHeight / 2 - bbox.height / 2, + }, + { + x: dx + nodeWidth / 2 - (bbox.width - width) / 2 - width, + y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2, + }, + { x: dx - nodeWidth / 2, y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2 }, + ]; + const pos = intersect.polygon(node, points, point); + return pos; + } else { + const points = [ + { x: dx - nodeWidth / 2 + (bbox.width - width) / 2, y: dy - nodeHeight / 2 }, + { x: dx - nodeWidth / 2 + (bbox.width - width) / 2 + width, y: dy - nodeHeight / 2 }, + { + x: dx - nodeWidth / 2 + (bbox.width - width) / 2 + width, + y: dy - nodeHeight / 2 + height, + }, + { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 + height }, + { x: dx + nodeWidth / 2, y: dy + nodeHeight / 2 }, + { x: dx - nodeWidth / 2, y: dy + nodeHeight / 2 }, + { x: dx - nodeWidth / 2, y: dy + nodeHeight / 2 - bbox.height }, + { x: dx - nodeWidth / 2 + (bbox.width - width) / 2, y: dy + nodeHeight / 2 - bbox.height }, + ]; + const pos = intersect.polygon(node, points, point); + return pos; + } + }; + + return shapeSvg; +}; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconSquare.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconSquare.ts new file mode 100644 index 000000000..908210f3d --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/iconSquare.ts @@ -0,0 +1,136 @@ +import { log } from '../../../logger.js'; +import { labelHelper, updateNodeBounds } from './util.js'; +import type { Node } from '../../types.d.ts'; +import type { SVG } from '../../../diagram-api/types.js'; +import { compileStyles, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import intersect from '../intersect/index.js'; +import { getIconSVG } from '../../icons.js'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; + +export const iconSquare = async (parent: SVG, node: Node) => { + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + const assetHeight = node.assetHeight ?? 48; + const assetWidth = node.assetWidth ?? 48; + const iconSize = Math.max(assetHeight, assetWidth); + const defaultWidth = getConfig()?.flowchart?.wrappingWidth; + node.width = Math.max(iconSize, defaultWidth ?? 0); + const { shapeSvg, bbox, halfPadding, label } = await labelHelper( + parent, + node, + 'icon-shape default' + ); + const { cssStyles } = node; + + const topLabel = node.pos === 't'; + + const height = iconSize + halfPadding * 2; + const width = iconSize + halfPadding * 2; + const { themeVariables } = getConfig(); + const { mainBkg } = themeVariables; + const { stylesMap } = compileStyles(node); + + const x = -width / 2; + const y = -height / 2; + + // @ts-ignore - rough is not typed + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, { stroke: stylesMap.get('fill') || mainBkg }); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const iconNode = rc.rectangle(x, y, width, height, options); + + const iconShape = shapeSvg.insert(() => iconNode, ':first-child'); + + if (node.icon) { + const iconElem = shapeSvg.append('g'); + iconElem.html( + `${await getIconSVG(node.icon, { height: iconSize, fallbackPrefix: '' })}` + ); + const iconBBox = iconElem.node().getBBox(); + const iconWidth = iconBBox.width; + const iconHeight = iconBBox.height; + iconElem.attr( + 'transform', + `translate(${-iconWidth / 2},${topLabel ? height / 2 - iconHeight - halfPadding + bbox.height / 2 : -height / 2 + halfPadding - bbox.height / 2})` + ); + } + + label.attr( + 'transform', + `translate(${-width / 2 + width / 2 - bbox.width / 2},${topLabel ? -height / 2 - 5 - bbox.height / 2 : height / 2 - bbox.height / 2})` + ); + + iconShape.attr('transform', `translate(${0},${topLabel ? bbox.height / 2 : -bbox.height / 2})`); + + if (cssStyles && node.look !== 'handDrawn') { + iconShape.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + iconShape.selectAll('path').attr('style', nodeStyles); + } + + updateNodeBounds(node, shapeSvg); + + node.intersect = function (point) { + log.info('iconSquare intersect', node, point); + if (!node.label) { + return intersect.rect(node, point); + } + const dx = node.x ?? 0; + const dy = node.y ?? 0; + const nodeWidth = node.width ?? 0; + const nodeHeight = node.height ?? 0; + + if (topLabel) { + const points = [ + { x: dx - nodeWidth / 2, y: dy - nodeHeight / 2 - bbox.height / 2 }, + { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 - bbox.height / 2 }, + { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2 }, + { + x: dx + nodeWidth / 2 - (bbox.width - width) / 2, + y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2, + }, + { + x: dx + nodeWidth / 2 - (bbox.width - width) / 2, + y: dy + nodeHeight / 2 - bbox.height / 2, + }, + { + x: dx + nodeWidth / 2 - (bbox.width - width) / 2 - width, + y: dy + nodeHeight / 2 - bbox.height / 2, + }, + { + x: dx + nodeWidth / 2 - (bbox.width - width) / 2 - width, + y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2, + }, + { x: dx - nodeWidth / 2, y: dy - nodeHeight / 2 + bbox.height - bbox.height / 2 }, + ]; + const pos = intersect.polygon(node, points, point); + return pos; + } else { + const points = [ + { x: dx - nodeWidth / 2 + (bbox.width - width) / 2, y: dy - nodeHeight / 2 }, + { x: dx - nodeWidth / 2 + (bbox.width - width) / 2 + width, y: dy - nodeHeight / 2 }, + { + x: dx - nodeWidth / 2 + (bbox.width - width) / 2 + width, + y: dy - nodeHeight / 2 + height, + }, + { x: dx + nodeWidth / 2, y: dy - nodeHeight / 2 + height }, + { x: dx + nodeWidth / 2, y: dy + nodeHeight / 2 }, + { x: dx - nodeWidth / 2, y: dy + nodeHeight / 2 }, + { x: dx - nodeWidth / 2, y: dy + nodeHeight / 2 - bbox.height }, + { x: dx - nodeWidth / 2 + (bbox.width - width) / 2, y: dy + nodeHeight / 2 - bbox.height }, + ]; + const pos = intersect.polygon(node, points, point); + return pos; + } + }; + + return shapeSvg; +}; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/imageSquare.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/imageSquare.ts new file mode 100644 index 000000000..8845cf7f5 --- /dev/null +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/imageSquare.ts @@ -0,0 +1,135 @@ +import { log } from '../../../logger.js'; +import { getNodeClasses, labelHelper, updateNodeBounds } from './util.js'; +import type { Node } from '../../types.js'; +import type { SVG } from '../../../diagram-api/types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; +import rough from 'roughjs'; +import intersect from '../intersect/index.js'; +import { createPathFromPoints } from './util.js'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; + +export const imageSquare = async (parent: SVG, node: Node) => { + //image dimensions + const img = new Image(); + img.src = node?.img ?? ''; + await img.decode(); + + const imageNaturalWidth = Number(img.naturalWidth.toString().replace('px', '')); + const imageNaturalHeight = Number(img.naturalHeight.toString().replace('px', '')); + + const defaultWidth = getConfig().flowchart?.wrappingWidth; + const imageWidth = Math.max( + node.label ? (defaultWidth ?? 0) : 0, + node?.assetWidth ?? imageNaturalWidth + ); + const imageHeight = node?.assetHeight ?? imageNaturalHeight; + // const htmlLabels = getConfig().flowchart?.htmlLabels + + const imagePoints = [ + { x: -imageWidth / 2, y: -imageHeight }, + { x: imageWidth / 2, y: -imageHeight }, + { x: imageWidth / 2, y: 0 }, + { x: -imageWidth / 2, y: 0 }, + ]; + + //label dimensions + const { labelStyles, nodeStyles } = styles2String(node); + node.labelStyle = labelStyles; + + // const { shapeSvg, bbox, halfPadding, label } = await labelHelper( + // parent, + // node, + // 'icon-shape default' + // ); + + const { cssStyles } = node; + // const defaultHeight = bbox.height; + // node.height = Math.max(node.height ?? 0, node.label ? (defaultHeight ?? 0) : 0, imageHeight); + const labelWidth = Math.max(node.width ?? 0, node.label ? (defaultWidth ?? 0) : 0, imageWidth); + node.width = node.label ? labelWidth : 0; + const { shapeSvg, bbox, label } = await labelHelper(parent, node, getNodeClasses(node)); + + // const width = Math.max(bbox.width + (node.padding ?? 0), node?.width ?? 0); + const height = Math.max(bbox.height + (node.padding ?? 0), node?.height ?? 0); + const labelHeight = node.label ? height : 0; + + const imagePosition = node?.pos ?? 'b'; + + const labelPoints = [ + { x: -labelWidth / 2, y: 0 }, + { x: labelWidth / 2, y: 0 }, + { x: labelWidth / 2, y: labelHeight }, + { x: -labelWidth / 2, y: labelHeight }, + ]; + + // @ts-ignore - rough is not typed + const rc = rough.svg(shapeSvg); + const options = userNodeOverrides(node, {}); + // const options = userNodeOverrides(node, { stroke: stylesMap.get('fill') || mainBkg }); + + if (node.look !== 'handDrawn') { + options.roughness = 0; + options.fillStyle = 'solid'; + } + + const imagePath = createPathFromPoints(imagePoints); + const imagePathNode = rc.path(imagePath, options); + + const linePath = createPathFromPoints(labelPoints); + const lineNode = rc.path(linePath, { ...options }); + + const imageShape = shapeSvg.insert(() => lineNode, ':first-child').attr('opacity', 0); + imageShape.insert(() => imagePathNode, ':first-child'); + + imageShape.attr('transform', `translate(${0},${(imageHeight - labelHeight) / 2})`); + + // Image operations + if (node.img) { + const image = shapeSvg.append('image'); + + // Set the image attributes + image.attr('href', node.img); + image.attr('width', imageWidth); + image.attr('height', imageHeight); + image.attr('preserveAspectRatio', 'none'); + + // const yPos = + // imagePosition === 'b' + // ? -(imageHeight / 2) + // : labelHeight / 2 - height + (bbox.y + (bbox.top ?? 0)) * 2; + // image.attr('transform', `translate(${-imageWidth / 2}, ${-imageHeight/2 -labelHeight/2})`); + const yPos = + imagePosition === 'b' ? -imageHeight / 2 - labelHeight / 2 : (-imageHeight + labelHeight) / 2; + image.attr('transform', `translate(${-imageWidth / 2}, ${yPos})`); + } + + if (cssStyles && node.look !== 'handDrawn') { + imageShape.selectAll('path').attr('style', cssStyles); + } + + if (nodeStyles && node.look !== 'handDrawn') { + imageShape.selectAll('path').attr('style', nodeStyles); + } + + const yPos = + imagePosition === 'b' + ? (imageHeight + labelHeight) / 2 - bbox.height - (bbox.y - (bbox.top ?? 0)) + : -(imageHeight + labelHeight) / 2 + (node?.padding ?? 0) / 2 - (bbox.y - (bbox.top ?? 0)); + + label.attr('transform', `translate(${-bbox.width / 2 - (bbox.x - (bbox.left ?? 0))},${yPos})`); + + updateNodeBounds(node, imageShape); + + node.intersect = function (point) { + log.info('imageSquare intersect', node, point); + + // Combine image and label points into a single shape + const combinedPoints = [...imagePoints, ...labelPoints]; + + // Use the polygon intersection with the translated points + const pos = intersect.polygon(node, combinedPoints, point); + return pos; + }; + + return shapeSvg; +}; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/invertedTrapezoid.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/invertedTrapezoid.ts index 295d148c8..232dc4199 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/invertedTrapezoid.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/invertedTrapezoid.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import { insertPolygonShape } from './insertPolygonShape.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/labelRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/labelRect.ts index 174ea5ae1..7aff91902 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/labelRect.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/labelRect.ts @@ -1,4 +1,4 @@ -import type { Node, RectOptions } from '$root/rendering-util/types.d.ts'; +import type { Node, RectOptions } from '../../types.js'; import { drawRect } from './drawRect.js'; import { labelHelper, updateNodeBounds } from './util.js'; import intersect from '../intersect/index.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanLeft.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanLeft.ts index cf08e8811..c1e897336 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanLeft.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanLeft.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import { insertPolygonShape } from './insertPolygonShape.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanRight.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanRight.ts index 31f3ba053..03d75864f 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanRight.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/leanRight.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import { insertPolygonShape } from './insertPolygonShape.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/lightningBolt.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/lightningBolt.ts index 8dee6de78..1eb8e4206 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/lightningBolt.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/lightningBolt.ts @@ -1,8 +1,8 @@ -import { log } from '$root/logger.js'; -import { getNodeClasses, updateNodeBounds, createPathFromPoints } from './util.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import type { SVG } from '$root/diagram-api/types.js'; -import { userNodeOverrides } from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import { log } from '../../../logger.js'; +import { createPathFromPoints, getNodeClasses, updateNodeBounds } from './util.js'; +import type { Node } from '../../types.d.ts'; +import type { SVG } from '../../../diagram-api/types.js'; +import { userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import intersect from '../intersect/index.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/linedCylinder.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/linedCylinder.ts index ee074fd46..e54de9898 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/linedCylinder.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/linedCylinder.ts @@ -1,6 +1,6 @@ import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; +import type { Node } from '../../types.d.ts'; import rough from 'roughjs'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/linedWaveEdgedRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/linedWaveEdgedRect.ts index 954bbadcd..d1f23c492 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/linedWaveEdgedRect.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/linedWaveEdgedRect.ts @@ -6,7 +6,7 @@ import { createPathFromPoints, } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; +import type { Node } from '../../types.d.ts'; import rough from 'roughjs'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/multiRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/multiRect.ts index a836277c6..5484ccc43 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/multiRect.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/multiRect.ts @@ -1,9 +1,6 @@ import { labelHelper, getNodeClasses, updateNodeBounds, createPathFromPoints } from './util.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import intersect from '../intersect/index.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/multiWaveEdgedRectangle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/multiWaveEdgedRectangle.ts index bec117c0b..39017c711 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/multiWaveEdgedRectangle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/multiWaveEdgedRectangle.ts @@ -6,7 +6,7 @@ import { generateFullSineWavePoints, } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; +import type { Node } from '../../types.d.ts'; import rough from 'roughjs'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts index 57bb79d7d..516713ddc 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/note.ts @@ -1,7 +1,7 @@ -import { log } from '$root/logger.js'; +import { log } from '../../../logger.js'; import { getNodeClasses, labelHelper, updateNodeBounds } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; +import type { Node } from '../../types.js'; import rough from 'roughjs'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/question.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/question.ts index ba770ab4e..d571e4927 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/question.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/question.ts @@ -1,11 +1,8 @@ -import { log } from '$root/logger.js'; +import { log } from '../../../logger.js'; import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import { insertPolygonShape } from './insertPolygonShape.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectLeftInvArrow.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectLeftInvArrow.ts index a31778029..1494d435b 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectLeftInvArrow.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectLeftInvArrow.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; export const rect_left_inv_arrow = async ( diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectWithTitle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectWithTitle.ts index 857e60b8b..a71ebabd7 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectWithTitle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/rectWithTitle.ts @@ -1,17 +1,14 @@ -import type { Node } from '$root/rendering-util/types.d.ts'; +import type { Node } from '../../types.js'; import { select } from 'd3'; -import { evaluate } from '$root/diagrams/common/common.js'; +import { evaluate } from '../../../diagrams/common/common.js'; import { updateNodeBounds } from './util.js'; import createLabel from '../createLabel.js'; import intersect from '../intersect/index.js'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; -import { getConfig } from '$root/diagram-api/diagramAPI.js'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; import { createRoundedRectPathD } from './roundedRectPath.js'; -import { log } from '$root/logger.js'; +import { log } from '../../../logger.js'; export const rectWithTitle = async (parent: SVGElement, node: Node) => { const { labelStyles, nodeStyles } = styles2String(node); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/roundedRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/roundedRect.ts index 82b3fcd54..e43c00dc0 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/roundedRect.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/roundedRect.ts @@ -1,4 +1,4 @@ -import type { Node, RectOptions } from '$root/rendering-util/types.d.ts'; +import type { Node, RectOptions } from '../../types.js'; import { drawRect } from './drawRect.js'; export const roundedRect = async (parent: SVGAElement, node: Node) => { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/shadedProcess.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/shadedProcess.ts index 30bdb872a..a15c14d64 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/shadedProcess.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/shadedProcess.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; export const shadedProcess = async (parent: SVGAElement, node: Node) => { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/slopedRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/slopedRect.ts index afadd61c8..6f467f9e8 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/slopedRect.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/slopedRect.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; export const slopedRect = async (parent: SVGAElement, node: Node) => { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/squareRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/squareRect.ts index 8daeaec7a..5ab8e2833 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/squareRect.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/squareRect.ts @@ -1,4 +1,4 @@ -import type { Node, RectOptions } from '$root/rendering-util/types.d.ts'; +import type { Node, RectOptions } from '../../types.js'; import { drawRect } from './drawRect.js'; export const squareRect = async (parent: SVGAElement, node: Node) => { 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 a94effe69..c18a077b4 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stadium.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stadium.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import { createRoundedRectPathD } from './roundedRectPath.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/state.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/state.ts index 20916e8b7..566a8a2b4 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/state.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/state.ts @@ -1,4 +1,4 @@ -import type { Node, RectOptions } from '$root/rendering-util/types.d.ts'; +import type { Node, RectOptions } from '../../types.js'; import { drawRect } from './drawRect.js'; export const state = async (parent: SVGAElement, node: Node) => { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateEnd.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateEnd.ts index 882f0ba49..54a6bfaee 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateEnd.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateEnd.ts @@ -1,10 +1,10 @@ import { updateNodeBounds } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import type { SVG } from '$root/diagram-api/types.js'; +import type { Node } from '../../types.js'; +import type { SVG } from '../../../diagram-api/types.js'; import rough from 'roughjs'; import { solidStateFill, styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; -import { getConfig } from '$root/diagram-api/diagramAPI.js'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; export const stateEnd = (parent: SVG, node: Node) => { const { labelStyles, nodeStyles } = styles2String(node); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateStart.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateStart.ts index 341b82e1c..30d606a84 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateStart.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/stateStart.ts @@ -1,10 +1,10 @@ import { updateNodeBounds } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import type { SVG } from '$root/diagram-api/types.js'; +import type { Node } from '../../types.js'; +import type { SVG } from '../../../diagram-api/types.js'; import rough from 'roughjs'; import { solidStateFill } from './handDrawnShapeStyles.js'; -import { getConfig } from '$root/diagram-api/diagramAPI.js'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; export const stateStart = (parent: SVG, node: Node) => { const { themeVariables } = getConfig(); 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 43d8017d1..e47a34f71 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/subroutine.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/subroutine.ts @@ -1,13 +1,10 @@ import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { getConfig } from '$root/diagram-api/diagramAPI.js'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import { insertPolygonShape } from './insertPolygonShape.js'; +import { getConfig } from '../../../config.js'; export const createSubroutinePathD = ( x: number, diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedRect.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedRect.ts index c1fadf2ea..93046dd5b 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedRect.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedRect.ts @@ -1,9 +1,6 @@ import { labelHelper, getNodeClasses, updateNodeBounds, createPathFromPoints } from './util.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import intersect from '../intersect/index.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedWaveEdgedRectangle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedWaveEdgedRectangle.ts index b3bb0b032..84539093b 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedWaveEdgedRectangle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/taggedWaveEdgedRectangle.ts @@ -6,7 +6,7 @@ import { createPathFromPoints, } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; +import type { Node } from '../../types.d.ts'; import rough from 'roughjs'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/text.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/text.ts index 31b5e8d2d..abc5c17fe 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/text.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/text.ts @@ -1,7 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { styles2String } from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String } from './handDrawnShapeStyles.js'; export async function text(parent: SVGAElement, node: Node): Promise { const { labelStyles, nodeStyles } = styles2String(node); 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 5fe982d80..822d9cd40 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/tiltedCylinder.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/tiltedCylinder.ts @@ -1,9 +1,6 @@ import { labelHelper, getNodeClasses, updateNodeBounds } from './util.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import intersect from '../intersect/index.js'; 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 57d9e2f98..c3844cdf7 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoid.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoid.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.js'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import { insertPolygonShape } from './insertPolygonShape.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoidalPentagon.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoidalPentagon.ts index 7bd9e620c..391a057b0 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoidalPentagon.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/trapezoidalPentagon.ts @@ -1,10 +1,7 @@ import { labelHelper, updateNodeBounds, getNodeClasses, createPathFromPoints } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; export const trapezoidalPentagon = async (parent: SVGAElement, node: Node) => { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/triangle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/triangle.ts index e6f1d9955..fdb149023 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/triangle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/triangle.ts @@ -1,15 +1,12 @@ -import { log } from '$root/logger.js'; +import { log } from '../../../logger.js'; import { labelHelper, updateNodeBounds, getNodeClasses } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import { createPathFromPoints } from './util.js'; -import { evaluate } from '$root/diagrams/common/common.js'; -import { getConfig } from '$root/diagram-api/diagramAPI.js'; +import { evaluate } from '../../../diagrams/common/common.js'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; export const triangle = async (parent: SVGAElement, node: Node): Promise => { const { labelStyles, nodeStyles } = styles2String(node); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.js b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.js index 0f58fa131..1e68bb204 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.js +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/util.js @@ -1,8 +1,8 @@ -import { createText } from '$root/rendering-util/createText.ts'; -import { getConfig } from '$root/diagram-api/diagramAPI.js'; +import { createText } from '../../createText.js'; +import { getConfig } from '../../../diagram-api/diagramAPI.js'; import { select } from 'd3'; -import { evaluate, sanitizeText } from '$root/diagrams/common/common.js'; -import { decodeEntities } from '$root/utils.js'; +import { evaluate, sanitizeText } from '../../../diagrams/common/common.js'; +import { decodeEntities } from '../../../utils.js'; export const labelHelper = async (parent, node, _classes) => { let cssClasses; @@ -36,6 +36,7 @@ export const labelHelper = async (parent, node, _classes) => { width: node.width || getConfig().flowchart.wrappingWidth, cssClasses: 'markdown-node-label', style: node.labelStyle, + addSvgBackground: !!node.icon || !!node.img, }); // Get the size of the label let bbox = text.getBBox(); diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/waveEdgedRectangle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/waveEdgedRectangle.ts index 28c258dd3..a2d8e66b9 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/waveEdgedRectangle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/waveEdgedRectangle.ts @@ -6,7 +6,7 @@ import { createPathFromPoints, } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; +import type { Node } from '../../types.d.ts'; import rough from 'roughjs'; import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/waveRectangle.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/waveRectangle.ts index 188e54f69..785cd1565 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/waveRectangle.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/waveRectangle.ts @@ -6,11 +6,8 @@ import { generateFullSineWavePoints, } from './util.js'; import intersect from '../intersect/index.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; export const waveRectangle = async (parent: SVGAElement, node: Node) => { diff --git a/packages/mermaid/src/rendering-util/rendering-elements/shapes/windowPane.ts b/packages/mermaid/src/rendering-util/rendering-elements/shapes/windowPane.ts index 799b12b93..fa21c3a93 100644 --- a/packages/mermaid/src/rendering-util/rendering-elements/shapes/windowPane.ts +++ b/packages/mermaid/src/rendering-util/rendering-elements/shapes/windowPane.ts @@ -1,9 +1,6 @@ import { labelHelper, getNodeClasses, updateNodeBounds, createPathFromPoints } from './util.js'; -import type { Node } from '$root/rendering-util/types.d.ts'; -import { - styles2String, - userNodeOverrides, -} from '$root/rendering-util/rendering-elements/shapes/handDrawnShapeStyles.js'; +import type { Node } from '../../types.d.ts'; +import { styles2String, userNodeOverrides } from './handDrawnShapeStyles.js'; import rough from 'roughjs'; import intersect from '../intersect/index.js'; diff --git a/packages/mermaid/src/rendering-util/setupViewPortForSVG.ts b/packages/mermaid/src/rendering-util/setupViewPortForSVG.ts index e21f3304b..d3df5ddb7 100644 --- a/packages/mermaid/src/rendering-util/setupViewPortForSVG.ts +++ b/packages/mermaid/src/rendering-util/setupViewPortForSVG.ts @@ -1,6 +1,6 @@ -import { configureSvgSize } from '$root/setupGraphViewbox.js'; -import type { SVG } from '$root/diagram-api/types.js'; -import { log } from '$root/logger.js'; +import { configureSvgSize } from '../setupGraphViewbox.js'; +import type { SVG } from '../diagram-api/types.js'; +import { log } from '../logger.js'; export const setupViewPortForSVG = ( svg: SVG, diff --git a/packages/mermaid/src/rendering-util/types.d.ts b/packages/mermaid/src/rendering-util/types.ts similarity index 96% rename from packages/mermaid/src/rendering-util/types.d.ts rename to packages/mermaid/src/rendering-util/types.ts index 190888c15..a9b063d1d 100644 --- a/packages/mermaid/src/rendering-util/types.d.ts +++ b/packages/mermaid/src/rendering-util/types.ts @@ -1,5 +1,5 @@ export type MarkdownWordType = 'normal' | 'strong' | 'em'; -import type { MermaidConfig } from '../../dist/config.type'; +import type { MermaidConfig } from '../config.type.js'; export interface MarkdownWord { content: string; type: MarkdownWordType; @@ -38,7 +38,6 @@ export interface Node { tooltip?: string; padding?: number; //REMOVE?, use from LayoutData.config - Keep, this could be shape specific shape?: string; - tooltip?: string; isGroup: boolean; width?: number; height?: number; @@ -65,6 +64,11 @@ export interface Node { y?: number; look?: string; + icon?: string; + pos?: 't' | 'b'; + img?: string; + assetWidth?: number; + assetHeight?: number; } // Common properties for any edge in the system diff --git a/packages/mermaid/src/types.ts b/packages/mermaid/src/types.ts index 05c2defe2..d7a958156 100644 --- a/packages/mermaid/src/types.ts +++ b/packages/mermaid/src/types.ts @@ -1,7 +1,16 @@ export interface NodeMetaData { shape?: string; label?: string; + icon?: string; + form?: string; + pos?: 't' | 'b'; + img?: string; + w?: string; + h?: string; } +import type { MermaidConfig } from './config.type.js'; +import type { Diagram } from './Diagram.ts'; + export interface Point { x: number; y: number; @@ -52,6 +61,18 @@ export interface ParseResult { * The diagram type, e.g. 'flowchart', 'sequence', etc. */ diagramType: string; + /** + * The config passed as YAML frontmatter or directives + */ + config: MermaidConfig; + + defaultConfig?: MermaidConfig; + + /** + * The diagram AST + * + */ + diagram: Diagram; } // This makes it clear that we're working with a d3 selected element of some kind, even though it's hard to specify the exact type. export type D3Element = any; diff --git a/packages/mermaid/tsconfig.json b/packages/mermaid/tsconfig.json index 0f06a1731..66c6600f6 100644 --- a/packages/mermaid/tsconfig.json +++ b/packages/mermaid/tsconfig.json @@ -3,11 +3,7 @@ "compilerOptions": { "rootDir": "./src", "outDir": "./dist", - "types": ["vitest/importMeta", "vitest/globals"], - "baseUrl": ".", // This must be set if "paths" is set - "paths": { - "$root/*": ["src/*"] - } + "types": ["vitest/importMeta", "vitest/globals"] }, "include": [ "./src/**/*.ts", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index 005c3bfc2..e7c5ccd09 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -111,8 +111,8 @@ importers: specifier: ^28.6.0 version: 28.8.2(@typescript-eslint/eslint-plugin@8.4.0(@typescript-eslint/parser@8.4.0(eslint@9.9.1(jiti@1.21.6))(typescript@5.4.5))(eslint@9.9.1(jiti@1.21.6))(typescript@5.4.5))(eslint@9.9.1(jiti@1.21.6))(jest@29.7.0(@types/node@20.16.4))(typescript@5.4.5) eslint-plugin-jsdoc: - specifier: ^48.2.9 - version: 48.11.0(eslint@9.9.1(jiti@1.21.6)) + specifier: ^50.0.0 + version: 50.2.2(eslint@9.9.1(jiti@1.21.6)) eslint-plugin-json: specifier: ^4.0.0 version: 4.0.1 @@ -1720,8 +1720,8 @@ packages: '@emnapi/runtime@1.2.0': resolution: {integrity: sha512-bV21/9LQmcQeCPEg3BDFtvwL6cwiTMksYNWQQ4KOxCZikEGalWtenoZ0wCiukJINlGCIi2KXx01g4FoH/LxpzQ==} - '@es-joy/jsdoccomment@0.46.0': - resolution: {integrity: sha512-C3Axuq1xd/9VqFZpW4YAzOx5O9q/LP46uIQy/iNDpHG3fmPa6TBtvfglMCs3RBiBxAIi0Go97r8+jvTt55XMyQ==} + '@es-joy/jsdoccomment@0.48.0': + resolution: {integrity: sha512-G6QUWIcC+KvSwXNsJyDTHvqUdNoAVJPPgkc3+Uk4WBKqZvoXhlvazOgm9aL0HwihJLQf0l+tOE2UFzXBqCqgDw==} engines: {node: '>=16'} '@esbuild/aix-ppc64@0.21.5': @@ -4793,8 +4793,8 @@ packages: jest: optional: true - eslint-plugin-jsdoc@48.11.0: - resolution: {integrity: sha512-d12JHJDPNo7IFwTOAItCeJY1hcqoIxE0lHA8infQByLilQ9xkqrRa6laWCnsuCrf+8rUnvxXY1XuTbibRBNylA==} + eslint-plugin-jsdoc@50.2.2: + resolution: {integrity: sha512-i0ZMWA199DG7sjxlzXn5AeYZxpRfMJjDPUl7lL9eJJX8TPRoIaxJU4ys/joP5faM5AXE1eqW/dslCj3uj4Nqpg==} engines: {node: '>=18'} peerDependencies: eslint: ^7.0.0 || ^8.0.0 || ^9.0.0 @@ -6107,8 +6107,8 @@ packages: jsbn@0.1.1: resolution: {integrity: sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==} - jsdoc-type-pratt-parser@4.0.0: - resolution: {integrity: sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==} + jsdoc-type-pratt-parser@4.1.0: + resolution: {integrity: sha512-Hicd6JK5Njt2QB6XYFS7ok9e37O8AYk3jTcppG4YVQnYjOemymvTcmc7OWsmq/Qqj5TdRFO5/x/tIPmBeRtGHg==} engines: {node: '>=12.0.0'} jsdom@24.1.3: @@ -10670,11 +10670,11 @@ snapshots: tslib: 2.7.0 optional: true - '@es-joy/jsdoccomment@0.46.0': + '@es-joy/jsdoccomment@0.48.0': dependencies: comment-parser: 1.4.1 esquery: 1.6.0 - jsdoc-type-pratt-parser: 4.0.0 + jsdoc-type-pratt-parser: 4.1.0 '@esbuild/aix-ppc64@0.21.5': optional: true @@ -14164,9 +14164,9 @@ snapshots: - supports-color - typescript - eslint-plugin-jsdoc@48.11.0(eslint@9.9.1(jiti@1.21.6)): + eslint-plugin-jsdoc@50.2.2(eslint@9.9.1(jiti@1.21.6)): dependencies: - '@es-joy/jsdoccomment': 0.46.0 + '@es-joy/jsdoccomment': 0.48.0 are-docs-informative: 0.0.2 comment-parser: 1.4.1 debug: 4.3.6(supports-color@8.1.1) @@ -15812,7 +15812,7 @@ snapshots: jsbn@0.1.1: {} - jsdoc-type-pratt-parser@4.0.0: {} + jsdoc-type-pratt-parser@4.1.0: {} jsdom@24.1.3: dependencies: diff --git a/scripts/tsc-check.ts b/scripts/tsc-check.ts new file mode 100644 index 000000000..7a5ff50a9 --- /dev/null +++ b/scripts/tsc-check.ts @@ -0,0 +1,175 @@ +/** + * Verify the as-built tarballs can be imported into a fresh, out-of-tree TypeScript project. + */ + +/* eslint-disable no-console */ +import { mkdtemp, mkdir, writeFile, readFile, readdir, copyFile, rm } from 'node:fs/promises'; +import { execFileSync } from 'child_process'; +import * as path from 'path'; +import { fileURLToPath } from 'url'; +import { tmpdir } from 'node:os'; + +const __filename = fileURLToPath(import.meta.url); // get the resolved path to the file +const __dirname = path.dirname(__filename); // get the name of the directory + +/** + * Packages to build and import + */ +const PACKAGES = { + mermaid: 'mermaid', + '@mermaid-js/layout-elk': 'mermaid-layout-elk', + // TODO: these don't import cleanly yet due to exotic tsconfig.json requirements + // '@mermaid-js/mermaid-zenuml': 'mermaid-zenuml', + // '@mermaid-js/parser': 'parser', +}; + +/** + * Files to create in the temporary package. + */ +const SRC = { + // a minimal description of a buildable package + 'package.json': (tarballs: Record) => + JSON.stringify( + { + dependencies: tarballs, + scripts: { build: 'tsc -b --verbose' }, + devDependencies: { + // these are somewhat-unexpectedly required, and a downstream would need + // to match the real `package.json` values + 'type-fest': '*', + '@types/d3': '^7.4.3', + '@types/dompurify': '^3.0.5', + typescript: '*', + }, + }, + null, + 2 + ), + // a fairly strict TypeScript configuration + 'tsconfig.json': () => + JSON.stringify( + { + compilerOptions: { + allowSyntheticDefaultImports: true, + composite: true, + declaration: true, + esModuleInterop: true, + incremental: true, + lib: ['dom', 'es2020'], + module: 'esnext', + moduleResolution: 'node', + noEmitOnError: true, + noImplicitAny: true, + noUnusedLocals: true, + sourceMap: true, + target: 'es2020', + rootDir: './src', + outDir: './lib', + strict: true, + tsBuildInfoFile: 'lib/.tsbuildinfo', + }, + }, + null, + 2 + ), + // the simplest possible script: will everything even import? + 'src/index.ts': (tarballs) => { + const imports: string[] = []; + const outputs: string[] = []; + let i = 0; + for (const pkg of Object.keys(tarballs)) { + imports.push(`import * as pkg_${i} from '${pkg}';`); + outputs.push(`console.log(pkg_${i});`); + i++; + } + return [...imports, ...outputs].join('\n'); + }, +}; + +/** + * Commands to run after source files are created. + * + * `npm` is used to detect any unwanted `pnpm`-specific runtime "features". + */ +const COMMANDS = [ + ['npm', 'install'], + ['npm', 'run', 'build'], +]; + +/** + * Built files to expect after commands are executed. + */ +const LIB = ['lib/index.js', 'lib/index.js.map', 'lib/index.d.ts', 'lib/.tsbuildinfo']; + +/** + * Run a small out-of-tree build. + */ +async function main() { + console.warn('Checking out-of-tree TypeScript build using', Object.keys(PACKAGES).join('\n')); + const cwd = await mkdtemp(path.join(tmpdir(), 'mermaid-tsc-check-')); + console.warn('... creating temporary folder', cwd); + const tarballs = await buildTarballs(cwd); + + for (const [filename, generate] of Object.entries(SRC)) { + const dest = path.join(cwd, filename); + await mkdir(path.dirname(dest), { recursive: true }); + console.warn('... creating', dest); + const text = generate(tarballs); + await writeFile(dest, text); + console.info(text); + } + + for (const argv of COMMANDS) { + console.warn('... in', cwd); + console.warn('>>>', ...argv); + execFileSync(argv[0], argv.slice(1), { cwd }); + } + + for (const lib of LIB) { + const checkLib = path.join(cwd, lib); + console.warn('... checking built file', checkLib); + await readFile(checkLib, 'utf-8'); + } + + console.warn('... deleting', cwd); + await rm(cwd, { recursive: true, force: true }); + console.warn('... tsc-check OK for\n', Object.keys(PACKAGES).join('\n')); +} + +/** Build all the tarballs. */ +async function buildTarballs(tmp: string): Promise> { + const dist = path.join(tmp, 'dist'); + await mkdir(dist); + const promises: Promise[] = []; + const tarballs: Record = {}; + for (const [pkg, srcPath] of Object.entries(PACKAGES)) { + promises.push(buildOneTarball(pkg, srcPath, dist, tarballs)); + } + await Promise.all(promises); + return tarballs; +} + +/** Build a single tarball. */ +async function buildOneTarball( + pkg: string, + srcPath: string, + dist: string, + tarballs: Record +): Promise { + const cwd = await mkdtemp(path.join(dist, 'pack-')); + const pkgDir = path.join(__dirname, '../packages', srcPath); + const argv = ['pnpm', 'pack', '--pack-destination', cwd]; + console.warn('>>>', ...argv); + execFileSync(argv[0], argv.slice(1), { cwd: pkgDir }); + const built = await readdir(cwd); + const dest = path.join(dist, built[0]); + await copyFile(path.join(cwd, built[0]), dest); + await rm(cwd, { recursive: true, force: true }); + tarballs[pkg] = dest; +} + +void main().catch((err) => { + console.error(err); + console.error('!!! tsc-check FAIL: temp folder left in place. see logs above for failure notes'); + process.exit(1); +}); diff --git a/vite.config.ts b/vite.config.ts index ed0ba10f7..fb31841d6 100644 --- a/vite.config.ts +++ b/vite.config.ts @@ -2,15 +2,10 @@ import jison from './.vite/jisonPlugin.js'; import jsonSchemaPlugin from './.vite/jsonSchemaPlugin.js'; import typescript from '@rollup/plugin-typescript'; import { defaultExclude, defineConfig } from 'vitest/config'; -import path from 'path'; export default defineConfig({ resolve: { extensions: ['.js'], - alias: { - // Define your alias here - $root: path.resolve(__dirname, 'packages/mermaid/src'), - }, }, plugins: [ jison(),