Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .build/jsonSchema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@ const MERMAID_CONFIG_DIAGRAM_KEYS = [
'packet',
'architecture',
'radar',
'icons',
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The icons key is added to MERMAID_CONFIG_DIAGRAM_KEYS, but unlike the other entries in this array (flowchart, sequence, gantt, etc.), icons is not a diagram-specific configuration. It's a top-level configuration that applies globally to all diagrams.

Adding it to this array might cause issues in the generateDefaults function, which expects all keys to be diagram configs with a $ref to a schema definition. The icons property uses $ref: '#/$defs/IconsConfig' (line 333 of config.schema.yaml), so it should work technically, but semantically it doesn't belong with diagram configs.

Consider either:

  1. Removing icons from this array if it doesn't need special default value handling, or
  2. Renaming the constant to better reflect that it includes non-diagram-specific configs as well (e.g., MERMAID_CONFIG_SUBSCHEMA_KEYS).
Suggested change
'icons',

Copilot uses AI. Check for mistakes.
] as const;

/**
Expand Down
1 change: 1 addition & 0 deletions .cspell/mermaid-terms.txt
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ mermaidchart
mermaidjs
mindmap
mindmaps
mmdc
mrtree
multigraph
nodesep
Expand Down
240 changes: 240 additions & 0 deletions cypress/integration/rendering/icons.spec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,240 @@
import { imgSnapshotTest } from '../../helpers/util';

describe('Icons rendering tests', () => {
it('should render icon from config pack', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
---
flowchart TB
A[Start] --> B@{ icon: 'logos:docker', label: 'Docker' }
B --> C[End]
`);
});

it('should render icons from different packs', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
simple-icons: "@iconify-json/simple-icons@1"
---
flowchart TB
A@{ icon: 'logos:aws', label: 'AWS' } --> B@{ icon: 'logos:docker', label: 'Docker' }
B --> C@{ icon: 'logos:kubernetes', label: 'K8s' }
C --> D@{ icon: 'simple-icons:github', label: 'GitHub' }
`);
});

it('should use custom CDN template', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
cdnTemplate: "https://cdn.jsdelivr.net/npm/\${packageSpec}/icons.json"
---
flowchart TB
A[Start] --> B@{ icon: 'logos:docker', label: 'Docker' }
B --> C[End]
`);
});

it('should use different allowed hosts', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
allowedHosts:
- cdn.jsdelivr.net
- unpkg.com
---
flowchart TB
A[Start] --> B@{ icon: 'logos:aws', label: 'AWS' }
`);
});

it('should render icon with label at top', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
---
flowchart TB
A[Start] --> B@{ icon: 'logos:docker', label: 'Docker Container', pos: 't' }
`);
});

it('should render icon with label at bottom', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
---
flowchart TB
A[Start] --> B@{ icon: 'logos:kubernetes', label: 'Kubernetes', pos: 'b' }
`);
});

it('should render icon with long label', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
---
flowchart TB
A[Start] --> B@{ icon: 'logos:docker', label: 'This is a very long label for Docker container orchestration', h: 64 }
`);
});

it('should render large icon', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
---
flowchart TB
A[Start] --> B@{ icon: 'logos:docker', label: 'Large', h: 80, w: 80 }
`);
});

it('should render small icon', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
---
flowchart TB
A[Start] --> B@{ icon: 'logos:docker', label: 'Small', h: 32, w: 32 }
`);
});

it('should apply custom styles to icon shape', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
---
flowchart TB
A[Start] --> B@{ icon: 'logos:docker', label: 'Styled', form: 'square' }
B --> C[End]
style B fill:#0db7ed,stroke:#333,stroke-width:4px
`);
});

it('should use classDef with icons', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
---
flowchart TB
classDef dockerIcon fill:#0db7ed,stroke:#fff,stroke-width:2px
classDef awsIcon fill:#FF9900,stroke:#fff,stroke-width:2px
A[Start] --> B@{ icon: 'logos:docker', label: 'Docker' }
B --> C@{ icon: 'logos:aws', label: 'AWS' }
B:::dockerIcon
C:::awsIcon
`);
});

it('should render in TB layout', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
---
flowchart TB
A[Start] --> B@{ icon: 'logos:docker', label: 'Docker' }
B --> C[End]
`);
});

it('should render in LR layout', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
---
flowchart LR
A[Start] --> B@{ icon: 'logos:kubernetes', label: 'K8s' }
B --> C[End]
`);
});

it('should handle unknown icon gracefully', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
---
flowchart TB
A[Start] --> B@{ icon: 'unknown:invalid', label: 'Unknown Icon' }
B --> C[End]
`);
});

it('should handle timeouts gracefully', () => {
imgSnapshotTest(`---
config:
icons:
timeout: 1
packs:
logos: "@iconify-json/logos@1"
---
flowchart TB
A[Start] --> B@{ icon: 'logos:aws', label: 'Timeout' }
B --> C[End]
`);
});

it('should handle missing pack gracefully', () => {
imgSnapshotTest(`flowchart TB
A[Start] --> B@{ icon: 'missing:icon', label: 'Missing Pack Icon' }
`);
});

it('should render multiple icons in sequence', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
---
flowchart TB
A[Start] --> B@{ icon: 'logos:aws', label: 'AWS' }
B --> C@{ icon: 'logos:docker', label: 'Docker' }
C --> D@{ icon: 'logos:kubernetes', label: 'K8s' }
D --> E[End]
`);
});

it('should render icons in parallel branches', () => {
imgSnapshotTest(`---
config:
icons:
packs:
logos: "@iconify-json/logos@1"
---
flowchart TB
A[Start] --> B@{ icon: 'logos:docker', label: 'Docker' }
A --> C@{ icon: 'logos:kubernetes', label: 'K8s' }
B --> D[End]
C --> D
`);
});
});
Comment on lines +1 to +240
Copy link

Copilot AI Nov 25, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[nitpick] The Cypress tests have significant repetition of the icon pack configuration (logos: "@iconify-json/logos@1"). Consider extracting common configuration patterns into helper functions or constants to improve maintainability and reduce duplication. For example:

const defaultIconConfig = `---
config:
  icons:
    packs:
      logos: "@iconify-json/logos@1"
---`;

const withIconConfig = (diagram: string) => `${defaultIconConfig}\n${diagram}`;

it('should render icon from config pack', () => {
  imgSnapshotTest(withIconConfig(`flowchart TB
    A[Start] --> B@{ icon: 'logos:docker', label: 'Docker' }
    B --> C[End]
  `));
});

This would make tests more concise and easier to maintain.

Copilot uses AI. Check for mistakes.
Loading
Loading