Compare commits

...

5 Commits

Author SHA1 Message Date
darshanr0107
0a23304d1a fix: ensure architecture diagram uses unified rendering
on-behalf-of: @Mermaid-Chart <hello@mermaidchart.com>
2025-09-29 15:13:19 +05:30
Shubham P
7effdc147b Merge pull request #6997 from mermaid-js/ci/enable-codeql-for-github-actions
ci(codeql): enable CodeQL for GitHub Actions
2025-09-25 08:47:48 +00:00
Alois Klink
6e67515f41 ci(codeql): enable CodeQL for GitHub Actions
Support for scanning GitHub Actions was added in 2024-12-17, see
https://github.blog/changelog/2024-12-17-find-and-fix-actions-workflows-vulnerabilities-with-codeql-public-preview/
2025-09-25 17:17:12 +09:00
Shubham P
d5c4eff251 Merge pull request #6972 from mermaid-js/renovate/patch-all-patch
fix(deps): update all patch dependencies (patch)
2025-09-22 13:49:30 +00:00
renovate[bot]
5324fd8dfd fix(deps): update all patch dependencies 2025-09-22 13:35:45 +00:00
11 changed files with 743 additions and 560 deletions

View File

@@ -26,8 +26,8 @@ jobs:
strategy: strategy:
fail-fast: false fail-fast: false
matrix: matrix:
language: ['javascript'] language: ['javascript', 'actions']
# CodeQL supports [ 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ] # CodeQL supports [ 'actions', 'cpp', 'csharp', 'go', 'java', 'javascript', 'python', 'ruby' ]
# Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support # Learn more about CodeQL language support at https://aka.ms/codeql-docs/language-support
steps: steps:

View File

@@ -63,12 +63,12 @@
] ]
}, },
"devDependencies": { "devDependencies": {
"@applitools/eyes-cypress": "^3.44.9", "@applitools/eyes-cypress": "^3.55.2",
"@argos-ci/cypress": "^6.1.1", "@argos-ci/cypress": "^6.1.1",
"@changesets/changelog-github": "^0.5.1", "@changesets/changelog-github": "^0.5.1",
"@changesets/cli": "^2.27.12", "@changesets/cli": "^2.29.7",
"@cspell/eslint-plugin": "^8.19.4", "@cspell/eslint-plugin": "^8.19.4",
"@cypress/code-coverage": "^3.12.49", "@cypress/code-coverage": "^3.14.6",
"@eslint/js": "^9.26.0", "@eslint/js": "^9.26.0",
"@rollup/plugin-typescript": "^12.1.4", "@rollup/plugin-typescript": "^12.1.4",
"@types/cors": "^2.8.19", "@types/cors": "^2.8.19",
@@ -77,22 +77,22 @@
"@types/jsdom": "^21.1.7", "@types/jsdom": "^21.1.7",
"@types/lodash": "^4.17.20", "@types/lodash": "^4.17.20",
"@types/mdast": "^4.0.4", "@types/mdast": "^4.0.4",
"@types/node": "^22.13.17", "@types/node": "^22.18.6",
"@types/rollup-plugin-visualizer": "^5.0.3", "@types/rollup-plugin-visualizer": "^5.0.3",
"@vitest/coverage-v8": "^3.0.9", "@vitest/coverage-v8": "^3.2.4",
"@vitest/spy": "^3.0.9", "@vitest/spy": "^3.2.4",
"@vitest/ui": "^3.0.9", "@vitest/ui": "^3.2.4",
"ajv": "^8.17.1", "ajv": "^8.17.1",
"chokidar": "3.6.0", "chokidar": "3.6.0",
"concurrently": "^9.1.2", "concurrently": "^9.2.1",
"cors": "^2.8.5", "cors": "^2.8.5",
"cpy-cli": "^5.0.0", "cpy-cli": "^5.0.0",
"cross-env": "^7.0.3", "cross-env": "^7.0.3",
"cspell": "^9.1.5", "cspell": "^9.2.1",
"cypress": "^14.5.4", "cypress": "^14.5.4",
"cypress-image-snapshot": "^4.0.1", "cypress-image-snapshot": "^4.0.1",
"cypress-split": "^1.24.21", "cypress-split": "^1.24.23",
"esbuild": "^0.25.9", "esbuild": "^0.25.10",
"eslint": "^9.26.0", "eslint": "^9.26.0",
"eslint-config-prettier": "^10.1.8", "eslint-config-prettier": "^10.1.8",
"eslint-plugin-cypress": "^4.3.0", "eslint-plugin-cypress": "^4.3.0",
@@ -106,10 +106,10 @@
"eslint-plugin-tsdoc": "^0.4.0", "eslint-plugin-tsdoc": "^0.4.0",
"eslint-plugin-unicorn": "^59.0.1", "eslint-plugin-unicorn": "^59.0.1",
"express": "^5.1.0", "express": "^5.1.0",
"globals": "^16.0.0", "globals": "^16.4.0",
"globby": "^14.1.0", "globby": "^14.1.0",
"husky": "^9.1.7", "husky": "^9.1.7",
"jest": "^30.0.5", "jest": "^30.1.3",
"jison": "^0.4.18", "jison": "^0.4.18",
"js-yaml": "^4.1.0", "js-yaml": "^4.1.0",
"jsdom": "^26.1.0", "jsdom": "^26.1.0",
@@ -118,18 +118,18 @@
"markdown-table": "^3.0.4", "markdown-table": "^3.0.4",
"nyc": "^17.1.0", "nyc": "^17.1.0",
"path-browserify": "^1.0.1", "path-browserify": "^1.0.1",
"prettier": "^3.5.3", "prettier": "^3.6.2",
"prettier-plugin-jsdoc": "^1.3.3", "prettier-plugin-jsdoc": "^1.3.3",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"rollup-plugin-visualizer": "^6.0.3", "rollup-plugin-visualizer": "^6.0.3",
"start-server-and-test": "^2.0.13", "start-server-and-test": "^2.1.2",
"tslib": "^2.8.1", "tslib": "^2.8.1",
"tsx": "^4.7.3", "tsx": "^4.20.5",
"typescript": "~5.7.3", "typescript": "~5.7.3",
"typescript-eslint": "^8.38.0", "typescript-eslint": "^8.38.0",
"vite": "^7.0.6", "vite": "^7.0.7",
"vite-plugin-istanbul": "^7.0.0", "vite-plugin-istanbul": "^7.0.0",
"vitest": "^3.0.9" "vitest": "^3.2.4"
}, },
"nyc": { "nyc": {
"report-dir": "coverage/cypress" "report-dir": "coverage/cypress"

View File

@@ -42,7 +42,7 @@
"khroma": "^2.1.0" "khroma": "^2.1.0"
}, },
"devDependencies": { "devDependencies": {
"concurrently": "^9.1.2", "concurrently": "^9.2.1",
"mermaid": "workspace:*", "mermaid": "workspace:*",
"rimraf": "^6.0.1" "rimraf": "^6.0.1"
}, },

View File

@@ -33,7 +33,7 @@
], ],
"license": "MIT", "license": "MIT",
"dependencies": { "dependencies": {
"@zenuml/core": "^3.35.2" "@zenuml/core": "^3.41.4"
}, },
"devDependencies": { "devDependencies": {
"mermaid": "workspace:^" "mermaid": "workspace:^"

View File

@@ -68,10 +68,10 @@
}, },
"dependencies": { "dependencies": {
"@braintree/sanitize-url": "^7.1.1", "@braintree/sanitize-url": "^7.1.1",
"@iconify/utils": "^3.0.1", "@iconify/utils": "^3.0.2",
"@mermaid-js/parser": "workspace:^", "@mermaid-js/parser": "workspace:^",
"@types/d3": "^7.4.3", "@types/d3": "^7.4.3",
"cytoscape": "^3.29.3", "cytoscape": "^3.33.1",
"cytoscape-cose-bilkent": "^4.1.0", "cytoscape-cose-bilkent": "^4.1.0",
"cytoscape-fcose": "^2.2.0", "cytoscape-fcose": "^2.2.0",
"d3": "^7.9.0", "d3": "^7.9.0",
@@ -82,7 +82,7 @@
"katex": "^0.16.22", "katex": "^0.16.22",
"khroma": "^2.1.0", "khroma": "^2.1.0",
"lodash-es": "^4.17.21", "lodash-es": "^4.17.21",
"marked": "^16.2.1", "marked": "^16.3.0",
"roughjs": "^4.6.6", "roughjs": "^4.6.6",
"stylis": "^4.3.6", "stylis": "^4.3.6",
"ts-dedent": "^2.2.0", "ts-dedent": "^2.2.0",
@@ -105,9 +105,9 @@
"@types/stylis": "^4.2.7", "@types/stylis": "^4.2.7",
"@types/uuid": "^10.0.0", "@types/uuid": "^10.0.0",
"ajv": "^8.17.1", "ajv": "^8.17.1",
"canvas": "^3.1.2", "canvas": "^3.2.0",
"chokidar": "3.6.0", "chokidar": "3.6.0",
"concurrently": "^9.1.2", "concurrently": "^9.2.1",
"csstree-validator": "^4.0.1", "csstree-validator": "^4.0.1",
"globby": "^14.1.0", "globby": "^14.1.0",
"jison": "^0.4.18", "jison": "^0.4.18",
@@ -116,14 +116,14 @@
"json-schema-to-typescript": "^15.0.4", "json-schema-to-typescript": "^15.0.4",
"micromatch": "^4.0.8", "micromatch": "^4.0.8",
"path-browserify": "^1.0.1", "path-browserify": "^1.0.1",
"prettier": "^3.5.3", "prettier": "^3.6.2",
"remark": "^15.0.1", "remark": "^15.0.1",
"remark-frontmatter": "^5.0.0", "remark-frontmatter": "^5.0.0",
"remark-gfm": "^4.0.1", "remark-gfm": "^4.0.1",
"rimraf": "^6.0.1", "rimraf": "^6.0.1",
"start-server-and-test": "^2.0.13", "start-server-and-test": "^2.1.2",
"type-fest": "^4.35.0", "type-fest": "^4.41.0",
"typedoc": "^0.28.12", "typedoc": "^0.28.13",
"typedoc-plugin-markdown": "^4.8.1", "typedoc-plugin-markdown": "^4.8.1",
"typescript": "~5.7.3", "typescript": "~5.7.3",
"unist-util-flatmap": "^1.0.0", "unist-util-flatmap": "^1.0.0",

View File

@@ -3,7 +3,9 @@ import type { ArchitectureDiagramConfig } from '../../config.type.js';
import DEFAULT_CONFIG from '../../defaultConfig.js'; import DEFAULT_CONFIG from '../../defaultConfig.js';
import type { DiagramDB } from '../../diagram-api/types.js'; import type { DiagramDB } from '../../diagram-api/types.js';
import type { D3Element } from '../../types.js'; import type { D3Element } from '../../types.js';
import { cleanAndMerge } from '../../utils.js'; import { cleanAndMerge, getEdgeId } from '../../utils.js';
import type { LayoutData, Node, Edge } from '../../rendering-util/types.js';
import { import {
clear as commonClear, clear as commonClear,
getAccDescription, getAccDescription,
@@ -351,15 +353,147 @@ export class ArchitectureDB implements DiagramDB {
public getDiagramTitle = getDiagramTitle; public getDiagramTitle = getDiagramTitle;
public getAccDescription = getAccDescription; public getAccDescription = getAccDescription;
public setAccDescription = setAccDescription; public setAccDescription = setAccDescription;
}
/** /**
* Typed wrapper for resolving an architecture diagram's config fields. Returns the default value if undefined * Converts architecture diagram data to LayoutData format for unified rendering
* @param field - the config field to access */
* @returns public getData(): LayoutData {
*/ const config = commonGetConfig();
// export function getConfigField<T extends keyof ArchitectureDiagramConfig>( const nodes: Node[] = [];
// field: T const edges: Edge[] = [];
// ): Required<ArchitectureDiagramConfig>[T] {
// return db.getConfig()[field]; const groups = this.getGroups();
// } for (const group of groups) {
const padding = this.getConfigField('padding');
const fontSize = this.getConfigField('fontSize');
const groupWidth = 200;
let groupHeight = 150;
if (group.title || group.icon) {
groupHeight += fontSize + padding;
}
nodes.push({
id: group.id,
label: group.title,
parentId: group.in,
isGroup: true,
shape: 'rect',
icon: group.icon,
width: groupWidth,
height: groupHeight,
padding: padding,
cssClasses: 'architecture-group',
cssCompiledStyles: [
'stroke: #cccccc',
'stroke-width: 2px',
'stroke-dasharray: 8,8',
'fill: transparent',
],
labelStyle: '',
look: config.look || 'classic',
rx: 5,
ry: 5,
});
}
const services = this.getServices();
for (const service of services) {
const iconSize = this.getConfigField('iconSize');
let nodeWidth = iconSize;
let nodeHeight = iconSize;
if (service.title) {
nodeHeight += iconSize * 0.3;
nodeWidth = Math.max(nodeWidth, iconSize * 1.5);
}
nodes.push({
id: service.id,
label: service.title,
parentId: service.in,
isGroup: false,
shape: service.icon || (service as any).iconText ? 'icon' : 'squareRect',
icon: service.icon ? `mermaid-architecture:${service.icon}` : 'mermaid-architecture:blank',
width: service.width || nodeWidth,
height: service.height || nodeHeight,
cssClasses: 'architecture-service',
look: config.look,
padding: this.getConfigField('padding') / 4,
description: (service as any).iconText ? [(service as any).iconText] : undefined,
assetWidth: iconSize,
assetHeight: iconSize,
});
}
const junctions = this.getJunctions();
for (const junction of junctions) {
nodes.push({
id: junction.id,
parentId: junction.in,
isGroup: false,
shape: 'squareRect',
width: 2,
height: 2,
cssClasses: 'architecture-junction',
look: config.look,
type: 'junction' as any,
padding: 0,
});
}
const architectureEdges = this.getEdges();
let edgeCounter = 0;
for (const edge of architectureEdges) {
const edgeData = {
id: getEdgeId(edge.lhsId, edge.rhsId, { counter: edgeCounter, prefix: 'L' }),
start: edge.lhsId,
end: edge.rhsId,
source: edge.lhsId,
target: edge.rhsId,
label: edge.title || '',
labelpos: 'c',
type: 'normal',
minlen: 2,
weight: 1,
classes: 'edge-thickness-normal edge-pattern-solid architecture-edge',
look: config.look || 'classic',
curve: 'linear',
arrowTypeStart: edge.lhsInto ? 'point' : 'none',
arrowTypeEnd: edge.rhsInto ? 'point' : 'none',
arrowheadStyle: 'fill: #333',
thickness: 'normal',
pattern: 'solid',
style: ['stroke: #333333', 'stroke-width: 3px', 'fill: none'],
cssCompiledStyles: [],
labelStyle: [],
lhsDir: edge.lhsDir,
rhsDir: edge.rhsDir,
lhsInto: edge.lhsInto,
rhsInto: edge.rhsInto,
lhsGroup: edge.lhsGroup,
rhsGroup: edge.rhsGroup,
} as Edge & {
lhsDir: any;
rhsDir: any;
lhsInto?: boolean;
rhsInto?: boolean;
lhsGroup?: boolean;
rhsGroup?: boolean;
};
edges.push(edgeData);
edgeCounter++;
}
const result = {
nodes,
edges,
config,
dataStructures: this.getDataStructures(),
};
return result;
}
}

View File

@@ -2,7 +2,7 @@ import type { DiagramDefinition } from '../../diagram-api/types.js';
import { parser } from './architectureParser.js'; import { parser } from './architectureParser.js';
import { ArchitectureDB } from './architectureDb.js'; import { ArchitectureDB } from './architectureDb.js';
import styles from './architectureStyles.js'; import styles from './architectureStyles.js';
import { renderer } from './architectureRenderer.js'; import { renderer } from './architectureRenderer-unified.js';
export const diagram: DiagramDefinition = { export const diagram: DiagramDefinition = {
parser, parser,

View File

@@ -0,0 +1,50 @@
import { getConfig } from '../../diagram-api/diagramAPI.js';
import type { DiagramStyleClassDef } from '../../diagram-api/types.js';
import { log } from '../../logger.js';
import { getDiagramElement } from '../../rendering-util/insertElementsForSize.js';
import { getRegisteredLayoutAlgorithm, render } from '../../rendering-util/render.js';
import { setupViewPortForSVG } from '../../rendering-util/setupViewPortForSVG.js';
import type { LayoutData } from '../../rendering-util/types.js';
import utils from '../../utils.js';
import { registerIconPacks } from '../../rendering-util/icons.js';
import { architectureIcons } from './architectureIcons.js';
export const getClasses = function (
_text: string,
_diagramObj: any
): Map<string, DiagramStyleClassDef> {
return new Map();
};
export const draw = async function (_text: string, id: string, _version: string, diag: any) {
registerIconPacks([
{
name: architectureIcons.prefix,
icons: architectureIcons,
},
]);
const { securityLevel, architecture: conf, layout } = getConfig();
const data4Layout = diag.db.getData() as LayoutData;
const svg = getDiagramElement(id, securityLevel);
data4Layout.type = diag.type;
data4Layout.layoutAlgorithm = getRegisteredLayoutAlgorithm(layout, { fallback: 'dagre' });
data4Layout.nodeSpacing = 100;
data4Layout.rankSpacing = 100;
data4Layout.markers = ['point'];
data4Layout.diagramId = id;
log.debug('Architecture layout data:', data4Layout);
await render(data4Layout, svg);
const padding = conf?.padding ?? 8;
utils.insertTitle(svg, 'architectureTitleText', 0, diag.db.getDiagramTitle());
setupViewPortForSVG(svg, padding, 'architecture', conf?.useMaxWidth ?? true);
};
export const renderer = { draw };

View File

@@ -2,6 +2,7 @@ import type { DiagramDBBase } from '../../diagram-api/types.js';
import type { ArchitectureDiagramConfig } from '../../config.type.js'; import type { ArchitectureDiagramConfig } from '../../config.type.js';
import type { D3Element } from '../../types.js'; import type { D3Element } from '../../types.js';
import type cytoscape from 'cytoscape'; import type cytoscape from 'cytoscape';
import type { LayoutData } from '../../rendering-util/types.js';
/*=======================================*\ /*=======================================*\
| Architecture Diagram Types | | Architecture Diagram Types |
@@ -256,7 +257,8 @@ export interface ArchitectureDB extends DiagramDBBase<ArchitectureDiagramConfig>
getEdges: () => ArchitectureEdge[]; getEdges: () => ArchitectureEdge[];
setElementForId: (id: string, element: D3Element) => void; setElementForId: (id: string, element: D3Element) => void;
getElementById: (id: string) => D3Element; getElementById: (id: string) => D3Element;
getDataStructures: () => ArchitectureDataStructures; getData: () => LayoutData;
getDirection: () => string;
} }
export type ArchitectureAdjacencyList = Record<string, ArchitectureDirectionPairMap>; export type ArchitectureAdjacencyList = Record<string, ArchitectureDirectionPairMap>;

View File

@@ -17,7 +17,7 @@
}, },
"dependencies": { "dependencies": {
"@mdi/font": "^7.4.47", "@mdi/font": "^7.4.47",
"@vueuse/core": "^13.1.0", "@vueuse/core": "^13.9.0",
"font-awesome": "^4.7.0", "font-awesome": "^4.7.0",
"jiti": "^2.4.2", "jiti": "^2.4.2",
"mermaid": "workspace:^", "mermaid": "workspace:^",
@@ -25,17 +25,17 @@
}, },
"devDependencies": { "devDependencies": {
"@iconify-json/carbon": "^1.2.13", "@iconify-json/carbon": "^1.2.13",
"@unocss/reset": "^66.0.0", "@unocss/reset": "^66.5.1",
"@vite-pwa/vitepress": "^1.0.0", "@vite-pwa/vitepress": "^1.0.0",
"@vitejs/plugin-vue": "^6.0.1", "@vitejs/plugin-vue": "^6.0.1",
"fast-glob": "^3.3.3", "fast-glob": "^3.3.3",
"https-localhost": "^4.7.1", "https-localhost": "^4.7.1",
"pathe": "^2.0.3", "pathe": "^2.0.3",
"unocss": "^66.4.2", "unocss": "^66.5.1",
"unplugin-vue-components": "^28.4.0", "unplugin-vue-components": "^28.4.1",
"vite": "^7.0.0", "vite": "^7.0.7",
"vite-plugin-pwa": "^1.0.0", "vite-plugin-pwa": "^1.0.3",
"vitepress": "1.6.3", "vitepress": "1.6.4",
"workbox-window": "^7.3.0" "workbox-window": "^7.3.0"
} }
} }

1013
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff