MaterialXLab API  0.0.1
APIs For MaterialXLab Libraries
Loading...
Searching...
No Matches
JsMaterialXGraph.js
Go to the documentation of this file.
1
7{
13 this.doc = doc;
14 this.graphDictionary = {};
15 this.connections = [];
16 this.includeGraphs = '';
17 }
18
25 this.includeGraphs = graphs;
26 }
27
33 return this.graphDictionary;
34 }
35
41 return this.connections;
42 }
43
54 updateGraphDictionaryPath(key, item, nodetype, type, value, graphDictionary) {
55 if (key in graphDictionary) {
56 graphDictionary[key].push([item, nodetype, type, value]);
57 } else {
58 graphDictionary[key] = [[item, nodetype, type, value]];
59 }
60 }
61
68 updateGraphDictionaryItem(item, graphDictionary) {
69 if (!item) return;
70
71 let parentElem = item.getParent();
72 if (!parentElem || !(parentElem instanceof mx.GraphElement)) return;
73
74 let key = parentElem.getNamePath();
75 let value = item.getNamePath();
76 let itemType = item.getType();
77 let itemCategory = item.getCategory();
78 let itemValue = '';
79
80 if (item instanceof mx.Node) {
81 let inputs = item.getInputs();
82 if (inputs.length === 1) {
83 itemValue = inputs[0].getValueString();
84 }
85 } else if (item instanceof mx.Input) {
86 itemValue = item.getValueString();
87 }
88
89 this.updateGraphDictionaryPath(key, value, itemCategory, itemType, itemValue, graphDictionary);
90 }
91
97 printGraphDictionary(graphDictionary) {
98 for (let graphPath in graphDictionary) {
99 if (graphPath === '') {
100 console.log('Root Document:');
101 } else {
102 console.log(graphPath + ':');
103 }
104
105 let filter = 'input';
106 for (let item of graphDictionary[graphPath]) {
107 if (item[1] !== filter) continue;
108 console.log('- ', item);
109 }
110
111 filter = 'output';
112 for (let item of graphDictionary[graphPath]) {
113 if (item[1] !== filter) continue;
114 console.log('- ', item);
115 }
116
117 filter = ['output', 'input'];
118 for (let item of graphDictionary[graphPath]) {
119 if (!filter.includes(item[1])) {
120 console.log('- ', item);
121 }
122 }
123 }
124 }
125
132 while (elem && !(elem instanceof mx.GraphElement)) {
133 elem = elem.getParent();
134 }
135 return elem;
136 }
137
144 if (!node) return '';
145
146 let defaultOutput = null;
147 if (node instanceof mx.Node) {
148 let nodedef = node.getNodeDef();
149 if (nodedef) {
150 defaultOutput = nodedef.getActiveOutputs()[0];
151 } else {
152 console.log('Cannot find nodedef for node:', node.getNamePath());
153 }
154 } else if (node instanceof mx.NodeGraph) {
155 defaultOutput = node.getOutputs()[0];
156 }
157
158 return defaultOutput ? defaultOutput.getName() : '';
159 }
160
167 appendPath(p1, p2) {
168 return p2 ? p1 + '/' + p2 : p1;
169 }
170
179 buildPortConnection(doc, portPath, connections, portIsNode) {
180 let root = doc.getDocument();
181 let port = root.getDescendant(portPath);
182 if (!port) {
183 console.log('Element not found:', portPath);
184 return;
185 }
186
187 if (!(port instanceof mx.Input) && !(port instanceof mx.Output)) {
188 console.log('Element is not an input or output');
189 return;
190 }
191
192 let parent = port.getParent();
193 let parentPath = parent.getNamePath();
194 let parentGraph = this.getParentGraph(port);
195
196 if ((port instanceof mx.Input) && (parent instanceof mx.NodeGraph)) {
197 parentGraph = parentGraph.getParent();
198 }
199
200 if (!parentGraph) {
201 console.log('Cannot find parent graph of port', port);
202 //return;
203 }
204 let parentGraphPath = parentGraph.getNamePath();
205
206 let outputName = port.getOutputString();
207
208 let destNode = portIsNode ? portPath : parentPath;
209 let destPort = portIsNode ? '' : port.getName();
210
211 let nodename = port.getAttribute('nodename');
212 if (nodename) {
213 let result;
214 if (!parentGraphPath) {
215 result = [this.appendPath(nodename, ''), outputName, destNode, destPort, 'nodename'];
216 } else {
217 result = [this.appendPath(parentGraphPath, nodename), outputName, destNode, destPort, 'nodename'];
218 }
219 connections.push(result);
220 return;
221 }
222
223 let nodegraph = port.getNodeGraphString();
224 if (nodegraph) {
225 if (!outputName) {
226 outputName = this.getDefaultOutput(parentGraph.getChild(nodegraph));
227 }
228 let result;
229 if (!parentGraphPath) {
230 result = [this.appendPath(nodegraph, outputName), '', destNode, destPort, 'nodename'];
231 } else {
232 result = [this.appendPath(parentGraphPath, nodegraph), outputName, destNode, destPort, 'nodegraph'];
233 }
234 connections.push(result);
235 return;
236 }
237
238 let interfaceName = port.getInterfaceName();
239 if (interfaceName) {
240 let result;
241 if (!parentGraphPath) {
242 if (!outputName) {
243 outputName = this.getDefaultOutput(parentGraph.getChild(interfaceName));
244 }
245 result = [this.appendPath(interfaceName, outputName), '', destNode, destPort, 'nodename'];
246 } else {
247 let outputName = '';
248 let itemValue = '';
249 if (destNode === parentGraphPath + '/' + interfaceName) {
250 let dictItem = this.graphDictionary[parentGraphPath];
251 if (dictItem) {
252 let found = false;
253 for (let item of dictItem) {
254 if (item[0] === parentGraphPath + '/' + interfaceName) {
255 found = true;
256 break;
257 }
258 }
259 if (found) {
260 console.log('Warning: Rename duplicate interface:', parentGraphPath + '/' + interfaceName + ':in');
261 interfaceName = interfaceName + ':in';
262 }
263 }
264 }
265
266 let found = false;
267 let dictItem = this.graphDictionary[parentGraphPath];
268 if (dictItem) {
269 for (let item of dictItem) {
270 if (item[0] === parentGraphPath + '/' + interfaceName) {
271 found = true;
272 break;
273 }
274 }
275 }
276
277 if (!found) {
278 this.updateGraphDictionaryPath(parentGraphPath, parentGraphPath + '/' + interfaceName, 'input', port.getType(), itemValue, this.graphDictionary);
279 }
280 result = [this.appendPath(parentGraphPath, interfaceName), outputName, destNode, destPort, 'interfacename'];
281 }
282 connections.push(result);
283 return;
284 }
285
286 if (outputName) {
287 let result;
288 if (!parentGraphPath) {
289 result = [this.appendPath(outputName, ''), '', parentPath, port.getName(), 'nodename'];
290 } else {
291 result = [this.appendPath(parentGraphPath, outputName), '', parentPath, port.getName(), 'output'];
292 }
293 connections.push(result);
294 return;
295 }
296 }
297
305 buildConnections(doc, graphElement, connections) {
306 let root = doc.getDocument();
307
308 for (let elem of graphElement.getChildren()) {
309 if (!elem.hasSourceUri()) {
310 if (elem instanceof mx.Input) {
311 this.buildPortConnection(root, elem.getNamePath(), connections, true);
312 } else if (elem instanceof mx.Output) {
313 this.buildPortConnection(root, elem.getNamePath(), connections, true);
314 } else if (elem instanceof mx.Node) {
315 let nodeInputs = elem.getInputs();
316 for (let nodeInput of nodeInputs) {
317 this.buildPortConnection(root, nodeInput.getNamePath(), connections, false);
318 }
319 } else if (elem instanceof mx.NodeGraph) {
320 let nodedef = elem.getNodeDef();
321 if (nodedef) {
322 connections.push([elem.getNamePath(), '', nodedef.getName(), '', 'nodedef']);
323 }
324 let visited = new Set();
325 let path = elem.getNamePath();
326 if (!visited.has(path)) {
327 visited.add(path);
328 this.buildConnections(root, elem, connections);
329 }
330 }
331 }
332 }
333 }
334
341 let graphDictionary = {};
342 let root = doc.getDocument();
343 let skipped = [];
344
345 for (let elem of doc.getChildren()) {
346 if (elem.hasSourceUri()) {
347 skipped.push(elem.getNamePath());
348 } else {
349 if ((elem instanceof mx.Input) || (elem instanceof mx.Output) || (elem instanceof mx.Node)) {
350 //console.log('Scan element:', elem.getNamePath(), elem.getCategory(), mx.NodeGraph);
351 this.updateGraphDictionaryItem(elem, graphDictionary);
352 } else if (elem instanceof mx.NodeGraph) {
353 //console.log('Scan graph:', elem.getNamePath(), elem.getCategory(), mx.NodeGraph);
354 if (elem.getAttribute('nodedef')) {
355 let nodeDef = elem.getAttribute('nodedef');
356 nodeDef = root.getDescendant(nodeDef);
357 if (nodeDef) {
358 for (let nodeDefInput of nodeDef.getInputs()) {
359 if (elem.getChild("def_" + nodeDefInput.getName())) {
360 continue;
361 }
362 let newInput = elem.addInput("def_" + nodeDefInput.getName(), nodeDefInput.getType());
363 newInput.copyContentFrom(nodeDefInput);
364 }
365 }
366 }
367
368 for (let node of elem.getInputs()) {
369 this.updateGraphDictionaryItem(node, graphDictionary);
370 }
371 for (let node of elem.getOutputs()) {
372 this.updateGraphDictionaryItem(node, graphDictionary);
373 }
374 for (let node of elem.getNodes()) {
375 this.updateGraphDictionaryItem(node, graphDictionary);
376 }
377 for (let node of elem.getTokens()) {
378 this.updateGraphDictionaryItem(node, graphDictionary);
379 }
380 } else if ((elem instanceof mx.NodeDef) || (elem instanceof mx.Token)) {
381 this.updateGraphDictionaryItem(elem, graphDictionary);
382 }
383 }
384 }
385
386 return graphDictionary;
387 }
388
394 this.connections = [];
395 this.graphDictionary = {};
396
397 let graphElement = this.doc;
398 if (this.includeGraphs) {
399 let graph = this.includeGraphs;
400 graphElement = this.doc.getDescendant(graph);
401 if (graphElement) {
402 graphElement.setSourceUri('');
403 console.log('Scan graph:', graphElement.getNamePath());
404 } else {
405 console.log('Graph not found:', graph);
406 }
407 }
408
409 this.graphDictionary = this.buildGraphDictionary(graphElement);
410 this.buildConnections(this.doc, graphElement, this.connections);
411 }
412
418 getJSON(inputFileName) {
419 let data = {
420 doc: 'Graph connections for: ' + inputFileName,
421 //copyright: 'Copyright 2024, NanMu Consulting. kwokcb@gmail.com',
422 graph: this.graphDictionary,
423 connections: this.connections
424 };
425 return JSON.stringify(data, null, 4);
426 }
427
434 exportToJSON(filename, inputFileName) {
435 let data = {
436 doc: 'Graph connections for: ' + inputFileName,
437 //copyright: 'Copyright 2024, NanMu Consulting. kwokcb@gmail.com',
438 graph: this.graphDictionary,
439 connections: this.connections
440 };
441
442 //let fs = require('fs');
443 //fs.writeFileSync(filename, JSON.stringify(data, null, 2));
444
445 let dataStr = "data:text/json;charset=utf-8," + encodeURIComponent(JSON.stringify(data, null, 2));
446 let downloadAnchorNode = document.createElement('a');
447 downloadAnchorNode.setAttribute("href", dataStr);
448 downloadAnchorNode.setAttribute("download", filename);
449 document.body.appendChild(downloadAnchorNode); // required for firefox
450 downloadAnchorNode.click();
451 downloadAnchorNode.remove();
452 }
453
459 importFromJSON(filename) {
460 let fs = require('fs');
461 let data = JSON.parse(fs.readFileSync(filename, 'utf8'));
462 this.graphDictionary = data.graph;
463 this.connections = data.connections;
464 }
465}
466
472{
479 constructor(graphDictionary, connections) {
480 this.graphDictionary = graphDictionary;
481 this.connections = connections;
482 this.mermaid = [];
483 this.orientation = 'LR';
484 this.emitCategory = false;
485 this.emitType = false;
486 }
487
493 setOrientation(orientation) {
494 this.orientation = orientation;
495 }
496
502 setEmitCategory(emitCategory) {
503 this.emitCategory = emitCategory;
504 }
505
511 setEmitType(emitType) {
512 this.emitType = emitType;
513 }
514
521 {
522 path = path.replace('/default', '/default1');
523 path = path.replace('/', '_');
524 path = path.replace(' ', '_');
525 return path;
526 }
527
538 let mermaid = [];
539 mermaid.push(`graph ${this.orientation}`);
540
541 for (let graphPath in this.graphDictionary) {
542 let isSubgraph = graphPath !== '';
543 if (isSubgraph) {
544 mermaid.push(` subgraph ${graphPath}`);
545 }
546
547 for (let item of this.graphDictionary[graphPath]) {
548 let path = item[0];
549 let label = path.split('/').pop();
550 // Sanitize the path name
551 path = this.sanitizeString(path)
552
553 if (this.emitCategory) {
554 label = item[1];
555 }
556
557 if (this.emitType) {
558 label += `:${item[2]}`;
559 }
560
561 if (item[3]) {
562 label += `:${item[3]}`;
563 }
564
565 if (['input', 'output'].includes(item[1])) {
566 mermaid.push(` ${path}([${label}])`);
567 mermaid.push(` style ${path} fill:#09D, color:#FFF`);
568 } else if (item[1] === 'surfacematerial') {
569 mermaid.push(` ${path}([${label}])`);
570 mermaid.push(` style ${path} fill:#090, color:#FFF`);
571 } else if (item[1] === 'nodedef') {
572 mermaid.push(` ${path}[[${label}]]`);
573 //mermaid.push(` style ${path} fill:#02F, color:#FFF`);
574 } else if (['ifequal', 'ifgreatereq', 'switch'].includes(item[1])) {
575 mermaid.push(` ${path}{${label}}`);
576 mermaid.push(` style ${path} fill:#C72, color:#FFF`);
577 } else if (item[1] === 'token') {
578 mermaid.push(` ${path}{{${label}}}`);
579 mermaid.push(` style ${path} fill:#222, color:#FFF`);
580 } else if (item[1] === 'constant') {
581 mermaid.push(` ${path}([${label}])`);
582 mermaid.push(` style ${path} fill:#888, color:#000`);
583 } else {
584 mermaid.push(` ${path}[${label}]`);
585 }
586 }
587
588 if (isSubgraph) {
589 mermaid.push(' end');
590 }
591 }
592
593 this.mermaid = mermaid;
594
595 for (let connection of this.connections)
596 {
597 // Sanitize path names
598 connection[0] = this.sanitizeString(connection[0])
599 connection[2] = this.sanitizeString(connection[2])
600
601 let source = connection[0];
602 let dest = connection[2];
603 let edge = '';
604
605 if (connection[1].length > 0) {
606 if (connection[3].length > 0) {
607 edge = `${connection[1]}-->${connection[3]}`;
608 } else {
609 edge = connection[1];
610 }
611 } else {
612 edge = connection[3];
613 }
614
615 let connectString = '';
616
617 if (connection[4] === 'value') {
618 let sourceNode = source.split('/').pop();
619 connectString = edge.length > 0
620 ? ` ${sourceNode}["${source}"] --${edge}--> ${dest}`
621 : ` ${sourceNode}["${source}"] --> ${dest}`;
622 } else {
623 connectString = edge.length > 0
624 ? ` ${source} --"${edge}"--> ${dest}`
625 : ` ${source} --> ${dest}`;
626 }
627
628 mermaid.push(connectString);
629 }
630
631 return mermaid;
632 }
633
639 write(filename) {
640 let fs = require('fs');
641 fs.writeFileSync(filename, this.export());
642 }
643
648 getGraph(wrap = true) {
649 let result = wrap
650 ? '```mermaid\n' + this.mermaid.join('\n') + '\n```'
651 : this.mermaid.join('\n');
652
653 result = result.replace('/default', '/default1');
654 return result;
655 }
656
658 return this.getGraph();
659 }
660}
661
675{
676 let graphBuilder = new MxGraphBuilder(doc);
677 //graphBuilder.importFromJSON(filename);
678 graphBuilder.setIncludeGraphs(opts.graphs)
679 console.log('Creating graph from MaterialX document...')
680 graphBuilder.execute()
681 if (opts.saveJSON)
682 {
683 console.log('Exporting graph to JSON (graph.json)...')
684 graphBuilder.exportToJSON('graph.json', opts.inputFileName)
685 }
686 jsonString = graphBuilder.getJSON(opts.inputFileName)
687
688 //console.log('Dictionary\n', graphBuilder.getDictionary())
689 //console.log('COnnetions\n', graphBuilder.getConnections())
690
691 let exporter = new MxMermaidGraphExporter(
692 graphBuilder.getDictionary(),
693 graphBuilder.getConnections()
694 );
695
696 console.log('Creating Mermaid from graph...')
697 exporter.setOrientation(opts.orientation);
698 exporter.setEmitCategory(opts.emitCategory);
699 exporter.setEmitType(opts.emitType);
700 exporter.execute();
701
702 result = exporter.getGraph(false)
703 return [result, jsonString];
704}
705
711{
715 constructor(compoundGraph) {
716 this.compoundGraph = compoundGraph;
717 this.options = this.getDefaultOptions();
718
719 this.DEFINITION_NAME = 'definitionName';
720 this.UI_NAME = 'uiName';
721 this.NODEGROUP = 'nodeGroup';
722 this.VERSION = 'version';
723 this.DEFAULT_VERSION = 'defaultVersion';
724 this.DEFINITION_PREFIX = 'definitionPrefix';
725 this.NODEGRAPH_PREFIX = 'nodegraphPrefix';
726 this.DOCUMENTATION = 'documentation';
727 this.NAMESPACE = 'namespace';
728 }
729
735 let options = {};
736 options[this.DEFINITION_NAME] = '';
737 options[this.UI_NAME] = '';
738 options[this.VERSION] = '1.0';
739 options[this.DEFAULT_VERSION] = true;
740 options[this.NODEGROUP] = 'procedural';
741 options[this.DEFINITION_PREFIX] = 'ND_';
742 options[this.NODEGRAPH_PREFIX] = 'NG_';
743 options[this.DOCUMENTATION] = '';
744 options[this.NAMESPACE] = '';
745 return options;
746 }
747
754 {
755 console.log('------------ sanitize: ', docString)
756 // Sanitize the string so it's valid for XML and HTML
757 // by replacing special characters with their HTML entities
758 //docString = docString.replace(/&/g, '&')
759 docString = docString.replace(/</g, '&lt;')
760 docString = docString.replace(/>/g, '&gt;')
761
762 // Remove any newlines
763 docString = docString.replace(/(\r\n|\n|\r)/gm, " ");
764
765 console.log('------------ sanitize 2: ', docString)
766 return docString;
767 }
768
774 setOptions(new_options)
775 {
776 //console.log('Set options:', new_options)
777 if (new_options) {
778 this.options = {};
779 for (let key in new_options) {
780 this.options[key] = new_options[key];
781 }
782 }
783 }
784
790 {
791 if (!this.compoundGraph) {
792 return null;
793 }
794 //console.log('Options:', this.options)
795 let nodeGraph = this.compoundGraph;
796
797 let category = nodeGraph.getName();
798 if (this.options['definitionName']) {
799 category = this.options['definitionName'];
800 }
801
802 let identifier = category;
803 if (this.options[this.VERSION])
804 identifier = identifier + '_' + this.options['version'];
805
806 let parameter_signature = '';
807 let outputs = nodeGraph.getOutputs();
808 for (let output of outputs) {
809 let outputType = output.getType();
810 parameter_signature = parameter_signature + '_' + outputType;
811 }
812 identifier = identifier + parameter_signature;
813 identifier = mx.createValidName(identifier)
814
815 let nodeDefName = this.options[this.DEFINITION_PREFIX] + identifier;
816 let nodegraphName = this.options[this.NODEGRAPH_PREFIX] + identifier;
817 let uiName = this.options[this.UI_NAME];
818 let defaultVersion = this.options[this.DEFAULT_VERSION];
819 let nodeGroup = this.options[this.NODEGROUP];
820 let version = this.options[this.VERSION]
821 let namespace = this.options[this.NAMESPACE]
822
823 let definitionDoc = mx.createDocument();
824
825 // Note that the pre 1.39 equivalent was removed.
826 let definition = definitionDoc.addNodeDefFromGraph(nodeGraph, nodeDefName, category, nodegraphName)
827 if (version.length > 0)
828 {
829 definition.setVersionString(version);
830 }
831 if (defaultVersion)
832 definition.setDefaultVersion(defaultVersion);
833 if (nodeGroup.length > 0)
834 {
835 definition.setNodeGroup(nodeGroup);
836 }
837 let functionalGraph = definitionDoc.getNodeGraph(nodegraphName);
838
839 if (uiName.length)
840 {
841 uiName = this.sanitizeXMLString(uiName)
842 definition.setAttribute('uiname', uiName);
843 }
844
845 if (namespace.length > 0)
846 {
847 namespace = mx.createValidName(namespace)
848 definition.setNamespace(namespace);
849 functionalGraph.setNamespace(namespace);
850 // WARNING: Need to rename the nodedef reference
851 functionalGraph.setNodeDefString(namespace + ":" + functionalGraph.getNodeDefString())
852 }
853
854 let docString = this.options[this.DOCUMENTATION]
855 if (docString)
856 {
857 docString = this.sanitizeXMLString(docString)
858 definition.setDocString(docString)
859 functionalGraph.setDocString(docString)
860 console.log('get doc string>>>>>>>>>>>>>>>>>>>>:', definition.getDocString())
861 }
862
863 /*
864 // Cleanup the result
865 let filterAttributes = ['nodegraph', 'nodename', 'channels', 'interfacename', 'xpos', 'ypos']
866
867 // Transfer input interface from the graph to the nodedef
868 for (let input of functionalGraph.getInputs()) {
869 let nodeDefInput = definition.addInput(input.getName(), input.getType())
870 if (nodeDefInput) {
871 nodeDefInput.copyContentFrom(input)
872 for (let filterAttribute of filterAttributes) {
873 nodeDefInput.removeAttribute(filterAttribute);
874 }
875 nodeDefInput.setSourceUri('')
876 input.setInterfaceName(nodeDefInput.getName())
877 }
878 }
879 for (let input of functionalGraph.getInputs()) {
880 functionalGraph.removeInput(input.getName())
881 }
882
883 for (let output of nodeGraph.getOutputs()) {
884 let nodeDefOutput = definition.getOutput(output.getName())
885 if (nodeDefOutput)
886 definition.removeOutput(output.getName())
887 definition.addOutput(output.getName(), output.getType())
888 if (nodeDefOutput)
889 nodeDefOutput.copyContentFrom(output)
890 for (let filterAttribute in filterAttributes)
891 nodeDefOutput.removeAttribute(filterAttribute)
892 nodeDefOutput.setSourceUri('')
893 }
894 for (let graphChild of functionalGraph.getChildren()) {
895 graphChild.removeAttribute('xpos');
896 graphChild.removeAttribute('ypos');
897 }
898 */
899 return definitionDoc;
900 }
901}
902
910function createMaterialXDefinitionFromNodeGraph(doc, nodeGraphName, options=null)
911{
912 let graph = doc.getDescendant(nodeGraphName)
913 console.log('Creating MaterialX definition from NodeGraph...',
914 graph.getName())
915 let creator = new MxDefinitionCreator(graph);
916 if (options)
917 creator.options = options;
918 return creator.execute();
919}
function createMaterialXDefinitionFromNodeGraph(doc, nodeGraphName, options=null)
Utility to create a MaterialX definition from a node graph.
function createMermaidGraphFromDocument(doc, opts)
Create a Mermaid graph from a MaterialX document.
Class which will create a MaterialX definition from a node graph.
setOptions(new_options)
Set the options for definition creation.
execute()
Create a new definition.
sanitizeXMLString(docString)
Sanitize a string to be safe to use with XML / HTML.
constructor(compoundGraph)
Constructor.
getDefaultOptions()
Get the default options for definition creation.
Class which will build node graph connectivity information from a MaterialX document.
buildPortConnection(doc, portPath, connections, portIsNode)
Store a port connection.
updateGraphDictionaryItem(item, graphDictionary)
Update the graph dictionary with a new item.
getJSON(inputFileName)
Get the JSON representation of the graph information.
exportToJSON(filename, inputFileName)
Export the graph information to a JSON file.
execute()
Build the graph information.
getParentGraph(elem)
Get the parent graph of an element.
updateGraphDictionaryPath(key, item, nodetype, type, value, graphDictionary)
Update the graph dictionary with a new item.
getConnections()
Get graph connections.
getDictionary()
Get the graph dictionary.
buildGraphDictionary(doc)
Build the graph dictionary.
constructor(doc)
Constructor.
importFromJSON(filename)
Import the graph information from a JSON file.
setIncludeGraphs(graphs)
Set graphs to include.
printGraphDictionary(graphDictionary)
Print the graph dictionary.
appendPath(p1, p2)
Append two paths together.
buildConnections(doc, graphElement, connections)
Build the connections between graph elements.
getDefaultOutput(node)
Get the default output of a node.
Class which will export a graph to Mermaid format.
write(filename)
Write the graph to a file.
getGraph(wrap=true)
Get the graph wrapped in a code block if desired.
setEmitCategory(emitCategory)
Set the emit the category versus the node name.
execute()
Build the graph.
setOrientation(orientation)
Set the orientation of the graph.
sanitizeString(path)
Sanitize the a node path to be safe to use with Mermaid.
setEmitType(emitType)
Emit the type of each node in the graph.
constructor(graphDictionary, connections)
Constructor.