diff --git a/.changeset/dark-bats-build.md b/.changeset/dark-bats-build.md new file mode 100644 index 00000000000..f7806c16b5b --- /dev/null +++ b/.changeset/dark-bats-build.md @@ -0,0 +1,5 @@ +--- +'mermaid': minor +--- + +feat: Added support for decimal start and increment values in the `autonumber` directive. diff --git a/cypress/integration/rendering/sequencediagram.spec.js b/cypress/integration/rendering/sequencediagram.spec.js index 0ec913a8c25..09d0d8a1ee0 100644 --- a/cypress/integration/rendering/sequencediagram.spec.js +++ b/cypress/integration/rendering/sequencediagram.spec.js @@ -242,6 +242,18 @@ describe('Sequence diagram', () => { ` ); }); + it('should render a sequence diagram with sequence numbers that are decimals and increase by a decimal value', () => { + imgSnapshotTest( + ` + sequenceDiagram + autonumber 10.1 .01 + Alice->Bob: Hello Bob, how are you? + Bob-->Alice: I am good thanks! + Alice->Bob: That is good to hear! + Bob->Alice: See you later! + ` + ); + }); describe('font settings', () => { it('should render different note fonts when configured', () => { imgSnapshotTest( diff --git a/docs/syntax/sequenceDiagram.md b/docs/syntax/sequenceDiagram.md index eb3cfc996cc..cfc97e67946 100644 --- a/docs/syntax/sequenceDiagram.md +++ b/docs/syntax/sequenceDiagram.md @@ -895,6 +895,16 @@ sequenceDiagram Bob-->>John: Jolly good! ``` +### Start and Increment values (v\+) + +It is possible to specify a starting value and an increment value for automatic numbering. Both the starting value and increment value can include decimals up to the hundredths place. + +Use the following syntax in your diagram definition: + +``` +autonumber +``` + ## Actor Menus Actors can have popup-menus containing individualized links to external pages. For example, if an actor represented a web service, useful links might include a link to the service health dashboard, repo containing the code for the service, or a wiki page describing the service. diff --git a/packages/mermaid/src/diagrams/sequence/parser/sequenceDiagram.jison b/packages/mermaid/src/diagrams/sequence/parser/sequenceDiagram.jison index f1364895b0c..04ede921876 100644 --- a/packages/mermaid/src/diagrams/sequence/parser/sequenceDiagram.jison +++ b/packages/mermaid/src/diagrams/sequence/parser/sequenceDiagram.jison @@ -27,7 +27,7 @@ \#[^\n]* /* skip comments */ \%%(?!\{)[^\n]* /* skip comments */ [^\}]\%\%[^\n]* /* skip comments */ -[0-9]+(?=[ \n]+) return 'NUM'; +([0-9]+(\.[0-9]{1,2})?|\.[0-9]{1,2})(?=[ \n]+) return 'NUM'; \@\{ { this.begin('CONFIG'); return 'CONFIG_START'; } [^\}]+ { return 'CONFIG_CONTENT'; } \} { this.popState(); this.popState(); return 'CONFIG_END'; } diff --git a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js index 5f4e06dcd02..40568891b2a 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js +++ b/packages/mermaid/src/diagrams/sequence/sequenceDiagram.spec.js @@ -479,6 +479,44 @@ Bob-->Alice: I am good thanks!`; expect(diagram.db.showSequenceNumbers()).toBe(true); }); + it('should allow sequence numbers to have decimals up to the hundredths place', async () => { + const str = ` + sequenceDiagram + autonumber 10.1 .01 + Alice->Bob:Hello Bob, how are you? + Note right of Bob: Bob thinks + Bob-->Alice: I am good thanks! + `; + + let error = false; + try { + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility auto numbers + } catch (e) { + error = true; + } + expect(error).toBe(false); + }); + + it('should not allow sequence numbers to have decimals to the thousandths place or greater', async () => { + const str = ` + sequenceDiagram + autonumber 10.001 + Alice->Bob:Hello Bob, how are you? + Note right of Bob: Bob thinks + Bob-->Alice: I am good thanks! + `; + + let error = false; + try { + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility auto numbers + } catch (e) { + error = true; + } + expect(error).toBe(true); + }); + it('should handle a sequenceDiagram definition with a title:', async () => { const diagram = await Diagram.fromText(` sequenceDiagram @@ -2211,6 +2249,40 @@ end`; expect(bounds.stopx).toBe(conf.width * 2 + conf.actorMargin); expect(bounds.stopy).toBe(models.lastLoop().stopy); }); + + it('should increment the sequence number with a decimal in the hundredths place', async () => { + const str = ` + sequenceDiagram + autonumber 10.01 .01 + Alice->Bob:Hello Bob, how are you? + Bob-->Alice: I am good thanks! + Alice-->Bob: Have a good day! + `; + + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility auto numbers + expect(diagram.db.showSequenceNumbers()).toBe(true); + expect(diagram.db.getMessages()[1].msgModel.sequenceIndex).toBe(10.01); + expect(diagram.db.getMessages()[2].msgModel.sequenceIndex).toBe(10.02); + expect(diagram.db.getMessages()[3].msgModel.sequenceIndex).toBe(10.03); + }); + + it('should increment the sequence number with a decimal in the tenths place', async () => { + const str = ` + sequenceDiagram + autonumber 10.1 .1 + Alice->Bob:Hello Bob, how are you? + Bob-->Alice: I am good thanks! + Alice-->Bob: Have a good day! + `; + + const diagram = await Diagram.fromText(str); + await diagram.renderer.draw(str, 'tst', '1.2.3', diagram); // needs to be rendered for the correct value of visibility auto numbers + expect(diagram.db.showSequenceNumbers()).toBe(true); + expect(diagram.db.getMessages()[1].msgModel.sequenceIndex).toBe(10.1); + expect(diagram.db.getMessages()[2].msgModel.sequenceIndex).toBe(10.2); + expect(diagram.db.getMessages()[3].msgModel.sequenceIndex).toBe(10.3); + }); }); describe('when rendering a sequenceDiagram with actor mirror activated', () => { diff --git a/packages/mermaid/src/diagrams/sequence/sequenceRenderer.ts b/packages/mermaid/src/diagrams/sequence/sequenceRenderer.ts index 04d5607ad4f..3600741e122 100644 --- a/packages/mermaid/src/diagrams/sequence/sequenceRenderer.ts +++ b/packages/mermaid/src/diagrams/sequence/sequenceRenderer.ts @@ -602,6 +602,15 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO x = 3.5; } + let fontSize = '12px'; + const sequenceIndexLength = sequenceIndex.toString().length; + + if (sequenceIndexLength > 5) { + fontSize = '7px'; + } else if (sequenceIndexLength > 3) { + fontSize = '9px'; + } + diagram .append('line') .attr('x1', startx) @@ -617,7 +626,7 @@ const drawMessage = async function (diagram, msgModel, lineStartY: number, diagO .attr('x', startx) .attr('y', lineStartY + 4) .attr('font-family', 'sans-serif') - .attr('font-size', '12px') + .attr('font-size', fontSize) .attr('text-anchor', 'middle') .attr('class', 'sequenceNumber') .text(sequenceIndex) @@ -1221,7 +1230,8 @@ export const draw = async function (_text: string, id: string, _version: string, diagObj.db.LINETYPE.BIDIRECTIONAL_DOTTED, ].includes(msg.type) ) { - sequenceIndex = sequenceIndex + sequenceIndexStep; + // hitting a floating point number error, so round to 2 decimal places + sequenceIndex = Math.round((sequenceIndex + sequenceIndexStep) * 100) / 100; } index++; } diff --git a/packages/mermaid/src/docs/syntax/sequenceDiagram.md b/packages/mermaid/src/docs/syntax/sequenceDiagram.md index 25b7704840b..c57f4ea4c93 100644 --- a/packages/mermaid/src/docs/syntax/sequenceDiagram.md +++ b/packages/mermaid/src/docs/syntax/sequenceDiagram.md @@ -607,6 +607,16 @@ sequenceDiagram Bob-->>John: Jolly good! ``` +### Start and Increment values (v+) + +It is possible to specify a starting value and an increment value for automatic numbering. Both the starting value and increment value can include decimals up to the hundredths place. + +Use the following syntax in your diagram definition: + +``` +autonumber +``` + ## Actor Menus Actors can have popup-menus containing individualized links to external pages. For example, if an actor represented a web service, useful links might include a link to the service health dashboard, repo containing the code for the service, or a wiki page describing the service.