1
0
mirror of https://github.com/svg/svgo.git synced 2025-07-31 07:44:22 +03:00

Make optimize synchronous (#1322)

Ref https://github.com/svg/svgo/issues/1015

Looks like `sax` is synchronous and we do not need to listen "end"
event. This allows to avoid all callbacks and make `optimize` method
synchronous.
This commit is contained in:
Bogdan Chadkin
2021-02-14 14:59:50 +03:00
committed by GitHub
parent b85d7f9885
commit 1dc5ee3ee1
8 changed files with 75 additions and 113 deletions

View File

@ -82,20 +82,18 @@ FS.readFile(filepath, 'utf8', function(err, data) {
throw err; throw err;
} }
svgo.optimize(data, {path: filepath}).then(function(result) { const result = svgo.optimize(data, {path: filepath});
console.log(result); console.log(result);
// { // {
// // optimized SVG data string // // optimized SVG data string
// data: '<svg width="10" height="20">test</svg>' // data: '<svg width="10" height="20">test</svg>'
// // additional info such as width/height // // additional info such as width/height
// info: { // info: {
// width: '10', // width: '10',
// height: '20' // height: '20'
// } // }
// } // }
});
}); });

View File

@ -21,56 +21,37 @@ var SVGO = function(config) {
this.config = CONFIG(config); this.config = CONFIG(config);
}; };
SVGO.prototype.optimize = function(svgstr, info) { SVGO.prototype.optimize = function(svgstr, info = {}) {
info = info || {}; const config = this.config;
return new Promise((resolve, reject) => { if (config.error) {
if (this.config.error) { throw Error(config.error);
reject(this.config.error); }
return; const maxPassCount = config.multipass ? 10 : 1;
let prevResultSize = Number.POSITIVE_INFINITY;
let svgjs = null;
for (let i = 0; i < maxPassCount; i += 1) {
svgjs = SVG2JS(svgstr);
if (svgjs.error == null) {
svgjs = PLUGINS(svgjs, info, config.plugins);
} }
svgjs = JS2SVG(svgjs, config.js2svg);
var config = this.config,
maxPassCount = config.multipass ? 10 : 1,
counter = 0,
prevResultSize = Number.POSITIVE_INFINITY,
optimizeOnceCallback = (svgjs) => {
if (svgjs.error) {
reject(svgjs.error);
return;
}
info.multipassCount = counter;
if (++counter < maxPassCount && svgjs.data.length < prevResultSize) {
prevResultSize = svgjs.data.length;
this._optimizeOnce(svgjs.data, info, optimizeOnceCallback);
} else {
if (config.datauri) {
svgjs.data = encodeSVGDatauri(svgjs.data, config.datauri);
}
if (info && info.path) {
svgjs.path = info.path;
}
resolve(svgjs);
}
};
this._optimizeOnce(svgstr, info, optimizeOnceCallback);
});
};
SVGO.prototype._optimizeOnce = function(svgstr, info, callback) {
var config = this.config;
SVG2JS(svgstr, function(svgjs) {
if (svgjs.error) { if (svgjs.error) {
callback(svgjs); throw Error(svgjs.error);
return;
} }
info.multipassCount = i;
svgjs = PLUGINS(svgjs, info, config.plugins); if (svgjs.data.length < prevResultSize) {
prevResultSize = svgjs.data.length
callback(JS2SVG(svgjs, config.js2svg)); } else {
}); if (config.datauri) {
svgjs.data = encodeSVGDatauri(svgjs.data, config.datauri);
}
if (info && info.path) {
svgjs.path = info.path;
}
return svgjs;
}
}
return svgjs;
}; };
/** /**

View File

@ -382,24 +382,23 @@ function processSVGData(config, info, data, output, input) {
var startTime = Date.now(), var startTime = Date.now(),
prevFileSize = Buffer.byteLength(data, 'utf8'); prevFileSize = Buffer.byteLength(data, 'utf8');
return svgo.optimize(data, info).then(function(result) { const result = svgo.optimize(data, info);
if (config.datauri) { if (config.datauri) {
result.data = encodeSVGDatauri(result.data, config.datauri); result.data = encodeSVGDatauri(result.data, config.datauri);
} }
var resultFileSize = Buffer.byteLength(result.data, 'utf8'), var resultFileSize = Buffer.byteLength(result.data, 'utf8'),
processingTime = Date.now() - startTime; processingTime = Date.now() - startTime;
return writeOutput(input, output, result.data).then(function() { return writeOutput(input, output, result.data).then(function() {
if (!config.quiet && output != '-') { if (!config.quiet && output != '-') {
if (input) { if (input) {
console.log(`\n${PATH.basename(input)}:`); console.log(`\n${PATH.basename(input)}:`);
}
printTimeInfo(processingTime);
printProfitInfo(prevFileSize, resultFileSize);
} }
}, printTimeInfo(processingTime);
error => Promise.reject(new Error(error.code === 'ENOTDIR' ? `Error: output '${output}' is not a directory.` : error))); printProfitInfo(prevFileSize, resultFileSize);
}); }
},
error => Promise.reject(new Error(error.code === 'ENOTDIR' ? `Error: output '${output}' is not a directory.` : error)));
} }
/** /**

View File

@ -19,16 +19,14 @@ var config = {
* Convert SVG (XML) string to SVG-as-JS object. * Convert SVG (XML) string to SVG-as-JS object.
* *
* @param {String} data input data * @param {String} data input data
* @param {Function} callback
*/ */
module.exports = function(data, callback) { module.exports = function(data) {
var sax = SAX.parser(config.strict, config), var sax = SAX.parser(config.strict, config),
root = new JSAPI({ elem: '#document', content: [] }), root = new JSAPI({ elem: '#document', content: [] }),
current = root, current = root,
stack = [root], stack = [root],
textContext = null, textContext = null;
parsingError = false;
function pushToContent(content) { function pushToContent(content) {
@ -163,23 +161,12 @@ module.exports = function(data, callback) {
}; };
sax.onend = function() {
if (!this.error) {
callback(root);
} else {
callback({ error: this.error.message });
}
};
try { try {
sax.write(data); sax.write(data).close();
return root;
} catch (e) { } catch (e) {
callback({ error: e.message }); return { error: e.message };
parsingError = true;
} }
if (!parsingError) sax.close();
function trim(elem) { function trim(elem) {
if (!elem.content) return elem; if (!elem.content) return elem;

View File

@ -27,6 +27,11 @@
"name": "Lev Solntsev", "name": "Lev Solntsev",
"email": "lev.sun@ya.ru", "email": "lev.sun@ya.ru",
"url": "http://github.com/GreLI" "url": "http://github.com/GreLI"
},
{
"name": "Bogdan Chadkin",
"email": "trysound@yandex.ru",
"url": "http://github.com/TrySound"
} }
], ],
"repository": { "repository": {

View File

@ -44,10 +44,9 @@ describe('plugins tests', function() {
js2svg : { pretty: true } js2svg : { pretty: true }
}); });
return svgo.optimize(orig, {path: file}).then(function(result) { const result = svgo.optimize(orig, {path: file});
//FIXME: results.data has a '\n' at the end while it should not //FIXME: results.data has a '\n' at the end while it should not
normalize(result.data).should.be.equal(should); normalize(result.data).should.be.equal(should);
});
}); });
}); });
@ -69,4 +68,4 @@ function readFile(file) {
resolve(data); resolve(data);
}); });
}); });
} }

View File

@ -30,10 +30,8 @@ describe('svg2js', function() {
throw err; throw err;
} }
SVG2JS(data, function(result) { root = SVG2JS(data)
root = result; done();
done();
});
}); });
}); });
@ -423,9 +421,7 @@ describe('svg2js', function() {
} }
try { try {
SVG2JS(data, function(result) { root = SVG2JS(data)
root = result;
});
} catch (e) { } catch (e) {
error = e; error = e;
} }
@ -473,9 +469,7 @@ describe('svg2js', function() {
FS.readFile(filepath, 'utf8', function(err, data) { FS.readFile(filepath, 'utf8', function(err, data) {
if (err) throw err; if (err) throw err;
SVG2JS(data, function(result) { root = SVG2JS(data);
root = result;
});
done(); done();
}); });
}); });

View File

@ -30,10 +30,9 @@ describe('indentation', function() {
js2svg : { pretty: true, indent: 2 } js2svg : { pretty: true, indent: 2 }
}); });
svgo.optimize(orig, {path: filepath}).then(function(result) { const result = svgo.optimize(orig, {path: filepath});
normalize(result.data).should.be.equal(should); normalize(result.data).should.be.equal(should);
done(); done();
});
}); });