-
-
Notifications
You must be signed in to change notification settings - Fork 8.8k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
refactor(v2): import lqip-loader, fix build on Node 13
- Loading branch information
Showing
9 changed files
with
344 additions
and
41 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,89 @@ | ||
## lqip-loader: low quality images placeholders for webpack | ||
|
||
### Installation | ||
|
||
``` | ||
npm install --save-dev @docusaurus/lqip-loader | ||
``` | ||
|
||
### Example | ||
|
||
Generating Base64 & dominant colours palette for a jpeg image imported in your JS bundle: | ||
|
||
> The large image file will be emitted & only 400byte of Base64 (if set to true in the loader options) will be bundled. | ||
`webpack.config.js` | ||
|
||
```json | ||
{ | ||
/** | ||
* OPTION A: | ||
* default file-loader fallback | ||
**/ | ||
test: /\.jpe?g$/, | ||
loaders: [ | ||
{ | ||
loader: '@docusaurus/lqip-loader', | ||
options: { | ||
path: '/media', // your image going to be in media folder in the output dir | ||
name: '[name].[ext]', // you can use [hash].[ext] too if you wish, | ||
base64: true, // default: true, gives the base64 encoded image | ||
palette: true // default: false, gives the dominant colours palette | ||
} | ||
} | ||
] | ||
|
||
/** | ||
* OPTION B: | ||
* Chained with your own url-loader or file-loader | ||
**/ | ||
test: /\.(png|jpe?g)$/, | ||
loaders: [ | ||
{ | ||
loader: '@docusaurus/lqip-loader', | ||
options: { | ||
base64: true, | ||
palette: false | ||
} | ||
}, | ||
{ | ||
loader: 'url-loader', | ||
options: { | ||
limit: 8000 | ||
} | ||
} | ||
] | ||
} | ||
``` | ||
|
||
`your-app-module.js` | ||
|
||
```js | ||
import banner from './images/banner.jpg'; | ||
|
||
console.log(banner.preSrc); | ||
// outputs: "data:image/jpeg;base64,/9j/2wBDAAYEBQYFBAYGBQYHBwYIChAKCgkJChQODwwQFxQYGBcUFhY.... | ||
|
||
// the object will have palette property, array will be sorted from most dominant colour to the least | ||
console.log(banner.palette); // [ '#628792', '#bed4d5', '#5d4340', '#ba454d', '#c5dce4', '#551f24' ] | ||
|
||
console.log(banner.src); // that's the original image URL to load later! | ||
``` | ||
|
||
### Important note | ||
|
||
To save memory and improve GPU performance, browsers (including Chrome started from 61.0.3163.38) will now render a slightly more crisp or pixelated Base64 encoded images. If you want the blur to be very intense (smooth), here's a fix! | ||
|
||
```css | ||
img { | ||
filter: blur(25px); | ||
} | ||
``` | ||
|
||
More history about the issue can be [found here](https://bugs.chromium.org/p/chromium/issues/detail?id=771110#c3) and [here](https://groups.google.com/a/chromium.org/forum/#!topic/blink-dev/6L_3ZZeuA0M). | ||
|
||
Alternatively, you can fill the container with a really cheap colour or gradient from the amazing palette we provide. | ||
|
||
### Credits | ||
|
||
This package has been imported from [`@endiliey/lqip-loader`](https://github.com/endiliey/lqip-loader) which was a fork of original [`lqip-loader`](https://github.com/zouhir/lqip-loader) created exclusively for Docusaurus. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,22 @@ | ||
{ | ||
"name": "@docusaurus/lqip-loader", | ||
"version": "2.0.0-alpha.50", | ||
"description": "Low Quality Image Placeholders (LQIP) loader for webpack", | ||
"main": "src/index.js", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"license": "MIT", | ||
"dependencies": { | ||
"loader-utils": "^1.2.3", | ||
"lodash.sortby": "^4.7.0", | ||
"node-vibrant": "^3.1.5" | ||
}, | ||
"peerDependencies": { | ||
"file-loader": "*", | ||
"sharp": "*" | ||
}, | ||
"engines": { | ||
"node": ">=10.9.0" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
const loaderUtils = require('loader-utils'); | ||
const lqip = require('./lqip'); | ||
|
||
module.exports = function (contentBuffer) { | ||
if (this.cacheable) { | ||
this.cacheable(); | ||
} | ||
const callback = this.async(); | ||
const imgPath = this.resourcePath; | ||
|
||
const config = loaderUtils.getOptions(this) || {}; | ||
config.base64 = 'base64' in config ? config.base64 : true; | ||
config.palette = 'palette' in config ? config.palette : false; | ||
|
||
let content = contentBuffer.toString('utf8'); | ||
const contentIsUrlExport = /^module.exports = "data:(.*)base64,(.*)/.test( | ||
content, | ||
); | ||
const contentIsFileExport = /^module.exports = (.*)/.test(content); | ||
|
||
let source = ''; | ||
const SOURCE_CHUNK = 1; | ||
|
||
if (contentIsUrlExport) { | ||
source = content.match(/^module.exports = (.*)/)[SOURCE_CHUNK]; | ||
} else { | ||
if (!contentIsFileExport) { | ||
// eslint-disable-next-line global-require | ||
const fileLoader = require('file-loader'); | ||
content = fileLoader.call(this, contentBuffer); | ||
} | ||
source = content.match(/^module.exports = (.*);/)[SOURCE_CHUNK]; | ||
} | ||
|
||
const outputPromises = []; | ||
|
||
if (config.base64 === true) { | ||
outputPromises.push(lqip.base64(imgPath)); | ||
} else { | ||
outputPromises.push(null); | ||
} | ||
|
||
// color palette generation is set to false by default | ||
// since it is little bit slower than base64 generation | ||
|
||
if (config.palette === true) { | ||
outputPromises.push(lqip.palette(imgPath)); | ||
} else { | ||
outputPromises.push(null); | ||
} | ||
|
||
Promise.all(outputPromises) | ||
.then((data) => { | ||
if (data) { | ||
const [preSrc, palette] = data; | ||
const param1 = preSrc ? `, "preSrc": ${JSON.stringify(preSrc)}` : ''; | ||
const param2 = palette ? `, "palette": ${JSON.stringify(palette)}` : ''; | ||
const result = `module.exports = {"src":${source}${param1}${param2}};`; | ||
callback(null, result); | ||
} else { | ||
callback('ERROR', null); | ||
} | ||
}) | ||
.catch((error) => { | ||
console.error(error); | ||
callback(error, null); | ||
}); | ||
}; | ||
|
||
module.exports.raw = true; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,75 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
const Vibrant = require('node-vibrant'); | ||
const path = require('path'); | ||
const sharp = require('sharp'); | ||
|
||
const {version} = require('../package.json'); | ||
const {toPalette, toBase64} = require('./utils'); | ||
|
||
const ERROR_EXT = `Error: Input file is missing or uses unsupported image format, lqip v${version}`; | ||
|
||
const SUPPORTED_MIMES = { | ||
jpeg: 'image/jpeg', | ||
jpg: 'image/jpeg', | ||
png: 'image/png', | ||
}; | ||
|
||
const base64 = (file) => { | ||
return new Promise((resolve, reject) => { | ||
let extension = path.extname(file) || ''; | ||
extension = extension.split('.').pop(); | ||
|
||
if (!SUPPORTED_MIMES[extension]) { | ||
return reject(ERROR_EXT); | ||
} | ||
|
||
return sharp(file) | ||
.resize(10) | ||
.toBuffer() | ||
.then((data) => { | ||
if (data) { | ||
return resolve(toBase64(SUPPORTED_MIMES[extension], data)); | ||
} | ||
return reject( | ||
new Error('Unhandled promise rejection in base64 promise'), | ||
); | ||
}) | ||
.catch((err) => { | ||
return reject(err); | ||
}); | ||
}); | ||
}; | ||
|
||
const palette = (file) => { | ||
return new Promise((resolve, reject) => { | ||
const vibrant = new Vibrant(file, {}); | ||
vibrant | ||
.getPalette() | ||
.then((pal) => { | ||
if (pal) { | ||
return resolve(toPalette(pal)); | ||
} | ||
return reject( | ||
new Error('Unhandled promise rejection in colorPalette', pal), | ||
); | ||
}) | ||
.catch((err) => { | ||
return reject(err); | ||
}); | ||
}); | ||
}; | ||
|
||
process.on('unhandledRejection', (up) => { | ||
throw up; | ||
}); | ||
|
||
module.exports = { | ||
base64, | ||
palette, | ||
}; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,49 @@ | ||
/** | ||
* Copyright (c) Facebook, Inc. and its affiliates. | ||
* | ||
* This source code is licensed under the MIT license found in the | ||
* LICENSE file in the root directory of this source tree. | ||
*/ | ||
|
||
const sortBy = require('lodash.sortby'); | ||
|
||
/** | ||
* toBase64 | ||
* @description it returns a Base64 image string with required formatting | ||
* to work on the web (<img src=".." /> or in CSS url('..')) | ||
* | ||
* @param extension: image file extension | ||
* @param data: base64 string | ||
* @returns {string} | ||
*/ | ||
const toBase64 = (extMimeType, data) => { | ||
return `data:${extMimeType};base64,${data.toString('base64')}`; | ||
}; | ||
|
||
/** | ||
* toPalette | ||
* @description takes a color swatch object, converts it to an array & returns | ||
* only hex color | ||
* | ||
* @param swatch | ||
* @returns {{palette: Array}} | ||
*/ | ||
const toPalette = (swatch) => { | ||
let palette = Object.keys(swatch).reduce((result, key) => { | ||
if (swatch[key] !== null) { | ||
result.push({ | ||
popularity: swatch[key].getPopulation(), | ||
hex: swatch[key].getHex(), | ||
}); | ||
} | ||
return result; | ||
}, []); | ||
palette = sortBy(palette, ['popularity']); | ||
palette = palette.map((color) => color.hex).reverse(); | ||
return palette; | ||
}; | ||
|
||
module.exports = { | ||
toBase64, | ||
toPalette, | ||
}; |
Oops, something went wrong.