Skip to content

Latest commit

 

History

History
99 lines (72 loc) · 4.71 KB

README.md

File metadata and controls

99 lines (72 loc) · 4.71 KB

Processing *.svg files in a node.js environment

This document shall summarise my findings on how to process *.svg files in a node.js environment. Regarding the *.svg library, the focus will be on paper.js. Most of the findings, however, should be applicable to other libraries, too.

General situation

There are two fundamental options for generating *.svgs on the server-side:

  • Option A: Move the browser to the server (e.g. using PhantomJS)
  • Option B: Do NOT move an actual browser to the server but actually draw in node.js (using JSDOM)

Option A: Move the browser to the server (e.g. using PhantomJS)

Option B: Do NOT move an actual browser to the server but actually draw in node.js (using JSDOM)

Now, the problem is that the JavaScript SVG libraries extensively use the DOM API to create an SVG document, append nodes to it and manipulate it in different ways. Node.js, however, - as opposed to the browser - lacks this kind of API.

The solution for this problem is JSDOM. JSDOM (https://github.com/tmpvar/jsdom) is a JavaScript implementation of the DOM that can be used with Node.js.

Technical requirements

Importing, processing and exporting an *.svg in paper.js

What we want to do is to import an *.svg file, modify it (e.g. by adding a rectangle) and then to export the modified *.svg again.

General problems you will encounter when trying to import *.svgs

Asynchronous node.js

Node.js is asynchronous, that is the code is generally executed concurrently rather than consecutively. Because loading *.svgs takes relatively longer, you need to make sure that the *.svg is actually loaded and available before you start using it.

If you load the *.svg but do not process it in the callback function, then the processing will be excecuted while the *.svg has not been loaded yet. The following code would allow for the correct behaviour:

project.importSVG('./svg-import/115784.svg', function(item) {
    
    // This is the callback function of the importSVG()
    
    // Do something to or with the imported *.svg
    // ...here...

    // Export the *.svg again
    var paper_svg = project.exportSVG({ asString: true });

    // Write the exported *.svg into a file on the system
    fs.writeFile(path.resolve("./svg-export/export.svg"), paper_svg, function (err) {
        if (err) throw err;
        console.log('*.svg exported and saved as /svg-export/export.svg!');
    });
});

Cascading of styles (problem when no fill is defined for the imported *.svg)

"It turns out that your SVG data doesn't define a fill but expects the default fill to cascade through. Unfortunately this doesn't seem to work on Node.js. I believe it's because styles don't cascade for SVG elements in JSDOM yet. I'd recommend explicitly setting styles in your SVG data for now."

  • Add the fill by editing the *.svg's XML:
    • e.g. add this in the SVG XML: fill="#000000"
  • TODO: Can the style be added automatically using code? E.g. in paper.js?

Paper.js does not feature 'futures' yet to manage synchronous workflow

  • (I still have to fully understand this...)

Current related issues

Digital hugs

  • Thanks to Jürg Lehni (paper.js) for providing the amazing paper.js library and assisting in solving issues. Please consider donating to his project here: http://paperjs.org/donation/

Sources