mirror of
				https://github.com/mermaid-js/mermaid.git
				synced 2025-10-27 17:04:10 +01:00 
			
		
		
		
	Compare commits
	
		
			3 Commits
		
	
	
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|   | 25c9e499b3 | ||
|   | be5d9bd623 | ||
|   | d851cc63bf | 
							
								
								
									
										92
									
								
								cypress/platform/cyto.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										92
									
								
								cypress/platform/cyto.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,92 @@ | ||||
| <html> | ||||
|   <head> | ||||
|     <link href="https://fonts.googleapis.com/css?family=Montserrat&display=swap" rel="stylesheet" /> | ||||
|     <link href="https://unpkg.com/tailwindcss@^1.0/dist/tailwind.min.css" rel="stylesheet" /> | ||||
|     <link | ||||
|       rel="stylesheet" | ||||
|       href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" | ||||
|     /> | ||||
|     <link | ||||
|       href="https://fonts.googleapis.com/css?family=Noto+Sans+SC&display=swap" | ||||
|       rel="stylesheet" | ||||
|     /> | ||||
|     <style> | ||||
|       body { | ||||
|         /* background: rgb(221, 208, 208); */ | ||||
|         /* background:#333; */ | ||||
|         font-family: 'Arial'; | ||||
|         /* font-size: 18px !important; */ | ||||
|         width: 100%; | ||||
|         /* display: flex; */ | ||||
|         /* flex-direction: column; */ | ||||
|         margin-left: 20px; | ||||
|       } | ||||
|       h1 { | ||||
|         color: grey; | ||||
|       } | ||||
|       .mermaid2, | ||||
|       .mermaid3 { | ||||
|         display: none; | ||||
|       } | ||||
|       .mermaid { | ||||
|       } | ||||
|       .mermaid svg { | ||||
|         border: 1px solid purple; | ||||
|         /* font-size: 18px !important; */ | ||||
|         /* fontfamily: 'courier'; */ | ||||
|       } | ||||
|       #cy { | ||||
|         width: 300px; | ||||
|         height: 300px; | ||||
|         display: block; | ||||
|       } | ||||
|     </style> | ||||
|   </head> | ||||
|   <body> | ||||
|     <div id="cy"></div> | ||||
|     <pre class="mermaid" style="width: 50%"> | ||||
| flowchart TD | ||||
| id1 --> id2--> id3[I am number 3 and I<br/>am a gigantic node<br/>am a gigantic node<br/>am a gigantic node<br/>am a gigantic node<br/>am a gigantic node]--> id4--> id5 --> id1 | ||||
| id5 --> id4 | ||||
| id5 --> id4 | ||||
|     </pre> | ||||
|     <pre class="mermaid2" style="width: 50%"> | ||||
| flowchart TD | ||||
| id1 --> id2--> id3 | ||||
| id2 --> id1 | ||||
|     </pre> | ||||
|     <script src="./mermaid.js"></script> | ||||
|     <script> | ||||
|       mermaid.parseError = function (err, hash) { | ||||
|         // console.error('Mermaid error: ', err); | ||||
|       }; | ||||
|       mermaid.initialize({ | ||||
|         maxTextSize: 900000, | ||||
|         startOnLoad: true, | ||||
|         securityLevel: 'loose', | ||||
|         logLevel: 0, | ||||
|         fontFamily: 'courier', | ||||
|         flowchart: { | ||||
|           // curve: 'curveLinear', | ||||
|           useMaxWidth: true, | ||||
|           htmlLabels: false, | ||||
|           fontFamily: 'courier', | ||||
|           defaultRenderer: 'cytoscape', | ||||
|           // defaultRenderer: 'dagre-wrapper', | ||||
|         }, | ||||
|       }); | ||||
|       function callback() { | ||||
|         alert('It worked'); | ||||
|       } | ||||
|  | ||||
|       function clickByFlow(elemName) { | ||||
|         const div = document.createElement('div'); | ||||
|         div.className = 'created-by-click'; | ||||
|         div.style = 'padding: 20px; background: green; color: white;'; | ||||
|         div.innerText = 'Clicked By Flow'; | ||||
|  | ||||
|         document.getElementsByTagName('body')[0].appendChild(div); | ||||
|       } | ||||
|     </script> | ||||
|   </body> | ||||
| </html> | ||||
| @@ -38,7 +38,7 @@ | ||||
|     </style> | ||||
|   </head> | ||||
|   <body> | ||||
|     <pre class="mermaid" style="width: 50%"> | ||||
|     <pre class="mermaid2" style="width: 50%"> | ||||
| 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; | ||||
| @@ -71,10 +71,12 @@ flowchart TD | ||||
|     end | ||||
|     end | ||||
|     </pre> | ||||
|     --> id2 --> id3(I have a long text) --> id4 --> id5 --> id1 | ||||
|     <pre class="mermaid" style="width: 50%"> | ||||
| flowchart TD | ||||
| id | ||||
| id1 | ||||
|     </pre> | ||||
|     <pre id="cy" style="width: 50%"></pre> | ||||
|     <pre class="mermaid2" style="width: 50%"> | ||||
| flowchart LR | ||||
|         a["<strong>Haiya</strong>"]===>b | ||||
| @@ -99,7 +101,7 @@ flowchart TD | ||||
|       class A someclass; | ||||
|       class C someclass; | ||||
|     </pre> | ||||
|     <pre class="mermaid" style="width: 50%"> | ||||
|     <pre class="mermaid2" style="width: 50%"> | ||||
|    sequenceDiagram | ||||
|       title: My Sequence Diagram Title | ||||
|       accTitle: My Acc Sequence Diagram | ||||
| @@ -109,14 +111,14 @@ flowchart TD | ||||
|       John-->>Alice: Great! | ||||
|       Alice-)John: See you later! | ||||
|     </pre> | ||||
|     <pre class="mermaid" style="width: 50%"> | ||||
|     <pre class="mermaid2" style="width: 50%"> | ||||
| graph TD | ||||
|     A -->|000| B | ||||
|     B -->|111| C | ||||
|  | ||||
|     linkStyle 1 stroke:#ff3,stroke-width:4px,color:red; | ||||
|     </pre> | ||||
|     <pre class="mermaid" style="width: 100%"> | ||||
|     <pre class="mermaid2" style="width: 100%"> | ||||
|   journey | ||||
|       accTitle: My User Journey Diagram | ||||
|       accDescr: My User Journey Diagram Description | ||||
| @@ -130,10 +132,10 @@ graph TD | ||||
|         Go downstairs: 5: Me | ||||
|         Sit down: 5: Me | ||||
|     </pre> | ||||
|     <pre class="mermaid" style="width: 100%"> | ||||
|     <pre class="mermaid2" style="width: 100%"> | ||||
|         info | ||||
|     </pre> | ||||
|     <pre class="mermaid" style="width: 100%"> | ||||
|     <pre class="mermaid2" style="width: 100%"> | ||||
| requirementDiagram | ||||
|       accTitle: My req Diagram | ||||
|       accDescr: My req Diagram Description | ||||
| @@ -174,7 +176,7 @@ requirementDiagram | ||||
|     test_req - contains -> test_req3 | ||||
|     test_req <- copies - test_entity2 | ||||
|     </pre> | ||||
|     <pre class="mermaid" style="width: 100%"> | ||||
|     <pre class="mermaid2" style="width: 100%"> | ||||
| gantt | ||||
|     dateFormat  YYYY-MM-DD | ||||
|     title       Adding GANTT diagram functionality to mermaid | ||||
| @@ -206,7 +208,7 @@ gantt | ||||
|     Add gantt diagram to demo page      :20h | ||||
|     Add another diagram to demo page    :48h | ||||
|     </pre> | ||||
|     <pre class="mermaid" style="width: 100%"> | ||||
|     <pre class="mermaid2" style="width: 100%"> | ||||
| stateDiagram | ||||
|   state Active { | ||||
|     Idle | ||||
| @@ -234,7 +236,7 @@ stateDiagram | ||||
|           end | ||||
|           B ->> A: Return | ||||
|     </pre> | ||||
|     <pre class="mermaid" style="width: 100%"> | ||||
|     <pre class="mermaid2" style="width: 100%"> | ||||
| classDiagram | ||||
| accTitle: My class diagram | ||||
| accDescr: My class diagram Description | ||||
| @@ -259,7 +261,7 @@ class Class10 { | ||||
|         A->>Bob: Hola | ||||
|         Bob-->A: Pasten ! | ||||
|     </pre> | ||||
|     <pre class="mermaid" style="width: 100%"> | ||||
|     <pre class="mermaid2" style="width: 100%"> | ||||
|       gitGraph | ||||
|        commit id: "ZERO" | ||||
|        branch develop | ||||
| @@ -288,7 +290,7 @@ flowchart TD | ||||
|       C -->|Two| E[iPhone] | ||||
|       C -->|Three| F[fa:fa-car Car] | ||||
|     </pre> | ||||
|     <pre class="mermaid" style="width: 100%"> | ||||
|     <pre class="mermaid2" style="width: 100%"> | ||||
|         classDiagram | ||||
|           Animal "1" <|-- Duck | ||||
|           Animal <|-- Fish | ||||
| @@ -311,7 +313,7 @@ flowchart TD | ||||
|             +run() | ||||
|           } | ||||
|     </pre> | ||||
|     <pre class="mermaid" style="width: 100%"> | ||||
|     <pre class="mermaid2" style="width: 100%"> | ||||
|         erDiagram | ||||
|     CAR ||--o{ NAMED-DRIVER : allows | ||||
|     CAR { | ||||
| @@ -343,6 +345,8 @@ flowchart TD | ||||
|           useMaxWidth: true, | ||||
|           htmlLabels: false, | ||||
|           fontFamily: 'courier', | ||||
|           defaultRenderer: 'cytoscape', | ||||
|           // defaultRenderer: 'dagre-wrapper', | ||||
|         }, | ||||
|       }); | ||||
|       function callback() { | ||||
|   | ||||
| @@ -64,6 +64,7 @@ | ||||
|   }, | ||||
|   "dependencies": { | ||||
|     "@braintree/sanitize-url": "^6.0.0", | ||||
|     "cytoscape": "^3.23.0", | ||||
|     "d3": "^7.0.0", | ||||
|     "dagre": "^0.8.5", | ||||
|     "dagre-d3": "^0.6.4", | ||||
|   | ||||
| @@ -8,8 +8,6 @@ import note from './shapes/note'; | ||||
| import { parseMember } from '../diagrams/class/svgDraw'; | ||||
| import { evaluate, sanitizeText as sanitize } from '../diagrams/common/common'; | ||||
|  | ||||
| const sanitizeText = (txt) => sanitize(txt, getConfig()); | ||||
|  | ||||
| const question = (parent, node) => { | ||||
|   const { shapeSvg, bbox } = labelHelper(parent, node, undefined, true); | ||||
|  | ||||
| @@ -1064,6 +1062,7 @@ export const insertNode = (elem, node, dir) => { | ||||
|   if (node.haveCallback) { | ||||
|     nodeElems[node.id].attr('class', nodeElems[node.id].attr('class') + ' clickable'); | ||||
|   } | ||||
|   return newEl; | ||||
| }; | ||||
| export const setNodeElem = (elem, node) => { | ||||
|   nodeElems[node.id] = elem; | ||||
|   | ||||
| @@ -41,9 +41,11 @@ import erStyles from '../diagrams/er/styles'; | ||||
| import flowParser from '../diagrams/flowchart/parser/flow'; | ||||
| import { flowDetector } from '../diagrams/flowchart/flowDetector'; | ||||
| import { flowDetectorV2 } from '../diagrams/flowchart/flowDetector-v2'; | ||||
| import { flowDetectorV3 } from '../diagrams/flowchart/flowDetector-v3'; | ||||
| import flowDb from '../diagrams/flowchart/flowDb'; | ||||
| import flowRenderer from '../diagrams/flowchart/flowRenderer'; | ||||
| import flowRendererV2 from '../diagrams/flowchart/flowRenderer-v2'; | ||||
| import flowRendererV3 from '../diagrams/flowchart/flowRenderer-v3'; | ||||
| import flowStyles from '../diagrams/flowchart/styles'; | ||||
|  | ||||
| // @ts-ignore: TODO Fix ts errors | ||||
| @@ -305,6 +307,20 @@ export const addDiagrams = () => { | ||||
|     }, | ||||
|     flowDetectorV2 | ||||
|   ); | ||||
|   registerDiagram( | ||||
|     'flowchart-v3', | ||||
|     { | ||||
|       parser: flowParser, | ||||
|       db: flowDb, | ||||
|       renderer: flowRendererV3, | ||||
|       styles: flowStyles, | ||||
|       init: () => { | ||||
|         flowDb.clear(); | ||||
|         flowDb.setGen('gen-3'); | ||||
|       }, | ||||
|     }, | ||||
|     flowDetectorV3 | ||||
|   ); | ||||
|   registerDiagram( | ||||
|     'gitGraph', | ||||
|     { parser: gitGraphParser, db: gitGraphDb, renderer: gitGraphRenderer, styles: gitGraphStyles }, | ||||
|   | ||||
| @@ -1,8 +1,23 @@ | ||||
| import type { DiagramDetector } from '../../diagram-api/detectType'; | ||||
|  | ||||
| import { log } from '../../diagram-api/diagramAPI'; | ||||
| export const flowDetectorV2: DiagramDetector = (txt, config) => { | ||||
|   log.info('Config in flowDetector-v2 defaultRenderer: ', config?.flowchart?.defaultRenderer); | ||||
|  | ||||
|   // If we have confgured to use cytoscape then we should always return false here | ||||
|   if (config?.flowchart?.defaultRenderer === 'cytoscape') { | ||||
|     log.info('flowDetector-v2 returning false'); | ||||
|     return false; | ||||
|   } else { | ||||
|     log.info('flowDetector-v2 not cytoscape'); | ||||
|   } | ||||
|  | ||||
|   // 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; | ||||
|   log.info('Config in flowDetector-v2 returning', txt.match(/^\s*flowchart/) !== null); | ||||
|   return txt.match(/^\s*flowchart/) !== null; | ||||
| }; | ||||
|  | ||||
| /* | ||||
| if (((_a = config === null || config === void 0 ? void 0 : config.flowchart) === null || _a === void 0 ? void 0 : _a.defaultRenderer) === 'dagre-wrapper1' && txt.match(/^\s*graph/) !== null) | ||||
| */ | ||||
|   | ||||
							
								
								
									
										8
									
								
								src/diagrams/flowchart/flowDetector-v3.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/diagrams/flowchart/flowDetector-v3.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| import type { DiagramDetector } from '../../diagram-api/detectType'; | ||||
|  | ||||
| export const flowDetectorV3: 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 === 'cytoscape' && txt.match(/^\s*graph/) !== null) | ||||
|     return true; | ||||
|   return txt.match(/^\s*flowchart/) !== null; | ||||
| }; | ||||
| @@ -12,7 +12,7 @@ import { interpolateToCurve, getStylesFromArray } from '../../utils'; | ||||
| import { setupGraphViewbox } from '../../setupGraphViewbox'; | ||||
| import addSVGAccessibilityFields from '../../accessibility'; | ||||
|  | ||||
| const conf = {}; | ||||
| let conf = {}; | ||||
| export const setConf = function (cnf) { | ||||
|   const keys = Object.keys(cnf); | ||||
|   for (let i = 0; i < keys.length; i++) { | ||||
| @@ -351,6 +351,7 @@ export const getClasses = function (text, diagObj) { | ||||
|  */ | ||||
|  | ||||
| export const draw = function (text, id, _version, diagObj) { | ||||
|   // const conf = config.getConfig(_version); | ||||
|   log.info('Drawing flowchart'); | ||||
|   diagObj.db.clear(); | ||||
|   flowDb.setGen('gen-2'); | ||||
|   | ||||
							
								
								
									
										549
									
								
								src/diagrams/flowchart/flowRenderer-v3.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										549
									
								
								src/diagrams/flowchart/flowRenderer-v3.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,549 @@ | ||||
| import graphlib from 'graphlib'; | ||||
| import { select, curveLinear, selectAll } from 'd3'; | ||||
|  | ||||
| import flowDb from './flowDb'; | ||||
| import { getConfig } from '../../config'; | ||||
| import { insertNode } from '../../dagre-wrapper/nodes.js'; | ||||
| import { render } from '../../dagre-wrapper/index.js'; | ||||
| import addHtmlLabel from 'dagre-d3/lib/label/add-html-label.js'; | ||||
| import { log } from '../../logger'; | ||||
| import common, { evaluate } from '../common/common'; | ||||
| import { interpolateToCurve, getStylesFromArray } from '../../utils'; | ||||
| import { setupGraphViewbox } from '../../setupGraphViewbox'; | ||||
| import addSVGAccessibilityFields from '../../accessibility'; | ||||
|  | ||||
| import cytoscape from 'cytoscape'; | ||||
|  | ||||
| const conf = {}; | ||||
| export const setConf = function (cnf) { | ||||
|   const keys = Object.keys(cnf); | ||||
|   for (let i = 0; i < keys.length; i++) { | ||||
|     conf[keys[i]] = cnf[keys[i]]; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| // /** | ||||
| //  * Function that adds the vertices found during parsing to the graph to be rendered. | ||||
| //  * | ||||
| //  * @param vert Object containing the vertices. | ||||
| //  * @param g The graph that is to be drawn. | ||||
| //  * @param svgId | ||||
| //  * @param root | ||||
| //  * @param doc | ||||
| //  * @param diagObj | ||||
| //  */ | ||||
| export const addVertices = function (vert, cy, svgId, root, doc, diagObj) { | ||||
|   const svg = root.select(`[id="${svgId}"]`); | ||||
|   const nodes = svg.insert('g').attr('class', 'nodes'); | ||||
|   const keys = Object.keys(vert); | ||||
|  | ||||
|   // Iterate through each item in the vertex object (containing all the vertices found) in the graph definition | ||||
|   keys.forEach(function (id) { | ||||
|     const vertex = vert[id]; | ||||
|  | ||||
|     /** | ||||
|      * Variable for storing the classes for the vertex | ||||
|      * | ||||
|      * @type {string} | ||||
|      */ | ||||
|     let classStr = 'default'; | ||||
|     if (vertex.classes.length > 0) { | ||||
|       classStr = vertex.classes.join(' '); | ||||
|     } | ||||
|  | ||||
|     const styles = getStylesFromArray(vertex.styles); | ||||
|  | ||||
|     // Use vertex id as text in the box if no text is provided by the graph definition | ||||
|     let vertexText = vertex.text !== undefined ? vertex.text : vertex.id; | ||||
|  | ||||
|     // We create a SVG label, either by delegating to addHtmlLabel or manually | ||||
|     let vertexNode; | ||||
|     if (evaluate(getConfig().flowchart.htmlLabels)) { | ||||
|       // TODO: addHtmlLabel accepts a labelStyle. Do we possibly have that? | ||||
|       const node = { | ||||
|         label: vertexText.replace( | ||||
|           /fa[lrsb]?:fa-[\w-]+/g, | ||||
|           (s) => `<i class='${s.replace(':', ' ')}'></i>` | ||||
|         ), | ||||
|       }; | ||||
|       vertexNode = addHtmlLabel(svg, node).node(); | ||||
|       vertexNode.parentNode.removeChild(vertexNode); | ||||
|     } else { | ||||
|       const svgLabel = doc.createElementNS('http://www.w3.org/2000/svg', 'text'); | ||||
|       svgLabel.setAttribute('style', styles.labelStyle.replace('color:', 'fill:')); | ||||
|  | ||||
|       const rows = vertexText.split(common.lineBreakRegex); | ||||
|  | ||||
|       for (let j = 0; j < rows.length; j++) { | ||||
|         const tspan = doc.createElementNS('http://www.w3.org/2000/svg', 'tspan'); | ||||
|         tspan.setAttributeNS('http://www.w3.org/XML/1998/namespace', 'xml:space', 'preserve'); | ||||
|         tspan.setAttribute('dy', '1em'); | ||||
|         tspan.setAttribute('x', '1'); | ||||
|         tspan.textContent = rows[j]; | ||||
|         svgLabel.appendChild(tspan); | ||||
|       } | ||||
|       vertexNode = svgLabel; | ||||
|     } | ||||
|  | ||||
|     let radious = 0; | ||||
|     let _shape = ''; | ||||
|     // Set the shape based parameters | ||||
|     switch (vertex.type) { | ||||
|       case 'round': | ||||
|         radious = 5; | ||||
|         _shape = 'rect'; | ||||
|         break; | ||||
|       case 'square': | ||||
|         _shape = 'rect'; | ||||
|         break; | ||||
|       case 'diamond': | ||||
|         _shape = 'question'; | ||||
|         break; | ||||
|       case 'hexagon': | ||||
|         _shape = 'hexagon'; | ||||
|         break; | ||||
|       case 'odd': | ||||
|         _shape = 'rect_left_inv_arrow'; | ||||
|         break; | ||||
|       case 'lean_right': | ||||
|         _shape = 'lean_right'; | ||||
|         break; | ||||
|       case 'lean_left': | ||||
|         _shape = 'lean_left'; | ||||
|         break; | ||||
|       case 'trapezoid': | ||||
|         _shape = 'trapezoid'; | ||||
|         break; | ||||
|       case 'inv_trapezoid': | ||||
|         _shape = 'inv_trapezoid'; | ||||
|         break; | ||||
|       case 'odd_right': | ||||
|         _shape = 'rect_left_inv_arrow'; | ||||
|         break; | ||||
|       case 'circle': | ||||
|         _shape = 'circle'; | ||||
|         break; | ||||
|       case 'ellipse': | ||||
|         _shape = 'ellipse'; | ||||
|         break; | ||||
|       case 'stadium': | ||||
|         _shape = 'stadium'; | ||||
|         break; | ||||
|       case 'subroutine': | ||||
|         _shape = 'subroutine'; | ||||
|         break; | ||||
|       case 'cylinder': | ||||
|         _shape = 'cylinder'; | ||||
|         break; | ||||
|       case 'group': | ||||
|         _shape = 'rect'; | ||||
|         break; | ||||
|       case 'doublecircle': | ||||
|         _shape = 'doublecircle'; | ||||
|         break; | ||||
|       default: | ||||
|         _shape = 'rect'; | ||||
|     } | ||||
|     // // Add the node | ||||
|     const node = { | ||||
|       labelStyle: styles.labelStyle, | ||||
|       shape: _shape, | ||||
|       labelText: vertexText, | ||||
|       rx: radious, | ||||
|       ry: radious, | ||||
|       class: classStr, | ||||
|       style: styles.style, | ||||
|       id: vertex.id, | ||||
|       link: vertex.link, | ||||
|       linkTarget: vertex.linkTarget, | ||||
|       tooltip: diagObj.db.getTooltip(vertex.id) || '', | ||||
|       domId: diagObj.db.lookUpDomId(vertex.id), | ||||
|       haveCallback: vertex.haveCallback, | ||||
|       width: vertex.type === 'group' ? 500 : undefined, | ||||
|       dir: vertex.dir, | ||||
|       type: vertex.type, | ||||
|       props: vertex.props, | ||||
|       padding: getConfig().flowchart.padding, | ||||
|     }; | ||||
|     const nodeEl = insertNode(nodes, node, vertex.dir); | ||||
|     const boundingBox = nodeEl.node().getBBox(); | ||||
|     cy.add({ | ||||
|       group: 'nodes', | ||||
|       data: { | ||||
|         id: vertex.id, | ||||
|         labelStyle: styles.labelStyle, | ||||
|         shape: _shape, | ||||
|         labelText: vertexText, | ||||
|         rx: radious, | ||||
|         ry: radious, | ||||
|         class: classStr, | ||||
|         style: styles.style, | ||||
|         link: vertex.link, | ||||
|         linkTarget: vertex.linkTarget, | ||||
|         tooltip: diagObj.db.getTooltip(vertex.id) || '', | ||||
|         domId: diagObj.db.lookUpDomId(vertex.id), | ||||
|         haveCallback: vertex.haveCallback, | ||||
|         width: vertex.type === 'group' ? 500 : undefined, | ||||
|         dir: vertex.dir, | ||||
|         type: vertex.type, | ||||
|         props: vertex.props, | ||||
|         padding: getConfig().flowchart.padding, | ||||
|         boundingBox, | ||||
|         el: nodeEl, | ||||
|       }, | ||||
|     }); | ||||
|  | ||||
|     log.trace('setNode', { | ||||
|       labelStyle: styles.labelStyle, | ||||
|       shape: _shape, | ||||
|       labelText: vertexText, | ||||
|       rx: radious, | ||||
|       ry: radious, | ||||
|       class: classStr, | ||||
|       style: styles.style, | ||||
|       id: vertex.id, | ||||
|       domId: diagObj.db.lookUpDomId(vertex.id), | ||||
|       width: vertex.type === 'group' ? 500 : undefined, | ||||
|       type: vertex.type, | ||||
|       dir: vertex.dir, | ||||
|       props: vertex.props, | ||||
|       padding: getConfig().flowchart.padding, | ||||
|     }); | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Add edges to graph based on parsed graph definition | ||||
|  * | ||||
|  * @param {object} edges The edges to add to the graph | ||||
|  * @param {object} g The graph object | ||||
|  * @param cy | ||||
|  * @param diagObj | ||||
|  */ | ||||
| export const addEdges = function (edges, cy, diagObj) { | ||||
|   // log.info('abc78 edges = ', edges); | ||||
|   let cnt = 0; | ||||
|   let linkIdCnt = {}; | ||||
|  | ||||
|   let defaultStyle; | ||||
|   let defaultLabelStyle; | ||||
|  | ||||
|   if (typeof edges.defaultStyle !== 'undefined') { | ||||
|     const defaultStyles = getStylesFromArray(edges.defaultStyle); | ||||
|     defaultStyle = defaultStyles.style; | ||||
|     defaultLabelStyle = defaultStyles.labelStyle; | ||||
|   } | ||||
|  | ||||
|   edges.forEach(function (edge) { | ||||
|     cnt++; | ||||
|  | ||||
|     // Identify Link | ||||
|     var linkIdBase = 'L-' + edge.start + '-' + edge.end; | ||||
|     // count the links from+to the same node to give unique id | ||||
|     if (typeof linkIdCnt[linkIdBase] === 'undefined') { | ||||
|       linkIdCnt[linkIdBase] = 0; | ||||
|       log.info('abc78 new entry', linkIdBase, linkIdCnt[linkIdBase]); | ||||
|     } else { | ||||
|       linkIdCnt[linkIdBase]++; | ||||
|       log.info('abc78 new entry', linkIdBase, linkIdCnt[linkIdBase]); | ||||
|     } | ||||
|     let linkId = linkIdBase + '-' + linkIdCnt[linkIdBase]; | ||||
|     log.info('abc78 new link id to be used is', linkIdBase, linkId, linkIdCnt[linkIdBase]); | ||||
|     var linkNameStart = 'LS-' + edge.start; | ||||
|     var linkNameEnd = 'LE-' + edge.end; | ||||
|  | ||||
|     const edgeData = { style: '', labelStyle: '' }; | ||||
|     edgeData.minlen = edge.length || 1; | ||||
|     //edgeData.id = 'id' + cnt; | ||||
|  | ||||
|     // Set link type for rendering | ||||
|     if (edge.type === 'arrow_open') { | ||||
|       edgeData.arrowhead = 'none'; | ||||
|     } else { | ||||
|       edgeData.arrowhead = 'normal'; | ||||
|     } | ||||
|  | ||||
|     // Check of arrow types, placed here in order not to break old rendering | ||||
|     edgeData.arrowTypeStart = 'arrow_open'; | ||||
|     edgeData.arrowTypeEnd = 'arrow_open'; | ||||
|  | ||||
|     /* eslint-disable no-fallthrough */ | ||||
|     switch (edge.type) { | ||||
|       case 'double_arrow_cross': | ||||
|         edgeData.arrowTypeStart = 'arrow_cross'; | ||||
|       case 'arrow_cross': | ||||
|         edgeData.arrowTypeEnd = 'arrow_cross'; | ||||
|         break; | ||||
|       case 'double_arrow_point': | ||||
|         edgeData.arrowTypeStart = 'arrow_point'; | ||||
|       case 'arrow_point': | ||||
|         edgeData.arrowTypeEnd = 'arrow_point'; | ||||
|         break; | ||||
|       case 'double_arrow_circle': | ||||
|         edgeData.arrowTypeStart = 'arrow_circle'; | ||||
|       case 'arrow_circle': | ||||
|         edgeData.arrowTypeEnd = 'arrow_circle'; | ||||
|         break; | ||||
|     } | ||||
|  | ||||
|     let style = ''; | ||||
|     let labelStyle = ''; | ||||
|  | ||||
|     switch (edge.stroke) { | ||||
|       case 'normal': | ||||
|         style = 'fill:none;'; | ||||
|         if (typeof defaultStyle !== 'undefined') { | ||||
|           style = defaultStyle; | ||||
|         } | ||||
|         if (typeof defaultLabelStyle !== 'undefined') { | ||||
|           labelStyle = defaultLabelStyle; | ||||
|         } | ||||
|         edgeData.thickness = 'normal'; | ||||
|         edgeData.pattern = 'solid'; | ||||
|         break; | ||||
|       case 'dotted': | ||||
|         edgeData.thickness = 'normal'; | ||||
|         edgeData.pattern = 'dotted'; | ||||
|         edgeData.style = 'fill:none;stroke-width:2px;stroke-dasharray:3;'; | ||||
|         break; | ||||
|       case 'thick': | ||||
|         edgeData.thickness = 'thick'; | ||||
|         edgeData.pattern = 'solid'; | ||||
|         edgeData.style = 'stroke-width: 3.5px;fill:none;'; | ||||
|         break; | ||||
|     } | ||||
|     if (typeof edge.style !== 'undefined') { | ||||
|       const styles = getStylesFromArray(edge.style); | ||||
|       style = styles.style; | ||||
|       labelStyle = styles.labelStyle; | ||||
|     } | ||||
|  | ||||
|     edgeData.style = edgeData.style += style; | ||||
|     edgeData.labelStyle = edgeData.labelStyle += labelStyle; | ||||
|  | ||||
|     if (typeof edge.interpolate !== 'undefined') { | ||||
|       edgeData.curve = interpolateToCurve(edge.interpolate, curveLinear); | ||||
|     } else if (typeof edges.defaultInterpolate !== 'undefined') { | ||||
|       edgeData.curve = interpolateToCurve(edges.defaultInterpolate, curveLinear); | ||||
|     } else { | ||||
|       edgeData.curve = interpolateToCurve(conf.curve, curveLinear); | ||||
|     } | ||||
|  | ||||
|     if (typeof edge.text === 'undefined') { | ||||
|       if (typeof edge.style !== 'undefined') { | ||||
|         edgeData.arrowheadStyle = 'fill: #333'; | ||||
|       } | ||||
|     } else { | ||||
|       edgeData.arrowheadStyle = 'fill: #333'; | ||||
|       edgeData.labelpos = 'c'; | ||||
|     } | ||||
|  | ||||
|     edgeData.labelType = 'text'; | ||||
|     edgeData.label = edge.text.replace(common.lineBreakRegex, '\n'); | ||||
|  | ||||
|     if (typeof edge.style === 'undefined') { | ||||
|       edgeData.style = edgeData.style || 'stroke: #333; stroke-width: 1.5px;fill:none;'; | ||||
|     } | ||||
|  | ||||
|     edgeData.labelStyle = edgeData.labelStyle.replace('color:', 'fill:'); | ||||
|  | ||||
|     edgeData.id = linkId; | ||||
|     edgeData.classes = 'flowchart-link ' + linkNameStart + ' ' + linkNameEnd; | ||||
|  | ||||
|     // Add the edge to the graph | ||||
|     cy.add({ group: 'edges', data: { source: edge.start, target: edge.end, edgeData, id: cnt } }); | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Returns the all the styles from classDef statements in the graph definition. | ||||
|  * | ||||
|  * @param text | ||||
|  * @param diagObj | ||||
|  * @returns {object} ClassDef styles | ||||
|  */ | ||||
| export const getClasses = function (text, diagObj) { | ||||
|   log.info('Extracting classes'); | ||||
|   diagObj.db.clear(); | ||||
|   try { | ||||
|     // Parse the graph definition | ||||
|     diagObj.parse(text); | ||||
|     return diagObj.db.getClasses(); | ||||
|   } catch (e) { | ||||
|     return; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Draws a flowchart in the tag with id: id based on the graph definition in text. | ||||
|  * | ||||
|  * @param text | ||||
|  * @param id | ||||
|  */ | ||||
|  | ||||
| export const draw = function (text, id, _version, diagObj) { | ||||
|   return new Promise(function (resolve, reject) { | ||||
|     const cy = cytoscape({ | ||||
|       // styleEnabled: false, | ||||
|       // animate: false, | ||||
|       // ready: function () { | ||||
|       //   log.info('Ready', this); | ||||
|       // }, | ||||
|       container: document.getElementById('cy'), // container to render in | ||||
|  | ||||
|       elements: [ | ||||
|         // list of graph elements to start with | ||||
|         // { // node a | ||||
|         //   data: { id: 'a' } | ||||
|         // }, | ||||
|         // { // node b | ||||
|         //   data: { id: 'b' } | ||||
|         // }, | ||||
|         // { // edge ab | ||||
|         //   data: { id: 'ab', source: 'a', target: 'b' } | ||||
|         // } | ||||
|       ], | ||||
|  | ||||
|       style: [ | ||||
|         // the stylesheet for the graph | ||||
|         { | ||||
|           selector: 'node', | ||||
|           style: { | ||||
|             'background-color': '#666', | ||||
|             label: 'data(labelText)', | ||||
|           }, | ||||
|         }, | ||||
|  | ||||
|         { | ||||
|           selector: 'edge', | ||||
|           style: { | ||||
|             width: 3, | ||||
|             'line-color': '#ccc', | ||||
|             'target-arrow-color': '#ccc', | ||||
|             'target-arrow-shape': 'triangle', | ||||
|             'curve-style': 'bezier', | ||||
|             label: 'data(id)', | ||||
|           }, | ||||
|         }, | ||||
|       ], | ||||
|  | ||||
|       layout: { | ||||
|         name: 'breadthfirst', | ||||
|         rows: 1, | ||||
|       }, | ||||
|     }); | ||||
|     log.info('Drawing flowchart using v3 renderer'); | ||||
|     // Fetch the default direction, use TD if none was found | ||||
|     let dir = diagObj.db.getDirection(); | ||||
|     if (typeof dir === 'undefined') { | ||||
|       dir = 'TD'; | ||||
|     } | ||||
|  | ||||
|     const { securityLevel, flowchart: conf } = getConfig(); | ||||
|     // const nodeSpacing = conf.nodeSpacing || 50; | ||||
|     // const rankSpacing = conf.rankSpacing || 50; | ||||
|  | ||||
|     // Handle root and document for when rendering in sandbox mode | ||||
|     let sandboxElement; | ||||
|     if (securityLevel === 'sandbox') { | ||||
|       sandboxElement = select('#i' + id); | ||||
|     } | ||||
|     const root = | ||||
|       securityLevel === 'sandbox' | ||||
|         ? select(sandboxElement.nodes()[0].contentDocument.body) | ||||
|         : select('body'); | ||||
|     const doc = securityLevel === 'sandbox' ? sandboxElement.nodes()[0].contentDocument : document; | ||||
|  | ||||
|     const svg = root.select(`[id="${id}"]`); | ||||
|     const edgesEl = svg.insert('g').attr('class', 'edges edgePath'); | ||||
|  | ||||
|     // Fetch the vertices/nodes and edges/links from the parsed graph definition | ||||
|     const vert = diagObj.db.getVertices(); | ||||
|     addVertices(vert, cy, id, root, doc, diagObj); | ||||
|     // c.style(); | ||||
|     // Make cytoscape care about the dimensisions of the nodes | ||||
|     cy.nodes().forEach(function (n) { | ||||
|       n.layoutDimensions = () => { | ||||
|         const boundingBox = n.data().boundingBox; | ||||
|         return { w: boundingBox.width, h: boundingBox.height }; | ||||
|       }; | ||||
|     }); | ||||
|  | ||||
|     const edges = diagObj.db.getEdges(); | ||||
|     addEdges(edges, cy, diagObj); | ||||
|  | ||||
|     cy.layout({ | ||||
|       // name: 'grid', | ||||
|       // name: 'circle', | ||||
|       name: 'cose', | ||||
|       // name: 'breadthfirst', | ||||
|       headless: true, | ||||
|       styleEnabled: false, | ||||
|       animate: false, | ||||
|     }).run(); | ||||
|     log.info('Positions', cy.nodes().positions()); | ||||
|     window.cy = cy; | ||||
|     cy.ready((e) => { | ||||
|       log.info('Ready', e); | ||||
|       setTimeout(() => { | ||||
|         cy.nodes().map((node, id) => { | ||||
|           const data = node.data(); | ||||
|           log.info('Position: (', node.position().x, ', ', node.position().y, ')', data); | ||||
|           data.el.attr('transform', `translate(${node.position().x}, ${node.position().y})`); | ||||
|           // document | ||||
|           //   .querySelector(`[id="${data.domId}"]`) | ||||
|           //   .setAttribute('transform', `translate(${node.position().x}, ${node.position().y})`); | ||||
|           log.info('Id = ', data.domId, svg.select(`[id="${data.domId}"]`), data.el.node()); | ||||
|         }); | ||||
|  | ||||
|         cy.edges().map((edge, id) => { | ||||
|           const data = edge.data(); | ||||
|           if (edge[0]._private.bodyBounds) { | ||||
|             const bounds = edge[0]._private.rscratch; | ||||
|             log.info( | ||||
|               id, | ||||
|               // 'x:', | ||||
|               // edge.controlPoints(), | ||||
|               // 'y:', | ||||
|               edge[0]._private.rscratch | ||||
|               // 'w:', | ||||
|               // edge.boundingbox().w, | ||||
|               // 'h:', | ||||
|               // edge.boundingbox().h, | ||||
|               // edge.midPoint() | ||||
|             ); | ||||
|             // data.el.attr('transform', `translate(${node.position().x}, ${node.position().y})`); | ||||
|             // edgesEl | ||||
|             //   .insert('line') | ||||
|             //   .attr('x1', bounds.startX) | ||||
|             //   .attr('y1', bounds.startY) | ||||
|             //   .attr('x2', bounds.endX) | ||||
|             //   .attr('y2', bounds.endY) | ||||
|             //   .attr('class', 'path'); | ||||
|             edgesEl | ||||
|               .insert('path') | ||||
|               // Todo use regular line function | ||||
|               .attr( | ||||
|                 'd', | ||||
|                 `M ${bounds.startX},${bounds.startY} L ${bounds.midX},${bounds.midY} L${bounds.endX},${bounds.endY} ` | ||||
|               ) | ||||
|               .attr('class', 'path') | ||||
|               .attr('fill', 'none'); | ||||
|           } | ||||
|         }); | ||||
|  | ||||
|         log.info(cy.json()); | ||||
|         setupGraphViewbox({}, svg, conf.diagramPadding, conf.useMaxWidth); | ||||
|         resolve(); | ||||
|       }, 500); | ||||
|     }); | ||||
|   }); | ||||
| }; | ||||
|  | ||||
| export default { | ||||
|   // setConf, | ||||
|   // addVertices, | ||||
|   // addEdges, | ||||
|   getClasses, | ||||
|   draw, | ||||
| }; | ||||
| @@ -118,12 +118,12 @@ export const decodeEntities = function (text: string): string { | ||||
|  *   element will be removed when rendering is completed. | ||||
|  * @returns {void} | ||||
|  */ | ||||
| const render = function ( | ||||
| const render = async function ( | ||||
|   id: string, | ||||
|   text: string, | ||||
|   cb: (svgCode: string, bindFunctions?: (element: Element) => void) => void, | ||||
|   container?: Element | ||||
| ): void { | ||||
| ): Promise<void> { | ||||
|   configApi.reset(); | ||||
|   text = text.replace(/\r\n?/g, '\n'); // parser problems on CRLF ignore all CR and leave LF;; | ||||
|   const graphInit = utils.detectInit(text); | ||||
| @@ -299,7 +299,7 @@ const render = function ( | ||||
|   svg.insertBefore(style1, firstChild); | ||||
|  | ||||
|   try { | ||||
|     diag.renderer.draw(text, id, pkg.version, diag); | ||||
|     await diag.renderer.draw(text, id, pkg.version, diag); | ||||
|   } catch (e) { | ||||
|     errorRenderer.draw(id, pkg.version); | ||||
|     throw e; | ||||
|   | ||||
							
								
								
									
										13
									
								
								yarn.lock
									
									
									
									
									
								
							
							
						
						
									
										13
									
								
								yarn.lock
									
									
									
									
									
								
							| @@ -4710,6 +4710,14 @@ cypress@9.7.0: | ||||
|     untildify "^4.0.0" | ||||
|     yauzl "^2.10.0" | ||||
|  | ||||
| cytoscape@^3.23.0: | ||||
|   version "3.23.0" | ||||
|   resolved "https://registry.yarnpkg.com/cytoscape/-/cytoscape-3.23.0.tgz#054ee05a6d0aa3b4f139382bbf2f4e5226df3c6d" | ||||
|   integrity sha512-gRZqJj/1kiAVPkrVFvz/GccxsXhF3Qwpptl32gKKypO4IlqnKBjTOu+HbXtEggSGzC5KCaHp3/F7GgENrtsFkA== | ||||
|   dependencies: | ||||
|     heap "^0.2.6" | ||||
|     lodash "^4.17.21" | ||||
|  | ||||
| "d3-array@2 - 3", "d3-array@2.10.0 - 3", "d3-array@2.5.0 - 3", d3-array@3: | ||||
|   version "3.1.1" | ||||
|   resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.1.1.tgz#7797eb53ead6b9083c75a45a681e93fc41bc468c" | ||||
| @@ -6775,6 +6783,11 @@ he@^1.1.0: | ||||
|   resolved "https://registry.yarnpkg.com/he/-/he-1.2.0.tgz#84ae65fa7eafb165fddb61566ae14baf05664f0f" | ||||
|   integrity sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw== | ||||
|  | ||||
| heap@^0.2.6: | ||||
|   version "0.2.7" | ||||
|   resolved "https://registry.yarnpkg.com/heap/-/heap-0.2.7.tgz#1e6adf711d3f27ce35a81fe3b7bd576c2260a8fc" | ||||
|   integrity sha512-2bsegYkkHO+h/9MGbn6KWcE45cHZgPANo5LXF7EvWdT0yT2EguSVO1nDgU5c8+ZOPwp2vMNa7YFsJhVcDR9Sdg== | ||||
|  | ||||
| highlight.js@^10.5.0: | ||||
|   version "10.7.3" | ||||
|   resolved "https://registry.yarnpkg.com/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" | ||||
|   | ||||
		Reference in New Issue
	
	Block a user