1
0
mirror of https://github.com/svg/svgo.git synced 2025-07-29 20:21:14 +03:00

lib/svgo: global API refactoring (close #37); temporarily remove PhantomJS and --test (close #38)

This commit is contained in:
deepsweet
2012-11-09 18:54:00 +02:00
parent 172b7ea296
commit 1b296adc7e
11 changed files with 223 additions and 232 deletions

26
examples/fromFile.js Normal file
View File

@ -0,0 +1,26 @@
var SVGO = require('../lib/svgo'),
svgo = new SVGO(/*{ custom config object }*/);
svgo
// optimize SVG file
.fromFile('../examples/test.svg')
// get optimized result
.then(function(min) {
console.log(min);
// output:
// {
// // optimized SVG data string
// data: '<svg width="10" height="20">test</svg>'
// // additional info such as width/height and start/end bytes length
// info: {
// width: '10',
// height: '20',
// startBytes: 59,
// endBytes: 38
// }
// }
})
// end promises chain
.done();

31
examples/fromStream.js Normal file
View File

@ -0,0 +1,31 @@
var FS = require('fs'),
PATH = require('path'),
path = PATH.resolve(__dirname, '../examples/test.svg'),
fileStream = FS.createReadStream(path, { encoding: 'utf8' });
var SVGO = require('../lib/svgo'),
svgo = new SVGO(/*{ custom config object }*/);
svgo
// optimize stream
.fromStream(fileStream)
// get optimized result
.then(function(min) {
console.log(min);
// output:
// {
// // optimized SVG data string
// data: '<svg width="10" height="20">test</svg>'
// // additional info such as width/height and start/end bytes length
// info: {
// width: '10',
// height: '20',
// startBytes: 59,
// endBytes: 38
// }
// }
})
// end promises chain
.done();

26
examples/fromString.js Normal file
View File

@ -0,0 +1,26 @@
var SVGO = require('../lib/svgo'),
svgo = new SVGO(/*{ custom config object }*/);
svgo
// optimize SVG data string
.fromString('<svg version="1.1" width="10" height="20">test</svg>')
// get optimized result
.then(function(min) {
console.log(min);
// output:
// {
// // optimized SVG data string
// data: '<svg width="10" height="20">test</svg>'
// // additional info such as width/height and start/end bytes length
// info: {
// width: '10',
// height: '20',
// startBytes: 52,
// endBytes: 38
// }
// }
})
// end promises chain
.done();

3
examples/test.svg Normal file
View File

@ -0,0 +1,3 @@
<svg version="1.1" width="10" height="20">
test
</svg>

After

Width:  |  Height:  |  Size: 59 B

View File

@ -11,10 +11,14 @@
*/
var INHERIT = require('inherit'),
Q = require('q'),
FS = require('fs'),
PATH = require('path'),
CONFIG = require('./svgo/config'),
SVG2JS = require('./svgo/svg2js'),
PLUGINS = require('./svgo/plugins'),
JS2SVG = require('./svgo/js2svg');
JS2SVG = require('./svgo/js2svg'),
decodeSVGDatauri = require('./svgo/tools').decodeSVGDatauri;
/**
* @class SVGO.
@ -34,27 +38,61 @@ module.exports = INHERIT(/** @lends SVGO.prototype */{
},
/**
* Main optimize function.
*
* @param {String} svgdata input data
*
* @return {String} output data deferred promise
*/
optimize: function(svgdata) {
fromString: function(str) {
str = decodeSVGDatauri(str);
return this.config
.then(function(config) {
return SVG2JS(svgdata, config.svg2js)
return SVG2JS(str, config.svg2js)
.then(function(jsdata) {
return JS2SVG(PLUGINS(jsdata, config.plugins), config.js2svg);
var out = JS2SVG(PLUGINS(jsdata, config.plugins), config.js2svg);
out.info.startBytes = Buffer.byteLength(str, 'utf-8');
out.info.endBytes = Buffer.byteLength(out.data, 'utf-8');
return out;
});
});
},
fromStream: function(stream) {
var deferred = Q.defer(),
inputData = [],
self = this;
stream.pause();
stream
.on('data', function(chunk) {
inputData.push(chunk);
})
.once('end', function() {
deferred.resolve(inputData.join());
})
.resume();
return deferred.promise
.then(function(str) {
return self.fromString(str);
});
},
fromFile: function(path) {
path = PATH.resolve(__dirname, path);
return this.fromStream(FS.createReadStream(path, { encoding: 'utf8' }));
}
});

View File

@ -1,9 +1,8 @@
var Q = require('q'),
FS = require('fs'),
var FS = require('fs'),
UTIL = require('util'),
SVGO = require('../svgo'),
info = JSON.parse(require('fs').readFileSync(__dirname + '/../../package.json')),
datauriPrefix = 'data:image/svg+xml;base64,';
encodeSVGDatauri = require('./tools').encodeSVGDatauri;
/**
* Command-Option-Argument.
@ -26,17 +25,19 @@ module.exports = require('coa').Cmd()
})
.end()
.opt()
.name('input').title('Input: stdin (default) | filename | Data URI base64 string')
.name('input').title('Input file, "-" for STDIN')
.short('i').long('input')
.def(process.stdin)
.val(function(val) {
return val || this.reject('Option --input must have a value.');
})
.end()
.opt()
.name('output').title('Output: stdout (default) | filename')
.name('string').title('Input SVG data string')
.short('s').long('string')
.end()
.opt()
.name('output').title('Output file (by default the same as the input), "-" for STDOUT')
.short('o').long('output')
.def(process.stdout)
.val(function(val) {
return val || this.reject('Option --output must have a value.');
})
@ -74,11 +75,6 @@ module.exports = require('coa').Cmd()
.long('pretty')
.flag()
.end()
.opt()
.name('test').title('Make a visual comparison of two files (PhantomJS pre-required)')
.long('test')
.flag()
.end()
.arg()
.name('input').title('Alias to --input')
.end()
@ -89,84 +85,64 @@ module.exports = require('coa').Cmd()
var input = args && args.input ? args.input : opts.input,
output = args && args.output ? args.output : opts.output,
inputData = [],
deferred = Q.defer(),
string = opts.string,
startTime = Date.now(),
endTime,
startBytes,
endBytes;
svgo;
// https://github.com/joyent/node/issues/2130
process.stdin.pause();
if (
(!input || input === '-') &&
!string &&
!opts.stdin &&
process.stdin.isTTY
) return this.usage();
// if value is a string and not a Data URI string
if (typeof input === 'string' && !isDatauri(input)) {
// then create stream
input = FS.createReadStream(input, { encoding: 'utf8' });
input.pause();
// --string
if (string) {
svgo = new SVGO({ coa: opts }).fromString(string);
}
// if run as just 'svgo' display help and exit
if (input.isTTY) return this.usage();
// datauri base64 string
if (typeof input === 'string') {
deferred.resolve(convertDatauriInput(input));
// stdin or file stream
} else {
input
.on('data', function(chunk) {
inputData.push(chunk);
})
.once('end', function() {
deferred.resolve(convertDatauriInput(inputData.join()));
})
.resume();
// STDIN
else if (input === '-') {
svgo = new SVGO({ coa: opts }).fromStream(process.stdin);
}
return deferred.promise
.then(function(svg) {
startBytes = Buffer.byteLength(svg, 'utf-8');
// file
else if (input) {
svgo = new SVGO({ coa: opts }).fromFile(input);
}
return new SVGO({ coa: opts }).optimize(svg);
})
.then(function(svgmin) {
endTime = Date.now();
endBytes = Buffer.byteLength(svgmin.data, 'utf-8');
return svgo.then(function(svgmin) {
// --datauri
if (opts.datauri) {
// convert to Data URI base64 string
svgmin.data = datauriPrefix + new Buffer(svgmin.data).toString('base64');
svgmin.data = encodeSVGDatauri(svgmin.data);
}
if (typeof output === 'string') {
// stdout
if (output === '-' || (input === '-' && !output)) {
process.stdout.write(svgmin.data + '\n');
}
// file
else {
// if input is from file - overwrite it
if (!output && input) {
output = input;
}
// output file
output = FS.createWriteStream(output, { encoding: 'utf8' });
}
output.write(svgmin.data);
if (output === process.stdout) {
output.write('\n');
} else {
output.end();
// print time info
printTimeInfo(startTime, endTime);
printTimeInfo(startTime, Date.now());
// print optimization profit info
printProfitInfo(startBytes, endBytes);
printProfitInfo(svgmin.info.startBytes, svgmin.info.endBytes);
// --test
if (opts.test) {
// make a visual comparison of two files with PhantomJS and print info
printPhantomTestInfo(
input.path,
output.path,
svgmin.info.width || 500,
svgmin.info.height || 500
);
}
}
})
@ -174,38 +150,6 @@ module.exports = require('coa').Cmd()
});
/**
* Check if string is a Data URI base64.
*
* @param {String} str input string
*
* @return {Boolean}
*/
function isDatauri(str) {
return str.substring(0, 26) === datauriPrefix;
}
/**
* Convert Data URI base64 string to plain SVG.
*
* @param {String} str input string
*
* @return {String} output string
*/
function convertDatauriInput(str) {
// if datauri base64 string
if (isDatauri(str)) {
// then convert
str = new Buffer(str.substring(26), 'base64').toString('utf8');
}
return str;
}
/**
* Print time info.
*
@ -235,40 +179,3 @@ function printProfitInfo(inBytes, outBytes) {
);
}
/**
* Make a visual comparison of two files with PhantomJS and print info.
*
* @param {String} file1 file1 path
* @param {String} file2 file2 path
* @param {Number} width width
* @param {Number} height height
*/
function printPhantomTestInfo(file1, file2, width, height) {
var PHANTOM = require('./phantom');
UTIL.print('Visual comparison: ');
PHANTOM.test(file1, file2, width, height)
.then(function(code) {
var answer;
if (code === 1) {
answer = 'OK';
} else if (code === 2) {
answer = 'Oops, files are not visually identical!\n\nIf you do not see any visual differences with your eyes then ALL IS OK and there are only very minor floating-point numbers rounding errors in some browsers.\nBut if you see significant errors then things are bad :), please create an issue at https://github.com/svg/svgo/issues';
} else if (code === 3) {
answer = 'Error while rendering SVG\nPlease create an issue at https://github.com/svg/svgo/issues';
} else if (code === 127) {
answer = 'Error, you need to install PhantomJS first http://phantomjs.org/download.html';
} else {
answer = 'Error, something went wrong\nPlease create an issue at https://github.com/svg/svgo/issues';
}
UTIL.print(answer + '\n\n');
});
}

View File

@ -1,30 +0,0 @@
var PATH = require('path'),
Q = require('Q'),
spawn = require('child_process').spawn;
/**
* Two SVG files rendering and visually comparing with PhantomJS.
*
* @see http://phantomjs.org/
* @see /lib/phantom_test.js
*
* @param {String} file1 file1
* @param {String} file2 file2
* @param {Number} width viewport width
* @param {Number} height viewport height
*
* @return {Object} deferred promise with exit code
*/
exports.test = function(file1, file2, width, height) {
var phantomTestFile = PATH.resolve(__dirname, './phantom_test.js'),
phantom = spawn('phantomjs', [phantomTestFile, file1, file2, width, height]),
deferred = Q.defer();
phantom.on('exit', function(code) {
deferred.resolve(code);
});
return deferred.promise;
};

View File

@ -1,40 +0,0 @@
/**
* Two SVG files rendering and visually comparing with PhantomJS.
*
* @see http://phantomjs.org/
* @see https://github.com/ariya/phantomjs/wiki/Screen-Capture
*/
var page = require('webpage').create(),
file1 = phantom.args[0],
file2 = phantom.args[1],
width = phantom.args[2],
height = phantom.args[3];
page.viewportSize = {
width: width,
height: height
};
open(file1, function(out1) {
open(file2, function(out2) {
if (out1.length === out2.length && out1 === out2) {
phantom.exit(1);
} else {
phantom.exit(2);
}
});
});
function open(file, callback) {
page.open(file, function(status) {
if (status !== 'success') {
phantom.exit(3);
} else {
callback(page.renderBase64('PNG'));
}
});
}

View File

@ -8,12 +8,12 @@ var UTIL = require('util'),
*
* @module svg2js
*
* @param {String} svgdata input data
* @param {String} svg input data
* @param {Object} config sax xml parser config
*
* @return {Object} output data deferred promise
*/
module.exports = function(svgdata, config) {
module.exports = function(svg, config) {
var deferred = Q.defer(),
sax = SAX.parser(config.strict, config),
@ -119,7 +119,7 @@ module.exports = function(svgdata, config) {
};
sax.write(svgdata).close();
sax.write(svg).close();
return deferred.promise;

View File

@ -1,3 +1,33 @@
var datauriSVGPrefix = exports.datauriSVGPrefix = 'data:image/svg+xml;base64,';
/**
* Encode plain SVG data string into Data URI base64 string.
*
* @param {String} str input string
*
* @return {String} output string
*/
exports.encodeSVGDatauri = function(str) {
return datauriSVGPrefix + new Buffer(str).toString('base64');
};
/**
* Decode SVG Data URI base64 string into plain SVG data string.
*
* @param {string} str input string
*
* @return {String} output string
*/
exports.decodeSVGDatauri = function(str) {
if (str.substring(0, 26) !== datauriSVGPrefix) return str;
return new Buffer(str.substring(26), 'base64').toString('utf8');
};
exports.extend = require('node.extend');
exports.flattenOneLevel = function(array) {

View File

@ -66,7 +66,7 @@ function getResult(name, index) {
.then(function(input) {
mySVGO.enableOnlyOne(name);
return mySVGO.optimize(input.toString());
return mySVGO.fromString(input.toString());
})
.then(function(min) {
return readFile(name + '.' + index +'.should.svg')