Skip to content

Commit

Permalink
fix(architecture): allow nested object array in config for icons
Browse files Browse the repository at this point in the history
  • Loading branch information
FelixMarcus committed Jan 22, 2025
1 parent 6423c79 commit 927bfd1
Show file tree
Hide file tree
Showing 13 changed files with 98 additions and 40 deletions.
19 changes: 19 additions & 0 deletions demos/architecture.html
Original file line number Diff line number Diff line change
Expand Up @@ -252,5 +252,24 @@ <h2>External Icons Demo</h2>
},
]);
</script>
<hr />

<h2>Config Loading External Icons Demo</h2>
<pre class="mermaid">
---
title: Config Loading External Icons Demo
config:
architecture:
fontSize: 32
icons:
- name: urllogos
url: 'https://unpkg.com/@iconify-json/logos/icons.json'
---
architecture-beta
service s3(urllogos:aws-s3)[Cloud Store]
service ec2(urllogos:aws-ec2)[Server]
service api(urllogos:aws-api-gateway)[Api Gateway]
</pre>
<hr />
</body>
</html>
2 changes: 1 addition & 1 deletion docs/config/setup/modules/defaultConfig.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

#### Defined in

[packages/mermaid/src/defaultConfig.ts:273](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L273)
[packages/mermaid/src/defaultConfig.ts:281](https://github.com/mermaid-js/mermaid/blob/master/packages/mermaid/src/defaultConfig.ts#L281)

---

Expand Down
5 changes: 4 additions & 1 deletion packages/mermaid/src/config.type.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1012,7 +1012,10 @@ export interface RequirementDiagramConfig extends BaseDiagramConfig {
*/
export interface ArchitectureDiagramConfig extends BaseDiagramConfig {
padding?: number;
icons?: unknown[];
icons?: {
name: string;
url: string;
}[];
iconSize?: number;
fontSize?: number;
}
Expand Down
14 changes: 11 additions & 3 deletions packages/mermaid/src/defaultConfig.ts
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { RequiredDeep } from 'type-fest';

import theme from './themes/index.js';
import type { MermaidConfig } from './config.type.js';
import theme from './themes/index.js';

// Uses our custom Vite jsonSchemaPlugin to load only the default values from
// our JSON Schema
Expand Down Expand Up @@ -256,14 +256,22 @@ const config: RequiredDeep<MermaidConfig> = {
...defaultConfigJson.packet,
},
architecture: {
...defaultConfigJson.architecture,
padding: 40,
fontSize: 16,
iconSize: 80,
icons: [
{
name: 'iconify-logos',
url: 'https://unpkg.com/@iconify-json/logos/icons.json',
},
],
},
};

const keyify = (obj: any, prefix = ''): string[] =>
Object.keys(obj).reduce((res: string[], el): string[] => {
if (Array.isArray(obj[el])) {
return res;
return [...res, prefix + el, ...obj[el].flatMap((it: any) => keyify([it], ''))];
} else if (typeof obj[el] === 'object' && obj[el] !== null) {
return [...res, prefix + el, ...keyify(obj[el], '')];
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,6 @@ export const db: ArchitectureDB = {
getAccTitle,
setAccDescription,
getAccDescription,

addService,
getServices,
addJunction,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
import type { Architecture } from '@mermaid-js/parser';
import { parse } from '@mermaid-js/parser';
import { log } from '../../logger.js';
import type { ParserDefinition } from '../../diagram-api/types.js';
import { log } from '../../logger.js';
import { populateCommonDb } from '../common/populateCommonDb.js';
import type { ArchitectureDB } from './architectureTypes.js';
import { db } from './architectureDb.js';
import type { ArchitectureDB } from './architectureTypes.js';

const populateDb = (ast: Architecture, db: ArchitectureDB) => {
populateCommonDb(ast, db);
Expand Down
28 changes: 18 additions & 10 deletions packages/mermaid/src/diagrams/architecture/architectureRenderer.ts
Original file line number Diff line number Diff line change
@@ -1,12 +1,14 @@
import { registerIconPacks } from '../../rendering-util/icons.js';
import type { Position } from 'cytoscape';
import cytoscape from 'cytoscape';
import type { FcoseLayoutOptions } from 'cytoscape-fcose';
import fcose from 'cytoscape-fcose';
import { select } from 'd3';
import { getConfig } from '../../config.js';
import type { MermaidConfig } from '../../config.type.js';
import type { DrawDefinition, SVG } from '../../diagram-api/types.js';
import type { Diagram } from '../../Diagram.js';
import { log } from '../../logger.js';
import { registerIconPacks } from '../../rendering-util/icons.js';
import { selectSvgElement } from '../../rendering-util/selectSvgElement.js';
import { setupGraphViewbox } from '../../setupGraphViewbox.js';
import { getConfigField } from './architectureDb.js';
Expand Down Expand Up @@ -36,16 +38,8 @@ import {
} from './architectureTypes.js';
import { drawEdges, drawGroups, drawJunctions, drawServices } from './svgDraw.js';

registerIconPacks([
{
name: architectureIcons.prefix,
icons: architectureIcons,
},
]);
cytoscape.use(fcose);

getConfigField('icons').forEach((iconLoader) => iconLoader);

function addServices(services: ArchitectureService[], cy: cytoscape.Core) {
services.forEach((service) => {
cy.add({
Expand Down Expand Up @@ -501,7 +495,21 @@ function layoutArchitecture(
});
}

const loadIcons = (config: MermaidConfig) => {
registerIconPacks([
{
name: architectureIcons.prefix,
icons: architectureIcons,
},
]);

registerIconPacks(config.architecture?.icons ?? []);
};

export const draw: DrawDefinition = async (text, id, _version, diagObj: Diagram) => {
const config = getConfig();
loadIcons(config);

const db = diagObj.db as ArchitectureDB;

const services = db.getServices();
Expand Down Expand Up @@ -530,7 +538,7 @@ export const draw: DrawDefinition = async (text, id, _version, diagObj: Diagram)
await drawGroups(groupElem, cy);
positionNodes(db, cy);

setupGraphViewbox(undefined, svg, getConfigField('padding'), getConfigField('useMaxWidth'));
setupGraphViewbox(undefined, svg, config.architecture?.padding, config.architecture?.useMaxWidth);
};

export const renderer = { draw };
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
import type { DiagramDB } from '../../diagram-api/types.js';
import type cytoscape from 'cytoscape';
import type { ArchitectureDiagramConfig } from '../../config.type.js';
import type { DiagramDB } from '../../diagram-api/types.js';
import type { D3Element } from '../../types.js';
import type cytoscape from 'cytoscape';

/*=======================================*\
| Architecture Diagram Types |
Expand Down
24 changes: 23 additions & 1 deletion packages/mermaid/src/preprocess.ts
Original file line number Diff line number Diff line change
Expand Up @@ -53,7 +53,29 @@ export function preprocessDiagram(code: string) {
const cleanedCode = cleanupText(code);
const frontMatterResult = processFrontmatter(cleanedCode);
const directiveResult = processDirectives(frontMatterResult.text);
const config = cleanAndMerge(frontMatterResult.config, directiveResult.directive);
const mergedConfig = cleanAndMerge(frontMatterResult.config, directiveResult.directive);

const hasArchitecture =
frontMatterResult.config.architecture || directiveResult.directive.architecture;

const icons = [
...(frontMatterResult.config.architecture?.icons ?? []),
...(directiveResult.directive.architecture?.icons ?? []),
];

const architecture = {
...(frontMatterResult.config.architecture ?? {}),
...(directiveResult.directive.architecture ?? {}),
icons,
};

const config = hasArchitecture
? {
...mergedConfig,
architecture,
}
: mergedConfig;

code = cleanupComments(directiveResult.text);
return {
code,
Expand Down
1 change: 0 additions & 1 deletion packages/mermaid/src/rendering-util/icons.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ export const registerIconPacks = (iconLoaders: IconLoader[]) => {
} else if ('url' in iconLoader) {
loaderStore.set(iconLoader.name, () => fetch(iconLoader.url).then((res) => res.json()));
} else {
log.error('Invalid icon loader:', iconLoader);
throw new Error('Invalid icon loader. Must have either "icons" or "loader" property.');
}
}
Expand Down
19 changes: 10 additions & 9 deletions packages/mermaid/src/schemas/config.schema.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -933,24 +933,25 @@ $defs: # JSON Schema definition (maybe we should move these to a separate file)
description: The object containing configurations specific for architecture diagrams
type: object
unevaluatedProperties: false
required:
- useMaxWidth
- padding
- iconSize
- fontSize
properties:
padding:
type: number
default: 40
icons:
type: array
default: []
items:
type: object
required:
- name
- url
properties:
name:
type: string
url:
type: string
iconSize:
type: number
default: 80
fontSize:
type: number
default: 16

MindmapDiagramConfig:
title: Mindmap Diagram Config
Expand Down
16 changes: 8 additions & 8 deletions packages/mermaid/src/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,12 @@ import {
curveBumpX,
curveBumpY,
curveBundle,
curveCardinal,
curveCardinalClosed,
curveCardinalOpen,
curveCardinal,
curveCatmullRom,
curveCatmullRomClosed,
curveCatmullRomOpen,
curveCatmullRom,
curveLinear,
curveLinearClosed,
curveMonotoneX,
Expand All @@ -23,16 +23,16 @@ import {
curveStepBefore,
select,
} from 'd3';
import common from './diagrams/common/common.js';
import { sanitizeDirective } from './utils/sanitizeDirective.js';
import { log } from './logger.js';
import { detectType } from './diagram-api/detectType.js';
import assignWithDepth from './assignWithDepth.js';
import type { MermaidConfig } from './config.type.js';
import memoize from 'lodash-es/memoize.js';
import merge from 'lodash-es/merge.js';
import assignWithDepth from './assignWithDepth.js';
import type { MermaidConfig } from './config.type.js';
import { detectType } from './diagram-api/detectType.js';
import { directiveRegex } from './diagram-api/regexes.js';
import common from './diagrams/common/common.js';
import { log } from './logger.js';
import type { D3Element, Point, TextDimensionConfig, TextDimensions } from './types.js';
import { sanitizeDirective } from './utils/sanitizeDirective.js';

export const ZERO_WIDTH_SPACE = '\u200b';

Expand Down
1 change: 0 additions & 1 deletion packages/mermaid/src/utils/sanitizeDirective.ts
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ export const sanitizeDirective = (args: any): void => {
!configKeys.has(key) ||
args[key] == null
) {
log.debug('sanitize deleting key: ', key);
delete args[key];
continue;
}
Expand Down

0 comments on commit 927bfd1

Please sign in to comment.