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:
@ -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'
|
||||||
// }
|
// }
|
||||||
// }
|
// }
|
||||||
|
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
75
lib/svgo.js
75
lib/svgo.js
@ -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;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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)));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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;
|
||||||
|
@ -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": {
|
||||||
|
@ -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);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
@ -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();
|
||||||
});
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user