diff --git a/.editorconfig b/.editorconfig new file mode 100644 index 0000000..a8c0f1e --- /dev/null +++ b/.editorconfig @@ -0,0 +1,7 @@ +root = true + +[*] +charset = utf-8 +indent_style = space +indent_size = 2 +end_of_line = lf \ No newline at end of file diff --git a/CHANGELOG.md b/CHANGELOG.md index a86c83a..657a9f8 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,4 +1,6 @@ # Change Log + + - Add `min` and `max` options to automatically generate a number of images, and `steps` option to say how many images ([#31](herrstucki/responsive-loader/pull/31)). ## v1.0.0 diff --git a/README.md b/README.md index 8d3cfa5..87eeff2 100644 --- a/README.md +++ b/README.md @@ -113,6 +113,9 @@ ReactDOM.render( - `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 the loader options 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) +- `min: integer` - as an alternative to manually specifying `sizes`, you can specify `min`, `max` and `steps`, and the sizes will be generated for you. +- `max: integer` - see `min` above +- `steps: integer` - configure the number of images generated between `min` and `max` (inclusive). Defaults to 4. - `quality: integer` — JPEG compression quality; defaults to `85` - `format: string` — either `png` or `jpg`; use to convert to another format; default format is inferred from the source file's extension - `placeholder: boolean` — A true or false value to specify wether to output a placeholder image as a data URI; defaults to `false` diff --git a/src/index.js b/src/index.js index e840428..58dc5ec 100644 --- a/src/index.js +++ b/src/index.js @@ -17,6 +17,9 @@ const EXTS = { type Config = { size: string | number | void, sizes: [string | number] | void, + min: string | number | void, + max: string | number | void, + steps: string | number | void, name: string | void, context: string | void, placeholderSize: string | number | void, @@ -32,7 +35,6 @@ module.exports = function loader(content: Buffer) { const loaderCallback = this.async(); const parsedResourceQuery = this.resourceQuery ? loaderUtils.parseQuery(this.resourceQuery) : {}; const config: Config = Object.assign({}, loaderUtils.getOptions(this), parsedResourceQuery); - const sizes = config.size || config.sizes || [Number.MAX_SAFE_INTEGER]; const outputContext: string = config.context || ''; const outputPlaceholder: boolean = Boolean(config.placeholder) || false; const placeholderSize: number = parseInt(config.placeholderSize, 10) || 40; @@ -68,6 +70,22 @@ module.exports = function loader(content: Buffer) { background }); + const min: number | void = config.min !== undefined ? Number(config.min) : undefined; + const max: number | void = config.max !== undefined ? Number(config.max) : undefined; + const steps: number = config.steps === undefined ? 4 : Number(config.steps); + + let generatedSizes; + if (typeof min === 'number' && max) { + generatedSizes = []; + + for (let step = 0; step < steps; step++) { + const size = min + (max - min) / (steps - 1) * step; + generatedSizes.push(Math.ceil(size)); + } + } + + const sizes = parsedResourceQuery.sizes || generatedSizes || config.size || config.sizes || [Number.MAX_SAFE_INTEGER]; + if (!sizes) { return loaderCallback(null, content); } diff --git a/test/jimp/build/__snapshots__/test.js.snap b/test/jimp/build/__snapshots__/test.js.snap index a4f0f0b..e3fb976 100644 --- a/test/jimp/build/__snapshots__/test.js.snap +++ b/test/jimp/build/__snapshots__/test.js.snap @@ -171,6 +171,67 @@ Object { } `; +exports[`with min and max sizes 1`] = ` +Object { + "height": 540, + "images": Array [ + Object { + "height": 540, + "path": "foobar/52dba34908ff9d9ed720ad3c51e5b651-600.jpg", + "width": 600, + }, + Object { + "height": 630, + "path": "foobar/86240606919a79fc3de5a7dbe5a97d87-700.jpg", + "width": 700, + }, + Object { + "height": 720, + "path": "foobar/f794cdac765d222d40585d283c49bddc-800.jpg", + "width": 800, + }, + ], + "placeholder": undefined, + "src": "foobar/52dba34908ff9d9ed720ad3c51e5b651-600.jpg", + "srcSet": "foobar/52dba34908ff9d9ed720ad3c51e5b651-600.jpg 600w,foobar/86240606919a79fc3de5a7dbe5a97d87-700.jpg 700w,foobar/f794cdac765d222d40585d283c49bddc-800.jpg 800w", + "toString": [Function], + "width": 600, +} +`; + +exports[`with min and max sizes, and default steps 1`] = ` +Object { + "height": 450, + "images": Array [ + Object { + "height": 450, + "path": "foobar/8b1d7d4d688417adcd8603807f44314e-500.jpg", + "width": 500, + }, + Object { + "height": 600, + "path": "foobar/24b8e1d900d0f26e0ac60c406f85c0ce-667.jpg", + "width": 667, + }, + Object { + "height": 751, + "path": "foobar/63dc049fe958369666cc1793fca64800-834.jpg", + "width": 834, + }, + Object { + "height": 900, + "path": "foobar/654f812ac2833fdf5dae880cceefa8c6-1000.jpg", + "width": 1000, + }, + ], + "placeholder": undefined, + "src": "foobar/8b1d7d4d688417adcd8603807f44314e-500.jpg", + "srcSet": "foobar/8b1d7d4d688417adcd8603807f44314e-500.jpg 500w,foobar/24b8e1d900d0f26e0ac60c406f85c0ce-667.jpg 667w,foobar/63dc049fe958369666cc1793fca64800-834.jpg 834w,foobar/654f812ac2833fdf5dae880cceefa8c6-1000.jpg 1000w", + "toString": [Function], + "width": 500, +} +`; + exports[`with placeholder image 1`] = ` Object { "height": 450, diff --git a/test/jimp/index.js b/test/jimp/index.js index 29850a9..3a9bfa0 100644 --- a/test/jimp/index.js +++ b/test/jimp/index.js @@ -48,3 +48,13 @@ test('png to jpeg with background color', () => { const output = require('../cat-transparent.png?background=0xFF0000FF&format=jpg'); expect(output).toMatchSnapshot(); }); + +test('with min and max sizes', () => { + const output = require('../cat-1000.jpg?min=600&max=800&steps=3'); + expect(output).toMatchSnapshot(); +}); + +test('with min and max sizes, and default steps', () => { + const output = require('../cat-1000.jpg?min=500&max=1000'); + expect(output).toMatchSnapshot(); +}); \ No newline at end of file diff --git a/test/sharp/build/__snapshots__/test.js.snap b/test/sharp/build/__snapshots__/test.js.snap index 6bf09cc..1a8d58d 100644 --- a/test/sharp/build/__snapshots__/test.js.snap +++ b/test/sharp/build/__snapshots__/test.js.snap @@ -148,6 +148,67 @@ Object { } `; +exports[`with min and max sizes 1`] = ` +Object { + "height": 540, + "images": Array [ + Object { + "height": 540, + "path": "foobar/2af17e12f0375a11dd41544eb39e7d1d-600.jpg", + "width": 600, + }, + Object { + "height": 630, + "path": "foobar/bf06fb2a494b7477a73c7ec05625c3bc-700.jpg", + "width": 700, + }, + Object { + "height": 720, + "path": "foobar/bf55049b4b942dfd0388b7396cea413f-800.jpg", + "width": 800, + }, + ], + "placeholder": undefined, + "src": "foobar/2af17e12f0375a11dd41544eb39e7d1d-600.jpg", + "srcSet": "foobar/2af17e12f0375a11dd41544eb39e7d1d-600.jpg 600w,foobar/bf06fb2a494b7477a73c7ec05625c3bc-700.jpg 700w,foobar/bf55049b4b942dfd0388b7396cea413f-800.jpg 800w", + "toString": [Function], + "width": 600, +} +`; + +exports[`with min and max sizes, and default steps 1`] = ` +Object { + "height": 450, + "images": Array [ + Object { + "height": 450, + "path": "foobar/953a024b44e6d2a7ea721eb06626b913-500.jpg", + "width": 500, + }, + Object { + "height": 600, + "path": "foobar/b0ed6bbd99877351fa6186d69e6691db-667.jpg", + "width": 667, + }, + Object { + "height": 751, + "path": "foobar/afc0583941b419b2f3d725572ec58c5c-834.jpg", + "width": 834, + }, + Object { + "height": 900, + "path": "foobar/c0e86e74879bf9156e7b1e92b38f293c-1000.jpg", + "width": 1000, + }, + ], + "placeholder": undefined, + "src": "foobar/953a024b44e6d2a7ea721eb06626b913-500.jpg", + "srcSet": "foobar/953a024b44e6d2a7ea721eb06626b913-500.jpg 500w,foobar/b0ed6bbd99877351fa6186d69e6691db-667.jpg 667w,foobar/afc0583941b419b2f3d725572ec58c5c-834.jpg 834w,foobar/c0e86e74879bf9156e7b1e92b38f293c-1000.jpg 1000w", + "toString": [Function], + "width": 500, +} +`; + exports[`with placeholder image 1`] = ` Object { "height": 450, diff --git a/test/sharp/index.js b/test/sharp/index.js index 7e32072..2cb9462 100644 --- a/test/sharp/index.js +++ b/test/sharp/index.js @@ -43,3 +43,13 @@ test('png to jpeg with background color', () => { const output = require('../cat-transparent.png?background=#FF0000&format=jpg'); expect(output).toMatchSnapshot(); }); + +test('with min and max sizes', () => { + const output = require('../cat-1000.jpg?min=600&max=800&steps=3'); + expect(output).toMatchSnapshot(); +}); + +test('with min and max sizes, and default steps', () => { + const output = require('../cat-1000.jpg?min=500&max=1000'); + expect(output).toMatchSnapshot(); +}); \ No newline at end of file