diff --git a/cypress/integration/other/external-diagrams.spec.js b/cypress/integration/other/external-diagrams.spec.js new file mode 100644 index 000000000..3a6c37e88 --- /dev/null +++ b/cypress/integration/other/external-diagrams.spec.js @@ -0,0 +1,13 @@ +describe('mermaid', () => { + describe('registerDiagram', () => { + it('should work on @mermaid-js/mermaid-mindmap and mermaid-example-diagram', () => { + const url = 'http://localhost:9000/external-diagrams-mindmap.html'; + cy.visit(url); + + cy.get('svg', { + // may be a bit slower than normal, since vite might need to re-compile mermaid/mermaid-mindmap/mermaid-example-diagram + timeout: 10000, + }).matchImageSnapshot(); + }); + }); +}); diff --git a/cypress/platform/external-diagrams-mindmap.html b/cypress/platform/external-diagrams-mindmap.html new file mode 100644 index 000000000..2d18532da --- /dev/null +++ b/cypress/platform/external-diagrams-mindmap.html @@ -0,0 +1,58 @@ + +
++mindmap + root + A + B + C + D + E + A2 + B2 + C2 + D2 + E2 + child1((Circle)) + grandchild 1 + grandchild 2 + child2(Round rectangle) + grandchild 3 + grandchild 4 + child3[Square] + grandchild 5 + ::icon(mdi mdi-fire) + gc6((grand+
child 6)) + ::icon(mdi mdi-fire) + gc7((grand
grand
child 8)) +
+ example-diagram ++ + + + + + + + + diff --git a/packages/mermaid-example-diagram/src/diagram-definition.ts b/packages/mermaid-example-diagram/src/diagram-definition.ts index c31b3d6e7..95f7cc11d 100644 --- a/packages/mermaid-example-diagram/src/diagram-definition.ts +++ b/packages/mermaid-example-diagram/src/diagram-definition.ts @@ -12,3 +12,5 @@ export const diagram = { styles, injectUtils, }; + +export { detector, id } from './detector'; diff --git a/packages/mermaid-mindmap/src/diagram-definition.ts b/packages/mermaid-mindmap/src/diagram-definition.ts index e7856289d..400cf9e7e 100644 --- a/packages/mermaid-mindmap/src/diagram-definition.ts +++ b/packages/mermaid-mindmap/src/diagram-definition.ts @@ -12,3 +12,5 @@ export const diagram = { styles: mindmapStyles, injectUtils, }; + +export { detector, id } from './detector'; diff --git a/packages/mermaid/src/Diagram.ts b/packages/mermaid/src/Diagram.ts index cdd771e4d..ebba8c9e3 100644 --- a/packages/mermaid/src/Diagram.ts +++ b/packages/mermaid/src/Diagram.ts @@ -106,11 +106,10 @@ export const getDiagramFromText = ( // registerDiagram(type, diagram, undefined, diagram.injectUtils); // // new diagram will try getDiagram again and if fails then it is a valid throw return loader().then(({ diagram }) => { - registerDiagram(type, diagram, undefined, diagram.injectUtils); + registerDiagram(type, diagram, undefined); return new Diagram(txt, parseError); }); } - // return new Diagram(txt, parseError); }; export default Diagram; diff --git a/packages/mermaid/src/diagram-api/diagramAPI.ts b/packages/mermaid/src/diagram-api/diagramAPI.ts index 6eeff6df1..4b21e7d8e 100644 --- a/packages/mermaid/src/diagram-api/diagramAPI.ts +++ b/packages/mermaid/src/diagram-api/diagramAPI.ts @@ -22,17 +22,34 @@ export interface Detectors { [key: string]: DiagramDetector; } +/** + * Registers the given diagram with Mermaid. + * + * Can be used for third-party custom diagrams. + * + * For third-party diagrams that are rarely used, we recommend instead setting + * the `lazyLoadedDiagrams` param in the Mermaid config, as that will instead + * only load the diagram when needed. + * + * @param id - A unique ID for the given diagram. + * @param diagram - The diagram definition. + * @param detector - Function that returns `true` if a given mermaid text is this diagram definition. + * + * @example How to add `@mermaid-js/mermaid-mindmap` to mermaid + * + * ```js + * import { + * diagram as mindmap, detector as mindmapDetector, id as mindmapId + * } from "@mermaid-js/mermaid-mindmap"; + * import mermaid from "mermaid"; + * + * mermaid.mermaidAPI.registerDiagram(mindmapId, mindmap, mindmapDetector); + * ``` + */ export const registerDiagram = ( id: string, diagram: DiagramDefinition, - detector?: DiagramDetector, - callback?: ( - _log: any, - _setLogLevel: any, - _getConfig: any, - _sanitizeText: any, - _setupGraphViewbox: any - ) => void + detector?: DiagramDetector ) => { log.debug(`Registering diagram ${id}`); if (diagrams[id]) { @@ -48,8 +65,9 @@ export const registerDiagram = ( addDetector(id, detector); } addStylesForDiagram(id, diagram.styles); - if (typeof callback !== 'undefined') { - callback(log, setLogLevel, getConfig, sanitizeText, setupGraphViewbox); + + if (diagram.injectUtils) { + diagram.injectUtils(log, setLogLevel, getConfig, sanitizeText, setupGraphViewbox); } log.debug(`Registered diagram ${id}. ${Object.keys(diagrams).join(', ')} diagrams registered.`); }; diff --git a/packages/mermaid/src/diagram-api/types.ts b/packages/mermaid/src/diagram-api/types.ts index 30ff25969..10aac48cf 100644 --- a/packages/mermaid/src/diagram-api/types.ts +++ b/packages/mermaid/src/diagram-api/types.ts @@ -14,7 +14,13 @@ export interface DiagramDefinition { parser: any; styles: any; init?: (config: MermaidConfig) => void; - injectUtils?: (utils: InjectUtils) => void; + injectUtils?: ( + _log: InjectUtils['_log'], + _setLogLevel: InjectUtils['_setLogLevel'], + _getConfig: InjectUtils['_getConfig'], + _sanitizeText: InjectUtils['_sanitizeText'], + _setupGraphViewbox: InjectUtils['_setupGraphViewbox'] + ) => void; } export interface DetectorRecord { diff --git a/packages/mermaid/src/mermaidAPI.ts b/packages/mermaid/src/mermaidAPI.ts index faba5fef8..34cd78697 100644 --- a/packages/mermaid/src/mermaidAPI.ts +++ b/packages/mermaid/src/mermaidAPI.ts @@ -18,6 +18,7 @@ import { compile, serialize, stringify } from 'stylis'; import pkg from '../package.json'; import * as configApi from './config'; import { addDiagrams } from './diagram-api/diagram-orchestration'; +import { registerDiagram } from './diagram-api/diagramAPI'; import classDb from './diagrams/class/classDb'; import flowDb from './diagrams/flowchart/flowDb'; import flowRenderer from './diagrams/flowchart/flowRenderer'; @@ -769,6 +770,8 @@ function initialize(options: MermaidConfig = {}) { addDiagrams(); } +export { registerDiagram }; + export const mermaidAPI = Object.freeze({ render, renderAsync, @@ -776,6 +779,7 @@ export const mermaidAPI = Object.freeze({ parseAsync, parseDirective, initialize, + registerDiagram, getConfig: configApi.getConfig, setConfig: configApi.setConfig, getSiteConfig: configApi.getSiteConfig,