Douglas Alan Maitelli
Douglas Alan Maitelli

Reputation: 101

Having problems to work with SVG using Inkscape in gulp task

Well, I'm trying to execute an inkscape task for every file in a gulp task.

The idea is to transform every SVG file I have in a compound path (an SVG composed only by one complex path).

I'm trying to achieve this with something like this:

gulp.task('minify-shapes', function() {
    function makeChange() {
        var Stream = require('stream');

        function transform(file, cb) {
            var svgConverter = new Inkscape(['--verb=ObjectToPath', '--export-plain-svg']);

            var stdout = new Stream();
            var bufs = [];

            console.log(file.history);

            stdout.on('data', function(d) {
                bufs.push(d);
            });

            stdout.on('end', function() {
                var buf = Buffer.concat(bufs);

                file.contents = buf;

                cb(null, file);
            });

            file.pipe(svgConverter).pipe(stdout);
        }

        return require('event-stream').map(transform);
    }

    return gulp.src('app/assets/shapes/**/*.svg')
        .pipe(makeChange())
        .pipe(gulp.dest('app/assets/shapes'));
});

The problem is, this npm package Inkscape works with streams, so I should somehow pipe Inkscape output and write back to gulp file.contents.

This seems to not work because the conversion of this Inkscape stream output to a buffer is async, so it's not work in sync with gulp task flow.

The error I'm receiving is:

stream.js:59
    dest.end();
         ^

TypeError: dest.end is not a function
    at Inkscape.onend (stream.js:59:10)
    at emitNone (events.js:91:20)
    at Inkscape.emit (events.js:185:7)
    at Inkscape.<anonymous> (node_modules\inkscape\lib\Inkscape.js:161:26)
    at emitNone (events.js:91:20)
    at ReadStream.emit (events.js:185:7)
    at endReadableNT (_stream_readable.js:926:12)
    at _combinedTickCallback (internal/process/next_tick.js:74:11)
    at process._tickCallback (internal/process/next_tick.js:98:9)

Can somebody help me?

Upvotes: 2

Views: 317

Answers (1)

Sven Schoenung
Sven Schoenung

Reputation: 30564

The file.contents property doesn't have to be a Buffer. It can also be stream. All you have to do is pass the buffer:false option to gulp.src().

Then it's as simple as replacing the existing file.contents stream with the new stream that is created by calling .pipe():

var gulp = require('gulp');
var map = require('event-stream').map;
var Inkscape = require('inkscape');

gulp.task('minify-shapes', function() {   
  return gulp.src('app/assets/shapes/**/*.svg', { buffer:false })
    .pipe(map(function(file, done) {
      var svgConverter = new Inkscape([
        '--verb=ObjectToPath', 
        '--export-plain-svg'
      ]);

      file.contents = file.contents.pipe(svgConverter);
      done(null, file);
    }))
    .pipe(gulp.dest('app/assets/shapes'));
});

Upvotes: 2

Related Questions