Sunday 14 May 2017

Return a resolved value from SVGO in a templating pipeline via callbacks

I'm using SVGO in a templating pipeline with gulp. The idea is to take a filename as a parameter in the html template and replace it with a parsed inline svg.

The problem is the rather weird callback-based api of SVGO, which I somehow need to plug in to the build script:

/**
* @param {String} filename - Name of the svg
* @param {Boolean} uriEncode - URIencode the result?
*/
const getSvg = (filename, uriEncode) => {
  const svgString = fs.readFileSync(`${path.src.svg}${filename}.svg`, 'utf-8');
  return optimizeSvg(svgString, uriEncode);
};

The problem starts here. Svgo has an async api which doesn't actually ever return anything. Declaring a variable in the outside scope doesn't work if the case the operation takes longer due to its async nature. In that case optimized remains undefined.

// returning the optimized svg - PROBLEM!
const optimizeSvg = (svgString, uriEncode) => {
  const svgo = new SVGO({ plugins });

  let optimized;
  svgo.optimize(svgString, output => (optimized = output.data));

  return uriEncode ? uriEncode(optimized) : optimized;
};

// template data getter trick
const tpl = {
  get data() {
    return {
      md: markdownToHtml,
      svg: getSvg,
    };
  },
};

// build html
gulp.task('html', () =>
  gulp
    .src([path.src.html + '**/*'])
    .pipe(template(tpl.data))
    .pipe(gulp.dest(path.dist.html))
);

The templating engine (https://github.com/sindresorhus/gulp-template) doesn't work with functions as parameters. A resolved value is a must, so I "tricked" it using a getter method.

Any help would be greatly appreciated. I feel like I'm missing something simple but crucial.



via Baxuz

No comments:

Post a Comment