Snap.svg icon indicating copy to clipboard operation
Snap.svg copied to clipboard

Snap.svg on Node.js

Open Tpower36 opened this issue 9 years ago • 10 comments
trafficstars

Hi! I'm asking because I found no documentation about this topic. Is it possible to use Snap.svg with Node.js? Did someone succeeded making it work server side?

Thanks in advance for your answers

Tpower36 avatar Apr 08 '16 06:04 Tpower36

On its own, not without modification. Node.js' require system is modeled after the CommonJS spec and there is issue #447 for it. Support would be awesome.

If you happen to be using webpack, or don't mind utilizing it, it has an imports-loader module that can help shim in CommonJS compatibility for the time being. The approach is detailed in #341.

To be clear webpack obviously is meant for the web but it's output targets are configurable and at the time of this writing contain options for: node-compatible CJS output, node-compatible asynchronous loading via fs/vm node modules, a webkit variant of the node output (for nw.js) and an electron variant of the node output.

r4j4h avatar Aug 07 '16 21:08 r4j4h

I recently posted the answer in SO about running Snap.svg in Node.js with jsdom.

In short:

const jsdom = require('jsdom');
const xmlserializer = require('xmlserializer');

jsdom.env('', ['node_modules/snapsvg/dist/snap.svg.js'], (error, window) => {
    if (error) throw error;

    const paper = window.Snap(100, 100);

    const rect = paper.rect(20, 20, 60, 60);
    rect.attr({fill: 'red'});

    const svg = xmlserializer.serializeToString(paper.node);
    window.close();

    console.log(svg);
});

hakatashi avatar Sep 19 '16 05:09 hakatashi

It can be solved with this loader config (seen in #341):

{
    test: require.resolve('snapsvg'),
    loader: 'imports-loader?this=>window,fix=>module.exports=0'
 }

roadev avatar Oct 04 '16 17:10 roadev

Did anyone manage to have it run well with node.js? Any best practices (or alternatives for *.svg processing in node.js)?

pwichmann avatar Dec 15 '16 05:12 pwichmann

@roadev I arrive here without knowing what "loader" is. Can you give a more fleshed out example of your solution based on #341 that is specific to node?

sparr avatar Mar 11 '17 23:03 sparr

@sparr See #483. It’s for working with webpack, which is a preferred way of bundling & managing JS for front-end code (it also allows you to use NPM for easy version management).

drwpow avatar Aug 11 '17 11:08 drwpow

Here's a way of doing it in typescript without any special bundler, just a refresh of @hakatashi's method. Note I have the "dom" in my "lib" array for the compiler to handle the types/jsdom .d.ts files.

    const dom = new jsdom.JSDOM(
      '<script src="node_modules/snapsvg/dist/snap.svg.js"/>',
      {
        runScripts: "dangerously",
        resources: "usable"
      }
    );

    const window = dom.window as typeof dom.window & { 
      Snap: typeof snap;
    };
    // have to be sure the snap module is loaded before proceeding
    await ((async () => {
      while (!window.Snap) {
        await bluebird.delay(100);
      }
    })());
    const height = 800;
    const width = 600;
    const surface = window.Snap(height, width);
    // start drawing
    // surface.circle(150, 150, 100);
    const rect = surface.rect(10, 10, 200, 125, 10, 10);
    
    //serialize
    xmlserializer.serializeToString(surface.node)

Sammons avatar May 27 '18 17:05 Sammons

@Sammons that’s awesome. Could you submit a PR that adds that to the README? That seems useful for others.

drwpow avatar May 28 '18 00:05 drwpow

but jsdom does not have implemented getBBox https://github.com/jsdom/jsdom/issues/918

APerricone avatar Dec 01 '19 11:12 APerricone

jsdom is on version 16 now.

anyone have an updated template to get this running with latest version of JSDOM?

addijhaq avatar Sep 17 '20 15:09 addijhaq