description and source-codefunction TinyPNG(opt, obj) {
var self = this;
this.conf = {
token: null,
options: {
key: '',
sigFile: false,
log: false,
force: false, ignore: false,
sameDest: false,
summarize: false,
parallel: true,
parallelMax: 5
}
};
this.stats = {
total: {
in: 0,
out: 0
},
compressed: 0,
skipped: 0
};
this.init = function(opt) {
if(typeof opt !== 'object') opt = { key: opt };
opt = util._extend(this.conf.options, opt);
if(!opt.key) throw new PluginError(PLUGIN_NAME, 'Missing API key!');
if(!opt.force) opt.force = gutil.env.force || false; // force match glob
if(!opt.ignore) opt.ignore = gutil.env.ignore || false; // ignore match glob
if(opt.summarise) opt.summarize = true; // chin chin, old chap!
this.conf.options = opt; // export opts
this.conf.token = new Buffer('api:' + opt.key).toString('base64'); // prep key
this.hash = new this.hasher(opt.sigFile).populate(); // init hasher class
return this;
};
this.stream = function() {
var self = this,
opt = this.conf.options,
emitted = false;
return (opt.parallel ? throughParallel : through).obj({maxConcurrency: opt.parallelMax}, function(file, enc, cb) {
if(self.utils.glob(file, opt.ignore)) return cb();
if(file.isNull()) {
return cb();
}
if(file.isStream()) {
this.emit('error', new PluginError(PLUGIN_NAME, 'Streams not supported'));
return cb();
}
if(file.isBuffer()) {
var hash = null;
if(opt.sigFile && !self.utils.glob(file, opt.force)) {
var result = self.hash.compare(file);
hash = result.hash;
if(result.match) {
self.utils.log('[skipping] ' + chalk.green('✔ ') + file.relative);
self.stats.skipped++;
return cb();
}
}
self.request(file).get(function(err, tinyFile) {
if(err) {
this.emit('error', new PluginError(PLUGIN_NAME, err));
return cb();
}
self.utils.log('[compressing] ' + chalk.green('✔ ') + file.relative + chalk.gray(' (done)'));
self.stats.compressed++;
self.stats.total.in += file.contents.toString().length;
self.stats.total.out += tinyFile.contents.toString().length;
if(opt.sigFile) {
var curr = {
file: file,
hash: hash
};
if(opt.sameDest) {
curr.file = tinyFile;
curr.hash = self.hash.calc(tinyFile);
}
self.hash.update(curr.file, curr.hash);
}
this.push(tinyFile);
return cb();
}.bind(this)); // maintain stream context
}
})
.on('error', function(err) {
emitted = true; // surely a method in the stream to handle this?
self.stats.skipped++;
self.utils.log(err.message);
})
.on('end', function() {
if(!emitted && opt.sigFile) self.hash.write(); // write sigs after complete
if(opt.summarize) {
var stats = self.stats,
info = util.format('Skipped: %s image%s, Compressed: %s image%s, Savings: %s (ratio: %s)',
stats.skipped,
stats.skipped == 1 ? '' : 's',
stats.compressed,
stats.compressed == ...