Skip to content

Commit

Permalink
Add support for streams
Browse files Browse the repository at this point in the history
  • Loading branch information
kevva committed Sep 14, 2017
1 parent fe14c58 commit a89bebb
Show file tree
Hide file tree
Showing 4 changed files with 52 additions and 36 deletions.
50 changes: 29 additions & 21 deletions index.js
Original file line number Diff line number Diff line change
@@ -1,23 +1,23 @@
'use strict';
const execBuffer = require('exec-buffer');
const execa = require('execa');
const isPng = require('is-png');
const isStream = require('is-stream');
const pngquant = require('pngquant-bin');

module.exports = opts => buf => {
module.exports = opts => input => {
opts = Object.assign({}, opts);

if (!Buffer.isBuffer(buf)) {
return Promise.reject(new TypeError('Expected a buffer'));
const isBuffer = Buffer.isBuffer(input);

if (!isBuffer && !isStream(input)) {
return Promise.reject(new TypeError(`Expected a Buffer or Stream, got ${typeof input}`));
}

if (!isPng(buf)) {
return Promise.resolve(buf);
if (isBuffer && !isPng(input)) {
return Promise.resolve(input);
}

const args = [
'--output', execBuffer.output,
execBuffer.input
];
const args = ['-'];

if (opts.floyd && typeof opts.floyd === 'number') {
args.push(`--floyd=${opts.floyd}`);
Expand Down Expand Up @@ -47,16 +47,24 @@ module.exports = opts => buf => {
args.push('--verbose');
}

return execBuffer({
input: buf,
bin: pngquant,
args
}).catch(err => {
if (err.code === 99) {
return buf;
}

err.message = err.stderr || err.message;
throw err;
const cp = execa(pngquant, args, {
encoding: null,
input
});

const promise = cp
.then(res => res.stdout)
.catch(err => {
if (err.code === 99) {
return input;
}

err.message = err.stderr || err.message;
throw err;
});

cp.stdout.then = promise.then.bind(promise);
cp.stdout.catch = promise.catch.bind(promise);

return cp.stdout;
};
5 changes: 3 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -40,13 +40,14 @@
"pngquant"
],
"dependencies": {
"exec-buffer": "^3.0.0",
"execa": "^0.8.0",
"is-png": "^1.0.0",
"is-stream": "^1.1.0",
"pngquant-bin": "^3.0.0"
},
"devDependencies": {
"ava": "*",
"pify": "^3.0.0",
"get-stream": "^3.0.0",
"xo": "*"
}
}
10 changes: 5 additions & 5 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,9 @@ imagemin(['images/*.png'], 'build/images', {use: [imageminPngquant()]}).then(()

## API

### imageminPngquant([options])(buffer)
### imageminPngquant([options])(input)

Returns a promise for a buffer.
Returns a `Promise` for a `Buffer`.

#### options

Expand Down Expand Up @@ -76,11 +76,11 @@ Default: `false`

Print verbose status messages.

#### buffer
#### input

Type: `Buffer`
Type: `Buffer` `Stream`

Buffer to optimize.
Buffer or stream to optimize.


## License
Expand Down
23 changes: 15 additions & 8 deletions test.js
Original file line number Diff line number Diff line change
@@ -1,22 +1,20 @@
import fs from 'fs';
import path from 'path';
import getStream from 'get-stream';
import isPng from 'is-png';
import pify from 'pify';
import test from 'ava';
import m from './';

const fsP = pify(fs);
import m from '.';

test('optimize a PNG', async t => {
const buf = await fsP.readFile(path.join(__dirname, 'fixture.png'));
const buf = await fs.readFileSync(path.join(__dirname, 'fixture.png'));
const data = await m()(buf);

t.true(data.length < buf.length);
t.true(isPng(data));
});

test('support pngquant options', async t => {
const buf = await fsP.readFile(path.join(__dirname, 'fixture.png'));
const buf = await fs.readFileSync(path.join(__dirname, 'fixture.png'));
const data = await m({
speed: 10,
quality: 100
Expand All @@ -26,15 +24,24 @@ test('support pngquant options', async t => {
t.true(isPng(data));
});

test('support streams', async t => {
const buf = await fs.readFileSync(path.join(__dirname, 'fixture.png'));
const stream = fs.createReadStream(path.join(__dirname, 'fixture.png'));
const data = await getStream.buffer(m()(stream));

t.true(data.length < buf.length);
t.true(isPng(data));
});

test('skip optimizing a non-PNG file', async t => {
const buf = await fsP.readFile(__filename);
const buf = await fs.readFileSync(__filename);
const data = await m()(buf);

t.is(data.length, buf.length);
});

test('skip optimizing a fully optimized PNG', async t => {
const buf = await fsP.readFile(path.join(__dirname, 'fixture-no-compress.png'));
const buf = await fs.readFileSync(path.join(__dirname, 'fixture-no-compress.png'));
const data = await m({quality: 100})(buf);
t.is(data.length, buf.length);
t.true(isPng(data));
Expand Down

0 comments on commit a89bebb

Please sign in to comment.