diff --git a/.build/jsonSchema.ts b/.build/jsonSchema.ts index 50b9ff097..7a700c1e2 100644 --- a/.build/jsonSchema.ts +++ b/.build/jsonSchema.ts @@ -19,6 +19,7 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [ 'xyChart', 'requirement', 'mindmap', + 'kanban', 'timeline', 'gitGraph', 'c4', diff --git a/.changeset/kind-drinks-invent.md b/.changeset/kind-drinks-invent.md new file mode 100644 index 000000000..244be2bf6 --- /dev/null +++ b/.changeset/kind-drinks-invent.md @@ -0,0 +1,5 @@ +--- +'mermaid': minor +--- + +Adding Kanban board, a new diagram type diff --git a/.changeset/thick-elephants-search.md b/.changeset/thick-elephants-search.md new file mode 100644 index 000000000..5e29c42d6 --- /dev/null +++ b/.changeset/thick-elephants-search.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +fix: error `mermaid.parse` on an invalid shape, so that it matches the errors thrown by `mermaid.render` diff --git a/.cspell/mermaid-terms.txt b/.cspell/mermaid-terms.txt index 8551bd196..cb6db41de 100644 --- a/.cspell/mermaid-terms.txt +++ b/.cspell/mermaid-terms.txt @@ -12,6 +12,7 @@ gantt gitgraph gzipped handDrawn +kanban knsv Knut marginx diff --git a/cypress/integration/rendering/kanban.spec.ts b/cypress/integration/rendering/kanban.spec.ts new file mode 100644 index 000000000..6293776d6 --- /dev/null +++ b/cypress/integration/rendering/kanban.spec.ts @@ -0,0 +1,136 @@ +import { imgSnapshotTest } from '../../helpers/util.ts'; + +describe('Kanban diagram', () => { + it('1: should render a kanban with a single section', () => { + imgSnapshotTest( + `kanban + id1[Todo] + docs[Create Documentation] + docs[Create Blog about the new diagram] + `, + {} + ); + }); + it('2: should render a kanban with multiple sections', () => { + imgSnapshotTest( + `kanban + id1[Todo] + docs[Create Documentation] + id2 + docs[Create Blog about the new diagram] + `, + {} + ); + }); + it('3: should render a kanban with a single wrapping node', () => { + imgSnapshotTest( + `kanban + id1[Todo] + id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping] + `, + {} + ); + }); + it('4: should handle the height of a section with a wrapping node at the end', () => { + imgSnapshotTest( + `kanban + id1[Todo] + id2[One line] + id3[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping] + `, + {} + ); + }); + it('5: should handle the height of a section with a wrapping node at the top', () => { + imgSnapshotTest( + `kanban + id1[Todo] + id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping] + id3[One line] + `, + {} + ); + }); + it('6: should handle the height of a section with a wrapping node in the middle', () => { + imgSnapshotTest( + `kanban + id1[Todo] + id2[One line] + id3[Title of diagram is more than 100 chars when user duplicates diagram with 100 char, wrapping] + id4[One line] + `, + {} + ); + }); + it('6: should handle assigments', () => { + imgSnapshotTest( + `kanban + id1[Todo] + docs[Create Documentation] + id2[In progress] + docs[Create Blog about the new diagram]@{ assigned: 'knsv' } + `, + {} + ); + }); + it('7: should handle prioritization', () => { + imgSnapshotTest( + `kanban + id2[In progress] + vh[Very High]@{ priority: 'Very High' } + h[High]@{ priority: 'High' } + m[Default priority] + l[Low]@{ priority: 'Low' } + vl[Very Low]@{ priority: 'Very Low' } + `, + {} + ); + }); + it('7: should handle external tickets', () => { + imgSnapshotTest( + `kanban + id1[Todo] + docs[Create Documentation] + id2[In progress] + docs[Create Blog about the new diagram]@{ ticket: MC-2037 } + `, + {} + ); + }); + it('8: should handle assignments, prioritization and tickets ids in the same item', () => { + imgSnapshotTest( + `kanban + id2[In progress] + docs[Create Blog about the new diagram]@{ priority: 'Very Low', ticket: MC-2037, assigned: 'knsv' } + `, + {} + ); + }); + it('10: Full example', () => { + imgSnapshotTest( + `--- +config: + kanban: + ticketBaseUrl: 'https://abc123.atlassian.net/browse/#TICKET#' +--- +kanban + id1[Todo] + docs[Create Documentation] + docs[Create Blog about the new diagram] + id7[In progress] + id6[Create renderer so that it works in all cases. We also add som extra text here for testing purposes. And some more just for the extra flare.] + id8[Design grammar]@{ assigned: 'knsv' } + id9[Ready for deploy] + id10[Ready for test] + id11[Done] + id5[define getData] + id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char]@{ ticket: MC-2036, priority: 'Very High'} + id3[Update DB function]@{ ticket: MC-2037, assigned: knsv, priority: 'High' } + id4[Create parsing tests]@{ ticket: MC-2038, assigned: 'K.Sveidqvist', priority: 'High' } + id66[last item]@{ priority: 'Very Low', assigned: 'knsv' } + id12[Can't reproduce] + `, + {} + ); + }); +}); diff --git a/cypress/platform/knsv2.html b/cypress/platform/knsv2.html index d93881018..1de071283 100644 --- a/cypress/platform/knsv2.html +++ b/cypress/platform/knsv2.html @@ -34,6 +34,7 @@ /* background: rgb(221, 208, 208); */ /* background: #333; */ font-family: 'Arial'; + /* color: white; */ /* font-size: 18px !important; */ } @@ -83,349 +84,36 @@
----- - title: hello2 - config: - look: handDrawn - layout: elk - elk: - - ---- -stateDiagram-v2 - direction LR - accTitle: An idealized Open Source supply-chain graph - - %% - state "🟦 Importer" as author_importer - state "🟥 Supplier, Owner" as author_owner - state "🟨🟥 Maintainer, Author\n🟨 Custodian" as author - state "🟩 Distributor" as repository_distributor - state "🟦 Importer" as language_importer - state "🟦🟨 Packager" as language_packager - state "🟦🟨 OSS Steward" as language_steward - state "🟨 Curator" as language_curator - state "🟩 Distributor" as language_distributor - state "🟦 Contributor" as contributor - state "🟦 Importer" as package_importer - state "🟨 Patcher" as package_patcher - state "🟨🟦 Builder\n🟨🟦 Packager\n🟨🟦 Containerizer" as package_packager - state "🟨 Curator" as package_curator - state "🟩 Distributor" as package_distributor - state "🟦 Importer" as integrator_importer - state "🟥 Supplier, Manufacturer, Owner" as integrator_owner - state "🟦🟨🟥 Integrator, Developer" as integrator_developer - state "🟩🟨 SBOM Redactor\n🟩 Publisher" as integrator_publisher - state "🟦🟨 Builder" as integrator_builder - state "🟨 Deployer" as deployer - state "🟦 Vuln. Checker" as integrator_checker - state "🟩🟨 SBOM Redactor" as redactor - state "🟦 Consumer\n🟦 User" as consumer - state "🟦 Auditor" as auditor_internal - state "🟦 Auditor" as auditor_external - - %% - classDef createsSBOM stroke:red,stroke-width:3px; - classDef updatesSBOM stroke:yellow,stroke-width:3px; - classDef assemblesSBOM stroke:yellow,stroke-width:3px; - classDef distributesSBOM stroke:green,stroke-width:3px; - classDef verifiesSBOM stroke:#07f,stroke-width:3px; - - %% - class author_importer verifiesSBOM - class author_owner createsSBOM - class manufacturer_owner createsSBOM - class author assemblesSBOM - class package_importer verifiesSBOM - class package_patcher updatesSBOM - class package_packager assemblesSBOM - class package_curator distributesSBOM - class package_distributor distributesSBOM - class language_importer verifiesSBOM - class language_packager assemblesSBOM - class language_steward updatesSBOM - class language_curator distributesSBOM - class language_distributor distributesSBOM - class repository_distributor distributesSBOM - class integrator_importer verifiesSBOM - class integrator_owner createsSBOM - class integrator_developer assemblesSBOM - class integrator_publisher distributesSBOM - class integrator_builder assemblesSBOM - class integrator_checker verifiesSBOM - class deployer assemblesSBOM - class redactor distributesSBOM - class auditor_internal verifiesSBOM - class auditor_external verifiesSBOM - - state "Maintainer Environment" as environment_maintainer { - [*] --> author_importer - [*] --> author - author_importer --> author - author_owner --> author - author --> language_packager - } - - [*] --> environment_maintainer - - state "Language Ecosystem" as ecosystem_lang { - [*] --> language_importer - [*] --> language_steward - [*] --> language_curator - [*] --> language_distributor - language_importer --> language_distributor - language_importer --> language_curator - language_steward --> language_curator - language_curator --> language_distributor - } - - language_packager --> ecosystem_lang - ecosystem_lang --> ecosystem_lang - - state "Public Collaboration Ecosystem" as ecosystem_repo { - [*] --> repository_distributor - } - - author --> ecosystem_repo - ecosystem_repo --> author - - repository_distributor --> contributor - contributor --> repository_distributor - - state "Package Ecosystem" as ecosystem_package { - [*] --> package_importer - [*] --> package_packager - [*] --> package_patcher - package_importer --> package_patcher - package_importer --> package_packager - package_patcher --> package_packager - package_packager --> package_curator - package_packager --> package_distributor - package_curator --> package_distributor - } - - repository_distributor --> ecosystem_package - language_distributor --> ecosystem_package - ecosystem_package --> ecosystem_package - - state "Integrator Environment" as environment_integrator { - [*] --> integrator_developer - [*] --> integrator_importer - integrator_importer --> integrator_developer - integrator_owner --> integrator_developer - integrator_builder --> integrator_publisher - integrator_developer --> integrator_checker - integrator_checker --> integrator_developer - auditor_internal --> integrator_developer - integrator_developer --> integrator_builder - integrator_developer --> auditor_internal - } - - repository_distributor --> environment_integrator - language_distributor --> environment_integrator - package_distributor --> environment_integrator - - state "Production Environment" as environment_prod { - [*] --> deployer - deployer --> redactor - } - - integrator_publisher --> [*] - integrator_developer --> environment_prod - integrator_builder --> environment_prod - integrator_publisher --> environment_prod - - deployer --> auditor_external - deployer --> consumer - redactor --> consumer - - - -- -
---- -config: - look: neo ---- -flowchart RL - subgraph " " - A5@{ shape: manual-file, label: "a label"} - B5@{ shape: manual-input, label: "a label" } - C5@{ shape: mul-doc, label: "a label" } - D5@{ shape: mul-proc, label: "a label" } - E5@{ shape: paper-tape, label: "a label" } - B3@{ shape: das, label: "a label" } - C3@{ shape: disk, label: "a label" } - D4@{ shape: lin-doc, label: "a label" } - E4@{ shape: loop-limit, label: "a label" } - end - subgraph " " - B6@{ shape: summary, label: "a label" } - C6@{ shape: tag-we-rect, label: "a label" } - D6@{ shape: tag-rect, label: "a label" } - A2@{ shape: fork} - B2@{ shape: hourglass } - C2@{ shape: comment, label: "I am a comment" } - D2@{ shape: bolt } - D3@{ shape: disp, label: "a label" } - C4@{ shape: junction, label: "a label" } - A4@{ shape: extract, label: "a label"} - B52[a fr]@{ shape: fr } - end - subgraph " " - A1@{ shape: text, label: This is a textblock} - B1@{ shape: card, label: "a label" } - C1@{ shape: lined-proc, label: "a label" } - D1@{ shape: start, label: "a label" } - E1@{ shape: stop, label: "a label" } - E2@{ shape: doc, label: "a label" } - A6@{ shape: stored-data, label: "a label"} - A3@{ shape: delay, label: "a label" } - E3@{ shape: div-proc, label: "a label" } - B4[a label]@{ shape: win-pane } - end --
---- - title: hello2 - config: - look: handDrawn - elk: - ---- -%%{init: {"flowchart": {"defaultRenderer": "elk"}} }%% -flowchart TD - - A([Start]) -->|go to booking page| B("select - ISBS booking no") - A --> QQ{cancel booking} - A --> RR{no show} - A --> SS{change booking} - B -->C(wmpay_request_payment.request_type= 'partial', - wmpay_request_payment.status= 'paid', - pos_booking.booking_status= ‘partial’ and 'full_deposit') - style C text-align:left - C -->D{manage booking} - - D -->|cancel|E[ระบบแสดงช่องให้กรอกเหตุผล] - E -->F{กดปุ่ม 'cancel' หรือไม่} - F -->|Yes|G[ระบบบันทึกค่าใหม่ - และไม่สามารถแก้ไขข้อมูลได้] - F -->|No|H[กดปุ่ม 'close'] - H -->|ระบบไม่เปลี่ยนแปลงข้อมูล|Z - G -->|ระบบส่งข้อมูล|I[(POS_database)] - I -->|pos_booking.booking_status='cancel'|Z([End]) - - - D -->|no show|J[ระบบแสดงช่องให้กรอกเหตุผล] - J -->K{กดปุ่ม 'noshow' หรือไม่} - K -->|Yes|L[ระบบสร้างใบเสร็จอัตโนมัติ - Product_id: 439, - ItemName: no show] - style L text-align:left - - K -->|No|O[กดปุ่ม 'close'] - O -->|ระบบไม่เปลี่ยนแปลงข้อมูล|Z - L -->M[ระบบบันทึกค่าใหม่] - M -->|ระบบส่งข้อมูล|N[(POS_database)] - N -->|pos_booking.booking_status=‘noshow’|Z - - - --
---- - title: hello2 - config: - look: handDrawn - layout: dagre - elk: - nodePlacementStrategy: BRANDES_KOEPF ---- -flowchart - A --> A - subgraph A - B --> B - subgraph B - C - end - end - - --
---- -config: - look: handdrawn - flowchart: - htmlLabels: true ---- -flowchart - A[I am a long text, where do I go??? handdrawn - true] --
---- -config: - flowchart: - htmlLabels: false ---- -flowchart - A[I am a long text, where do I go??? classic - false] --
---- -config: - flowchart: - htmlLabels: true ---- -flowchart - A[I am a long text, where do I go??? classic - true] --
-flowchart LR - id1(Start)-->id2(Stop) - style id1 fill:#f9f,stroke:#333,stroke-width:4px - style id2 fill:#bbf,stroke:#f66,stroke-width:2px,color:#fff,stroke-dasharray: 5 5 - - -- -
- flowchart LR - A:::foo & B:::bar --> C:::foobar - classDef foo stroke:#f00 - classDef bar stroke:#0f0 - classDef ash color:red - class C ash - style C stroke:#00f, fill:black - --
- stateDiagram - A:::foo - B:::bar --> C:::foobar - classDef foo stroke:#f00 - classDef bar stroke:#0f0 - style C stroke:#00f, fill:black, color:white - +kanban + id2[In progress] + docs[Create Blog about the new diagram]@{ priority: 'Very Low', ticket: MC-2037, assigned: 'knsv' }-
-flowchart TB - A@{ - label: "aksljhf kasjdh" - } +--- +config: + kanban: + ticketBaseUrl: 'https://mermaidchart.atlassian.net/browse/#TICKET#' + # sectionWidth: 300 +--- +kanban + Todo + [Create Documentation] + docs[Create Blog about the new diagram] + id7[In progress] + id6[Create renderer so that it works in all cases. We also add som extra text here for testing purposes. And some more just for the extra flare.] + id9[Ready for deploy] + id8[Design grammar]@{ assigned: 'knsv' } + id10[Ready for test] + id4[Create parsing tests]@{ ticket: MC-2038, assigned: 'K.Sveidqvist', priority: 'High' } + id66[last item]@{ priority: 'Very Low', assigned: 'knsv' } + id11[Done] + id5[define getData] + id2[Title of diagram is more than 100 chars when user duplicates diagram with 100 char]@{ ticket: MC-2036, priority: 'Very High'} + id3[Update DB function]@{ ticket: MC-2037, assigned: knsv, priority: 'High' } + + id12[Can't reproduce] + id3[Weird flickering in Firefox]