diff --git a/cypress/platform/knsv.html b/cypress/platform/knsv.html index c98ce70c8..6ce545082 100644 --- a/cypress/platform/knsv.html +++ b/cypress/platform/knsv.html @@ -38,7 +38,7 @@
-+flowchart LR classDef aPID stroke:#4e4403,fill:#fdde29,color:#4e4403,rx:5px,ry:5px; classDef crm stroke:#333333,fill:#DCDCDC,color:#333333,rx:5px,ry:5px; @@ -99,7 +99,7 @@ flowchart TD class A someclass; class C someclass;-+sequenceDiagram title: My Sequence Diagram Title accTitle: My Acc Sequence Diagram @@ -109,14 +109,14 @@ flowchart TD John-->>Alice: Great! Alice-)John: See you later!-+graph TD A -->|000| B B -->|111| C linkStyle 1 stroke:#ff3,stroke-width:4px,color:red;-+journey accTitle: My User Journey Diagram accDescr: My User Journey Diagram Description @@ -130,10 +130,10 @@ graph TD Go downstairs: 5: Me Sit down: 5: Me-+info-+requirementDiagram accTitle: My req Diagram accDescr: My req Diagram Description @@ -174,7 +174,7 @@ requirementDiagram test_req - contains -> test_req3 test_req <- copies - test_entity2-+gantt dateFormat YYYY-MM-DD title Adding GANTT diagram functionality to mermaid @@ -206,7 +206,7 @@ gantt Add gantt diagram to demo page :20h Add another diagram to demo page :48h-+stateDiagram state Active { Idle @@ -234,7 +234,7 @@ stateDiagram end B ->> A: Return-+classDiagram accTitle: My class diagram accDescr: My class diagram Description @@ -259,7 +259,7 @@ class Class10 { A->>Bob: Hola Bob-->A: Pasten !-+gitGraph commit id: "ZERO" branch develop @@ -288,7 +288,7 @@ flowchart TD C -->|Two| E[iPhone] C -->|Three| F[fa:fa-car Car]-+classDiagram Animal "1" <|-- Duck Animal <|-- Fish @@ -311,7 +311,7 @@ flowchart TD +run() }-+erDiagram CAR ||--o{ NAMED-DRIVER : allows CAR { diff --git a/package.json b/package.json index a791f0574..fa3b69dda 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "mermaid", - "version": "9.1.6", + "version": "9.2.0-rc1", "description": "Markdownish syntax for generating flowcharts, sequence diagrams, class diagrams, gantt charts and git graphs.", "main": "dist/mermaid.min.js", "module": "dist/mermaid.esm.min.mjs", diff --git a/src/diagram-api/detectType.ts b/src/diagram-api/detectType.ts index 87b681767..817de5149 100644 --- a/src/diagram-api/detectType.ts +++ b/src/diagram-api/detectType.ts @@ -1,26 +1,12 @@ import { MermaidConfig } from '../config.type'; -export type DiagramDetector = (text: string) => boolean; +export type DiagramDetector = (text: string, config?: MermaidConfig) => boolean; const directive = /[%]{2}[{]\s*(?:(?:(\w+)\s*:|(\w+))\s*(?:(?:(\w+))|((?:(?![}][%]{2}).|\r?\n)*))?\s*)(?:[}][%]{2})?/gi; const anyComment = /\s*%%.*\n/gm; const detectors: Record= {}; -const diagramMatchers: Record = { - c4: /^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/, - sequence: /^\s*sequenceDiagram/, - gantt: /^\s*gantt/, - classDiagram: /^\s*classDiagram-v2/, - stateDiagram: /^\s*stateDiagram-v2/, - 'flowchart-v2': /^\s*flowchart/, // Might need to add |graph to fix #3391 - info: /^\s*info/, - pie: /^\s*pie/, - er: /^\s*erDiagram/, - journey: /^\s*journey/, - // gitGraph: /^\s*gitGraph/, - requirement: /^\s*requirement(Diagram)?/, -}; /** * @function detectType Detects the type of the graph text. Takes into consideration the possible @@ -47,28 +33,9 @@ const diagramMatchers: Record = { */ export const detectType = function (text: string, config?: MermaidConfig): string { text = text.replace(directive, '').replace(anyComment, '\n'); - for (const [diagram, matcher] of Object.entries(diagramMatchers)) { - if (text.match(matcher)) { - return diagram; - } - } - - if (text.match(/^\s*classDiagram/)) { - if (config?.class?.defaultRenderer === 'dagre-wrapper') return 'classDiagram'; - return 'class'; - } - - if (text.match(/^\s*stateDiagram/)) { - if (config?.state?.defaultRenderer === 'dagre-wrapper') return 'stateDiagram'; - return 'state'; - } - - if (config?.flowchart?.defaultRenderer === 'dagre-wrapper') { - return 'flowchart-v2'; - } for (const [key, detector] of Object.entries(detectors)) { - if (detector(text)) { + if (detector(text, config)) { return key; } } diff --git a/src/diagram-api/diagram-orchestration.ts b/src/diagram-api/diagram-orchestration.ts index ea0c76ffa..b9b0520c9 100644 --- a/src/diagram-api/diagram-orchestration.ts +++ b/src/diagram-api/diagram-orchestration.ts @@ -1,20 +1,310 @@ import { registerDiagram } from './diagramAPI'; -import * as mindmapDb from '../diagrams/mindmap/mindmapDb'; -import mindmapRenderer from '../diagrams/mindmap/mindmapRenderer'; + // @ts-ignore: TODO Fix ts errors import mindmapParser from '../diagrams/mindmap/parser/mindmap'; +import * as mindmapDb from '../diagrams/mindmap/mindmapDb'; import { mindmapDetector } from '../diagrams/mindmap/mindmapDetector'; +import mindmapRenderer from '../diagrams/mindmap/mindmapRenderer'; import mindmapStyles from '../diagrams/mindmap/styles'; -import gitGraphDb from '../diagrams/git/gitGraphAst'; -import gitGraphRenderer from '../diagrams/git/gitGraphRenderer'; // @ts-ignore: TODO Fix ts errors import gitGraphParser from '../diagrams/git/parser/gitGraph'; import { gitGraphDetector } from '../diagrams/git/gitGraphDetector'; +import gitGraphDb from '../diagrams/git/gitGraphAst'; +import gitGraphRenderer from '../diagrams/git/gitGraphRenderer'; import gitGraphStyles from '../diagrams/git/styles'; +// @ts-ignore: TODO Fix ts errors +import c4Parser from '../diagrams/c4/parser/c4Diagram'; +import { c4Detector } from '../diagrams/c4/c4Detector'; +import c4Db from '../diagrams/c4/c4Db'; +import c4Renderer from '../diagrams/c4/c4Renderer'; +import c4Styles from '../diagrams/c4/styles'; + +// @ts-ignore: TODO Fix ts errors +import classParser from '../diagrams/class/parser/classDiagram'; +import { classDetector } from '../diagrams/class/classDetector'; +import { classDetectorV2 } from '../diagrams/class/classDetector-V2'; +import classDb from '../diagrams/class/classDb'; +import classRenderer from '../diagrams/class/classRenderer'; +import classRendererV2 from '../diagrams/class/classRenderer-v2'; +import classStyles from '../diagrams/class/styles'; + +// @ts-ignore: TODO Fix ts errors +import erParser from '../diagrams/er/parser/erDiagram'; +import { erDetector } from '../diagrams/er/erDetector'; +import erDb from '../diagrams/er/erDb'; +import erRenderer from '../diagrams/er/erRenderer'; +import erStyles from '../diagrams/er/styles'; + +// @ts-ignore: TODO Fix ts errors +import flowParser from '../diagrams/flowchart/parser/flow'; +import { flowDetector } from '../diagrams/flowchart/flowDetector'; +import { flowDetectorV2 } from '../diagrams/flowchart/flowDetector-v2'; +import flowDb from '../diagrams/flowchart/flowDb'; +import flowRenderer from '../diagrams/flowchart/flowRenderer'; +import flowRendererV2 from '../diagrams/flowchart/flowRenderer-v2'; +import flowStyles from '../diagrams/flowchart/styles'; + +// @ts-ignore: TODO Fix ts errors +import ganttParser from '../diagrams/gantt/parser/gantt'; +import { ganttDetector } from '../diagrams/gantt/ganttDetector'; +import ganttDb from '../diagrams/gantt/ganttDb'; +import ganttRenderer from '../diagrams/gantt/ganttRenderer'; +import ganttStyles from '../diagrams/gantt/styles'; + +// @ts-ignore: TODO Fix ts errors +import infoParser from '../diagrams/info/parser/info'; +import infoDb from '../diagrams/info/infoDb'; +import infoRenderer from '../diagrams/info/infoRenderer'; +import { infoDetector } from '../diagrams/info/infoDetector'; +import infoStyles from '../diagrams/info/styles'; + +// @ts-ignore: TODO Fix ts errors +import pieParser from '../diagrams/pie/parser/pie'; +import { pieDetector } from '../diagrams/pie/pieDetector'; +import pieDb from '../diagrams/pie/pieDb'; +import pieRenderer from '../diagrams/pie/pieRenderer'; +import pieStyles from '../diagrams/pie/styles'; + +// @ts-ignore: TODO Fix ts errors +import requirementParser from '../diagrams/requirement/parser/requirementDiagram'; +import { requirementDetector } from '../diagrams/requirement/requirementDetector'; +import requirementDb from '../diagrams/requirement/requirementDb'; +import requirementRenderer from '../diagrams/requirement/requirementRenderer'; +import requirementStyles from '../diagrams/requirement/styles'; + +// @ts-ignore: TODO Fix ts errors +import sequenceParser from '../diagrams/sequence/parser/sequenceDiagram'; +import { sequenceDetector } from '../diagrams/sequence/sequenceDetector'; +import sequenceDb from '../diagrams/sequence/sequenceDb'; +import sequenceRenderer from '../diagrams/sequence/sequenceRenderer'; +import sequenceStyles from '../diagrams/sequence/styles'; + +// @ts-ignore: TODO Fix ts errors +import stateParser from '../diagrams/state/parser/stateDiagram'; +import { stateDetector } from '../diagrams/state/stateDetector'; +import { stateDetectorV2 } from '../diagrams/state/stateDetector-V2'; +import stateDb from '../diagrams/state/stateDb'; +import stateRenderer from '../diagrams/state/stateRenderer'; +import stateRendererV2 from '../diagrams/state/stateRenderer-v2'; +import stateStyles from '../diagrams/state/styles'; + +// @ts-ignore: TODO Fix ts errors +import journeyParser from '../diagrams/user-journey/parser/journey'; +import { journeyDetector } from '../diagrams/user-journey/journeyDetector'; +import journeyDb from '../diagrams/user-journey/journeyDb'; +import journeyRenderer from '../diagrams/user-journey/journeyRenderer'; +import journeyStyles from '../diagrams/user-journey/styles'; + export const addDiagrams = () => { - // Register mindmap and other built-in diagrams + registerDiagram( + 'c4', + { + parser: c4Parser, + db: c4Db, + renderer: c4Renderer, + styles: c4Styles, + init: (cnf) => { + c4Renderer.setConf(cnf.c4); + }, + }, + c4Detector + ); + registerDiagram( + 'class', + { + parser: classParser, + db: classDb, + renderer: classRenderer, + styles: classStyles, + init: (cnf) => { + if (!cnf.class) { + cnf.class = {}; + } + cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + classDb.clear(); + }, + }, + classDetector + ); + registerDiagram( + 'classDiagram', + { + parser: classParser, + db: classDb, + renderer: classRendererV2, + styles: classStyles, + init: (cnf) => { + if (!cnf.class) { + cnf.class = {}; + } + cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + classDb.clear(); + }, + }, + classDetectorV2 + ); + registerDiagram( + 'er', + { + parser: erParser, + db: erDb, + renderer: erRenderer, + styles: erStyles, + }, + erDetector + ); + registerDiagram( + 'gantt', + { + parser: ganttParser, + db: ganttDb, + renderer: ganttRenderer, + styles: ganttStyles, + }, + ganttDetector + ); + registerDiagram( + 'info', + { + parser: infoParser, + db: infoDb, + renderer: infoRenderer, + styles: infoStyles, + }, + infoDetector + ); + registerDiagram( + 'pie', + { + parser: pieParser, + db: pieDb, + renderer: pieRenderer, + styles: pieStyles, + }, + pieDetector + ); + registerDiagram( + 'requirement', + { + parser: requirementParser, + db: requirementDb, + renderer: requirementRenderer, + styles: requirementStyles, + }, + requirementDetector + ); + registerDiagram( + 'sequence', + { + parser: sequenceParser, + db: sequenceDb, + renderer: sequenceRenderer, + styles: sequenceStyles, + init: (cnf) => { + if (!cnf.sequence) { + cnf.sequence = {}; + } + cnf.sequence.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + if ('sequenceDiagram' in cnf) { + throw new Error( + '`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.' + ); + } + sequenceDb.setWrap(cnf.wrap); + sequenceRenderer.setConf(cnf.sequence); + }, + }, + sequenceDetector + ); + registerDiagram( + 'state', + { + parser: stateParser, + db: stateDb, + renderer: stateRenderer, + styles: stateStyles, + init: (cnf) => { + if (!cnf.state) { + cnf.state = {}; + } + cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + stateDb.clear(); + }, + }, + stateDetector + ); + registerDiagram( + 'stateDiagram', + { + parser: stateParser, + db: stateDb, + renderer: stateRendererV2, + styles: stateStyles, + init: (cnf) => { + if (!cnf.state) { + cnf.state = {}; + } + cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + stateDb.clear(); + }, + }, + stateDetectorV2 + ); + registerDiagram( + 'journey', + { + parser: journeyParser, + db: journeyDb, + renderer: journeyRenderer, + styles: journeyStyles, + init: (cnf) => { + journeyRenderer.setConf(cnf.journey); + journeyDb.clear(); + }, + }, + journeyDetector + ); + + registerDiagram( + 'flowchart', + { + parser: flowParser, + db: flowDb, + renderer: flowRendererV2, + styles: flowStyles, + init: (cnf) => { + flowRenderer.setConf(cnf.flowchart); + if (!cnf.flowchart) { + cnf.flowchart = {}; + } + cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + flowDb.clear(); + flowDb.setGen('gen-1'); + }, + }, + flowDetector + ); + registerDiagram( + 'flowchart-v2', + { + parser: flowParser, + db: flowDb, + renderer: flowRendererV2, + styles: flowStyles, + init: (cnf) => { + flowRendererV2.setConf(cnf.flowchart); + if (!cnf.flowchart) { + cnf.flowchart = {}; + } + cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; + flowDb.clear(); + flowDb.setGen('gen-2'); + }, + }, + flowDetectorV2 + ); registerDiagram( 'gitGraph', { parser: gitGraphParser, db: gitGraphDb, renderer: gitGraphRenderer, styles: gitGraphStyles }, diff --git a/src/diagram-api/diagramAPI.spec.ts b/src/diagram-api/diagramAPI.spec.ts index f72384c11..e0c7a283d 100644 --- a/src/diagram-api/diagramAPI.spec.ts +++ b/src/diagram-api/diagramAPI.spec.ts @@ -1,5 +1,8 @@ import { detectType } from './detectType'; import { getDiagram, registerDiagram } from './diagramAPI'; +import { addDiagrams } from './diagram-orchestration'; + +addDiagrams(); describe('DiagramAPI', () => { it('should return default diagrams', () => { diff --git a/src/diagram-api/diagramAPI.ts b/src/diagram-api/diagramAPI.ts index 652e66465..9a86c5b51 100644 --- a/src/diagram-api/diagramAPI.ts +++ b/src/diagram-api/diagramAPI.ts @@ -1,70 +1,23 @@ -import c4Db from '../diagrams/c4/c4Db'; -import c4Renderer from '../diagrams/c4/c4Renderer'; -import c4Styles from '../diagrams/c4/styles'; -// @ts-ignore: TODO Fix ts errors -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'; -import classStyles from '../diagrams/class/styles'; -// @ts-ignore: TODO Fix ts errors -import classParser from '../diagrams/class/parser/classDiagram'; -import erDb from '../diagrams/er/erDb'; -import erRenderer from '../diagrams/er/erRenderer'; -// @ts-ignore: TODO Fix ts errors -import erParser from '../diagrams/er/parser/erDiagram'; -import erStyles from '../diagrams/er/styles'; -import flowDb from '../diagrams/flowchart/flowDb'; -import flowRenderer from '../diagrams/flowchart/flowRenderer'; -import flowRendererV2 from '../diagrams/flowchart/flowRenderer-v2'; -import flowStyles from '../diagrams/flowchart/styles'; -// @ts-ignore: TODO Fix ts errors -import flowParser from '../diagrams/flowchart/parser/flow'; -import ganttDb from '../diagrams/gantt/ganttDb'; -import ganttRenderer from '../diagrams/gantt/ganttRenderer'; -// @ts-ignore: TODO Fix ts errors -import ganttParser from '../diagrams/gantt/parser/gantt'; -import ganttStyles from '../diagrams/gantt/styles'; - -import infoDb from '../diagrams/info/infoDb'; -import infoRenderer from '../diagrams/info/infoRenderer'; -// @ts-ignore: TODO Fix ts errors -import infoParser from '../diagrams/info/parser/info'; -import infoStyles from '../diagrams/info/styles'; -// @ts-ignore: TODO Fix ts errors -import pieParser from '../diagrams/pie/parser/pie'; -import pieDb from '../diagrams/pie/pieDb'; -import pieRenderer from '../diagrams/pie/pieRenderer'; -import pieStyles from '../diagrams/pie/styles'; -// @ts-ignore: TODO Fix ts errors -import requirementParser from '../diagrams/requirement/parser/requirementDiagram'; -import requirementDb from '../diagrams/requirement/requirementDb'; -import requirementRenderer from '../diagrams/requirement/requirementRenderer'; -import requirementStyles from '../diagrams/requirement/styles'; -// @ts-ignore: TODO Fix ts errors -import sequenceParser from '../diagrams/sequence/parser/sequenceDiagram'; -import sequenceDb from '../diagrams/sequence/sequenceDb'; -import sequenceRenderer from '../diagrams/sequence/sequenceRenderer'; -import sequenceStyles from '../diagrams/sequence/styles'; -// @ts-ignore: TODO Fix ts errors -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 stateStyles from '../diagrams/state/styles'; -import journeyDb from '../diagrams/user-journey/journeyDb'; -import journeyRenderer from '../diagrams/user-journey/journeyRenderer'; -import journeyStyles from '../diagrams/user-journey/styles'; -// @ts-ignore: TODO Fix ts errors -import journeyParser from '../diagrams/user-journey/parser/journey'; -import { addDetector, DiagramDetector } from './detectType'; -import { log as _log } from '../logger'; +import { addDetector, DiagramDetector as _DiagramDetector } from './detectType'; +import { log as _log, setLogLevel as _setLogLevel } from '../logger'; import { getConfig as _getConfig } from '../config'; import { sanitizeText as _sanitizeText } from '../diagrams/common/common'; import { MermaidConfig } from '../config.type'; import { setupGraphViewbox as _setupGraphViewbox } from '../setupGraphViewbox'; import { addStylesForDiagram } from '../styles'; +/* + Packaging and exposing resources for externa diagrams so that they can import + diagramAPI and have access to selct parts of mermaid common code reqiored to + create diagrams worling like the internal diagrams. +*/ +export const log = _log; +export const setLogLevel = _setLogLevel; +export type DiagramDetector = _DiagramDetector; +export const getConfig = _getConfig; +export const sanitizeText = (text: string) => _sanitizeText(text, getConfig()); +export const setupGraphViewbox = _setupGraphViewbox; + export interface DiagramDefinition { db: any; renderer: any; @@ -73,158 +26,7 @@ export interface DiagramDefinition { init?: (config: MermaidConfig) => void; } -const diagrams: Record = { - c4: { - db: c4Db, - renderer: c4Renderer, - parser: c4Parser, - init: (cnf) => { - c4Renderer.setConf(cnf.c4); - }, - styles: c4Styles, - }, - class: { - db: classDb, - renderer: classRenderer, - parser: classParser, - init: (cnf) => { - if (!cnf.class) { - cnf.class = {}; - } - cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - classDb.clear(); - }, - styles: classStyles, - }, - classDiagram: { - db: classDb, - renderer: classRendererV2, - parser: classParser, - init: (cnf) => { - if (!cnf.class) { - cnf.class = {}; - } - cnf.class.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - classDb.clear(); - }, - styles: classStyles, - }, - er: { - db: erDb, - renderer: erRenderer, - parser: erParser, - styles: erStyles, - }, - flowchart: { - db: flowDb, - renderer: flowRenderer, - parser: flowParser, - init: (cnf) => { - flowRenderer.setConf(cnf.flowchart); - if (!cnf.flowchart) { - cnf.flowchart = {}; - } - cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - flowDb.clear(); - flowDb.setGen('gen-1'); - }, - styles: flowStyles, - }, - 'flowchart-v2': { - db: flowDb, - renderer: flowRendererV2, - parser: flowParser, - init: (cnf) => { - flowRendererV2.setConf(cnf.flowchart); - if (!cnf.flowchart) { - cnf.flowchart = {}; - } - cnf.flowchart.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - flowDb.clear(); - flowDb.setGen('gen-2'); - }, - styles: flowStyles, - }, - gantt: { - db: ganttDb, - renderer: ganttRenderer, - parser: ganttParser, - styles: ganttStyles, - }, - info: { - db: infoDb, - renderer: infoRenderer, - parser: infoParser, - styles: infoStyles, - }, - pie: { - db: pieDb, - renderer: pieRenderer, - parser: pieParser, - styles: pieStyles, - }, - requirement: { - db: requirementDb, - renderer: requirementRenderer, - parser: requirementParser, - styles: requirementStyles, - }, - sequence: { - db: sequenceDb, - renderer: sequenceRenderer, - parser: sequenceParser, - init: (cnf) => { - if (!cnf.sequence) { - cnf.sequence = {}; - } - cnf.sequence.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - if ('sequenceDiagram' in cnf) { - throw new Error( - '`mermaid config.sequenceDiagram` has been renamed to `config.sequence`. Please update your mermaid config.' - ); - } - sequenceDb.setWrap(cnf.wrap); - sequenceRenderer.setConf(cnf.sequence); - }, - styles: sequenceStyles, - }, - state: { - db: stateDb, - renderer: stateRenderer, - parser: stateParser, - init: (cnf) => { - if (!cnf.state) { - cnf.state = {}; - } - cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - stateDb.clear(); - }, - styles: stateStyles, - }, - stateDiagram: { - db: stateDb, - renderer: stateRendererV2, - parser: stateParser, - init: (cnf) => { - if (!cnf.state) { - cnf.state = {}; - } - cnf.state.arrowMarkerAbsolute = cnf.arrowMarkerAbsolute; - stateDb.clear(); - }, - styles: stateStyles, - }, - journey: { - db: journeyDb, - renderer: journeyRenderer, - parser: journeyParser, - init: (cnf) => { - journeyRenderer.setConf(cnf.journey); - journeyDb.clear(); - }, - styles: journeyStyles, - }, -}; +const diagrams: Record = {}; export const registerDiagram = ( id: string, @@ -245,8 +47,3 @@ export const getDiagram = (name: string): DiagramDefinition => { } throw new Error(`Diagram ${name} not found.`); }; - -export const log = _log; -export const getConfig = _getConfig; -export const sanitizeText = (text: string) => _sanitizeText(text, getConfig()); -export const setupGraphViewbox = _setupGraphViewbox; diff --git a/src/diagrams/c4/c4Detector.ts b/src/diagrams/c4/c4Detector.ts new file mode 100644 index 000000000..2be62bff1 --- /dev/null +++ b/src/diagrams/c4/c4Detector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const c4Detector: DiagramDetector = (txt) => { + return txt.match(/^\s*C4Context|C4Container|C4Component|C4Dynamic|C4Deployment/) !== null; +}; diff --git a/src/diagrams/class/classDetector-V2.ts b/src/diagrams/class/classDetector-V2.ts new file mode 100644 index 000000000..a0e270100 --- /dev/null +++ b/src/diagrams/class/classDetector-V2.ts @@ -0,0 +1,9 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const classDetectorV2: DiagramDetector = (txt, config) => { + // If we have confgured to use dagre-wrapper then we should return true in this function for classDiagram code thus making it use the new class diagram + if (txt.match(/^\s*classDiagram/) !== null && config?.class?.defaultRenderer === 'dagre-wrapper') + return true; + // We have not opted to use the new renderer so we should return true if we detect a class diagram + return txt.match(/^\s*classDiagram-v2/) !== null; +}; diff --git a/src/diagrams/class/classDetector.ts b/src/diagrams/class/classDetector.ts new file mode 100644 index 000000000..19d8bd2f5 --- /dev/null +++ b/src/diagrams/class/classDetector.ts @@ -0,0 +1,8 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const classDetector: DiagramDetector = (txt, config) => { + // If we have confgured to use dagre-wrapper then we should never return true in this function + if (config?.class?.defaultRenderer === 'dagre-wrapper') return false; + // We have not opted to use the new renderer so we should return true if we detect a class diagram + return txt.match(/^\s*classDiagram/) !== null; +}; diff --git a/src/diagrams/er/erDetector.ts b/src/diagrams/er/erDetector.ts new file mode 100644 index 000000000..a17eafb81 --- /dev/null +++ b/src/diagrams/er/erDetector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const erDetector: DiagramDetector = (txt) => { + return txt.match(/^\s*erDiagram/) !== null; +}; diff --git a/src/diagrams/flowchart/flowDetector-v2.ts b/src/diagrams/flowchart/flowDetector-v2.ts new file mode 100644 index 000000000..f73748c79 --- /dev/null +++ b/src/diagrams/flowchart/flowDetector-v2.ts @@ -0,0 +1,8 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const flowDetectorV2: DiagramDetector = (txt, config) => { + // If we have confgured to use dagre-wrapper then we should return true in this function for graph code thus making it use the new flowchart diagram + if (config?.flowchart?.defaultRenderer === 'dagre-wrapper' && txt.match(/^\s*graph/) !== null) + return true; + return txt.match(/^\s*flowchart/) !== null; +}; diff --git a/src/diagrams/flowchart/flowDetector.ts b/src/diagrams/flowchart/flowDetector.ts new file mode 100644 index 000000000..edc9096c0 --- /dev/null +++ b/src/diagrams/flowchart/flowDetector.ts @@ -0,0 +1,8 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const flowDetector: DiagramDetector = (txt, config) => { + // If we have confired to only use new flow charts this function shohuld always return false + // as in not signalling true for a legacy flowchart + if (config?.flowchart?.defaultRenderer === 'dagre-wrapper') return false; + return txt.match(/^\s*graph/) !== null; +}; diff --git a/src/diagrams/flowchart/flowRenderer.addEdges.spec.js b/src/diagrams/flowchart/flowRenderer.addEdges.spec.js new file mode 100644 index 000000000..1bcb076f1 --- /dev/null +++ b/src/diagrams/flowchart/flowRenderer.addEdges.spec.js @@ -0,0 +1,154 @@ +import flowDb from './flowDb'; +import flowParser from './parser/flow'; +import flowRenderer from './flowRenderer'; +import Diagram from '../../Diagram'; +import { addDiagrams } from '../../diagram-api/diagram-orchestration'; +addDiagrams(); +afterEach(() => { + jest.restoreAllMocks(); +}); + +describe('when using mermaid and ', function () { + describe('when calling addEdges ', function () { + beforeEach(function () { + flowParser.parser.yy = flowDb; + flowDb.clear(); + flowDb.setGen('gen-2'); + }); + it('should handle edges with text', function () { + const diag = new Diagram('graph TD;A-->|text ex|B;'); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B-'); + expect(options.arrowhead).toBe('normal'); + expect(options.label.match('text ex')).toBeTruthy(); + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + + it('should handle edges without text', function () { + const diag = new Diagram('graph TD;A-->B;'); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B-'); + expect(options.arrowhead).toBe('normal'); + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + + it('should handle open-ended edges', function () { + const diag = new Diagram('graph TD;A---B;'); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B-'); + expect(options.arrowhead).toBe('none'); + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + + it('should handle edges with styles defined', function () { + const diag = new Diagram('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;'); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B-'); + expect(options.arrowhead).toBe('none'); + expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;'); + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + it('should handle edges with interpolation defined', function () { + const diag = new Diagram('graph TD;A---B; linkStyle 0 interpolate basis'); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B-'); + expect(options.arrowhead).toBe('none'); + expect(options.curve).toBe('basis'); // mocked as string + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + it('should handle edges with text and styles defined', function () { + const diag = new Diagram( + 'graph TD;A---|the text|B; linkStyle 0 stroke:val1,stroke-width:val2;' + ); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B-'); + expect(options.arrowhead).toBe('none'); + expect(options.label.match('the text')).toBeTruthy(); + expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;'); + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + + it('should set fill to "none" by default when handling edges', function () { + const diag = new Diagram('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;'); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B'); + expect(options.arrowhead).toBe('none'); + expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;'); + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + + it('should not set fill to none if fill is set in linkStyle', function () { + const diag = new Diagram( + 'graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2,fill:blue;' + ); + diag.db.getVertices(); + const edges = diag.db.getEdges(); + const mockG = { + setEdge: function (start, end, options) { + expect(start).toContain('flowchart-A-'); + expect(end).toContain('flowchart-B-'); + expect(options.arrowhead).toBe('none'); + expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:blue;'); + }, + }; + + flowRenderer.addEdges(edges, mockG, diag); + }); + }); +}); diff --git a/src/diagrams/gantt/ganttDetector.ts b/src/diagrams/gantt/ganttDetector.ts new file mode 100644 index 000000000..926792dcf --- /dev/null +++ b/src/diagrams/gantt/ganttDetector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const ganttDetector: DiagramDetector = (txt) => { + return txt.match(/^\s*gantt/) !== null; +}; diff --git a/src/diagrams/info/infoDetector.ts b/src/diagrams/info/infoDetector.ts new file mode 100644 index 000000000..68f2ac794 --- /dev/null +++ b/src/diagrams/info/infoDetector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const infoDetector: DiagramDetector = (txt) => { + return txt.match(/^\s*info/) !== null; +}; diff --git a/src/diagrams/mindmap/mindmap.spec.js b/src/diagrams/mindmap/mindmap.spec.js index 155b566fb..e7909ef50 100644 --- a/src/diagrams/mindmap/mindmap.spec.js +++ b/src/diagrams/mindmap/mindmap.spec.js @@ -1,6 +1,6 @@ import { parser as mindmap } from './parser/mindmap'; import * as mindmapDB from './mindmapDb'; -import { setLogLevel } from '../../logger'; +import { setLogLevel } from '../../diagram-api/diagramAPI'; describe('when parsing a mindmap ', function () { beforeEach(function () { diff --git a/src/diagrams/mindmap/mindmapDb.js b/src/diagrams/mindmap/mindmapDb.js index 48b242c9e..68906c5fb 100644 --- a/src/diagrams/mindmap/mindmapDb.js +++ b/src/diagrams/mindmap/mindmapDb.js @@ -1,6 +1,5 @@ /** Created by knut on 15-01-14. */ -import { sanitizeText, getConfig } from '../../diagram-api/diagramAPI'; -import { log as _log } from '../../logger'; +import { sanitizeText, getConfig, log as _log } from '../../diagram-api/diagramAPI'; let nodes = []; let cnt = 0; diff --git a/src/diagrams/mindmap/svgDraw.js b/src/diagrams/mindmap/svgDraw.js index 511c46e20..0b5c5e264 100644 --- a/src/diagrams/mindmap/svgDraw.js +++ b/src/diagrams/mindmap/svgDraw.js @@ -1,4 +1,3 @@ -const lineBreakRegex = /
/gi; import { select } from 'd3'; import * as db from './mindmapDb'; @@ -15,7 +14,6 @@ function wrap(text, width) { .reverse(), word, line = [], - lineNumber = 0, lineHeight = 1.1, // ems y = text.attr('y'), dy = parseFloat(text.attr('dy')), diff --git a/src/diagrams/pie/pieDetector.ts b/src/diagrams/pie/pieDetector.ts new file mode 100644 index 000000000..1e122b0e0 --- /dev/null +++ b/src/diagrams/pie/pieDetector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const pieDetector: DiagramDetector = (txt) => { + return txt.match(/^\s*pie/) !== null; +}; diff --git a/src/diagrams/requirement/requirementDetector.ts b/src/diagrams/requirement/requirementDetector.ts new file mode 100644 index 000000000..2e1aa93ae --- /dev/null +++ b/src/diagrams/requirement/requirementDetector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const requirementDetector: DiagramDetector = (txt) => { + return txt.match(/^\s*requirement(Diagram)?/) !== null; +}; diff --git a/src/diagrams/sequence/sequenceDetector.ts b/src/diagrams/sequence/sequenceDetector.ts new file mode 100644 index 000000000..e68433255 --- /dev/null +++ b/src/diagrams/sequence/sequenceDetector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const sequenceDetector: DiagramDetector = (txt) => { + return txt.match(/^\s*sequenceDiagram/) !== null; +}; diff --git a/src/diagrams/sequence/sequenceDiagram.spec.js b/src/diagrams/sequence/sequenceDiagram.spec.js index 808eb567e..5479e49e4 100644 --- a/src/diagrams/sequence/sequenceDiagram.spec.js +++ b/src/diagrams/sequence/sequenceDiagram.spec.js @@ -1,12 +1,8 @@ -// import sequence from './parser/sequenceDiagram'; -// import sequenceDb from './sequenceDb'; import * as configApi from '../../config'; -// import renderer from './sequenceRenderer'; import mermaidAPI from '../../mermaidAPI'; -// import '../../diagram-api/diagramAPI'; import Diagram from '../../Diagram'; - -// console.log('sequenceDiagram', sequenceDb); +import { addDiagrams } from '../../diagram-api/diagram-orchestration'; +addDiagrams(); /** * @param conf * @param key diff --git a/src/diagrams/state/stateDetector-V2.ts b/src/diagrams/state/stateDetector-V2.ts new file mode 100644 index 000000000..8082a47bd --- /dev/null +++ b/src/diagrams/state/stateDetector-V2.ts @@ -0,0 +1,8 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const stateDetectorV2: DiagramDetector = (text, config) => { + if (text.match(/^\s*stateDiagram-v2/) !== null) return true; + if (text.match(/^\s*stateDiagram/) && config?.state?.defaultRenderer === 'dagre-wrapper') + return true; + return false; +}; diff --git a/src/diagrams/state/stateDetector.ts b/src/diagrams/state/stateDetector.ts new file mode 100644 index 000000000..79dd6586b --- /dev/null +++ b/src/diagrams/state/stateDetector.ts @@ -0,0 +1,8 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const stateDetector: DiagramDetector = (txt, config) => { + // If we have confired to only use new state diagrams this function should always return false + // as in not signalling true for a legacy state diagram + if (config?.state?.defaultRenderer === 'dagre-wrapper') return false; + return txt.match(/^\s*stateDiagram/) !== null; +}; diff --git a/src/diagrams/user-journey/journeyDetector.ts b/src/diagrams/user-journey/journeyDetector.ts new file mode 100644 index 000000000..77c8688ae --- /dev/null +++ b/src/diagrams/user-journey/journeyDetector.ts @@ -0,0 +1,5 @@ +import type { DiagramDetector } from '../../diagram-api/detectType'; + +export const journeyDetector: DiagramDetector = (txt) => { + return txt.match(/^\s*journey/) !== null; +}; diff --git a/src/mermaid.spec.js b/src/mermaid.spec.js index c6014dfff..fcd83a61b 100644 --- a/src/mermaid.spec.js +++ b/src/mermaid.spec.js @@ -2,8 +2,6 @@ import mermaid from './mermaid'; import { mermaidAPI } from './mermaidAPI'; import flowDb from './diagrams/flowchart/flowDb'; import flowParser from './diagrams/flowchart/parser/flow'; -import flowRenderer from './diagrams/flowchart/flowRenderer'; -import Diagram from './Diagram'; const spyOn = jest.spyOn; @@ -58,149 +56,6 @@ describe('when using mermaid and ', function () { }); }); - describe('when calling addEdges ', function () { - beforeEach(function () { - flowParser.parser.yy = flowDb; - flowDb.clear(); - flowDb.setGen('gen-2'); - }); - it('should handle edges with text', function () { - const diag = new Diagram('graph TD;A-->|text ex|B;'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - - const mockG = { - setEdge: function (start, end, options) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B-'); - expect(options.arrowhead).toBe('normal'); - expect(options.label.match('text ex')).toBeTruthy(); - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - - it('should handle edges without text', function () { - const diag = new Diagram('graph TD;A-->B;'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - - const mockG = { - setEdge: function (start, end, options) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B-'); - expect(options.arrowhead).toBe('normal'); - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - - it('should handle open-ended edges', function () { - const diag = new Diagram('graph TD;A---B;'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - - const mockG = { - setEdge: function (start, end, options) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B-'); - expect(options.arrowhead).toBe('none'); - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - - it('should handle edges with styles defined', function () { - const diag = new Diagram('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - - const mockG = { - setEdge: function (start, end, options) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B-'); - expect(options.arrowhead).toBe('none'); - expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;'); - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - it('should handle edges with interpolation defined', function () { - const diag = new Diagram('graph TD;A---B; linkStyle 0 interpolate basis'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - - const mockG = { - setEdge: function (start, end, options) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B-'); - expect(options.arrowhead).toBe('none'); - expect(options.curve).toBe('basis'); // mocked as string - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - it('should handle edges with text and styles defined', function () { - const diag = new Diagram( - 'graph TD;A---|the text|B; linkStyle 0 stroke:val1,stroke-width:val2;' - ); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - - const mockG = { - setEdge: function (start, end, options) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B-'); - expect(options.arrowhead).toBe('none'); - expect(options.label.match('the text')).toBeTruthy(); - expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;'); - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - - it('should set fill to "none" by default when handling edges', function () { - const diag = new Diagram('graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2;'); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - - const mockG = { - setEdge: function (start, end, options) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B'); - expect(options.arrowhead).toBe('none'); - expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:none;'); - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - - it('should not set fill to none if fill is set in linkStyle', function () { - const diag = new Diagram( - 'graph TD;A---B; linkStyle 0 stroke:val1,stroke-width:val2,fill:blue;' - ); - diag.db.getVertices(); - const edges = diag.db.getEdges(); - const mockG = { - setEdge: function (start, end, options) { - expect(start).toContain('flowchart-A-'); - expect(end).toContain('flowchart-B-'); - expect(options.arrowhead).toBe('none'); - expect(options.style).toBe('stroke:val1;stroke-width:val2;fill:blue;'); - }, - }; - - flowRenderer.addEdges(edges, mockG, diag); - }); - }); - describe('checking validity of input ', function () { beforeEach(function () { flowParser.parser.yy = flowDb; diff --git a/test.js b/test.js deleted file mode 100644 index fa728c6ed..000000000 --- a/test.js +++ /dev/null @@ -1,8 +0,0 @@ -/** - * - */ -function apa() { - // comment's - const a = 1; - return 'apa' + a; -}