diff --git a/.changeset/weak-carpets-cross.md b/.changeset/weak-carpets-cross.md new file mode 100644 index 0000000000..d111e6db84 --- /dev/null +++ b/.changeset/weak-carpets-cross.md @@ -0,0 +1,5 @@ +--- +'@mermaid-js/parser': patch +--- + +fix: Allow most characters in architecture node titles diff --git a/demos/architecture.html b/demos/architecture.html index 6d978d9525..8a3621aa52 100644 --- a/demos/architecture.html +++ b/demos/architecture.html @@ -64,6 +64,14 @@

Default icon (?) from unknown icon name


+

Non-Alphanumeric Title

+
+      architecture-beta
+        service noalpha(server)[Non-Alpha]
+        service noalpha2(disk)[A/B/C]
+    
+
+

Split Direction

       architecture-beta
diff --git a/packages/parser/src/language/architecture/architecture.langium b/packages/parser/src/language/architecture/architecture.langium
index 11af262432..63225152ee 100644
--- a/packages/parser/src/language/architecture/architecture.langium
+++ b/packages/parser/src/language/architecture/architecture.langium
@@ -4,10 +4,10 @@ import "../common/common";
 entry Architecture:
     NEWLINE*
     "architecture-beta"
+    NEWLINE*
     (
-    NEWLINE* TitleAndAccessibilities
-    | NEWLINE* Statement*
-    | NEWLINE*
+    TitleAndAccessibilities
+    | Statement*
     )
 ;
 
@@ -50,6 +50,6 @@ terminal ARROW_DIRECTION: 'L' | 'R' | 'T' | 'B';
 terminal ARCH_ID: /[\w]+/;
 terminal ARCH_TEXT_ICON: /\("[^"]+"\)/;
 terminal ARCH_ICON: /\([\w-:]+\)/;
-terminal ARCH_TITLE: /\[[\w ]+\]/;
+terminal ARCH_TITLE: /\[[^[\]]+\]/;
 terminal ARROW_GROUP: /\{group\}/;
 terminal ARROW_INTO: /<|>/;
diff --git a/packages/parser/tests/architecture.test.ts b/packages/parser/tests/architecture.test.ts
new file mode 100644
index 0000000000..896be886cf
--- /dev/null
+++ b/packages/parser/tests/architecture.test.ts
@@ -0,0 +1,56 @@
+import { describe, expect, it } from 'vitest';
+
+import { Architecture } from '../src/language/index.js';
+import { expectNoErrorsOrAlternatives, architectureParse as parse } from './test-util.js';
+
+describe('architecture', () => {
+  it.each([
+    `architecture-beta`,
+    `  architecture-beta  `,
+    `\tarchitecture-beta\t`,
+    `
+    \tarchitecture-beta
+    `,
+    `
+
+
+    \tarchitecture-beta
+
+
+
+    `,
+  ])('should handle regular architecture', (context: string) => {
+    const result = parse(context);
+    expectNoErrorsOrAlternatives(result);
+    expect(result.value.$type).toBe(Architecture);
+  });
+
+  it.each([
+    `architecture-beta
+
+      group foo(cloud)`,
+    `architecture-beta
+
+      service foo(server)
+
+      `,
+  ])('should handle group and service', (context: string) => {
+    const result = parse(context);
+    expectNoErrorsOrAlternatives(result);
+    expect(result.value.$type).toBe(Architecture);
+  });
+
+  it.each([
+    `architecture-beta
+      service foo(cloud)[Foo]
+      service bar(cloud)[Foo-Bar]
+      service bar2(cloud)[Foo/Bar]
+      service bar3(cloud)[Foo:Bar]
+      service bar4(cloud)["Foo:Bar"]
+      `,
+  ])('should handle labels with non-alpha characters', (context: string) => {
+    const result = parse(context);
+    expectNoErrorsOrAlternatives(result);
+    expect(result.value.$type).toBe(Architecture);
+  });
+});
diff --git a/packages/parser/tests/test-util.ts b/packages/parser/tests/test-util.ts
index 5cb487758b..691132cc46 100644
--- a/packages/parser/tests/test-util.ts
+++ b/packages/parser/tests/test-util.ts
@@ -7,11 +7,14 @@ import type {
   PieServices,
   GitGraph,
   GitGraphServices,
+  Architecture,
+  ArchitectureServices,
 } from '../src/language/index.js';
 import {
   createInfoServices,
   createPieServices,
   createGitGraphServices,
+  createArchitectureServices,
 } from '../src/language/index.js';
 
 const consoleMock = vi.spyOn(console, 'log').mockImplementation(() => undefined);
@@ -52,6 +55,17 @@ export function createPieTestServices() {
 }
 export const pieParse = createPieTestServices().parse;
 
+const architectureServices: ArchitectureServices = createArchitectureServices().Architecture;
+const architectureParser: LangiumParser = architectureServices.parser.LangiumParser;
+export function createArchitectureTestServices() {
+  const parse = (input: string) => {
+    return architectureParser.parse(input);
+  };
+
+  return { services: architectureServices, parse };
+}
+export const architectureParse = createArchitectureTestServices().parse;
+
 const gitGraphServices: GitGraphServices = createGitGraphServices().GitGraph;
 const gitGraphParser: LangiumParser = gitGraphServices.parser.LangiumParser;
 export function createGitGraphTestServices() {