Skip to content

Commit a4bb0b5

Browse files
knsvclaude
andcommitted
fix(state): allow colons in transition and state description text
The DESCR lexer rule in stateDiagram.jison excluded colons from the character class, causing parse errors when transition labels contained colons (e.g. "recoverable error (ex: timeout)"). Changed the regex to use an alternation that permits colons followed by non-colon characters, while still preventing the `:::` style separator from being consumed. Resolves #7418 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 3b5f67d commit a4bb0b5

File tree

3 files changed

+40
-1
lines changed

3 files changed

+40
-1
lines changed
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'mermaid': patch
3+
---
4+
5+
fix: allow colons in stateDiagram-v2 transition and state description text

packages/mermaid/src/diagrams/state/parser/state-parser.spec.js

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,40 @@ describe('state parser can parse...', () => {
126126
});
127127
});
128128

129+
describe('colons in transition descriptions (issue #7418)', () => {
130+
it('should allow a colon inside transition text', () => {
131+
const diagramText = `stateDiagram-v2
132+
locked --> pending : recoverable error (ex: timeout)`;
133+
stateDiagram.parser.parse(diagramText);
134+
135+
const relationships = stateDiagram.parser.yy.getRelations();
136+
expect(relationships).toHaveLength(1);
137+
expect(relationships[0].id1).toEqual('locked');
138+
expect(relationships[0].id2).toEqual('pending');
139+
expect(relationships[0].relationTitle).toEqual('recoverable error (ex: timeout)');
140+
});
141+
142+
it('should allow multiple colons inside transition text', () => {
143+
const diagramText = `stateDiagram-v2
144+
A --> B : info: key: value`;
145+
stateDiagram.parser.parse(diagramText);
146+
147+
const relationships = stateDiagram.parser.yy.getRelations();
148+
expect(relationships).toHaveLength(1);
149+
expect(relationships[0].relationTitle).toEqual('info: key: value');
150+
});
151+
152+
it('should allow a colon inside state description text', () => {
153+
const diagramText = `stateDiagram-v2
154+
myState : status: active`;
155+
stateDiagram.parser.parse(diagramText);
156+
157+
const states = stateDiagram.parser.yy.getStates();
158+
expect(states.get('myState')).not.toBeUndefined();
159+
expect(states.get('myState').descriptions.join(' ')).toEqual('status: active');
160+
});
161+
});
162+
129163
describe('unsafe properties as state names', () => {
130164
it.each(['__proto__', 'constructor'])('should allow %s as a state name', function (prop) {
131165
stateDiagram.parser.parse(`

packages/mermaid/src/diagrams/state/parser/stateDiagram.jison

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -140,7 +140,7 @@ accDescr\s*"{"\s* { this.begin("acc_descr_multili
140140
<INITIAL,struct>"[*]" { /* console.log('EDGE_STATE=',yytext); */ return 'EDGE_STATE'; }
141141
<INITIAL,struct>[^:\n\s\-\{]+ { /* console.log('=>ID=',yytext); */ return 'ID'; }
142142
// <INITIAL,struct>\s*":"[^\+\->:\n;]+ { yytext = yytext.trim(); /* console.log('Descr = ', yytext); */ return 'DESCR'; }
143-
<INITIAL,struct>\s*":"[^:\n;]+ { yytext = yytext.trim(); /* console.log('Descr = ', yytext); */ return 'DESCR'; }
143+
<INITIAL,struct>\s*":"(?:[^:\n;]|":"[^:\n;])+ { yytext = yytext.trim(); /* console.log('Descr = ', yytext); */ return 'DESCR'; }
144144

145145
<INITIAL,struct>"-->" return '-->';
146146
<struct>"--" return 'CONCURRENT';

0 commit comments

Comments
 (0)