How i can use mxGraph instance in node.js

蹲街弑〆低调 提交于 2021-02-10 07:26:59

问题


I'm trying use mxGraph instance in node.js to prepare XML export with my custom logic (works with front-end, i'm just moving logic to back-end). Is it possible to use full API of mxGraph instance in nodej.js, i'm wondering about methods like graph.getDefaultParent() etc.

I'm trying load new instance using correct, generated by plugin XML, but code below won't affect on model (no other errors)

 const dom = new JSDOM();

        global.window = dom.window;
        global.document = dom.window.document;
        global.navigator = {
            userAgent: '',
            appName: '',
            appVersion: '',
        };

        new JSDOM(
            `<!DOCTYPE html>
                <html>
                    <body>
                    <div id="container"></div>
                    <script type="text/javascript">
                        const graphInstance = new mxGraph(document.getElementById('container'));

                        const xmlDocument = new DOMParser().parseFromString(window.content, 'text/xml');
                        const node = xmlDocument.documentElement;
                        let decoder = new mxCodec(xmlDocument);
                        decoder.decode(node, graphInstance.getModel());

                        console.log(graphInstance.getModel()); //  looks exactly like before decode
                    </script>
                    </body>
                </html>`,
            {
                runScripts: 'dangerously',
                beforeParse(window) {
                    const { mxGraph, mxUtils, mxCodec } = require('../../static/flow-chart/js/mxClient/js/mxClient');

                    window.DOMParser = require('xmldom').DOMParser;
                    window.content = content //  mxGraph's XML, using in front-end too
                        .replace('</mxGraphModel>', '')
                        .replace('<mxGraphModel>', '');
                    window.mxGraph = mxGraph;
                    window.mxUtils = mxUtils;
                    window.mxCodec = mxCodec;
                }
            }
        );

What console loge throws:

mxCell {
  value: undefined,
  geometry: undefined,
  style: undefined,
  children: 
   [ mxCell {
       value: undefined,
       geometry: undefined,
       style: undefined,
       parent: [Circular],
       id: '1',
       mxObjectId: 'mxCell#5' } ],
  id: '0',
  mxObjectId: 'mxCell#4' }
mxGraphModel {
  currentEdit: 
   mxUndoableEdit {
     source: [Circular],
     changes: [],
     significant: true,
     notify: [Function] },
  root: 
   mxCell {
     value: undefined,
     geometry: undefined,
     style: undefined,
     children: [ [Object] ],
     id: '0',
     mxObjectId: 'mxCell#4' },
  nextId: 2,
  cells: 
   { '0': 
      mxCell {
        value: undefined,
        geometry: undefined,
        style: undefined,
        children: [Array],
        id: '0',
        mxObjectId: 'mxCell#4' },
     '1': 
      mxCell {
        value: undefined,
        geometry: undefined,
        style: undefined,
        parent: [Object],
        id: '1',
        mxObjectId: 'mxCell#5' } },
  updateLevel: 0,
  endingUpdate: false,
  eventListeners: 
   [ 'change',
     [Function],
     'change',
     [Function],
     'change',
     [Function],
     'change',
     [Function],
     'change',
     [Function],
     'change',
     [Function] ] }

回答1:


Hi and many thanks for suggesting jsdom. The following snippet generates xml and embeds it into html:

'use strict';
const jsdom = require("jsdom");
const { JSDOM } = jsdom;
const dom = new JSDOM();

global.window = dom.window;
global.document = window.document;
global.XMLSerializer = window.XMLSerializer
global.navigator = window.navigator;

var viewerModulePath = "mxgraph";
const mxgraph = require(viewerModulePath)({
  // These are wrong but harmless at the moment.
  mxImageBasePath: "./src/images",
  mxBasePath: "./src"
});

const {mxGraph, mxCodec, mxUtils} = mxgraph;

const helloWorldGraph = makeHelloWorld();
console.log(graphToHTML(helloWorldGraph));

function makeHelloWorld() {
  // Extracted from https://github.com/jgraph/mxgraph/blob/master/javascript/examples/helloworld.html
  const graph = new mxGraph();

  // Gets the default parent for inserting new cells. This
  // is normally the first child of the root (ie. layer 0).
  var parent = graph.getDefaultParent();

  // Adds cells to the model in a single step
  graph.getModel().beginUpdate();
  try {
    var v1 = graph.insertVertex(parent, null, 'Hello,', 20, 20, 80, 30);
    var v2 = graph.insertVertex(parent, null, 'World!', 200, 150, 80, 30);
    var e1 = graph.insertEdge(parent, null, '', v1, v2);
  } finally {
    // Updates the display
    graph.getModel().endUpdate();
  }
  return graph;
}

function graphToXML(graph) {
  var encoder = new mxCodec();
  var result = encoder.encode(graph.getModel());
  return mxUtils.getXml(result);
}

function graphToHTML(graph) {
  const xml = graphToXML(graph);
  return getHtml2(xml, "Hello World!");
}

// Extracted from https://github.com/jgraph/drawio/blob/master/src/main/webapp/js/diagramly/EditorUi.js#L1452
function getHtml2(xml, title, redirect) {

  const EditorUi = {
    drawHost: 'https://www.draw.io'
  }

  var js = EditorUi.drawHost + '/js/viewer.min.js';
  var foldingEnabled = false;

  // Makes XHTML compatible
  if (redirect != null) {
    redirect = redirect.replace(/&/g, '&amp;');
  }

  var data = {highlight: '#0000ff', nav: foldingEnabled, resize: false, xml: xml, toolbar: ''};

  var style = 'max-width:100%;border:1px solid transparent;';

  return ((redirect == null) ? '<!--[if IE]><meta http-equiv="X-UA-Compatible" content="IE=5,IE=9" ><![endif]-->\n' : '') +
    '<!DOCTYPE html>\n<html' + ((redirect != null) ? ' xmlns="http://www.w3.org/1999/xhtml">' : '>') +
    '\n<head>\n' + ((redirect == null) ? ((title != null) ? '<title>' + mxUtils.htmlEntities(title) +
      '</title>\n' : '') : '<title>Draw.io Diagram</title>\n') +
    ((redirect != null) ? '<meta http-equiv="refresh" content="0;URL=\'' + redirect + '\'"/>\n' : '') +
    '<meta charset="utf-8"/>\n</head>\n<body>' +
    '\n<div class="mxgraph" style="' + style + '" data-mxgraph="' + mxUtils.htmlEntities(JSON.stringify(data)) + '"></div>\n' +
    ((redirect == null) ? '<script type="text/javascript" src="' + js + '"></script>' :
    '<a style="position:absolute;top:50%;left:50%;margin-top:-128px;margin-left:-64px;" ' +
    'href="' + redirect + '" target="_blank"><img border="0" ' +
    'src="' + EditorUi.drawHost + '/images/drawlogo128.png"/></a>') +
    '\n</body>\n</html>\n';
}

Save this in an html file for example:

npm install mxgraph jdom
node helloworld.js > helloworld.html

The layout algorithms are also working fine.

I had a shot at extracting more code from diagramly to support the SVG canvas but it felt convoluted and unmaintainable. Jsdom does support canvas so technically it should be possible to generate SVG from nodejs alone.

I hope this helps!



来源:https://stackoverflow.com/questions/55711473/how-i-can-use-mxgraph-instance-in-node-js

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!