Skip to content

Commit

Permalink
Add option for default sizes & setting output context (#12)
Browse files Browse the repository at this point in the history
Ability to declare a default Sizes array in webpack.config.js, and uses those sizes in case neither sizes nor size are declared in the query.

Default name, context, quality, and background options can now also be defined.

Additionally this interprets the context variable, if present in the query or settings.
This allows flexibility when outputting files.
  • Loading branch information
alex-ketch authored and jstcki committed Aug 20, 2016
1 parent abbf2c8 commit 9497ba7
Show file tree
Hide file tree
Showing 4 changed files with 51 additions and 7 deletions.
23 changes: 22 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,33 @@ Or use it in CSS (only the first resized image will be used, if you use multiple

### Options

- `sizes: array`: specify all widths you want to use; if a specified size exceeds the original image's width, the latter will be used (i.e. images won't be scaled up)
- `sizes: array`: specify all widths you want to use; if a specified size exceeds the original image's width, the latter will be used (i.e. images won't be scaled up). You may also declare a default `sizes` array in `responsiveLoader` in your `webpack.config.js`.
- `size: integer`: specify one width you want to use; if the specified size exceeds the original image's width, the latter will be used (i.e. images won't be scaled up)
- `quality: integer`: JPEG compression quality; defaults to `95`
- `ext: string`: either `png`, `jpg`, or `gif`; use to convert to another format; defaults to original file's extension
- `background: hex`: Background fill when converting transparent to opaque images; defaults to `0xFFFFFFFF` (note: make sure this is a valid hex number)


### Examples

Set a default `sizes` array, so you don't have to declare them with each `require`.

```js
module.exports = {
entry: {...},
output: {...},
module: {
loaders: [{
test: /\.(jpe?g|png)$/i,
loader: 'responsive'
]}
},
responsiveLoader: {
sizes: [300, 600, 1200, 2000]
}
}
```

## Notes

- Doesn't support `1x`, `2x` sizes.
Expand Down
16 changes: 10 additions & 6 deletions index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,13 @@ module.exports = function loader(content) {
const loaderCallback = this.async();
const query = loaderUtils.parseQuery(this.query);
const options = this.options.responsiveLoader || {};
const sizes = query.sizes || query.size || [Number.MAX_SAFE_INTEGER];
const name = query.name || '[hash]-[width].';
const sizes = query.sizes || query.size || options.sizes || [Number.MAX_SAFE_INTEGER];
const name = query.name || options.name || '[hash]-[width].';
const outputContext = query.context || options.context || '';
// JPEG compression
const quality = parseInt(query.quality, 10) || 95;
const quality = parseInt(query.quality, 10) || options.quality || 95;
// Useful when converting from PNG to JPG
const background = parseInt(query.background, 16) || 0xFFFFFFFF;
const background = parseInt(query.background, 16) || options.background || 0xFFFFFFFF;
// Specify ext to convert to another format
const ext = query.ext || path.extname(this.resourcePath).replace(/\./, '');
const mime = MIMES[ext];
Expand All @@ -35,7 +36,7 @@ module.exports = function loader(content) {

if (options.pass) {
// emit original content only
const f = loaderUtils.interpolateName(loaderContext, '[hash].[ext]', {content: content});
const f = loaderUtils.interpolateName(loaderContext, '[hash].[ext]', {context: outputContext, content: content});
loaderContext.emitFile(f, content);
const p = '__webpack_public_path__ + ' + JSON.stringify(f);
return loaderCallback(null, 'module.exports = {srcSet:' + p + ',images:[{path:' + p + ',width:1}],src: ' + p + ',toString:function(){return ' + p + '}};');
Expand All @@ -57,7 +58,10 @@ module.exports = function loader(content) {
return queueCallback(queueErr);
}

const fileName = loaderUtils.interpolateName(loaderContext, name + ext, {content: buf}).replace(/\[width\]/ig, width);
const fileName = loaderUtils.interpolateName(loaderContext, name + ext, {
context: outputContext,
content: buf
}).replace(/\[width\]/ig, width);

loaderContext.emitFile(fileName, buf);

Expand Down
16 changes: 16 additions & 0 deletions test/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,3 +15,19 @@ test('single size', t => {
t.equal('foobar/ac8fbe83765514062b5da3b8966cd475-500.jpg', single.toString());
t.end();
});

test('with size defined in webpack.config.js', t => {
const multi = require('../index!./cat-1000.jpg');
t.equal('foobar/ac8fbe83765514062b5da3b8966cd475-500.jpg 500w,foobar/16c2a62d860f67276d750a7777ec932e-750.jpg 750w,foobar/6582e69db43187e14b01fa76c021cf71-1000.jpg 1000w', multi.srcSet);
t.equal('foobar/ac8fbe83765514062b5da3b8966cd475-500.jpg', multi.src);
t.equal('foobar/ac8fbe83765514062b5da3b8966cd475-500.jpg', multi.toString());
t.end();
});

test('output should be relative to context', t => {
const multi = require('../index?name=[path][hash]-[width].&context=./!./cat-1000.jpg');
t.equal('foobar/test/ac8fbe83765514062b5da3b8966cd475-500.jpg 500w,foobar/test/16c2a62d860f67276d750a7777ec932e-750.jpg 750w,foobar/test/6582e69db43187e14b01fa76c021cf71-1000.jpg 1000w', multi.srcSet);
t.equal('foobar/test/ac8fbe83765514062b5da3b8966cd475-500.jpg', multi.src);
t.equal('foobar/test/ac8fbe83765514062b5da3b8966cd475-500.jpg', multi.toString());
t.end();
});
3 changes: 3 additions & 0 deletions test/webpack.config.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@ const path = require('path');

module.exports = {
entry: path.resolve(__dirname, 'index'),
responsiveLoader: {
sizes: [500, 750, 1000]
},
output: {
path: path.resolve(__dirname, 'build'),
publicPath: 'foobar/',
Expand Down

0 comments on commit 9497ba7

Please sign in to comment.