Merge branch 'develop' into knsv/mindmap-refactoring

This commit is contained in:
darshanr0107
2025-07-30 15:07:32 +05:30
committed by GitHub
13 changed files with 1390 additions and 72 deletions

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Update casing of ID in requirement diagram

View File

@@ -0,0 +1,5 @@
---
'mermaid': patch
---
fix: Update flowchart direction TD's behavior to be the same as TB

View File

@@ -0,0 +1,189 @@
---
references:
- "File: /packages/mermaid/src/diagrams/flowchart/flowDiagram.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/flowDb.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/flowDetector.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/flowDetector-v2.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/flowRenderer-v3-unified.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/styles.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/types.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/flowChartShapes.js"
- "File: /packages/mermaid/src/diagrams/flowchart/parser/flowParser.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/elk/detector.ts"
generationTime: 2025-07-23T10:31:53.266Z
---
flowchart TD
%% Entry Points and Detection
Input["User Input Text"] --> Detection{Detection Phase}
Detection --> flowDetector["flowDetector.ts<br/>detector(txt, config)"]
Detection --> flowDetectorV2["flowDetector-v2.ts<br/>detector(txt, config)"]
Detection --> elkDetector["elk/detector.ts<br/>detector(txt, config)"]
flowDetector --> |"Checks /^\s*graph/"| DetectLegacy{Legacy Flowchart?}
flowDetectorV2 --> |"Checks /^\s*flowchart/"| DetectNew{New Flowchart?}
elkDetector --> |"Checks /^\s*flowchart-elk/"| DetectElk{ELK Layout?}
DetectLegacy --> |Yes| LoadDiagram
DetectNew --> |Yes| LoadDiagram
DetectElk --> |Yes| LoadDiagram
%% Loading Phase
LoadDiagram["loader() function"] --> flowDiagram["flowDiagram.ts<br/>diagram object"]
flowDiagram --> DiagramStructure{Diagram Components}
DiagramStructure --> Parser["parser: flowParser"]
DiagramStructure --> Database["db: new FlowDB()"]
DiagramStructure --> Renderer["renderer: flowRenderer-v3-unified"]
DiagramStructure --> Styles["styles: flowStyles"]
DiagramStructure --> Init["init: (cnf: MermaidConfig)"]
%% Parser Phase
Parser --> flowParser["parser/flowParser.ts<br/>newParser.parse(src)"]
flowParser --> |"Preprocesses src"| RemoveWhitespace["Remove trailing whitespace<br/>src.replace(/}\s*\n/g, '}\n')"]
RemoveWhitespace --> flowJison["parser/flow.jison<br/>flowJisonParser.parse(newSrc)"]
flowJison --> ParseGraph["Parse Graph Structure"]
ParseGraph --> ParseVertices["Parse Vertices"]
ParseGraph --> ParseEdges["Parse Edges"]
ParseGraph --> ParseSubgraphs["Parse Subgraphs"]
ParseGraph --> ParseClasses["Parse Classes"]
ParseGraph --> ParseStyles["Parse Styles"]
%% Database Phase - FlowDB Class
Database --> FlowDBClass["flowDb.ts<br/>FlowDB class"]
FlowDBClass --> DBInit["constructor()<br/>- Initialize counters<br/>- Bind methods<br/>- Setup toolTips<br/>- Call clear()"]
DBInit --> DBMethods{FlowDB Methods}
DBMethods --> addVertex["addVertex(id, textObj, type, style,<br/>classes, dir, props, metadata)"]
DBMethods --> addLink["addLink(_start[], _end[], linkData)"]
DBMethods --> addSingleLink["addSingleLink(_start, _end, type, id)"]
DBMethods --> setDirection["setDirection(dir)"]
DBMethods --> addSubGraph["addSubGraph(nodes[], id, title)"]
DBMethods --> addClass["addClass(id, style)"]
DBMethods --> setClass["setClass(ids, className)"]
DBMethods --> setTooltip["setTooltip(ids, tooltip)"]
DBMethods --> setClickEvent["setClickEvent(id, functionName, args)"]
DBMethods --> setClickFun["setClickFun(id, functionName, args)"]
%% Vertex Processing
addVertex --> VertexProcess{Vertex Processing}
VertexProcess --> CreateVertex["Create FlowVertex object<br/>- id, labelType, domId<br/>- styles[], classes[]"]
VertexProcess --> SanitizeText["sanitizeText(textObj.text)"]
VertexProcess --> ParseMetadata["Parse YAML metadata<br/>yaml.load(yamlData)"]
VertexProcess --> SetVertexProps["Set vertex properties<br/>- shape, label, icon, form<br/>- pos, img, constraint, w, h"]
%% Edge Processing
addSingleLink --> EdgeProcess{Edge Processing}
EdgeProcess --> CreateEdge["Create FlowEdge object<br/>- start, end, type, text<br/>- labelType, classes[]"]
EdgeProcess --> ProcessLinkText["Process link text<br/>- sanitizeText()<br/>- strip quotes"]
EdgeProcess --> SetEdgeProps["Set edge properties<br/>- type, stroke, length"]
EdgeProcess --> GenerateEdgeId["Generate edge ID<br/>getEdgeId(start, end, counter)"]
EdgeProcess --> ValidateEdgeLimit["Validate edge limit<br/>maxEdges check"]
%% Data Collection
DBMethods --> GetData["getData()"]
GetData --> CollectNodes["Collect nodes[] from vertices"]
GetData --> CollectEdges["Collect edges[] from edges"]
GetData --> ProcessSubGraphs["Process subgraphs<br/>- parentDB Map<br/>- subGraphDB Map"]
GetData --> AddNodeFromVertex["addNodeFromVertex()<br/>for each vertex"]
GetData --> ProcessEdgeTypes["destructEdgeType()<br/>arrowTypeStart, arrowTypeEnd"]
%% Node Creation
AddNodeFromVertex --> NodeCreation{Node Creation}
NodeCreation --> FindExistingNode["findNode(nodes, vertex.id)"]
NodeCreation --> CreateBaseNode["Create base node<br/>- id, label, parentId<br/>- cssStyles, cssClasses<br/>- shape, domId, tooltip"]
NodeCreation --> GetCompiledStyles["getCompiledStyles(classDefs)"]
NodeCreation --> GetTypeFromVertex["getTypeFromVertex(vertex)"]
%% Rendering Phase
Renderer --> flowRendererV3["flowRenderer-v3-unified.ts<br/>draw(text, id, version, diag)"]
flowRendererV3 --> RenderInit["Initialize rendering<br/>- getConfig()<br/>- handle securityLevel<br/>- getDiagramElement()"]
RenderInit --> GetLayoutData["diag.db.getData()<br/>as LayoutData"]
GetLayoutData --> SetupLayoutData["Setup layout data<br/>- type, layoutAlgorithm<br/>- direction, spacing<br/>- markers, diagramId"]
SetupLayoutData --> CallRender["render(data4Layout, svg)"]
CallRender --> SetupViewPort["setupViewPortForSVG(svg, padding)"]
SetupViewPort --> ProcessLinks["Process vertex links<br/>- create anchor elements<br/>- handle click events"]
%% Shape Rendering
CallRender --> ShapeSystem["flowChartShapes.js<br/>Shape Functions"]
ShapeSystem --> ShapeFunctions{Shape Functions}
ShapeFunctions --> question["question(parent, bbox, node)"]
ShapeFunctions --> hexagon["hexagon(parent, bbox, node)"]
ShapeFunctions --> rect_left_inv_arrow["rect_left_inv_arrow(parent, bbox, node)"]
ShapeFunctions --> lean_right["lean_right(parent, bbox, node)"]
ShapeFunctions --> lean_left["lean_left(parent, bbox, node)"]
ShapeFunctions --> insertPolygonShape["insertPolygonShape(parent, w, h, points)"]
ShapeFunctions --> intersectPolygon["intersectPolygon(node, points, point)"]
ShapeFunctions --> intersectRect["intersectRect(node, point)"]
%% Styling System
Styles --> stylesTS["styles.ts<br/>getStyles(options)"]
stylesTS --> StyleOptions["FlowChartStyleOptions<br/>- arrowheadColor, border2<br/>- clusterBkg, mainBkg<br/>- fontFamily, textColor"]
StyleOptions --> GenerateCSS["Generate CSS styles<br/>- .label, .cluster-label<br/>- .node, .edgePath<br/>- .flowchart-link, .edgeLabel"]
GenerateCSS --> GetIconStyles["getIconStyles()"]
%% Type System
Parser --> TypeSystem["types.ts<br/>Type Definitions"]
TypeSystem --> FlowVertex["FlowVertex interface"]
TypeSystem --> FlowEdge["FlowEdge interface"]
TypeSystem --> FlowClass["FlowClass interface"]
TypeSystem --> FlowSubGraph["FlowSubGraph interface"]
TypeSystem --> FlowVertexTypeParam["FlowVertexTypeParam<br/>Shape types"]
%% Utility Functions
DBMethods --> UtilityFunctions{Utility Functions}
UtilityFunctions --> lookUpDomId["lookUpDomId(id)"]
UtilityFunctions --> getClasses["getClasses()"]
UtilityFunctions --> getDirection["getDirection()"]
UtilityFunctions --> getVertices["getVertices()"]
UtilityFunctions --> getEdges["getEdges()"]
UtilityFunctions --> getSubGraphs["getSubGraphs()"]
UtilityFunctions --> clear["clear()"]
UtilityFunctions --> defaultConfig["defaultConfig()"]
%% Event Handling
ProcessLinks --> EventHandling{Event Handling}
EventHandling --> setupToolTips["setupToolTips(element)"]
EventHandling --> bindFunctions["bindFunctions(element)"]
EventHandling --> runFunc["utils.runFunc(functionName, args)"]
%% Common Database Functions
DBMethods --> CommonDB["commonDb.js functions"]
CommonDB --> setAccTitle["setAccTitle()"]
CommonDB --> getAccTitle["getAccTitle()"]
CommonDB --> setAccDescription["setAccDescription()"]
CommonDB --> getAccDescription["getAccDescription()"]
CommonDB --> setDiagramTitle["setDiagramTitle()"]
CommonDB --> getDiagramTitle["getDiagramTitle()"]
CommonDB --> commonClear["clear()"]
%% Final Output
ProcessLinks --> FinalSVG["Final SVG Output"]
%% Layout Algorithm Selection
SetupLayoutData --> LayoutAlgorithm{Layout Algorithm}
LayoutAlgorithm --> Dagre["dagre<br/>(default)"]
LayoutAlgorithm --> DagreWrapper["dagre-wrapper<br/>(v2 renderer)"]
LayoutAlgorithm --> ELK["elk<br/>(external package)"]
%% Testing Components
FlowDBClass --> TestFiles["Test Files"]
TestFiles --> flowDbSpec["flowDb.spec.ts"]
TestFiles --> flowChartShapesSpec["flowChartShapes.spec.js"]
TestFiles --> ParserTests["parser/*.spec.js files<br/>- flow-text.spec.js<br/>- flow-edges.spec.js<br/>- flow-style.spec.js<br/>- subgraph.spec.js"]
%% Configuration
Init --> ConfigSetup["Configuration Setup"]
ConfigSetup --> FlowchartConfig["cnf.flowchart config"]
ConfigSetup --> ArrowMarkers["arrowMarkerAbsolute"]
ConfigSetup --> LayoutConfig["layout config"]
ConfigSetup --> SetConfig["setConfig() calls"]

View File

@@ -0,0 +1,307 @@
---
references:
- "File: /packages/mermaid/src/mermaidAPI.ts"
- "File: /packages/mermaid/src/mermaid.ts"
generationTime: 2025-01-28T16:30:00.000Z
---
sequenceDiagram
participant User as User/Browser
participant Mermaid as mermaid.ts
participant Queue as executionQueue
participant API as mermaidAPI.ts
participant Config as configApi
participant Preprocessor as preprocessDiagram
participant DiagramAPI as diagram-api
participant Diagram as Diagram.fromText
participant Renderer as diagram.renderer
participant Styles as Styling System
participant DOM as DOM/SVG
Note over User, DOM: Mermaid Complete API Flow
%% Initialization Phase
User->>+Mermaid: mermaid.initialize(config)
Mermaid->>+API: mermaidAPI.initialize(config)
API->>API: assignWithDepth({}, userOptions)
API->>API: handle legacy fontFamily config
API->>Config: saveConfigFromInitialize(options)
alt Theme Configuration Available
API->>API: check if theme in theme object
API->>API: set themeVariables from theme
else Default Theme
API->>API: use default theme variables
end
API->>Config: setSiteConfig(options) or getSiteConfig()
API->>API: setLogLevel(config.logLevel)
API->>DiagramAPI: addDiagrams()
API-->>-Mermaid: initialization complete
Mermaid-->>-User: ready to render
%% Content Loaded Event
User->>DOM: document.load event
DOM->>+Mermaid: contentLoaded()
opt startOnLoad is true
Mermaid->>Config: getConfig()
Config-->>Mermaid: { startOnLoad: true }
Mermaid->>Mermaid: run()
end
Mermaid-->>-DOM: event handling complete
%% Main Run Function
User->>+Mermaid: mermaid.run(options)
Mermaid->>Mermaid: runThrowsErrors(options)
Mermaid->>Config: getConfig()
Config-->>Mermaid: configuration object
alt nodes provided
Mermaid->>Mermaid: use provided nodes
else querySelector provided
Mermaid->>DOM: document.querySelectorAll(querySelector)
DOM-->>Mermaid: nodesToProcess
end
Mermaid->>Mermaid: new InitIDGenerator(deterministicIds, seed)
loop For each diagram element
Mermaid->>DOM: check element.getAttribute('data-processed')
opt not processed
Mermaid->>DOM: element.setAttribute('data-processed', 'true')
Mermaid->>Mermaid: generate unique id
Mermaid->>DOM: get element.innerHTML
Mermaid->>Mermaid: entityDecode and clean text
Mermaid->>Mermaid: detectInit(txt)
Mermaid->>Queue: render(id, txt, element)
end
end
Mermaid-->>-User: processing initiated
%% Render Function (Queued)
activate Queue
Queue->>+API: mermaidAPI.render(id, text, container)
API->>DiagramAPI: addDiagrams()
API->>+Preprocessor: processAndSetConfigs(text)
Preprocessor->>Preprocessor: preprocessDiagram(text)
Preprocessor->>Config: reset()
Preprocessor->>Config: addDirective(processed.config)
Preprocessor-->>-API: { code, config }
API->>Config: getConfig()
Config-->>API: current configuration
opt text length > maxTextSize
API->>API: text = MAX_TEXTLENGTH_EXCEEDED_MSG
end
API->>API: setup id selectors and element IDs
API->>API: determine security level (sandbox/loose)
%% DOM Setup
alt svgContainingElement provided
alt isSandboxed
API->>DOM: sandboxedIframe(select(svgContainingElement), iFrameID)
API->>DOM: select iframe contentDocument body
else
API->>DOM: select(svgContainingElement)
end
else no container
API->>API: removeExistingElements(document, id, divId, iFrameId)
alt isSandboxed
API->>DOM: sandboxedIframe(select('body'), iFrameID)
else
API->>DOM: select('body')
end
end
API->>DOM: appendDivSvgG(root, id, enclosingDivID, fontFamily, XMLNS_XLINK_STD)
%% Diagram Creation
API->>+Diagram: Diagram.fromText(text, { title: processed.title })
Diagram->>DiagramAPI: detect diagram type
Diagram->>DiagramAPI: load appropriate diagram
Diagram-->>-API: diagram instance
opt parsing error occurred
API->>+Diagram: Diagram.fromText('error')
Diagram-->>-API: error diagram
API->>API: store parseEncounteredException
end
%% Style Generation
API->>DOM: get svg element and firstChild
API->>Renderer: diag.renderer.getClasses(text, diag)
Renderer-->>API: diagramClassDefs
API->>+Styles: createUserStyles(config, diagramType, diagramClassDefs, idSelector)
Styles->>Styles: createCssStyles(config, classDefs)
opt config.themeCSS defined
Styles->>Styles: append themeCSS
end
opt fontFamily configured
Styles->>Styles: add CSS variables for fonts
end
opt classDefs exist
loop For each styleClassDef
opt has styles
Styles->>Styles: cssImportantStyles for each CSS element
end
opt has textStyles
Styles->>Styles: cssImportantStyles for tspan elements
end
end
end
Styles->>Styles: getStyles(graphType, userCSSstyles, themeVariables)
Styles->>Styles: serialize(compile(svgId{allStyles}), stringify)
Styles-->>-API: compiled CSS rules
API->>DOM: create style element
API->>DOM: style.innerHTML = rules
API->>DOM: svg.insertBefore(style, firstChild)
%% Diagram Rendering
API->>+Renderer: diag.renderer.draw(text, id, version, diag)
Renderer->>Renderer: diagram-specific rendering logic
Renderer->>DOM: create SVG elements
Renderer->>DOM: apply positioning and styling
Renderer-->>-API: rendered diagram
opt rendering error
alt suppressErrorRendering
API->>API: removeTempElements()
API->>Mermaid: throw error
else
API->>Renderer: errorRenderer.draw(text, id, version)
end
end
%% Accessibility and Cleanup
API->>DOM: select svg element
API->>Diagram: diag.db.getAccTitle()
API->>Diagram: diag.db.getAccDescription()
API->>API: addA11yInfo(diagramType, svgNode, a11yTitle, a11yDescr)
API->>DOM: set xmlns for foreignobject elements
API->>DOM: get innerHTML from enclosing div
API->>+API: cleanUpSvgCode(svgCode, isSandboxed, arrowMarkerAbsolute)
opt not useArrowMarkerUrls and not sandboxed
API->>API: replace marker-end URLs with anchors
end
API->>API: decodeEntities(svgCode)
API->>API: replace <br> with <br/>
API-->>-API: cleaned SVG code
alt isSandboxed
API->>+API: putIntoIFrame(svgCode, svgEl)
API->>API: calculate iframe height
API->>API: toBase64 encode SVG content
API->>API: create iframe with sandbox attributes
API-->>-API: iframe HTML
else not loose security
API->>API: DOMPurify.sanitize(svgCode, options)
end
API->>API: attachFunctions()
API->>API: removeTempElements()
opt parseEncounteredException
API->>Mermaid: throw parseEncounteredException
end
API-->>-Queue: { diagramType, svg: svgCode, bindFunctions }
%% Return to Web Integration
activate Mermaid
Queue-->>Mermaid: render result
Mermaid->>DOM: element.innerHTML = svg
opt postRenderCallback
Mermaid->>User: postRenderCallback(id)
end
opt bindFunctions exist
Mermaid->>DOM: bindFunctions(element)
end
deactivate Mermaid
%% Parse Function Flow
User->>+Mermaid: mermaid.parse(text, parseOptions)
activate Queue
Queue->>+API: mermaidAPI.parse(text, parseOptions)
API->>DiagramAPI: addDiagrams()
API->>Preprocessor: processAndSetConfigs(text)
Preprocessor-->>API: { code, config }
API->>Diagram: getDiagramFromText(code)
Diagram-->>API: diagram instance
API-->>-Queue: { diagramType: diagram.type, config }
Queue-->>-Mermaid: parse result
Mermaid-->>-User: ParseResult or false
%% External Diagram Registration
User->>+Mermaid: registerExternalDiagrams(diagrams, options)
Mermaid->>DiagramAPI: addDiagrams()
Mermaid->>DiagramAPI: registerLazyLoadedDiagrams(...diagrams)
opt lazyLoad is false
Mermaid->>DiagramAPI: loadRegisteredDiagrams()
end
Mermaid-->>-User: registration complete
%% Error Handling
Note over Mermaid, API: Error Handling Throughout
alt Error occurs
API->>Mermaid: throw error
Mermaid->>+Mermaid: handleError(error, errors, parseError)
Mermaid->>Mermaid: log.warn(error)
alt isDetailedError
Mermaid->>User: parseError(error.str, error.hash)
else
Mermaid->>User: parseError(error)
end
opt not suppressErrors
Mermaid->>User: throw error
end
Mermaid-->>-User: error handled
end
%% Configuration Details
Note over Config: Configuration Functions
Note right of Config: Functions:<br/>- reset()<br/>- getConfig()<br/>- setConfig()<br/>- getSiteConfig()<br/>- updateSiteConfig()<br/>- saveConfigFromInitialize()
Note over Styles: CSS Generation
Note right of Styles: Features:<br/>- createCssStyles()<br/>- createUserStyles()<br/>- cssImportantStyles()<br/>- Theme integration<br/>- Class definitions
Note over API: Security Levels
Note right of API: Modes:<br/>- sandbox: iframe isolation<br/>- loose: minimal sanitization<br/>- default: DOMPurify sanitization
Note over API: Helper Functions
Note right of API: Utilities:<br/>- cleanUpSvgCode()<br/>- putIntoIFrame()<br/>- appendDivSvgG()<br/>- removeExistingElements()

View File

@@ -0,0 +1,180 @@
---
references:
- "File: /packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts"
- "File: /packages/mermaid/src/diagrams/mindmap/mindmapDb.ts"
- "File: /packages/mermaid/src/diagrams/mindmap/detector.ts"
- "File: /packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts"
- "File: /packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts"
- "File: /packages/mermaid/src/diagrams/mindmap/styles.ts"
- "File: /packages/mermaid/src/diagrams/mindmap/svgDraw.ts"
generationTime: 2025-01-28T16:00:00.000Z
---
sequenceDiagram
participant User as User Input Text
participant Detector as detector.ts
participant Loader as DiagramLoader
participant Definition as mindmap-definition.ts
participant Parser as parser/mindmap.jison
participant DB as MindmapDB
participant Renderer as mindmapRenderer.ts
participant Cytoscape as cytoscape.js
participant SVGDraw as svgDraw.ts
participant Styles as styles.ts
participant Output as Final SVG
Note over User, Output: Mindmap Implementation Flow
%% Detection Phase
User->>Detector: /^\s*mindmap/ text input
activate Detector
Detector->>Detector: detector(txt) validates pattern
Detector->>Loader: loader() function called
deactivate Detector
activate Loader
Loader->>Definition: import mindmap-definition.js
deactivate Loader
%% Core Structure Setup
activate Definition
Definition->>DB: get db() → new MindmapDB()
Definition->>Renderer: setup renderer
Definition->>Parser: setup parser
Definition->>Styles: setup styles
deactivate Definition
%% Database Initialization
activate DB
Note over DB: MindmapDB Constructor
DB->>DB: initialize nodes array
DB->>DB: setup nodeType constants
DB->>DB: bind methods
DB->>DB: clear() state
%% Parsing Phase
activate Parser
User->>Parser: mindmap syntax text
loop For each node in hierarchy
Parser->>DB: addNode(level, id, descr, type)
activate DB
DB->>DB: sanitizeText(id, descr)
DB->>DB: getType(startStr, endStr)
Note right of DB: Shape Detection:<br/>[ → RECT<br/>( → ROUNDED_RECT<br/>(( → CIRCLE<br/>)) → BANG<br/>{{ → HEXAGON
DB->>DB: getParent(level)
DB->>DB: create MindmapNode
DB->>DB: add to hierarchy
deactivate DB
end
opt Icon/Class Decoration
Parser->>DB: decorateNode(decoration)
DB->>DB: set icon/class properties
end
deactivate Parser
%% Data Preparation
Renderer->>DB: getData() for layout
activate DB
DB->>DB: collect all nodes
DB->>DB: build parent-child relationships
DB-->>Renderer: return node hierarchy
deactivate DB
%% Rendering Pipeline
activate Renderer
Note over Renderer: Rendering Phase
Renderer->>Cytoscape: initialize cytoscape
activate Cytoscape
loop For each node in mindmap
Renderer->>Cytoscape: addNodes(mindmap, cy, conf, level)
Cytoscape->>Cytoscape: create node data
Cytoscape->>Cytoscape: set position (x, y)
end
loop For parent-child relationships
Renderer->>Cytoscape: add edges
Cytoscape->>Cytoscape: create edge data
end
Renderer->>Cytoscape: configure cose-bilkent layout
Cytoscape->>Cytoscape: calculate optimal positions
Cytoscape-->>Renderer: return positioned graph
deactivate Cytoscape
%% SVG Generation
Renderer->>SVGDraw: drawNodes(db, svg, mindmap, section, conf)
activate SVGDraw
loop For each node recursively
SVGDraw->>SVGDraw: select shape function
alt Default Shape
SVGDraw->>SVGDraw: defaultBkg() - rounded rectangle
else Rectangle Shape
SVGDraw->>SVGDraw: rectBkg() - sharp corners
else Circle Shape
SVGDraw->>SVGDraw: circleBkg() - perfect circle
else Cloud Shape
SVGDraw->>SVGDraw: cloudBkg() - organic curves
else Bang Shape
SVGDraw->>SVGDraw: bangBkg() - explosion style
else Hexagon Shape
SVGDraw->>SVGDraw: hexagonBkg() - six sides
end
SVGDraw->>SVGDraw: create SVG elements
SVGDraw->>SVGDraw: add text labels
SVGDraw->>SVGDraw: position node
opt Node has children
SVGDraw->>SVGDraw: drawNodes() recursive call
end
end
deactivate SVGDraw
%% Edge Rendering
Renderer->>Renderer: drawEdges(edgesEl, cy)
loop For each edge
Renderer->>Renderer: extract edge bounds
Renderer->>Renderer: draw SVG path
end
%% Styling Application
Renderer->>Styles: getStyles(options)
activate Styles
Styles->>Styles: genSections(options)
loop For THEME_COLOR_LIMIT sections
Styles->>Styles: generate color scale
Styles->>Styles: create CSS rules
Note right of Styles: .section-X fills<br/>.edge-depth-X widths<br/>.node-icon-X colors
end
Styles->>Styles: apply theme integration
Styles-->>Renderer: return compiled CSS
deactivate Styles
%% Final Assembly
Renderer->>Output: selectSvgElement()
Renderer->>Output: setupGraphViewbox()
Renderer->>Output: apply styles
Renderer->>Output: add interactive elements
deactivate Renderer
activate Output
Note over Output: Final Mindmap Features
Output->>Output: responsive layout
Output->>Output: accessibility attributes
Output->>Output: hover effects
Output->>Output: click handling
Output-->>User: rendered mindmap
deactivate Output
%% Configuration Details
Note over DB, Styles: Configuration Options
Note right of DB: Padding Calculations:<br/>Base padding from config<br/>RECT: ×2 padding<br/>ROUNDED_RECT: ×2 padding<br/>HEXAGON: ×2 padding
Note right of Styles: Section Management:<br/>MAX_SECTIONS = 12<br/>Dynamic color generation<br/>Git theme integration
Note right of Renderer: Layout Parameters:<br/>Cytoscape configuration<br/>coseBilkent settings<br/>Node spacing rules

View File

@@ -97,8 +97,8 @@
"eslint-config-prettier": "^10.1.8",
"eslint-plugin-cypress": "^4.3.0",
"eslint-plugin-html": "^8.1.3",
"eslint-plugin-jest": "^28.11.2",
"eslint-plugin-jsdoc": "^50.6.17",
"eslint-plugin-jest": "^28.14.0",
"eslint-plugin-jsdoc": "^50.8.0",
"eslint-plugin-json": "^4.0.1",
"eslint-plugin-lodash": "^8.0.0",
"eslint-plugin-markdown": "^5.1.0",
@@ -126,7 +126,7 @@
"tslib": "^2.8.1",
"tsx": "^4.7.3",
"typescript": "~5.7.3",
"typescript-eslint": "^8.32.1",
"typescript-eslint": "^8.38.0",
"vite": "^7.0.3",
"vite-plugin-istanbul": "^7.0.0",
"vitest": "^3.0.6"

View File

@@ -165,3 +165,20 @@ describe('flow db getData', () => {
expect(edges[3].curve).toBe('stepBefore');
});
});
describe('flow db direction', () => {
let flowDb: FlowDB;
beforeEach(() => {
flowDb = new FlowDB();
});
it('should set direction to TB when TD is set', () => {
flowDb.setDirection('TD');
expect(flowDb.getDirection()).toBe('TB');
});
it('should correctly set direction irrespective of leading spaces', () => {
flowDb.setDirection(' TD');
expect(flowDb.getDirection()).toBe('TB');
});
});

View File

@@ -406,7 +406,8 @@ You have to call mermaid.initialize.`
*
*/
public setDirection(dir: string) {
this.direction = dir;
this.direction = dir.trim();
if (/.*</.exec(this.direction)) {
this.direction = 'RL';
}

View File

@@ -0,0 +1,189 @@
---
references:
- "File: /packages/mermaid/src/diagrams/flowchart/flowDiagram.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/flowDb.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/flowDetector.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/flowDetector-v2.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/flowRenderer-v3-unified.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/styles.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/types.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/flowChartShapes.js"
- "File: /packages/mermaid/src/diagrams/flowchart/parser/flowParser.ts"
- "File: /packages/mermaid/src/diagrams/flowchart/elk/detector.ts"
generationTime: 2025-07-23T10:31:53.266Z
---
flowchart TD
%% Entry Points and Detection
Input["User Input Text"] --> Detection{Detection Phase}
Detection --> flowDetector["flowDetector.ts<br/>detector(txt, config)"]
Detection --> flowDetectorV2["flowDetector-v2.ts<br/>detector(txt, config)"]
Detection --> elkDetector["elk/detector.ts<br/>detector(txt, config)"]
flowDetector --> |"Checks /^\s*graph/"| DetectLegacy{Legacy Flowchart?}
flowDetectorV2 --> |"Checks /^\s*flowchart/"| DetectNew{New Flowchart?}
elkDetector --> |"Checks /^\s*flowchart-elk/"| DetectElk{ELK Layout?}
DetectLegacy --> |Yes| LoadDiagram
DetectNew --> |Yes| LoadDiagram
DetectElk --> |Yes| LoadDiagram
%% Loading Phase
LoadDiagram["loader() function"] --> flowDiagram["flowDiagram.ts<br/>diagram object"]
flowDiagram --> DiagramStructure{Diagram Components}
DiagramStructure --> Parser["parser: flowParser"]
DiagramStructure --> Database["db: new FlowDB()"]
DiagramStructure --> Renderer["renderer: flowRenderer-v3-unified"]
DiagramStructure --> Styles["styles: flowStyles"]
DiagramStructure --> Init["init: (cnf: MermaidConfig)"]
%% Parser Phase
Parser --> flowParser["parser/flowParser.ts<br/>newParser.parse(src)"]
flowParser --> |"Preprocesses src"| RemoveWhitespace["Remove trailing whitespace<br/>src.replace(/}\s*\n/g, '}\n')"]
RemoveWhitespace --> flowJison["parser/flow.jison<br/>flowJisonParser.parse(newSrc)"]
flowJison --> ParseGraph["Parse Graph Structure"]
ParseGraph --> ParseVertices["Parse Vertices"]
ParseGraph --> ParseEdges["Parse Edges"]
ParseGraph --> ParseSubgraphs["Parse Subgraphs"]
ParseGraph --> ParseClasses["Parse Classes"]
ParseGraph --> ParseStyles["Parse Styles"]
%% Database Phase - FlowDB Class
Database --> FlowDBClass["flowDb.ts<br/>FlowDB class"]
FlowDBClass --> DBInit["constructor()<br/>- Initialize counters<br/>- Bind methods<br/>- Setup toolTips<br/>- Call clear()"]
DBInit --> DBMethods{FlowDB Methods}
DBMethods --> addVertex["addVertex(id, textObj, type, style,<br/>classes, dir, props, metadata)"]
DBMethods --> addLink["addLink(_start[], _end[], linkData)"]
DBMethods --> addSingleLink["addSingleLink(_start, _end, type, id)"]
DBMethods --> setDirection["setDirection(dir)"]
DBMethods --> addSubGraph["addSubGraph(nodes[], id, title)"]
DBMethods --> addClass["addClass(id, style)"]
DBMethods --> setClass["setClass(ids, className)"]
DBMethods --> setTooltip["setTooltip(ids, tooltip)"]
DBMethods --> setClickEvent["setClickEvent(id, functionName, args)"]
DBMethods --> setClickFun["setClickFun(id, functionName, args)"]
%% Vertex Processing
addVertex --> VertexProcess{Vertex Processing}
VertexProcess --> CreateVertex["Create FlowVertex object<br/>- id, labelType, domId<br/>- styles[], classes[]"]
VertexProcess --> SanitizeText["sanitizeText(textObj.text)"]
VertexProcess --> ParseMetadata["Parse YAML metadata<br/>yaml.load(yamlData)"]
VertexProcess --> SetVertexProps["Set vertex properties<br/>- shape, label, icon, form<br/>- pos, img, constraint, w, h"]
%% Edge Processing
addSingleLink --> EdgeProcess{Edge Processing}
EdgeProcess --> CreateEdge["Create FlowEdge object<br/>- start, end, type, text<br/>- labelType, classes[]"]
EdgeProcess --> ProcessLinkText["Process link text<br/>- sanitizeText()<br/>- strip quotes"]
EdgeProcess --> SetEdgeProps["Set edge properties<br/>- type, stroke, length"]
EdgeProcess --> GenerateEdgeId["Generate edge ID<br/>getEdgeId(start, end, counter)"]
EdgeProcess --> ValidateEdgeLimit["Validate edge limit<br/>maxEdges check"]
%% Data Collection
DBMethods --> GetData["getData()"]
GetData --> CollectNodes["Collect nodes[] from vertices"]
GetData --> CollectEdges["Collect edges[] from edges"]
GetData --> ProcessSubGraphs["Process subgraphs<br/>- parentDB Map<br/>- subGraphDB Map"]
GetData --> AddNodeFromVertex["addNodeFromVertex()<br/>for each vertex"]
GetData --> ProcessEdgeTypes["destructEdgeType()<br/>arrowTypeStart, arrowTypeEnd"]
%% Node Creation
AddNodeFromVertex --> NodeCreation{Node Creation}
NodeCreation --> FindExistingNode["findNode(nodes, vertex.id)"]
NodeCreation --> CreateBaseNode["Create base node<br/>- id, label, parentId<br/>- cssStyles, cssClasses<br/>- shape, domId, tooltip"]
NodeCreation --> GetCompiledStyles["getCompiledStyles(classDefs)"]
NodeCreation --> GetTypeFromVertex["getTypeFromVertex(vertex)"]
%% Rendering Phase
Renderer --> flowRendererV3["flowRenderer-v3-unified.ts<br/>draw(text, id, version, diag)"]
flowRendererV3 --> RenderInit["Initialize rendering<br/>- getConfig()<br/>- handle securityLevel<br/>- getDiagramElement()"]
RenderInit --> GetLayoutData["diag.db.getData()<br/>as LayoutData"]
GetLayoutData --> SetupLayoutData["Setup layout data<br/>- type, layoutAlgorithm<br/>- direction, spacing<br/>- markers, diagramId"]
SetupLayoutData --> CallRender["render(data4Layout, svg)"]
CallRender --> SetupViewPort["setupViewPortForSVG(svg, padding)"]
SetupViewPort --> ProcessLinks["Process vertex links<br/>- create anchor elements<br/>- handle click events"]
%% Shape Rendering
CallRender --> ShapeSystem["flowChartShapes.js<br/>Shape Functions"]
ShapeSystem --> ShapeFunctions{Shape Functions}
ShapeFunctions --> question["question(parent, bbox, node)"]
ShapeFunctions --> hexagon["hexagon(parent, bbox, node)"]
ShapeFunctions --> rect_left_inv_arrow["rect_left_inv_arrow(parent, bbox, node)"]
ShapeFunctions --> lean_right["lean_right(parent, bbox, node)"]
ShapeFunctions --> lean_left["lean_left(parent, bbox, node)"]
ShapeFunctions --> insertPolygonShape["insertPolygonShape(parent, w, h, points)"]
ShapeFunctions --> intersectPolygon["intersectPolygon(node, points, point)"]
ShapeFunctions --> intersectRect["intersectRect(node, point)"]
%% Styling System
Styles --> stylesTS["styles.ts<br/>getStyles(options)"]
stylesTS --> StyleOptions["FlowChartStyleOptions<br/>- arrowheadColor, border2<br/>- clusterBkg, mainBkg<br/>- fontFamily, textColor"]
StyleOptions --> GenerateCSS["Generate CSS styles<br/>- .label, .cluster-label<br/>- .node, .edgePath<br/>- .flowchart-link, .edgeLabel"]
GenerateCSS --> GetIconStyles["getIconStyles()"]
%% Type System
Parser --> TypeSystem["types.ts<br/>Type Definitions"]
TypeSystem --> FlowVertex["FlowVertex interface"]
TypeSystem --> FlowEdge["FlowEdge interface"]
TypeSystem --> FlowClass["FlowClass interface"]
TypeSystem --> FlowSubGraph["FlowSubGraph interface"]
TypeSystem --> FlowVertexTypeParam["FlowVertexTypeParam<br/>Shape types"]
%% Utility Functions
DBMethods --> UtilityFunctions{Utility Functions}
UtilityFunctions --> lookUpDomId["lookUpDomId(id)"]
UtilityFunctions --> getClasses["getClasses()"]
UtilityFunctions --> getDirection["getDirection()"]
UtilityFunctions --> getVertices["getVertices()"]
UtilityFunctions --> getEdges["getEdges()"]
UtilityFunctions --> getSubGraphs["getSubGraphs()"]
UtilityFunctions --> clear["clear()"]
UtilityFunctions --> defaultConfig["defaultConfig()"]
%% Event Handling
ProcessLinks --> EventHandling{Event Handling}
EventHandling --> setupToolTips["setupToolTips(element)"]
EventHandling --> bindFunctions["bindFunctions(element)"]
EventHandling --> runFunc["utils.runFunc(functionName, args)"]
%% Common Database Functions
DBMethods --> CommonDB["commonDb.js functions"]
CommonDB --> setAccTitle["setAccTitle()"]
CommonDB --> getAccTitle["getAccTitle()"]
CommonDB --> setAccDescription["setAccDescription()"]
CommonDB --> getAccDescription["getAccDescription()"]
CommonDB --> setDiagramTitle["setDiagramTitle()"]
CommonDB --> getDiagramTitle["getDiagramTitle()"]
CommonDB --> commonClear["clear()"]
%% Final Output
ProcessLinks --> FinalSVG["Final SVG Output"]
%% Layout Algorithm Selection
SetupLayoutData --> LayoutAlgorithm{Layout Algorithm}
LayoutAlgorithm --> Dagre["dagre<br/>(default)"]
LayoutAlgorithm --> DagreWrapper["dagre-wrapper<br/>(v2 renderer)"]
LayoutAlgorithm --> ELK["elk<br/>(external package)"]
%% Testing Components
FlowDBClass --> TestFiles["Test Files"]
TestFiles --> flowDbSpec["flowDb.spec.ts"]
TestFiles --> flowChartShapesSpec["flowChartShapes.spec.js"]
TestFiles --> ParserTests["parser/*.spec.js files<br/>- flow-text.spec.js<br/>- flow-edges.spec.js<br/>- flow-style.spec.js<br/>- subgraph.spec.js"]
%% Configuration
Init --> ConfigSetup["Configuration Setup"]
ConfigSetup --> FlowchartConfig["cnf.flowchart config"]
ConfigSetup --> ArrowMarkers["arrowMarkerAbsolute"]
ConfigSetup --> LayoutConfig["layout config"]
ConfigSetup --> SetConfig["setConfig() calls"]

View File

@@ -0,0 +1,307 @@
---
references:
- "File: /packages/mermaid/src/mermaidAPI.ts"
- "File: /packages/mermaid/src/mermaid.ts"
generationTime: 2025-01-28T16:30:00.000Z
---
sequenceDiagram
participant User as User/Browser
participant Mermaid as mermaid.ts
participant Queue as executionQueue
participant API as mermaidAPI.ts
participant Config as configApi
participant Preprocessor as preprocessDiagram
participant DiagramAPI as diagram-api
participant Diagram as Diagram.fromText
participant Renderer as diagram.renderer
participant Styles as Styling System
participant DOM as DOM/SVG
Note over User, DOM: Mermaid Complete API Flow
%% Initialization Phase
User->>+Mermaid: mermaid.initialize(config)
Mermaid->>+API: mermaidAPI.initialize(config)
API->>API: assignWithDepth({}, userOptions)
API->>API: handle legacy fontFamily config
API->>Config: saveConfigFromInitialize(options)
alt Theme Configuration Available
API->>API: check if theme in theme object
API->>API: set themeVariables from theme
else Default Theme
API->>API: use default theme variables
end
API->>Config: setSiteConfig(options) or getSiteConfig()
API->>API: setLogLevel(config.logLevel)
API->>DiagramAPI: addDiagrams()
API-->>-Mermaid: initialization complete
Mermaid-->>-User: ready to render
%% Content Loaded Event
User->>DOM: document.load event
DOM->>+Mermaid: contentLoaded()
opt startOnLoad is true
Mermaid->>Config: getConfig()
Config-->>Mermaid: { startOnLoad: true }
Mermaid->>Mermaid: run()
end
Mermaid-->>-DOM: event handling complete
%% Main Run Function
User->>+Mermaid: mermaid.run(options)
Mermaid->>Mermaid: runThrowsErrors(options)
Mermaid->>Config: getConfig()
Config-->>Mermaid: configuration object
alt nodes provided
Mermaid->>Mermaid: use provided nodes
else querySelector provided
Mermaid->>DOM: document.querySelectorAll(querySelector)
DOM-->>Mermaid: nodesToProcess
end
Mermaid->>Mermaid: new InitIDGenerator(deterministicIds, seed)
loop For each diagram element
Mermaid->>DOM: check element.getAttribute('data-processed')
opt not processed
Mermaid->>DOM: element.setAttribute('data-processed', 'true')
Mermaid->>Mermaid: generate unique id
Mermaid->>DOM: get element.innerHTML
Mermaid->>Mermaid: entityDecode and clean text
Mermaid->>Mermaid: detectInit(txt)
Mermaid->>Queue: render(id, txt, element)
end
end
Mermaid-->>-User: processing initiated
%% Render Function (Queued)
activate Queue
Queue->>+API: mermaidAPI.render(id, text, container)
API->>DiagramAPI: addDiagrams()
API->>+Preprocessor: processAndSetConfigs(text)
Preprocessor->>Preprocessor: preprocessDiagram(text)
Preprocessor->>Config: reset()
Preprocessor->>Config: addDirective(processed.config)
Preprocessor-->>-API: { code, config }
API->>Config: getConfig()
Config-->>API: current configuration
opt text length > maxTextSize
API->>API: text = MAX_TEXTLENGTH_EXCEEDED_MSG
end
API->>API: setup id selectors and element IDs
API->>API: determine security level (sandbox/loose)
%% DOM Setup
alt svgContainingElement provided
alt isSandboxed
API->>DOM: sandboxedIframe(select(svgContainingElement), iFrameID)
API->>DOM: select iframe contentDocument body
else
API->>DOM: select(svgContainingElement)
end
else no container
API->>API: removeExistingElements(document, id, divId, iFrameId)
alt isSandboxed
API->>DOM: sandboxedIframe(select('body'), iFrameID)
else
API->>DOM: select('body')
end
end
API->>DOM: appendDivSvgG(root, id, enclosingDivID, fontFamily, XMLNS_XLINK_STD)
%% Diagram Creation
API->>+Diagram: Diagram.fromText(text, { title: processed.title })
Diagram->>DiagramAPI: detect diagram type
Diagram->>DiagramAPI: load appropriate diagram
Diagram-->>-API: diagram instance
opt parsing error occurred
API->>+Diagram: Diagram.fromText('error')
Diagram-->>-API: error diagram
API->>API: store parseEncounteredException
end
%% Style Generation
API->>DOM: get svg element and firstChild
API->>Renderer: diag.renderer.getClasses(text, diag)
Renderer-->>API: diagramClassDefs
API->>+Styles: createUserStyles(config, diagramType, diagramClassDefs, idSelector)
Styles->>Styles: createCssStyles(config, classDefs)
opt config.themeCSS defined
Styles->>Styles: append themeCSS
end
opt fontFamily configured
Styles->>Styles: add CSS variables for fonts
end
opt classDefs exist
loop For each styleClassDef
opt has styles
Styles->>Styles: cssImportantStyles for each CSS element
end
opt has textStyles
Styles->>Styles: cssImportantStyles for tspan elements
end
end
end
Styles->>Styles: getStyles(graphType, userCSSstyles, themeVariables)
Styles->>Styles: serialize(compile(svgId{allStyles}), stringify)
Styles-->>-API: compiled CSS rules
API->>DOM: create style element
API->>DOM: style.innerHTML = rules
API->>DOM: svg.insertBefore(style, firstChild)
%% Diagram Rendering
API->>+Renderer: diag.renderer.draw(text, id, version, diag)
Renderer->>Renderer: diagram-specific rendering logic
Renderer->>DOM: create SVG elements
Renderer->>DOM: apply positioning and styling
Renderer-->>-API: rendered diagram
opt rendering error
alt suppressErrorRendering
API->>API: removeTempElements()
API->>Mermaid: throw error
else
API->>Renderer: errorRenderer.draw(text, id, version)
end
end
%% Accessibility and Cleanup
API->>DOM: select svg element
API->>Diagram: diag.db.getAccTitle()
API->>Diagram: diag.db.getAccDescription()
API->>API: addA11yInfo(diagramType, svgNode, a11yTitle, a11yDescr)
API->>DOM: set xmlns for foreignobject elements
API->>DOM: get innerHTML from enclosing div
API->>+API: cleanUpSvgCode(svgCode, isSandboxed, arrowMarkerAbsolute)
opt not useArrowMarkerUrls and not sandboxed
API->>API: replace marker-end URLs with anchors
end
API->>API: decodeEntities(svgCode)
API->>API: replace <br> with <br/>
API-->>-API: cleaned SVG code
alt isSandboxed
API->>+API: putIntoIFrame(svgCode, svgEl)
API->>API: calculate iframe height
API->>API: toBase64 encode SVG content
API->>API: create iframe with sandbox attributes
API-->>-API: iframe HTML
else not loose security
API->>API: DOMPurify.sanitize(svgCode, options)
end
API->>API: attachFunctions()
API->>API: removeTempElements()
opt parseEncounteredException
API->>Mermaid: throw parseEncounteredException
end
API-->>-Queue: { diagramType, svg: svgCode, bindFunctions }
%% Return to Web Integration
activate Mermaid
Queue-->>Mermaid: render result
Mermaid->>DOM: element.innerHTML = svg
opt postRenderCallback
Mermaid->>User: postRenderCallback(id)
end
opt bindFunctions exist
Mermaid->>DOM: bindFunctions(element)
end
deactivate Mermaid
%% Parse Function Flow
User->>+Mermaid: mermaid.parse(text, parseOptions)
activate Queue
Queue->>+API: mermaidAPI.parse(text, parseOptions)
API->>DiagramAPI: addDiagrams()
API->>Preprocessor: processAndSetConfigs(text)
Preprocessor-->>API: { code, config }
API->>Diagram: getDiagramFromText(code)
Diagram-->>API: diagram instance
API-->>-Queue: { diagramType: diagram.type, config }
Queue-->>-Mermaid: parse result
Mermaid-->>-User: ParseResult or false
%% External Diagram Registration
User->>+Mermaid: registerExternalDiagrams(diagrams, options)
Mermaid->>DiagramAPI: addDiagrams()
Mermaid->>DiagramAPI: registerLazyLoadedDiagrams(...diagrams)
opt lazyLoad is false
Mermaid->>DiagramAPI: loadRegisteredDiagrams()
end
Mermaid-->>-User: registration complete
%% Error Handling
Note over Mermaid, API: Error Handling Throughout
alt Error occurs
API->>Mermaid: throw error
Mermaid->>+Mermaid: handleError(error, errors, parseError)
Mermaid->>Mermaid: log.warn(error)
alt isDetailedError
Mermaid->>User: parseError(error.str, error.hash)
else
Mermaid->>User: parseError(error)
end
opt not suppressErrors
Mermaid->>User: throw error
end
Mermaid-->>-User: error handled
end
%% Configuration Details
Note over Config: Configuration Functions
Note right of Config: Functions:<br/>- reset()<br/>- getConfig()<br/>- setConfig()<br/>- getSiteConfig()<br/>- updateSiteConfig()<br/>- saveConfigFromInitialize()
Note over Styles: CSS Generation
Note right of Styles: Features:<br/>- createCssStyles()<br/>- createUserStyles()<br/>- cssImportantStyles()<br/>- Theme integration<br/>- Class definitions
Note over API: Security Levels
Note right of API: Modes:<br/>- sandbox: iframe isolation<br/>- loose: minimal sanitization<br/>- default: DOMPurify sanitization
Note over API: Helper Functions
Note right of API: Utilities:<br/>- cleanUpSvgCode()<br/>- putIntoIFrame()<br/>- appendDivSvgG()<br/>- removeExistingElements()

View File

@@ -0,0 +1,180 @@
---
references:
- "File: /packages/mermaid/src/diagrams/mindmap/mindmap-definition.ts"
- "File: /packages/mermaid/src/diagrams/mindmap/mindmapDb.ts"
- "File: /packages/mermaid/src/diagrams/mindmap/detector.ts"
- "File: /packages/mermaid/src/diagrams/mindmap/mindmapTypes.ts"
- "File: /packages/mermaid/src/diagrams/mindmap/mindmapRenderer.ts"
- "File: /packages/mermaid/src/diagrams/mindmap/styles.ts"
- "File: /packages/mermaid/src/diagrams/mindmap/svgDraw.ts"
generationTime: 2025-01-28T16:00:00.000Z
---
sequenceDiagram
participant User as User Input Text
participant Detector as detector.ts
participant Loader as DiagramLoader
participant Definition as mindmap-definition.ts
participant Parser as parser/mindmap.jison
participant DB as MindmapDB
participant Renderer as mindmapRenderer.ts
participant Cytoscape as cytoscape.js
participant SVGDraw as svgDraw.ts
participant Styles as styles.ts
participant Output as Final SVG
Note over User, Output: Mindmap Implementation Flow
%% Detection Phase
User->>Detector: /^\s*mindmap/ text input
activate Detector
Detector->>Detector: detector(txt) validates pattern
Detector->>Loader: loader() function called
deactivate Detector
activate Loader
Loader->>Definition: import mindmap-definition.js
deactivate Loader
%% Core Structure Setup
activate Definition
Definition->>DB: get db() → new MindmapDB()
Definition->>Renderer: setup renderer
Definition->>Parser: setup parser
Definition->>Styles: setup styles
deactivate Definition
%% Database Initialization
activate DB
Note over DB: MindmapDB Constructor
DB->>DB: initialize nodes array
DB->>DB: setup nodeType constants
DB->>DB: bind methods
DB->>DB: clear() state
%% Parsing Phase
activate Parser
User->>Parser: mindmap syntax text
loop For each node in hierarchy
Parser->>DB: addNode(level, id, descr, type)
activate DB
DB->>DB: sanitizeText(id, descr)
DB->>DB: getType(startStr, endStr)
Note right of DB: Shape Detection:<br/>[ → RECT<br/>( → ROUNDED_RECT<br/>(( → CIRCLE<br/>)) → BANG<br/>{{ → HEXAGON
DB->>DB: getParent(level)
DB->>DB: create MindmapNode
DB->>DB: add to hierarchy
deactivate DB
end
opt Icon/Class Decoration
Parser->>DB: decorateNode(decoration)
DB->>DB: set icon/class properties
end
deactivate Parser
%% Data Preparation
Renderer->>DB: getData() for layout
activate DB
DB->>DB: collect all nodes
DB->>DB: build parent-child relationships
DB-->>Renderer: return node hierarchy
deactivate DB
%% Rendering Pipeline
activate Renderer
Note over Renderer: Rendering Phase
Renderer->>Cytoscape: initialize cytoscape
activate Cytoscape
loop For each node in mindmap
Renderer->>Cytoscape: addNodes(mindmap, cy, conf, level)
Cytoscape->>Cytoscape: create node data
Cytoscape->>Cytoscape: set position (x, y)
end
loop For parent-child relationships
Renderer->>Cytoscape: add edges
Cytoscape->>Cytoscape: create edge data
end
Renderer->>Cytoscape: configure cose-bilkent layout
Cytoscape->>Cytoscape: calculate optimal positions
Cytoscape-->>Renderer: return positioned graph
deactivate Cytoscape
%% SVG Generation
Renderer->>SVGDraw: drawNodes(db, svg, mindmap, section, conf)
activate SVGDraw
loop For each node recursively
SVGDraw->>SVGDraw: select shape function
alt Default Shape
SVGDraw->>SVGDraw: defaultBkg() - rounded rectangle
else Rectangle Shape
SVGDraw->>SVGDraw: rectBkg() - sharp corners
else Circle Shape
SVGDraw->>SVGDraw: circleBkg() - perfect circle
else Cloud Shape
SVGDraw->>SVGDraw: cloudBkg() - organic curves
else Bang Shape
SVGDraw->>SVGDraw: bangBkg() - explosion style
else Hexagon Shape
SVGDraw->>SVGDraw: hexagonBkg() - six sides
end
SVGDraw->>SVGDraw: create SVG elements
SVGDraw->>SVGDraw: add text labels
SVGDraw->>SVGDraw: position node
opt Node has children
SVGDraw->>SVGDraw: drawNodes() recursive call
end
end
deactivate SVGDraw
%% Edge Rendering
Renderer->>Renderer: drawEdges(edgesEl, cy)
loop For each edge
Renderer->>Renderer: extract edge bounds
Renderer->>Renderer: draw SVG path
end
%% Styling Application
Renderer->>Styles: getStyles(options)
activate Styles
Styles->>Styles: genSections(options)
loop For THEME_COLOR_LIMIT sections
Styles->>Styles: generate color scale
Styles->>Styles: create CSS rules
Note right of Styles: .section-X fills<br/>.edge-depth-X widths<br/>.node-icon-X colors
end
Styles->>Styles: apply theme integration
Styles-->>Renderer: return compiled CSS
deactivate Styles
%% Final Assembly
Renderer->>Output: selectSvgElement()
Renderer->>Output: setupGraphViewbox()
Renderer->>Output: apply styles
Renderer->>Output: add interactive elements
deactivate Renderer
activate Output
Note over Output: Final Mindmap Features
Output->>Output: responsive layout
Output->>Output: accessibility attributes
Output->>Output: hover effects
Output->>Output: click handling
Output-->>User: rendered mindmap
deactivate Output
%% Configuration Details
Note over DB, Styles: Configuration Options
Note right of DB: Padding Calculations:<br/>Base padding from config<br/>RECT: ×2 padding<br/>ROUNDED_RECT: ×2 padding<br/>HEXAGON: ×2 padding
Note right of Styles: Section Management:<br/>MAX_SECTIONS = 12<br/>Dynamic color generation<br/>Git theme integration
Note right of Renderer: Layout Parameters:<br/>Cytoscape configuration<br/>coseBilkent settings<br/>Node spacing rules

View File

@@ -54,7 +54,7 @@ export async function requirementBox<T extends SVGGraphicsElement>(
if (isRequirementNode) {
const idHeight = await addText(
shapeSvg,
`${requirementNode.requirementId ? `id: ${requirementNode.requirementId}` : ''}`,
`${requirementNode.requirementId ? `ID: ${requirementNode.requirementId}` : ''}`,
accumulativeHeight,
node.labelStyle
);

72
pnpm-lock.yaml generated
View File

@@ -116,10 +116,10 @@ importers:
specifier: ^8.1.3
version: 8.1.3
eslint-plugin-jest:
specifier: ^28.11.2
specifier: ^28.14.0
version: 28.14.0(@typescript-eslint/eslint-plugin@8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.26.0(jiti@2.4.2))(jest@30.0.4(@types/node@22.13.5))(typescript@5.7.3)
eslint-plugin-jsdoc:
specifier: ^50.6.17
specifier: ^50.8.0
version: 50.8.0(eslint@9.26.0(jiti@2.4.2))
eslint-plugin-json:
specifier: ^4.0.1
@@ -203,7 +203,7 @@ importers:
specifier: ~5.7.3
version: 5.7.3
typescript-eslint:
specifier: ^8.32.1
specifier: ^8.38.0
version: 8.38.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)
vite:
specifier: ^7.0.3
@@ -3485,10 +3485,6 @@ packages:
peerDependencies:
typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/scope-manager@8.32.0':
resolution: {integrity: sha512-jc/4IxGNedXkmG4mx4nJTILb6TMjL66D41vyeaPWvDUmeYQzF3lKtN15WsAeTr65ce4mPxwopPSo1yUUAWw0hQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/scope-manager@8.38.0':
resolution: {integrity: sha512-WJw3AVlFFcdT9Ri1xs/lg8LwDqgekWXWhH3iAF+1ZM+QPd7oxQ6jvtW/JPwzAScxitILUIFs0/AnQ/UWHzbATQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -3510,10 +3506,6 @@ packages:
resolution: {integrity: sha512-iZqi+Ds1y4EDYUtlOOC+aUmxnE9xS/yCigkjA7XpTKV6nCBd3Hp/PRGGmdwnfkV2ThMyYldP1wRpm/id99spTQ==}
engines: {node: ^18.18.0 || >=20.0.0}
'@typescript-eslint/types@8.32.0':
resolution: {integrity: sha512-O5Id6tGadAZEMThM6L9HmVf5hQUXNSxLVKeGJYWNhhVseps/0LddMkp7//VDkzwJ69lPL0UmZdcZwggj9akJaA==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/types@8.38.0':
resolution: {integrity: sha512-wzkUfX3plUqij4YwWaJyqhiPE5UCRVlFpKn1oCRn2O1bJ592XxWJj8ROQ3JD5MYXLORW84063z3tZTb/cs4Tyw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -3527,25 +3519,12 @@ packages:
typescript:
optional: true
'@typescript-eslint/typescript-estree@8.32.0':
resolution: {integrity: sha512-pU9VD7anSCOIoBFnhTGfOzlVFQIA1XXiQpH/CezqOBaDppRwTglJzCC6fUQGpfwey4T183NKhF1/mfatYmjRqQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/typescript-estree@8.38.0':
resolution: {integrity: sha512-fooELKcAKzxux6fA6pxOflpNS0jc+nOQEEOipXFNjSlBS6fqrJOVY/whSn70SScHrcJ2LDsxWrneFoWYSVfqhQ==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/utils@8.32.0':
resolution: {integrity: sha512-8S9hXau6nQ/sYVtC3D6ISIDoJzS1NsCK+gluVhLN2YkBPX+/1wkwyUiDKnxRh15579WoOIyVWnoyIf3yGI9REw==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
peerDependencies:
eslint: ^8.57.0 || ^9.0.0
typescript: '>=4.8.4 <5.9.0'
'@typescript-eslint/utils@8.38.0':
resolution: {integrity: sha512-hHcMA86Hgt+ijJlrD8fX0j1j8w4C92zue/8LOPAFioIno+W0+L7KqE8QZKCcPGc/92Vs9x36w/4MPTJhqXdyvg==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -3557,10 +3536,6 @@ packages:
resolution: {integrity: sha512-cDF0/Gf81QpY3xYyJKDV14Zwdmid5+uuENhjH2EqFaF0ni+yAyq/LzMaIJdhNJXZI7uLzwIlA+V7oWoyn6Curg==}
engines: {node: ^18.18.0 || >=20.0.0}
'@typescript-eslint/visitor-keys@8.32.0':
resolution: {integrity: sha512-1rYQTCLFFzOI5Nl0c8LUpJT8HxpwVRn9E4CkMsYfuN6ctmQqExjSTzzSk0Tz2apmXy7WU6/6fyaZVVA/thPN+w==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
'@typescript-eslint/visitor-keys@8.38.0':
resolution: {integrity: sha512-pWrTcoFNWuwHlA9CvlfSsGWs14JxfN1TH25zM5L7o0pRLhsoZkDnTsXfQRJBEWJoV5DL0jf+Z+sxiud+K0mq1g==}
engines: {node: ^18.18.0 || ^20.9.0 || >=21.1.0}
@@ -12777,7 +12752,7 @@ snapshots:
'@es-joy/jsdoccomment@0.50.2':
dependencies:
'@types/estree': 1.0.7
'@typescript-eslint/types': 8.32.0
'@typescript-eslint/types': 8.38.0
comment-parser: 1.4.1
esquery: 1.6.0
jsdoc-type-pratt-parser: 4.1.0
@@ -14320,11 +14295,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/scope-manager@8.32.0':
dependencies:
'@typescript-eslint/types': 8.32.0
'@typescript-eslint/visitor-keys': 8.32.0
'@typescript-eslint/scope-manager@8.38.0':
dependencies:
'@typescript-eslint/types': 8.38.0
@@ -14348,8 +14318,6 @@ snapshots:
'@typescript-eslint/types@7.18.0': {}
'@typescript-eslint/types@8.32.0': {}
'@typescript-eslint/types@8.38.0': {}
'@typescript-eslint/typescript-estree@7.18.0(typescript@5.7.3)':
@@ -14367,20 +14335,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/typescript-estree@8.32.0(typescript@5.7.3)':
dependencies:
'@typescript-eslint/types': 8.32.0
'@typescript-eslint/visitor-keys': 8.32.0
debug: 4.4.1(supports-color@8.1.1)
fast-glob: 3.3.3
is-glob: 4.0.3
minimatch: 9.0.5
semver: 7.7.2
ts-api-utils: 2.1.0(typescript@5.7.3)
typescript: 5.7.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/typescript-estree@8.38.0(typescript@5.7.3)':
dependencies:
'@typescript-eslint/project-service': 8.38.0(typescript@5.7.3)
@@ -14397,17 +14351,6 @@ snapshots:
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)':
dependencies:
'@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0(jiti@2.4.2))
'@typescript-eslint/scope-manager': 8.32.0
'@typescript-eslint/types': 8.32.0
'@typescript-eslint/typescript-estree': 8.32.0(typescript@5.7.3)
eslint: 9.26.0(jiti@2.4.2)
typescript: 5.7.3
transitivePeerDependencies:
- supports-color
'@typescript-eslint/utils@8.38.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)':
dependencies:
'@eslint-community/eslint-utils': 4.7.0(eslint@9.26.0(jiti@2.4.2))
@@ -14424,11 +14367,6 @@ snapshots:
'@typescript-eslint/types': 7.18.0
eslint-visitor-keys: 3.4.3
'@typescript-eslint/visitor-keys@8.32.0':
dependencies:
'@typescript-eslint/types': 8.32.0
eslint-visitor-keys: 4.2.0
'@typescript-eslint/visitor-keys@8.38.0':
dependencies:
'@typescript-eslint/types': 8.38.0
@@ -16956,7 +16894,7 @@ snapshots:
eslint-plugin-jest@28.14.0(@typescript-eslint/eslint-plugin@8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.26.0(jiti@2.4.2))(jest@30.0.4(@types/node@22.13.5))(typescript@5.7.3):
dependencies:
'@typescript-eslint/utils': 8.32.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)
'@typescript-eslint/utils': 8.38.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)
eslint: 9.26.0(jiti@2.4.2)
optionalDependencies:
'@typescript-eslint/eslint-plugin': 8.38.0(@typescript-eslint/parser@8.38.0(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3))(eslint@9.26.0(jiti@2.4.2))(typescript@5.7.3)