From f7d7fe42aa83974432f65d2dd4c40bd97a1724f1 Mon Sep 17 00:00:00 2001 From: darshanr0107 Date: Mon, 27 Oct 2025 13:33:48 +0530 Subject: [PATCH] fix: prevent edge direction tokens L,R,T,B from breaking ID parsing on-behalf-of: @Mermaid-Chart --- .changeset/lucky-cases-switch.md | 5 ++ .../architecture/architecture.langium | 5 +- packages/parser/tests/architecture.test.ts | 58 +++++++++++++++++++ 3 files changed, 65 insertions(+), 3 deletions(-) create mode 100644 .changeset/lucky-cases-switch.md diff --git a/.changeset/lucky-cases-switch.md b/.changeset/lucky-cases-switch.md new file mode 100644 index 000000000..dac42549b --- /dev/null +++ b/.changeset/lucky-cases-switch.md @@ -0,0 +1,5 @@ +--- +'mermaid': patch +--- + +fix: Allow IDs starting with L, R, T, or B in parser diff --git a/packages/parser/src/language/architecture/architecture.langium b/packages/parser/src/language/architecture/architecture.langium index 2e97372bd..b7d38e50d 100644 --- a/packages/parser/src/language/architecture/architecture.langium +++ b/packages/parser/src/language/architecture/architecture.langium @@ -20,11 +20,11 @@ fragment Statement: ; fragment LeftPort: - ':'lhsDir=ARROW_DIRECTION + ':' lhsDir=ID ; fragment RightPort: - rhsDir=ARROW_DIRECTION':' + rhsDir=ID ':' ; fragment Arrow: @@ -47,6 +47,5 @@ Edge: lhsId=ID lhsGroup?=ARROW_GROUP? Arrow rhsId=ID rhsGroup?=ARROW_GROUP? EOL ; -terminal ARROW_DIRECTION: 'L' | 'R' | 'T' | 'B'; terminal ARROW_GROUP: /\{group\}/; terminal ARROW_INTO: /<|>/; diff --git a/packages/parser/tests/architecture.test.ts b/packages/parser/tests/architecture.test.ts index 4dcce17d3..58f49dd99 100644 --- a/packages/parser/tests/architecture.test.ts +++ b/packages/parser/tests/architecture.test.ts @@ -19,6 +19,64 @@ describe('architecture', () => { }); }); + describe('should handle services', () => { + it('should handle service with icon', () => { + const context = `architecture-beta + service TH(disk) + `; + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Architecture); + expect(result.value.services).toHaveLength(1); + expect(result.value.services?.[0].id).toBe('TH'); + expect(result.value.services?.[0].icon).toBe('disk'); + }); + + it('should handle service with icon starting with arrow direction letters', () => { + const context = `architecture-beta + service T(disk) + service TH(database) + service L(server) + service R(cloud) + service B(internet) + service TOP(disk) + service LEFT(disk) + service RIGHT(disk) + service BOTTOM(disk) + `; + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Architecture); + expect(result.value.services).toHaveLength(9); + }); + + it('should handle service with icon and title', () => { + const context = `architecture-beta + service db(database)[Database] + `; + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Architecture); + expect(result.value.services).toHaveLength(1); + expect(result.value.services?.[0].id).toBe('db'); + expect(result.value.services?.[0].icon).toBe('database'); + expect(result.value.services?.[0].title).toBe('Database'); + }); + + it('should handle service in a group', () => { + const context = `architecture-beta + group api(cloud)[API] + service db(database)[Database] in api + `; + const result = parse(context); + expectNoErrorsOrAlternatives(result); + expect(result.value.$type).toBe(Architecture); + expect(result.value.services).toHaveLength(1); + expect(result.value.services?.[0].id).toBe('db'); + expect(result.value.services?.[0].in).toBe('api'); + }); + }); + describe('should handle TitleAndAccessibilities', () => { it.each([ `architecture-beta title sample title`,