rough-stuff/rough

How to use rough.js in node.js to save an svg file?

sieste opened this issue · 2 comments

(Disclaimer: I also asked this on stackoverflow here)

The html code below is a minimal example to create an svg element displaying a simple rough.js polygon generated from an array of data. I want to use the js code in a nodejs program that generates the same svg and saves it to a file. What would be the simplest way of achieving this?

<html>
<head>
  <script src="https://unpkg.com/roughjs@latest/bundled/rough.js"></script>
</head>
<body>
  <script>
    var svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
    var rc = rough.svg(svg);
    var data = [[40, 20], [140, 30], [100, 130]];
    svg.appendChild(rc.polygon(data));
    document.body.appendChild(svg);
  </script>
</body>
</html>

(I figured it out, reposting my SO answer here in case it's of interest. I'm happy for this issue to be closed or deleted.)

The solution I found uses xmldom (from this github issue):

// file generate-rough-svg.js
const { DOMImplementation, XMLSerializer } = require('xmldom');
const xmlSerializer = new XMLSerializer();
const document = new DOMImplementation().createDocument('http://www.w3.org/1999/xhtml', 'html', null);
const rough = require('roughjs');
const svg = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
const rc = rough.svg(svg);
var data = [[40, 20], [140, 30], [100, 130]]
svg.appendChild(rc.polygon(data))
let xml = xmlSerializer.serializeToString(svg);
console.log(xml)

Now I can run

node generate-rough-svg.js > image.svg

to generate the svg file.

My solution is a simple mock

const simpleDomMock = {
  ownerDocument: {
    createElementNS: (ns, tagName) => {
      const children = []
      const attrs = {}
      return {
        tagName,
        attrs,
        setAttribute: (key, value) => (attrs[key] = value),
        appendChild: node => children.push(node),
        children,
      }
    },
  },
}

Usage:

const rough = require('roughjs/bundled/rough.cjs.js').svg(domMock)
const rect = rough.rectangle(0, 0, 1, 1)

rect is now of the structure

{ tagName: 'g',
  attrs: {},
  setAttribute: [Function: setAttribute],
  appendChild: [Function: appendChild],
  children:
   [ { tagName: 'path',
       attrs: [Object],
       setAttribute: [Function: setAttribute],
       appendChild: [Function: appendChild],
       children: [] } ] }

So now you can use what every you want to serialize this to the desired format.