mirror of
				https://github.com/mermaid-js/mermaid.git
				synced 2025-10-31 10:54:15 +01:00 
			
		
		
		
	#3061 Log handing and other fixes, error handling in diagram creation
This commit is contained in:
		| @@ -97,7 +97,7 @@ export const getBuildConfig = ({ minify, core, watch, entryName }: BuildOptions) | ||||
|  | ||||
|   if (watch && config.build) { | ||||
|     config.build.watch = { | ||||
|       include: 'src/**', | ||||
|       include: ['packages/mermaid-mindmap/src/**', 'packages/mermaid/src/**'], | ||||
|     }; | ||||
|   } | ||||
|  | ||||
|   | ||||
| @@ -45,12 +45,12 @@ | ||||
|   </head> | ||||
|   <body> | ||||
|     <div>Security check</div> | ||||
|     <pre id="diagram" class="mermaid2"> | ||||
| flowchart LR | ||||
|       A --> B | ||||
|     </pre> | ||||
|     <pre id="diagram" class="mermaid"> | ||||
|         mindmap | ||||
| flowchart LR | ||||
|       A -> B | ||||
|     </pre> | ||||
|     <pre id="diagram" class="mermaid2"> | ||||
|         mindmap(( | ||||
|           root | ||||
|             ch1 | ||||
|             ch2 | ||||
| @@ -71,6 +71,10 @@ flowchart LR | ||||
|       function callback() { | ||||
|         alert('It worked'); | ||||
|       } | ||||
|       mermaid.parseError = function (err, hash) { | ||||
|         console.error('In parse error:'); | ||||
|         console.error(err); | ||||
|       }; | ||||
|     </script> | ||||
|   </body> | ||||
| </html> | ||||
|   | ||||
| @@ -29,7 +29,7 @@ | ||||
|     "clean": "rimraf dist", | ||||
|     "build:vite": "ts-node-esm --transpileOnly --project=.vite/tsconfig.json .vite/build.ts", | ||||
|     "build:types": "concurrently \"tsc -p ./packages/mermaid/tsconfig.json --emitDeclarationOnly\" \"tsc -p ./packages/mermaid-mindmap/tsconfig.json --emitDeclarationOnly\"", | ||||
|     "build:watch": "pnpm build:code --watch", | ||||
|     "build:watch": "pnpm build:vite --watch", | ||||
|     "build": "pnpm clean; concurrently \"pnpm build:vite\" \"pnpm build:types\"", | ||||
|     "dev": "concurrently \"pnpm build:vite --watch\" \"ts-node-esm .vite/server\"", | ||||
|     "docs:build": "ts-node-esm --transpileOnly packages/mermaid/src/docs.mts", | ||||
|   | ||||
| @@ -41,10 +41,13 @@ export const injectUtils = ( | ||||
|   _sanitizeText: any, | ||||
|   _setupGraphViewbox: any | ||||
| ) => { | ||||
|   _log.info('Mermaid utils injected'); | ||||
|   log.trace = _log.trace; | ||||
|   log.debug = _log.debug; | ||||
|   log.info = _log.info; | ||||
|   log.warn = _log.warn; | ||||
|   log.error = _log.error; | ||||
|   log.fatal = _log.fatal; | ||||
|   setLogLevel = _setLogLevel; | ||||
|   getConfig = _getConfig; | ||||
|   sanitizeText = _sanitizeText; | ||||
| @@ -55,6 +58,7 @@ export const injectUtils = ( | ||||
| const warning = (..._args: any[]) => { | ||||
|   console.error('Log function was called before initialization'); | ||||
| }; | ||||
|  | ||||
| export let log = { | ||||
|   trace: warning, | ||||
|   debug: warning, | ||||
|   | ||||
| @@ -1,5 +1,5 @@ | ||||
| /** Created by knut on 15-01-14. */ | ||||
| import { sanitizeText, getConfig, log as _log } from './mermaidUtils'; | ||||
| import { sanitizeText, getConfig, log } from './mermaidUtils'; | ||||
|  | ||||
| let nodes = []; | ||||
| let cnt = 0; | ||||
| @@ -131,9 +131,19 @@ export const type2Str = (type) => { | ||||
|       return 'no-border'; | ||||
|   } | ||||
| }; | ||||
|  | ||||
| export let parseError; // = (str, hash) | ||||
| //  => { | ||||
| //   const error = { str, hash }; | ||||
| //   throw error; | ||||
| // }; | ||||
| export const setErrorHandler = (handler) => { | ||||
|   parseError = handler; | ||||
| }; | ||||
|  | ||||
| // Expose logger to grammar | ||||
| export const log = _log; | ||||
| export let graphType = 'mindmap'; | ||||
| export const getLogger = () => log; | ||||
|  | ||||
| export const getNodeById = (id) => nodes[id]; | ||||
| export const getElementById = (id) => elements[id]; | ||||
| // export default { | ||||
|   | ||||
| @@ -215,51 +215,53 @@ function positionNodes(node, conf) { | ||||
|  * @param {any} version | ||||
|  * @param diagObj | ||||
|  */ | ||||
|  | ||||
| export const draw = (text, id, version, diagObj) => { | ||||
|   const conf = getConfig(); | ||||
|   try { | ||||
|     log.debug('Renering info diagram\n' + text); | ||||
|  | ||||
|     const securityLevel = getConfig().securityLevel; | ||||
|     // Handle root and Document for when rendering in sanbox mode | ||||
|     let sandboxElement; | ||||
|     if (securityLevel === 'sandbox') { | ||||
|       sandboxElement = select('#i' + id); | ||||
|     } | ||||
|     const root = | ||||
|       securityLevel === 'sandbox' | ||||
|         ? select(sandboxElement.nodes()[0].contentDocument.body) | ||||
|         : select('body'); | ||||
|     // Parse the graph definition | ||||
|   // This is done only for throwing the error if the text is not valid. | ||||
|   diagObj.db.clear(); | ||||
|   // Parse the graph definition | ||||
|   diagObj.parser.parse(text); | ||||
|  | ||||
|     const svg = root.select('#' + id); | ||||
|   log.debug('Renering info diagram\n' + text); | ||||
|  | ||||
|     svg.append('g'); | ||||
|     const mm = diagObj.db.getMindmap(); | ||||
|  | ||||
|     // Draw the graph and start with drawing the nodes without proper position | ||||
|     // this gives us the size of the nodes and we can set the positions later | ||||
|  | ||||
|     const edgesElem = svg.append('g'); | ||||
|     edgesElem.attr('class', 'mindmap-edges'); | ||||
|     const nodesElem = svg.append('g'); | ||||
|     nodesElem.attr('class', 'mindmap-nodes'); | ||||
|     drawNodes(nodesElem, mm, -1, conf); | ||||
|  | ||||
|     // Next step is to layout the mindmap, giving each node a position | ||||
|  | ||||
|     const positionedMindmap = layoutMindmap(mm, conf); | ||||
|  | ||||
|     // After this we can draw, first the edges and the then nodes with the correct position | ||||
|     drawEdges(edgesElem, positionedMindmap, null, 0, -1, conf); | ||||
|     positionNodes(positionedMindmap, conf); | ||||
|  | ||||
|     // Setup the view box and size of the svg element | ||||
|     setupGraphViewbox(undefined, svg, conf.mindmap.padding, conf.mindmap.useMaxWidth); | ||||
|   } catch (e) { | ||||
|     log.error('Error while rendering info diagram'); | ||||
|     log.error(e.message); | ||||
|   const securityLevel = getConfig().securityLevel; | ||||
|   // Handle root and Document for when rendering in sanbox mode | ||||
|   let sandboxElement; | ||||
|   if (securityLevel === 'sandbox') { | ||||
|     sandboxElement = select('#i' + id); | ||||
|   } | ||||
|   const root = | ||||
|     securityLevel === 'sandbox' | ||||
|       ? select(sandboxElement.nodes()[0].contentDocument.body) | ||||
|       : select('body'); | ||||
|   // Parse the graph definition | ||||
|  | ||||
|   const svg = root.select('#' + id); | ||||
|  | ||||
|   svg.append('g'); | ||||
|   const mm = diagObj.db.getMindmap(); | ||||
|  | ||||
|   // Draw the graph and start with drawing the nodes without proper position | ||||
|   // this gives us the size of the nodes and we can set the positions later | ||||
|  | ||||
|   const edgesElem = svg.append('g'); | ||||
|   edgesElem.attr('class', 'mindmap-edges'); | ||||
|   const nodesElem = svg.append('g'); | ||||
|   nodesElem.attr('class', 'mindmap-nodes'); | ||||
|   drawNodes(nodesElem, mm, -1, conf); | ||||
|  | ||||
|   // Next step is to layout the mindmap, giving each node a position | ||||
|  | ||||
|   const positionedMindmap = layoutMindmap(mm, conf); | ||||
|  | ||||
|   // After this we can draw, first the edges and the then nodes with the correct position | ||||
|   drawEdges(edgesElem, positionedMindmap, null, 0, -1, conf); | ||||
|   positionNodes(positionedMindmap, conf); | ||||
|  | ||||
|   // Setup the view box and size of the svg element | ||||
|   setupGraphViewbox(undefined, svg, conf.mindmap.padding, conf.mindmap.useMaxWidth); | ||||
| }; | ||||
|  | ||||
| export default { | ||||
|   | ||||
| @@ -17,21 +17,21 @@ | ||||
|  | ||||
| %% | ||||
|  | ||||
| \s*\%\%.*          {yy.log.trace('Found comment',yytext);} | ||||
| \s*\%\%.*          {yy.getLogger().trace('Found comment',yytext);} | ||||
| // \%\%[^\n]*\n                             /* skip comments */ | ||||
| "mindmap"		       return 'MINDMAP'; | ||||
| ":::"              { this.begin('CLASS'); } | ||||
| <CLASS>.+			     { this.popState();return 'CLASS'; } | ||||
| <CLASS>\n				   { this.popState();} | ||||
| // [\s]*"::icon("   { this.begin('ICON'); } | ||||
| "::icon("   { yy.log.trace('Begin icon');this.begin('ICON'); } | ||||
| "::icon("   { yy.getLogger().trace('Begin icon');this.begin('ICON'); } | ||||
| [\n]+               return 'NL'; | ||||
| <ICON>[^\)]+			 { return 'ICON'; } | ||||
| <ICON>\)				   {yy.log.trace('end icon');this.popState();} | ||||
| "-)"               { yy.log.trace('Exploding node'); this.begin('NODE');return 'NODE_DSTART'; } | ||||
| "(-"               { yy.log.trace('Cloud'); this.begin('NODE');return 'NODE_DSTART'; } | ||||
| "))"               { yy.log.trace('Explosion Bang'); this.begin('NODE');return 'NODE_DSTART'; } | ||||
| ")"               { yy.log.trace('Cloud Bang'); this.begin('NODE');return 'NODE_DSTART'; } | ||||
| <ICON>\)				   {yy.getLogger().trace('end icon');this.popState();} | ||||
| "-)"               { yy.getLogger().trace('Exploding node'); this.begin('NODE');return 'NODE_DSTART'; } | ||||
| "(-"               { yy.getLogger().trace('Cloud'); this.begin('NODE');return 'NODE_DSTART'; } | ||||
| "))"               { yy.getLogger().trace('Explosion Bang'); this.begin('NODE');return 'NODE_DSTART'; } | ||||
| ")"               { yy.getLogger().trace('Cloud Bang'); this.begin('NODE');return 'NODE_DSTART'; } | ||||
| "(("               { this.begin('NODE');return 'NODE_DSTART'; } | ||||
| "("                { this.begin('NODE');return 'NODE_DSTART'; } | ||||
| "["                { this.begin('NODE');return 'NODE_DSTART'; } | ||||
| @@ -39,18 +39,18 @@ | ||||
| // !(-\()            return 'NODE_ID'; | ||||
| [^\(\[\n\-\)]+         return 'NODE_ID'; | ||||
| <<EOF>>            return 'EOF'; | ||||
| <NODE>["]          { yy.log.trace('Starting NSTR');this.begin("NSTR");} | ||||
| <NSTR>[^"]+        { yy.log.trace('description:', yytext); return "NODE_DESCR";} | ||||
| <NODE>["]          { yy.getLogger().trace('Starting NSTR');this.begin("NSTR");} | ||||
| <NSTR>[^"]+        { yy.getLogger().trace('description:', yytext); return "NODE_DESCR";} | ||||
| <NSTR>["]          {this.popState();} | ||||
| <NODE>[\)]\)         {this.popState();yy.log.trace('node end ))');return "NODE_DEND";} | ||||
| <NODE>[\)]         {this.popState();yy.log.trace('node end )');return "NODE_DEND";} | ||||
| <NODE>[\]]         {this.popState();yy.log.trace('node end ...',yytext);return "NODE_DEND";} | ||||
| <NODE>"(-"         {this.popState();yy.log.trace('node end (-');return "NODE_DEND";} | ||||
| <NODE>"-)"         {this.popState();yy.log.trace('node end (-');return "NODE_DEND";} | ||||
| <NODE>"(("         {this.popState();yy.log.trace('node end ((');return "NODE_DEND";} | ||||
| <NODE>"("         {this.popState();yy.log.trace('node end ((');return "NODE_DEND";} | ||||
| <NODE>[^\)\]\(]+     { yy.log.trace('Long description:', yytext);   return 'NODE_DESCR';} | ||||
| <NODE>.+(?!\(\()     { yy.log.trace('Long description:', yytext);   return 'NODE_DESCR';} | ||||
| <NODE>[\)]\)         {this.popState();yy.getLogger().trace('node end ))');return "NODE_DEND";} | ||||
| <NODE>[\)]         {this.popState();yy.getLogger().trace('node end )');return "NODE_DEND";} | ||||
| <NODE>[\]]         {this.popState();yy.getLogger().trace('node end ...',yytext);return "NODE_DEND";} | ||||
| <NODE>"(-"         {this.popState();yy.getLogger().trace('node end (-');return "NODE_DEND";} | ||||
| <NODE>"-)"         {this.popState();yy.getLogger().trace('node end (-');return "NODE_DEND";} | ||||
| <NODE>"(("         {this.popState();yy.getLogger().trace('node end ((');return "NODE_DEND";} | ||||
| <NODE>"("         {this.popState();yy.getLogger().trace('node end ((');return "NODE_DEND";} | ||||
| <NODE>[^\)\]\(]+     { yy.getLogger().trace('Long description:', yytext);   return 'NODE_DESCR';} | ||||
| <NODE>.+(?!\(\()     { yy.getLogger().trace('Long description:', yytext);   return 'NODE_DESCR';} | ||||
| // [\[]               return 'NODE_START'; | ||||
| // .+                 return 'TXT' ; | ||||
|  | ||||
| @@ -68,10 +68,10 @@ start | ||||
| 	; | ||||
|  | ||||
| stop | ||||
|   : NL {yy.log.trace('Stop NL ');} | ||||
|   | EOF {yy.log.trace('Stop EOF ');} | ||||
|   | stop NL {yy.log.trace('Stop NL2 ');} | ||||
|   | stop EOF {yy.log.trace('Stop EOF2 ');} | ||||
|   : NL {yy.getLogger().trace('Stop NL ');} | ||||
|   | EOF {yy.getLogger().trace('Stop EOF ');} | ||||
|   | stop NL {yy.getLogger().trace('Stop NL2 ');} | ||||
|   | stop EOF {yy.getLogger().trace('Stop EOF2 ');} | ||||
|   ; | ||||
| document | ||||
| 	: document statement stop | ||||
| @@ -79,10 +79,10 @@ document | ||||
| 	; | ||||
|  | ||||
| statement | ||||
| 	: SPACELIST node       { yy.log.trace('Node: ',$2.id);yy.addNode($1.length, $2.id, $2.descr, $2.type);  } | ||||
| 	| SPACELIST ICON       { yy.log.trace('Icon: ',$2);yy.decorateNode({icon: $2}); } | ||||
| 	: SPACELIST node       { yy.getLogger().trace('Node: ',$2.id);yy.addNode($1.length, $2.id, $2.descr, $2.type);  } | ||||
| 	| SPACELIST ICON       { yy.getLogger().trace('Icon: ',$2);yy.decorateNode({icon: $2}); } | ||||
| 	| SPACELIST CLASS      { yy.decorateNode({class: $2}); } | ||||
| 	| node					       { yy.log.trace('Node: ',$1.id);yy.addNode(0, $1.id, $1.descr, $1.type);  } | ||||
| 	| node					       { yy.getLogger().trace('Node: ',$1.id);yy.addNode(0, $1.id, $1.descr, $1.type);  } | ||||
| 	| ICON                 { yy.decorateNode({icon: $1}); } | ||||
| 	| CLASS                { yy.decorateNode({class: $1}); } | ||||
|   | SPACELIST | ||||
| @@ -97,12 +97,12 @@ node | ||||
|  | ||||
| nodeWithoutId | ||||
|   :   NODE_DSTART NODE_DESCR NODE_DEND | ||||
| 	      { yy.log.trace("node found ..", $1); $$ = { id: $2, descr: $2, type: yy.getType($1, $3) }; } | ||||
| 	      { yy.getLogger().trace("node found ..", $1); $$ = { id: $2, descr: $2, type: yy.getType($1, $3) }; } | ||||
|   ; | ||||
|  | ||||
| nodeWithId | ||||
| 	:  NODE_ID             { $$ = { id: $1, descr: $1, type: yy.nodeType.DEFAULT }; } | ||||
| 	|  NODE_ID NODE_DSTART NODE_DESCR NODE_DEND | ||||
| 	                       { yy.log.trace("node found ..", $1); $$ = { id: $1, descr: $3, type: yy.getType($2, $4) }; } | ||||
| 	                       { yy.getLogger().trace("node found ..", $1); $$ = { id: $1, descr: $3, type: yy.getType($2, $4) }; } | ||||
| 	; | ||||
| %% | ||||
|   | ||||
| @@ -5,10 +5,10 @@ if (typeof document !== 'undefined') { | ||||
|   if (window.mermaid && typeof window.mermaid.detectors === 'object') { | ||||
|     window.mermaid.detectors.push({ id: 'mindmap', detector: mindmapDetector }); | ||||
|   } else { | ||||
|     console.error('window.mermaid.detectors not found'); // eslint-disable-line no-console | ||||
|     // console.error('window.mermaid.detectors was not found!'); // eslint-disable-line no-console | ||||
|     window.mermaid = {}; | ||||
|     window.mermaid.detectors = [{ id: 'mindmap', detector: mindmapDetector }]; | ||||
|     console.error('Detectors now:', window.mermaid.detectors); // eslint-disable-line no-console | ||||
|     // console.error('Detectors now:', window.mermaid.detectors); // eslint-disable-line no-console | ||||
|   } | ||||
|  | ||||
|   /*! | ||||
|   | ||||
| @@ -15,33 +15,19 @@ export class Diagram { | ||||
|     this.type = detectType(txt, cnf); | ||||
|     const diagram = getDiagram(this.type); | ||||
|     log.debug('Type ' + this.type); | ||||
|     // console.log('Type ' + this.type); | ||||
|     // Setup diagram | ||||
|     this.db = diagram.db; | ||||
|     this.db.clear?.(); | ||||
|     this.renderer = diagram.renderer; | ||||
|     this.parser = diagram.parser; | ||||
|     // console.log('Setting db to !', this.db); | ||||
|     this.parser.parser.yy = this.db; | ||||
|     if (diagram.init) { | ||||
|       diagram.init(cnf); | ||||
|       log.debug('Initialized diagram ' + this.type, cnf); | ||||
|     } | ||||
|     this.txt += '\n'; | ||||
|     try { | ||||
|       this.parser.parser.yy.graphType = this.type; | ||||
|       this.parser.parser.yy.parseError = (str: string, hash: string) => { | ||||
|         const error = { str, hash }; | ||||
|         throw error; | ||||
|       }; | ||||
|     } catch (error) { | ||||
|       log.error('error', error); | ||||
|     } | ||||
|     try { | ||||
|       this.parse(this.txt, parseError); | ||||
|     } catch (error) { | ||||
|       log.error('error', error); | ||||
|     } | ||||
|  | ||||
|     this.parse(this.txt, parseError); | ||||
|   } | ||||
|  | ||||
|   // eslint-disable-next-line @typescript-eslint/ban-types | ||||
|   | ||||
| @@ -53,7 +53,7 @@ const init = function ( | ||||
|   callback?: Function | ||||
| ) { | ||||
|   try { | ||||
|     console.error('Detectors in init', mermaid.detectors); // eslint-disable-line | ||||
|     log.info('Detectors in init', mermaid.detectors); // eslint-disable-line | ||||
|     mermaid.detectors.forEach(({ id, detector }) => { | ||||
|       addDetector(id, detector); | ||||
|     }); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user
	 Knut Sveidqvist
					Knut Sveidqvist