From 790f71bb1a118e82fb92b4fbf7fe2ccbd3c8e5a3 Mon Sep 17 00:00:00 2001 From: Sidharth Vinod Date: Thu, 29 Aug 2024 14:00:21 +0530 Subject: [PATCH] feat: Move architecture icons into iconify format --- .../architecture/architectureIcons.ts | 43 ++++++++ .../architecture/architectureRenderer.ts | 6 +- .../diagrams/architecture/icons/default.ts | 99 ------------------- .../architecture/icons/svgRegister.ts | 50 ---------- .../src/diagrams/architecture/svgDraw.ts | 20 ++-- 5 files changed, 58 insertions(+), 160 deletions(-) create mode 100644 packages/mermaid/src/diagrams/architecture/architectureIcons.ts delete mode 100644 packages/mermaid/src/diagrams/architecture/icons/default.ts delete mode 100644 packages/mermaid/src/diagrams/architecture/icons/svgRegister.ts diff --git a/packages/mermaid/src/diagrams/architecture/architectureIcons.ts b/packages/mermaid/src/diagrams/architecture/architectureIcons.ts new file mode 100644 index 000000000..dd6c99f9c --- /dev/null +++ b/packages/mermaid/src/diagrams/architecture/architectureIcons.ts @@ -0,0 +1,43 @@ +import { unknownIcon } from '$root/rendering-util/icons.js'; +import type { IconifyJSON } from '@iconify/types'; + +const wrapIcon = (icon: string) => { + return `${icon}`; +}; + +export const architectureIcons: IconifyJSON = { + prefix: 'mermaid-architecture', + height: 80, + width: 80, + icons: { + database: { + body: wrapIcon( + '' + ), + }, + server: { + body: wrapIcon( + '' + ), + }, + disk: { + body: wrapIcon( + '' + ), + }, + internet: { + body: wrapIcon( + '' + ), + }, + cloud: { + body: wrapIcon( + '' + ), + }, + unknown: unknownIcon, + blank: { + body: wrapIcon(''), + }, + }, +}; diff --git a/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts b/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts index 558b90483..84b9ed655 100644 --- a/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts +++ b/packages/mermaid/src/diagrams/architecture/architectureRenderer.ts @@ -1,3 +1,4 @@ +import { registerIconPacks } from '$root/rendering-util/icons.js'; import type { Position } from 'cytoscape'; import cytoscape from 'cytoscape'; import type { FcoseLayoutOptions } from 'cytoscape-fcose'; @@ -9,6 +10,7 @@ import { log } from '../../logger.js'; import { selectSvgElement } from '../../rendering-util/selectSvgElement.js'; import { setupGraphViewbox } from '../../setupGraphViewbox.js'; import { getConfigField } from './architectureDb.js'; +import { architectureIcons } from './architectureIcons.js'; import type { ArchitectureDataStructures, ArchitectureJunction, @@ -30,11 +32,9 @@ import { isArchitectureDirectionY, nodeData, } from './architectureTypes.js'; -import { defaultIconLibrary } from './icons/default.js'; -import { registerIconLibrary } from './icons/svgRegister.js'; import { drawEdges, drawGroups, drawJunctions, drawServices } from './svgDraw.js'; -registerIconLibrary(defaultIconLibrary); +registerIconPacks(architectureIcons); cytoscape.use(fcose); function addServices(services: ArchitectureService[], cy: cytoscape.Core) { diff --git a/packages/mermaid/src/diagrams/architecture/icons/default.ts b/packages/mermaid/src/diagrams/architecture/icons/default.ts deleted file mode 100644 index 8c33df09c..000000000 --- a/packages/mermaid/src/diagrams/architecture/icons/default.ts +++ /dev/null @@ -1,99 +0,0 @@ -import { createIcon, type IconLibrary } from './svgRegister.js'; - -export const defaultIconLibrary: IconLibrary = { - database: createIcon( - ` - - - - - - - -`, - 80 - ), - server: createIcon( - ` - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -`, - 80 - ), - disk: createIcon( - ` - - - - - - - - - -`, - 80 - ), - internet: createIcon( - ` - - - - - - - - -`, - 80 - ), - cloud: createIcon( - ` - - - `, - 80 - ), - unknown: createIcon( - ` - - ? -`, - 80 - ), - blank: createIcon( - ` - -`, - 80 - ), -}; diff --git a/packages/mermaid/src/diagrams/architecture/icons/svgRegister.ts b/packages/mermaid/src/diagrams/architecture/icons/svgRegister.ts deleted file mode 100644 index 712644afa..000000000 --- a/packages/mermaid/src/diagrams/architecture/icons/svgRegister.ts +++ /dev/null @@ -1,50 +0,0 @@ -import { log } from '$root/logger.js'; -import type { Selection } from 'd3-selection'; - -export type IconResolver = ( - parent: Selection, - width?: number -) => Selection; -export type IconLibrary = Record; - -/** - * Converts an SVG Icon passed as a string into a properly formatted IconResolver - * @param icon - html code for the svg icon as a string (the SVG tag should not be included) - * @param originalSize - the original size of the SVG Icon in pixels - * @returns IconResolver - */ -export const createIcon: (icon: string, originalSize: number) => IconResolver = ( - icon, - originalSize -) => { - return ( - parent: Selection, - size: number = originalSize - ) => { - parent.html(`${icon}`); - return parent; - }; -}; - -const icons: IconLibrary = {}; - -export const isIconNameInUse = (name: string): boolean => { - return icons[name] !== undefined; -}; - -export const registerIconLibrary = (library: IconLibrary) => { - Object.entries(library).forEach(([name, resolver]) => { - if (!isIconNameInUse(name)) { - icons[name] = resolver; - } else { - log.warn(`Icon with name ${name} already exists. Skipping registration.`); - } - }); -}; - -export const getIcon = (name: string): IconResolver | null => { - if (isIconNameInUse(name)) { - return icons[name]; - } - return icons.unknown; -}; diff --git a/packages/mermaid/src/diagrams/architecture/svgDraw.ts b/packages/mermaid/src/diagrams/architecture/svgDraw.ts index ef3ddb7f6..d1c053f71 100644 --- a/packages/mermaid/src/diagrams/architecture/svgDraw.ts +++ b/packages/mermaid/src/diagrams/architecture/svgDraw.ts @@ -1,10 +1,10 @@ -// TODO remove no-console -/* eslint-disable no-console */ +import { getIconSVG } from '$root/rendering-util/icons.js'; import type cytoscape from 'cytoscape'; import { getConfig } from '../../diagram-api/diagramAPI.js'; import { createText } from '../../rendering-util/createText.js'; import type { D3Element } from '../../types.js'; import { db, getConfigField } from './architectureDb.js'; +import { architectureIcons } from './architectureIcons.js'; import { ArchitectureDirectionArrow, ArchitectureDirectionArrowShift, @@ -20,7 +20,6 @@ import { type ArchitectureJunction, type ArchitectureService, } from './architectureTypes.js'; -import { getIcon } from './icons/svgRegister.js'; export const drawEdges = async function (edgesEl: D3Element, cy: cytoscape.Core) { const padding = getConfigField('padding'); @@ -198,7 +197,6 @@ export const drawGroups = async function (groupsEl: D3Element, cy: cytoscape.Cor const data = nodeData(node); if (data.type === 'group') { const { h, w, x1, y1 } = node.boundingBox(); - console.log(`Draw group (${data.id}): pos=(${x1}, ${y1}), dim=(${w}, ${h})`); groupsEl .append('rect') @@ -213,7 +211,9 @@ export const drawGroups = async function (groupsEl: D3Element, cy: cytoscape.Cor let shiftedY1 = y1; if (data.icon) { const bkgElem = groupLabelContainer.append('g'); - getIcon(data.icon)?.(bkgElem, groupIconSize); + bkgElem.html( + `${getIconSVG(data.icon, { height: groupIconSize, width: groupIconSize, fallbackPrefix: architectureIcons.prefix })}` + ); bkgElem.attr( 'transform', 'translate(' + @@ -290,15 +290,19 @@ export const drawServices = async function ( textElem.attr('transform', 'translate(' + iconSize / 2 + ', ' + iconSize + ')'); } - let bkgElem = serviceElem.append('g'); + const bkgElem = serviceElem.append('g'); if (service.icon) { // TODO: should a warning be given to end-users saying which icon names are available? // if (!isIconNameInUse(service.icon)) { // throw new Error(`Invalid SVG Icon name: "${service.icon}"`); // } - bkgElem = getIcon(service.icon)?.(bkgElem, iconSize); + bkgElem.html( + `${getIconSVG(service.icon, { height: iconSize, width: iconSize, fallbackPrefix: architectureIcons.prefix })}` + ); } else if (service.iconText) { - bkgElem = getIcon('blank')?.(bkgElem, iconSize); + bkgElem.html( + `${getIconSVG('blank', { height: iconSize, width: iconSize, fallbackPrefix: architectureIcons.prefix })}` + ); const textElemContainer = bkgElem.append('g'); const fo = textElemContainer .append('foreignObject')