Return data from svg2img via callback

Given the chunks coming from imagemagick are getting stored memory and
then tucked into a cache, this function could as easily return a buffer
via callback. Streaming is just making it more complex. (And trickier to
test!)
This commit is contained in:
Paul Melnikow 2017-04-05 22:40:47 -04:00 committed by Thaddee Tyl
parent ad1e419d42
commit 0760d17d82
5 changed files with 20 additions and 38 deletions

View File

@ -62,7 +62,9 @@ if (color[0] === ':') {
badge(badgeData, function produceOutput(svg) {
if (/png|jpg|gif/.test(format)) {
svg2img(svg, format, process.stdout);
svg2img(svg, format, function (data) {
process.stdout.write(data);
});
} else {
console.log(svg);
}

View File

@ -6,12 +6,12 @@ var imageMagick = gm.subClass({ imageMagick: true });
// The following is an arbitrary limit (~1.5MB, 1.5kB/image).
var imgCache = new LruCache(1000);
module.exports = function (svg, format, out, cb) {
module.exports = function (svg, format, callback) {
var cacheIndex = format + svg;
if (imgCache.has(cacheIndex)) {
// We own a cache for this svg conversion.
(new DataStream(imgCache.get(cacheIndex))).pipe(out);
cb && cb();
var result = imgCache.get(cacheIndex);
callback(result);
return;
}
@ -24,28 +24,13 @@ module.exports = function (svg, format, out, cb) {
if (err) { console.error(err); return; }
var chunks = [];
stdout.on('data', function(chunk) { chunks.push(chunk); });
stdout.on('end', function() { imgCache.set(cacheIndex, chunks); });
stdout.pipe(out);
stdout.on('finish', function() {
var result = Buffer.concat(chunks);
imgCache.set(cacheIndex, result);
callback(result);
});
});
};
// To simplify testing.
module.exports._imgCache = imgCache;
// Fake stream from the cache.
var Readable = require('stream').Readable;
var util = require('util');
function DataStream(data) {
Readable.call(this);
this.data = data;
this.i = 0;
}
util.inherits(DataStream, Readable);
DataStream.prototype._read = function() {
while (this.i < this.data.length) {
var keepPushing = this.push(this.data[this.i]);
this.i++;
if (!keepPushing) { return; }
}
this.push(null);
};

View File

@ -58,7 +58,6 @@
"eslint": "^3.18.0",
"is-png": "^1.0.0",
"is-svg": "^2.1.0",
"memory-streams": "^0.1.2",
"mocha": "^3.2.0",
"sinon": "^2.1.0"
}

View File

@ -6127,7 +6127,9 @@ function sendSVG(res, askres, end) {
function sendOther(format, res, askres, end) {
askres.setHeader('Content-Type', 'image/' + format);
svg2img(res, format, askres);
svg2img(res, format, function (data) {
end(null, {template: streamFromString(data)});
});
}
function sendJSON(res, askres, end) {

View File

@ -1,6 +1,5 @@
const assert = require('assert');
const sinon = require('sinon');
const WritableStream = require('memory-streams').WritableStream;
const isPng = require('is-png');
const badge = require('../lib/badge');
@ -13,10 +12,8 @@ describe('The rasterizer', function () {
it('should produce PNG', function(done) {
badge({ text: ['cactus', 'grown'], format: 'svg' }, svg => {
const out = new WritableStream();
svg2img(svg, 'png', out, () => {
assert.ok(isPng(out.toBuffer()));
svg2img(svg, 'png', data => {
assert.ok(isPng(data));
done();
});
});
@ -24,15 +21,12 @@ describe('The rasterizer', function () {
it('should cache its results', function(done) {
badge({ text: ['will-this', 'be-cached?'], format: 'svg' }, svg => {
const out1 = new WritableStream();
const out2 = new WritableStream();
svg2img(svg, 'png', out1, () => {
assert.ok(isPng(out1.toBuffer()));
svg2img(svg, 'png', data1 => {
assert.ok(isPng(data1));
assert.equal(cacheGet.called, false);
svg2img(svg, 'png', out2, () => {
assert.ok(isPng(out2.toBuffer()));
svg2img(svg, 'png', data2 => {
assert.ok(isPng(data2));
assert.ok(cacheGet.calledOnce);
done();