diff --git a/docs/Setup.md b/docs/Setup.md index e1c8879cd..432002d3a 100644 --- a/docs/Setup.md +++ b/docs/Setup.md @@ -1433,24 +1433,6 @@ Returns **[object][5]** The siteConfig Returns **[object][5]** The siteConfig -## setConfig - -## setConfig - -| Function | Description | Type | Values | -| ------------- | ------------------------------------- | ----------- | --------------------------------------- | -| setSiteConfig | Sets the siteConfig to desired values | Put Request | Any Values, except ones in secure array | - -**Notes**: Sets the currentConfig. The parameter conf is sanitized based on the siteConfig.secure -keys. Any values found in conf with key found in siteConfig.secure will be replaced with the -corresponding siteConfig value. - -### Parameters - -- `conf` **any** The potential currentConfig - -Returns **any** The currentConfig merged with the sanitized conf - ## render Function that renders an svg with a graph from a chart definition. Usage example below. @@ -1479,6 +1461,24 @@ $(function () { Returns **any** +## setConfig + +## setConfig + +| Function | Description | Type | Values | +| ------------- | ------------------------------------- | ----------- | --------------------------------------- | +| setSiteConfig | Sets the siteConfig to desired values | Put Request | Any Values, except ones in secure array | + +**Notes**: Sets the currentConfig. The parameter conf is sanitized based on the siteConfig.secure +keys. Any values found in conf with key found in siteConfig.secure will be replaced with the +corresponding siteConfig value. + +### Parameters + +- `conf` **any** The potential currentConfig + +Returns **any** The currentConfig merged with the sanitized conf + ## getConfig ## getConfig diff --git a/jest.config.js b/jest.config.js index ebc6b9fb0..65ea3ef58 100644 --- a/jest.config.js +++ b/jest.config.js @@ -1,5 +1,6 @@ const path = require('path'); +/** @type {import('ts-jest/dist/types').InitialOptionsTsJest} */ module.exports = { testEnvironment: 'jsdom', preset: 'ts-jest', @@ -11,7 +12,7 @@ module.exports = { ], }, transformIgnorePatterns: ['/node_modules/(?!dagre-d3-renderer/lib|khroma).*\\.js'], - testPathIgnorePatterns: ['/node_modules/', '.cache'], + testPathIgnorePatterns: ['/node_modules/', '.cache', './cypress'], moduleNameMapper: { '\\.(css|scss)$': 'identity-obj-proxy', }, diff --git a/package.json b/package.json index abb1c29a5..7185e73f5 100644 --- a/package.json +++ b/package.json @@ -41,7 +41,7 @@ "test": "yarn lint && jest src/.*", "test:watch": "jest --watch src", "prepublishOnly": "yarn build && yarn test", - "prepare": "husky install && yarn build", + "prepare": "husky install", "pre-commit": "lint-staged" }, "repository": { diff --git a/src/Diagram.ts b/src/Diagram.ts index 0a558f0d7..df6633cda 100644 --- a/src/Diagram.ts +++ b/src/Diagram.ts @@ -1,6 +1,6 @@ import * as configApi from './config'; import { log } from './logger'; -import { getDiagrams } from './diagram-api/diagramAPI'; +import { getDiagram } from './diagram-api/diagramAPI'; import { detectType } from './diagram-api/detectType'; export class Diagram { type = 'graph'; @@ -8,28 +8,19 @@ export class Diagram { renderer; db; constructor(public txt: string, parseError?: Function) { - const diagrams = getDiagrams(); const cnf = configApi.getConfig(); this.txt = txt; this.type = detectType(txt, cnf); + const diagram = getDiagram(this.type); log.debug('Type ' + this.type); - - // console.log('this.type', this.type, diagrams[this.type]); // Setup diagram - // @ts-ignore - this.db = diagrams[this.type].db; + this.db = diagram.db; this.db.clear?.(); - - // @ts-ignore - this.renderer = diagrams[this.type].renderer; - // @ts-ignore - this.parser = diagrams[this.type].parser; - // @ts-ignore + this.renderer = diagram.renderer; + this.parser = diagram.parser; this.parser.parser.yy = this.db; - // @ts-ignore - if (typeof diagrams[this.type].init === 'function') { - // @ts-ignore - diagrams[this.type].init(cnf); + if (diagram.init) { + diagram.init(cnf); log.debug('Initialized diagram ' + this.type, cnf); } this.txt += '\n'; @@ -51,7 +42,6 @@ export class Diagram { } catch (error) { // Is this the correct way to access mermiad's parseError() // method ? (or global.mermaid.parseError()) ? - // @ts-ignore if (parseError) { // @ts-ignore if (error.str != undefined) { @@ -61,7 +51,6 @@ export class Diagram { parseError(error.str, error.hash); } else { // assume it is just error string and pass it on - // @ts-ignore parseError(error); } } else { diff --git a/src/config.type.ts b/src/config.type.ts index 632eac73a..a59d39547 100644 --- a/src/config.type.ts +++ b/src/config.type.ts @@ -29,6 +29,7 @@ export interface MermaidConfig { gitGraph?: GitGraphDiagramConfig; c4?: C4DiagramConfig; dompurifyConfig?: DOMPurify.Config; + wrap?: boolean; } // TODO: More configs needs to be moved in here @@ -289,6 +290,7 @@ export interface GanttDiagramConfig extends BaseDiagramConfig { } export interface SequenceDiagramConfig extends BaseDiagramConfig { + arrowMarkerAbsolute?: boolean; hideUnusedParticipants?: boolean; activationWidth?: number; diagramMarginX?: number; @@ -326,6 +328,7 @@ export interface SequenceDiagramConfig extends BaseDiagramConfig { } export interface FlowchartDiagramConfig extends BaseDiagramConfig { + arrowMarkerAbsolute?: boolean; diagramPadding?: number; htmlLabels?: boolean; nodeSpacing?: number; diff --git a/src/diagram-api/diagram-orchestration.ts b/src/diagram-api/diagram-orchestration.ts index ecdb7e467..f8b793ac4 100644 --- a/src/diagram-api/diagram-orchestration.ts +++ b/src/diagram-api/diagram-orchestration.ts @@ -23,10 +23,7 @@ import { gitGraphDetector } from '../diagrams/git/gitGraphDetector'; export const addDiagrams = () => { registerDiagram( 'gitGraph', - gitGraphParser, - gitGraphDb, - gitGraphRenderer, - undefined, + { parser: gitGraphParser, db: gitGraphDb, renderer: gitGraphRenderer }, gitGraphDetector ); }; diff --git a/src/diagram-api/diagramAPI.spec.ts b/src/diagram-api/diagramAPI.spec.ts new file mode 100644 index 000000000..ce12a6433 --- /dev/null +++ b/src/diagram-api/diagramAPI.spec.ts @@ -0,0 +1,29 @@ +import { detectType } from './detectType'; +import { getDiagram, registerDiagram } from './diagramAPI'; + +describe('DiagramAPI', () => { + it('should return default diagrams', () => { + expect(getDiagram('sequence')).not.toBeNull(); + }); + + it('should throw error if diagram is not defined', () => { + expect(() => getDiagram('loki')).toThrow(); + }); + + it('should handle diagram registrations', () => { + expect(() => getDiagram('loki')).toThrow(); + // TODO Q: Shouldn't this be throwing an error? + expect(detectType('loki diagram')).toBe('flowchart'); + registerDiagram( + 'loki', + { + db: {}, + parser: {}, + renderer: {}, + }, + (text: string) => text.includes('loki') + ); + expect(getDiagram('loki')).not.toBeNull(); + expect(detectType('loki diagram')).toBe('loki'); + }); +}); diff --git a/src/diagram-api/diagramAPI.ts b/src/diagram-api/diagramAPI.ts index 7589ff47d..870940d8d 100644 --- a/src/diagram-api/diagramAPI.ts +++ b/src/diagram-api/diagramAPI.ts @@ -1,44 +1,62 @@ -// @ts-nocheck import c4Db from '../diagrams/c4/c4Db'; import c4Renderer from '../diagrams/c4/c4Renderer'; +// @ts-ignore import c4Parser from '../diagrams/c4/parser/c4Diagram'; import classDb from '../diagrams/class/classDb'; import classRenderer from '../diagrams/class/classRenderer'; import classRendererV2 from '../diagrams/class/classRenderer-v2'; +// @ts-ignore import classParser from '../diagrams/class/parser/classDiagram'; import erDb from '../diagrams/er/erDb'; import erRenderer from '../diagrams/er/erRenderer'; +// @ts-ignore import erParser from '../diagrams/er/parser/erDiagram'; import flowDb from '../diagrams/flowchart/flowDb'; import flowRenderer from '../diagrams/flowchart/flowRenderer'; import flowRendererV2 from '../diagrams/flowchart/flowRenderer-v2'; +// @ts-ignore import flowParser from '../diagrams/flowchart/parser/flow'; import ganttDb from '../diagrams/gantt/ganttDb'; import ganttRenderer from '../diagrams/gantt/ganttRenderer'; +// @ts-ignore import ganttParser from '../diagrams/gantt/parser/gantt'; import infoDb from '../diagrams/info/infoDb'; import infoRenderer from '../diagrams/info/infoRenderer'; +// @ts-ignore import infoParser from '../diagrams/info/parser/info'; +// @ts-ignore import pieParser from '../diagrams/pie/parser/pie'; import pieDb from '../diagrams/pie/pieDb'; import pieRenderer from '../diagrams/pie/pieRenderer'; +// @ts-ignore import requirementParser from '../diagrams/requirement/parser/requirementDiagram'; import requirementDb from '../diagrams/requirement/requirementDb'; import requirementRenderer from '../diagrams/requirement/requirementRenderer'; +// @ts-ignore import sequenceParser from '../diagrams/sequence/parser/sequenceDiagram'; import sequenceDb from '../diagrams/sequence/sequenceDb'; import sequenceRenderer from '../diagrams/sequence/sequenceRenderer'; +// @ts-ignore import stateParser from '../diagrams/state/parser/stateDiagram'; import stateDb from '../diagrams/state/stateDb'; import stateRenderer from '../diagrams/state/stateRenderer'; import stateRendererV2 from '../diagrams/state/stateRenderer-v2'; import journeyDb from '../diagrams/user-journey/journeyDb'; import journeyRenderer from '../diagrams/user-journey/journeyRenderer'; +// @ts-ignore import journeyParser from '../diagrams/user-journey/parser/journey'; -import { addDetector } from './detectType'; +import { addDetector, DiagramDetector } from './detectType'; import { log } from '../logger'; +import { MermaidConfig } from '../config.type'; -const diagrams = { +export interface DiagramDefinition { + db: any; + renderer: any; + parser: any; + init?: (config: MermaidConfig) => void; +} + +const diagrams: Record = { c4: { db: c4Db, renderer: c4Renderer, @@ -52,6 +70,9 @@ const diagrams = { renderer: classRenderer, parser: classParser, init: (cnf) => { + if (!cnf.class) { + cnf.class = {}; + } cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; classDb.clear(); }, @@ -61,6 +82,9 @@ const diagrams = { renderer: classRendererV2, parser: classParser, init: (cnf) => { + if (!cnf.class) { + cnf.class = {}; + } cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; classDb.clear(); }, @@ -76,6 +100,9 @@ const diagrams = { parser: flowParser, init: (cnf) => { flowRenderer.setConf(cnf.flowchart); + if (!cnf.flowchart) { + cnf.flowchart = {}; + } cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; flowDb.clear(); flowDb.setGen('gen-1'); @@ -87,6 +114,9 @@ const diagrams = { parser: flowParser, init: (cnf) => { flowRendererV2.setConf(cnf.flowchart); + if (!cnf.flowchart) { + cnf.flowchart = {}; + } cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; flowDb.clear(); flowDb.setGen('gen-2'); @@ -96,15 +126,7 @@ const diagrams = { db: ganttDb, renderer: ganttRenderer, parser: ganttParser, - init: (cnf) => { - ganttRenderer.setConf(cnf.gantt); - }, }, - // git: { - // db: gitGraphAst, - // renderer: gitGraphRenderer, - // parser: gitGraphParser, - // }, info: { db: infoDb, renderer: infoRenderer, @@ -125,11 +147,12 @@ const diagrams = { renderer: sequenceRenderer, parser: sequenceParser, init: (cnf) => { + if (!cnf.sequence) { + cnf.sequence = {}; + } cnf.sequence.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - if (cnf.sequenceDiagram) { - // backwards compatibility - sequenceRenderer.setConf(Object.assign(cnf.sequence, cnf.sequenceDiagram)); - console.error( + if ('sequenceDiagram' in cnf) { + throw new Error( '`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.' ); } @@ -142,6 +165,10 @@ const diagrams = { renderer: stateRenderer, parser: stateParser, init: (cnf) => { + // TODO Q: Why is state diagram init setting cnf.class.arrowMarkerAbsolute ? + if (!cnf.class) { + cnf.class = {}; + } cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; stateDb.clear(); }, @@ -151,6 +178,10 @@ const diagrams = { renderer: stateRendererV2, parser: stateParser, init: (cnf) => { + // TODO Q: Why is state diagram init setting cnf.class.arrowMarkerAbsolute ? + if (!cnf.class) { + cnf.class = {}; + } cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; stateDb.clear(); }, @@ -165,16 +196,22 @@ const diagrams = { }, }, }; -// console.log(sequenceDb); -export const registerDiagram = (id, parser, db, renderer, init, detector) => { + +export const registerDiagram = ( + id: string, + diagram: DiagramDefinition, + detector: DiagramDetector +) => { if (diagrams[id]) { log.warn(`Diagram ${id} already registered.`); } - diagrams[id] = { parser, db, renderer, init }; + diagrams[id] = diagram; addDetector(id, detector); }; -export const getDiagrams = () => { - // console.log('diagrams', diagrams); - return diagrams; +export const getDiagram = (name: string): DiagramDefinition => { + if (name in diagrams) { + return diagrams[name]; + } + throw new Error(`Diagram ${name} not found.`); }; diff --git a/src/diagrams/flowchart/flowDb.js b/src/diagrams/flowchart/flowDb.js index 0fe14a541..e3921ecb6 100644 --- a/src/diagrams/flowchart/flowDb.js +++ b/src/diagrams/flowchart/flowDb.js @@ -425,7 +425,7 @@ funs.push(setupToolTips); * * @param ver */ -export const clear = function (ver) { +export const clear = function (ver = 'gen-1') { vertices = {}; classes = {}; edges = []; @@ -436,7 +436,7 @@ export const clear = function (ver) { subCount = 0; tooltips = []; firstGraphFlag = true; - version = ver || 'gen-1'; + version = ver; commonClear(); }; export const setGen = (ver) => {