Fix flowchart arrow parsing to support lowercase, digits, and edge text

- Added lookahead patterns for arrows followed by lowercase letters (fixes #2492)
- Added lookahead patterns for arrows followed by digits (fixes Sample 4 & 5)
- Preserved edge text functionality with pipe delimiter lookahead
- Applied fix to all arrow types: solid (--), thick (==), dotted (-.-)
- Added comprehensive test coverage (21 tests total)
This commit is contained in:
Justin Greywolf
2025-10-21 13:01:53 -07:00
parent 3ac107508b
commit 8127d01db7
2 changed files with 51 additions and 19 deletions

View File

@@ -91,4 +91,39 @@ describe('Flowchart arrow parsing - Issue #2492', () => {
expect(() => flow.parser.parse(diagram)).not.toThrow();
});
});
describe('Arrows with edge text', () => {
it('should parse arrow with edge text followed by uppercase node', () => {
const diagram = 'graph TD\nA-->|text|B';
expect(() => flow.parser.parse(diagram)).not.toThrow();
});
it('should parse arrow with edge text followed by lowercase node', () => {
const diagram = 'graph TD\nA-->|text|b';
expect(() => flow.parser.parse(diagram)).not.toThrow();
});
it('should parse multiple arrows with edge text (regression test)', () => {
const diagram = 'graph TD\nA-->|Get money|B\nB-->C\nC-->|One|D\nC-->|Two|E';
expect(() => flow.parser.parse(diagram)).not.toThrow();
});
});
describe('Arrows followed by digits', () => {
it('should parse --> followed by digit', () => {
const diagram = 'graph LR\n47-->48';
expect(() => flow.parser.parse(diagram)).not.toThrow();
});
it('should parse --> followed by node starting with digit', () => {
const diagram = 'graph LR\nA-->48(Node)';
expect(() => flow.parser.parse(diagram)).not.toThrow();
});
it('should parse complex diagram with digit node IDs (Sample 4)', () => {
const diagram =
'graph LR\n47(SAM.CommonFA.FMESummary)-->48(SAM.CommonFA.CommonFAFinanceBudget)\n37(SAM.CommonFA.BudgetSubserviceLineVolume)-->48(SAM.CommonFA.CommonFAFinanceBudget)';
expect(() => flow.parser.parse(diagram)).not.toThrow();
});
});
});

View File

@@ -152,30 +152,27 @@ that id.
"," return 'COMMA';
"*" return 'MULT';
<INITIAL,edgeText>\s*[xo<]?\-\-+[xo>]\s+ { this.popState(); return 'LINK'; }
<INITIAL,edgeText>\s*[xo<]?\-\-+[xo>](?=[A-Z]) { this.popState(); return 'LINK'; }
<INITIAL,edgeText>\s*[xo<]?\-\-+[xo>](?=[a-z]) { this.popState(); return 'LINK'; }
<INITIAL,edgeText>\s*[xo<]?\-\-+[-](?=[A-Z]) { this.popState(); return 'LINK'; }
<INITIAL,edgeText>\s*[xo<]?\-\-+[-]\s+ { this.popState(); return 'LINK'; }
<INITIAL,edgeText>\s*[xo<]?\-\-+[-](?=[a-z]) { this.popState(); return 'LINK'; }
<INITIAL>\s*[xo<]?\-\-\s* { this.pushState("edgeText"); return 'START_LINK'; }
<INITIAL,edgeText>\s*[xo<]?\-\-+[-xo>]\s+ { this.popState(); return 'LINK'; }
<INITIAL>\s*[xo<]?\-\-+[-xo>](?=[A-Z]) { return 'LINK'; }
<INITIAL>\s*[xo<]?\-\-+[-xo>](?=[a-z]) { return 'LINK'; }
<INITIAL>\s*[xo<]?\-\-+[-xo>](?=[0-9]) { return 'LINK'; }
<INITIAL,edgeText>\s*[xo<]?\-\-+[-xo>](?=\s*\|) { this.popState(); return 'LINK'; }
<INITIAL>\s*[xo<]?\-\-\s* { this.pushState("edgeText"); return 'START_LINK'; }
<edgeText>[^-]|\-(?!\-)+ return 'EDGE_TEXT';
<INITIAL,thickEdgeText>\s*[xo<]?\=\=+[xo>]\s+ { this.popState(); return 'LINK'; }
<INITIAL,thickEdgeText>\s*[xo<]?\=\=+[xo>](?=[A-Z]) { this.popState(); return 'LINK'; }
<INITIAL,thickEdgeText>\s*[xo<]?\=\=+[xo>](?=[a-z]) { this.popState(); return 'LINK'; }
<INITIAL,thickEdgeText>\s*[xo<]?\=\=+[=](?=[A-Z]) { this.popState(); return 'LINK'; }
<INITIAL,thickEdgeText>\s*[xo<]?\=\=+[=]\s+ { this.popState(); return 'LINK'; }
<INITIAL,thickEdgeText>\s*[xo<]?\=\=+[=](?=[a-z]) { this.popState(); return 'LINK'; }
<INITIAL,thickEdgeText>\s*[xo<]?\=\=+[=xo>]\s+ { this.popState(); return 'LINK'; }
<INITIAL>\s*[xo<]?\=\=+[=xo>](?=[A-Z]) { return 'LINK'; }
<INITIAL>\s*[xo<]?\=\=+[=xo>](?=[a-z]) { return 'LINK'; }
<INITIAL>\s*[xo<]?\=\=+[=xo>](?=[0-9]) { return 'LINK'; }
<INITIAL,thickEdgeText>\s*[xo<]?\=\=+[=xo>](?=\s*\|) { this.popState(); return 'LINK'; }
<INITIAL>\s*[xo<]?\=\=\s* { this.pushState("thickEdgeText"); return 'START_LINK'; }
<thickEdgeText>[^=]|\=(?!=) return 'EDGE_TEXT';
<INITIAL,dottedEdgeText>\s*[xo<]?\-?\.+\-[xo>]\s+ { this.popState(); return 'LINK'; }
<INITIAL,dottedEdgeText>\s*[xo<]?\-?\.+\-[xo>](?=[A-Z]) { this.popState(); return 'LINK'; }
<INITIAL,dottedEdgeText>\s*[xo<]?\-?\.+\-[xo>](?=[a-z]) { this.popState(); return 'LINK'; }
<INITIAL,dottedEdgeText>\s*[xo<]?\-?\.+\-(?=[A-Z]) { this.popState(); return 'LINK'; }
<INITIAL,dottedEdgeText>\s*[xo<]?\-?\.+\-\s+ { this.popState(); return 'LINK'; }
<INITIAL,dottedEdgeText>\s*[xo<]?\-?\.+\-(?=[a-z]) { this.popState(); return 'LINK'; }
<INITIAL,dottedEdgeText>\s*[xo<]?\-?\.+\-[xo>]?\s+ { this.popState(); return 'LINK'; }
<INITIAL>\s*[xo<]?\-?\.+\-[xo>]?(?=[A-Z]) { return 'LINK'; }
<INITIAL>\s*[xo<]?\-?\.+\-[xo>]?(?=[a-z]) { return 'LINK'; }
<INITIAL>\s*[xo<]?\-?\.+\-[xo>]?(?=[0-9]) { return 'LINK'; }
<INITIAL,dottedEdgeText>\s*[xo<]?\-?\.+\-[xo>]?(?=\s*\|) { this.popState(); return 'LINK'; }
<INITIAL>\s*[xo<]?\-\.\s* { this.pushState("dottedEdgeText"); return 'START_LINK'; }
<dottedEdgeText>[^\.]|\.(?!-) return 'EDGE_TEXT';