Research
Security News
Malicious npm Packages Inject SSH Backdoors via Typosquatted Libraries
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
@elderjs/plugin-images
Advanced tools
Easily generate and manage responsive images for your Elder.js site.
Easily generate responsive images for your Elder.js site or use the underlying code as a library.
The core of this library offers much of the functionality of the well known gatsby-image
plugin for Elder.js. In library mode, it will compress your images and upload them to s3 generating a manifest that is compatible with Elder.js should you wish to use this plugin and allow your users to host their images elsewhere.
demo For a demo of this plugin in action visit: nicholasreese.com and look at the header and post images.
This plugin works on several production sites but may still have rough edges. PRs are welcome.
Dealing with responsive images isn't easy. Often you need to compress in many different sizes, fiddle with picture formats, and figure out lazy loading and browser compatibility.
This plugin aims to simplify this and will take folder of non-responsive images and:
So where you would usually have a non-responsive image of: /images/wide.jpeg
You can now use an Elder.js shortcode {{picture src='/images/wide.jpeg' /}}
which will output (something like):
<picture
><source type="image/webp" media="(min-width: 1200px)" srcset="/images/wide-ejs-1200.webp" />
<source type="image/webp" media="(min-width: 992px)" srcset="/images/wide-ejs-992.webp" />
<source type="image/webp" media="(min-width: 768px)" srcset="/images/wide-ejs-768.webp" />
<source
type="image/webp"
media="(min-width: 576px)"
srcset="/images/wide-ejs-576.webp, /images/wide-ejs-576@2x.webp 2x" />
<source
type="image/webp"
media="(min-width: 400px)"
srcset="/images/wide-ejs-400.webp, /images/wide-ejs-400@2x.webp 2x" />
<source
type="image/webp"
media="(min-width: 350px)"
srcset="/images/wide-ejs-350.webp, /images/wide-ejs-350@2x.webp 2x" />
<source type="image/webp" srcset="/images/wide-ejs-200.webp, /images/wide-ejs-200@2x.webp 2x" />
<source media="(min-width: 1200px)" srcset="/images/wide-ejs-1200.jpeg" />
<source media="(min-width: 992px)" srcset="/images/wide-ejs-992.jpeg" />
<source media="(min-width: 768px)" srcset="/images/wide-ejs-768.jpeg" />
<source media="(min-width: 576px)" srcset="/images/wide-ejs-576.jpeg, /images/wide-ejs-576@2x.jpeg 2x" />
<source media="(min-width: 400px)" srcset="/images/wide-ejs-400.jpeg, /images/wide-ejs-400@2x.jpeg 2x" />
<source media="(min-width: 350px)" srcset="/images/wide-ejs-350.jpeg, /images/wide-ejs-350@2x.jpeg 2x" />
<source srcset="/images/wide-ejs-200.jpeg, /images/wide-ejs-200@2x.jpeg 2x" />
<img
src="data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAEAAoDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAAAAID/8QAFQEBAQAAAAAAAAAAAAAAAAAAAAL/2gAMAwEAAhADEAAAAcZIf//EABgQAAIDAAAAAAAAAAAAAAAAAAABAhIx/9oACAEBAAEFAtlVH//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQMBAT8Bf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Bf//EABYQAQEBAAAAAAAAAAAAAAAAAAACMf/aAAgBAQAGPwKWP//EABcQAQEBAQAAAAAAAAAAAAAAAAERACH/2gAIAQEAAT8hVXXtpmuf/9oADAMBAAIAAwAAABCL/8QAFBEBAAAAAAAAAAAAAAAAAAAAAP/aAAgBAwEBPxB//8QAFREBAQAAAAAAAAAAAAAAAAAAAAH/2gAIAQIBAT8Qr//EABoQAQACAwEAAAAAAAAAAAAAAAEAESExUdH/2gAIAQEAAT8QaBDoacRSUXfX2f/Z"
class="lazy blur-up loaded"
data-ll-status="loaded"
/></picture>
In addition to the {{picture src='' alt='' /}}
shortcode. This plugin adds the following to the helper
object available in all Elder.js hooks after bootstrap:
helpers.images.src(path)
Takes a relative path of the image and returns all the srcsets and data from the ejs-image-manifest.json
.
helpers.images.picture(path, {maxWidth: 2000, class:'', alt: '', ignoreCssString: false})
Takes a path
and opts
object and outputs the <picture>
tag similar to the shortcode.
opts
maxWidth
The largest responsive image to be included.class
a class added to the <picture>
alt
alt tag added to the <img>
.ignoreCssString
option to make the image ignore the default cssString
styles.If you need to use custom styles for a specific image instance but don't want to disable the default styles (cssString
), you can set the ignoreCssString
option to true
. It will change the wrapper class .ejs
to be .custom-ejs
so that the default styles won't have an impact on this particular image instance.
helpers.images.largest(path, {maxWidth: 2000})
A small utility to find the largest file (up to the maxWidth) for a given image.
The default plugin config assumes the following structure for your images:
root
| -- images
| -- | -- image files
It will automatically create:
root
| -- images
| -- | -- image files
| -- | -- ejs-image-manifest.json
| -- | -- sizes
| -- | -- | -- (resized images)
npm install --save @elderjs/plugin-images vanilla-lazyload
elder.config.js
:Once installed, open your elder.config.js
and configure the plugin by adding @elderjs/plugin-images
to your plugin object.
plugins: {
...
'@elderjs/plugin-images': {
folders: [
{
src: '/images/*', // glob of where your original images are. Relative to rootDir/process.cwd() defined in your elder.config.js. Careful with **.
// src: 'articles/**/*' is also acceptable
output: '/images/', // where files should be put within the distDir defined in your elder.config.js.
},
],
}
...
}
placeholder: false
in your config..ejs
class. Set cssString:false
. This will disable the plugin from generating any css which gives you full control and will help keep your site from being impacted by future css changes.plugins: {
'@elderjs/plugin-images': {
debug: false, // help with debugging
s3: {
AWS_ACCESS_KEY_ID: process.env.AWS_ACCESS_KEY_ID, // aws_access_key_id
AWS_SECRET_ACCESS_KEY: process.env.AWS_SECRET_ACCESS_KEY, // aws_secret_access_key
S3_BUCKET: process.env.S3_BUCKET, // s3 bucket name
S3_BUCKET_URL: process.env.S3_BUCKET_URL, // the bucket url
USE_S3_HOSTING: true, // images will be hosted on s3 instead of inserting relative url.
},
folders: [
{
src: '/images/', // where your original images are. Relative to rootDir/process.cwd() defined in your elder.config.js.
output: '/images/', // where files should be put within the distDir defined in your elder.config.js.
},
],
widths: [1280, 992, 768, 576, 400, 350, 200], // Sizes the images will be resized to.
fileTypes: ['webp'], // file types in addition to jpeg/png.
imageManifest: '/images/ejs-image-manifest.json', // relative to root dir or an async function
cacheFolder: '/images/sizes/', // relative to root dir
scales: [1, 2], // 1x, 2x sizes
placeholder: { // placeholder settings. See sharp.
resize: {
width: 10,
fit: sharp.fit.cover,
},
jpeg: {
// resize settings for the placeholder. See sharp.
quality: 50,
progressive: true,
optimizeScans: true,
chromaSubsampling: '4:2:0',
trellisQuantisation: true,
quantisationTable: 2,
},
},
quality: 70, // quality to save the resized images in.
cssString: ``, // if you want to overwrite the default css added
addVanillaLazy: true, // if you want to disable the lazyload plugin and add your own.
vanillaLazyLocation: '/static/vanillaLazy.min.js', // vanillaLazy's location relative to the root of the site. The plugin will move it to your public folder for you.
}
}
Within your project's root, you can add the following to further optimize this plugin's usage.
/images/sizes/
/images/*.json
Explicitly default cache related values to elder.config.js
imageManifest: '/images/ejs-image-manifest.json',
cacheFolder: '/images/sizes/',
and created package script to clear the cache when it feels appropriate
//src/cleanImageCache.js
const del = require('del');
const path = require('path');
const { getConfig } = require('@elderjs/elderjs');
const { rootDir, plugins } = getConfig();
console.log(' Clearing out image cache.');
if (plugins['@elderjs/plugin-images'] !== undefined) {
const plugin = plugins['@elderjs/plugin-images'];
if (plugin.imageManifest !== undefined) {
del.sync(path.join(rootDir, plugin.imageManifest));
}
if (plugin.cacheFolder !== undefined) {
del.sync(path.join(rootDir, plugin.cacheFolder));
}
}
node ./src/cleanImageCache.js
If you are struggling with the plugin doing unexpected things, remove your ejs-image-manifest.json
and let the plugin rebuild it from scratch. Generally this won't result in generating new images but can help clean up issues caused by an out of sync manifest.json.
This plugin also exports a processImages
function which will generate sizes and optionally upload them to s3 just like it would work with the Elder.js plugin.
processImages
params:
image
objects (defined below).images
array for processImages
// images = [
// {
// src, // file path or buffer
// rel, // the relative url where the image will be found on the site. (used in the manifest) '/image/foo.jpg'
// ext, // extension : 'png', 'jpg', 'webp'
// }
// ]
This is useful if you let your users upload images to a dashboard and you want to store the processed image sizes in a database... but still want to use this plugin.
This was our use case at ElderGuide.com. Images are uploaded to an internal dashboard by our team the buffer can be sent directly to the processImages
function which will generate a manifest and upload the resulting images to s3.
We then take the json
generated by the library and toss it in the DB for longer term storage.
Then to use the imageManifest
option in the Elder.js to build a compatible manifest.
This allows us to centrally host our images and still get all of the benefits of this plugin.
Below is an example imageManifest
function:
plugins: {
'@elderjs/plugin-images': {
// rest of the config
imageManifest: async () => {
// you can do a db call to build the manifest.
return {
'/images/advice-seekers.jpg': {
width: 200,
height: 200,
format: 'jpeg',
original: '/images/advice-seekers.jpg',
sizes: [
...
],
placeholder:
'data:image/jpeg;base64,/9j/2wBDABALDA4MChAODQ4SERATGCgaGBYWGDEjJR0oOjM9PDkzODdASFxOQERXRTc4UG1RV19iZ2hnPk1xeXBkeFxlZ2P/2wBDARESEhgVGC8aGi9jQjhCY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2NjY2P/wgARCAAKAAoDASIAAhEBAxEB/8QAFgABAQEAAAAAAAAAAAAAAAAABAIG/8QAFAEBAAAAAAAAAAAAAAAAAAAAAP/aAAwDAQACEAMQAAABpefWf//EABoQAQABBQAAAAAAAAAAAAAAAAEAAhETFCH/2gAIAQEAAQUCK3Z5Bc12f//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQMBAT8Bf//EABQRAQAAAAAAAAAAAAAAAAAAAAD/2gAIAQIBAT8Bf//EABkQAAMAAwAAAAAAAAAAAAAAAAABMRBBgf/aAAgBAQAGPwJrUx0p/8QAGhABAQEAAwEAAAAAAAAAAAAAAREAITFhkf/aAAgBAQABPyFahWxz1DTILW57Pu//2gAMAwEAAgADAAAAEOP/xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oACAEDAQE/EH//xAAUEQEAAAAAAAAAAAAAAAAAAAAA/9oACAECAQE/EH//xAAcEAEAAwACAwAAAAAAAAAAAAABABEhMUFhobH/2gAIAQEAAT8Q7qhCGy68r7i67OQ5pvXI2v1T/9k=',
},
};
},
}
}
For production we proxy the s3 images in via a Cloudflare worker... in local development we set USE_S3_HOSTING
to true allowing us to preview the images without the proxy.
This is really an advanced use case but power users should be aware it exists.
Thanks to @meigo for helping make this work on Windows and many of the scripts in this readme.
FAQs
Easily generate and manage responsive images for your Elder.js site.
The npm package @elderjs/plugin-images receives a total of 30 weekly downloads. As such, @elderjs/plugin-images popularity was classified as not popular.
We found that @elderjs/plugin-images demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 2 open source maintainers collaborating on the project.
Did you know?
Socket for GitHub automatically highlights issues in each pull request and monitors the health of all your open source dependencies. Discover the contents of your packages and block harmful activity before you install or update your dependencies.
Research
Security News
Socket’s threat research team has detected six malicious npm packages typosquatting popular libraries to insert SSH backdoors.
Security News
MITRE's 2024 CWE Top 25 highlights critical software vulnerabilities like XSS, SQL Injection, and CSRF, reflecting shifts due to a refined ranking methodology.
Security News
In this segment of the Risky Business podcast, Feross Aboukhadijeh and Patrick Gray discuss the challenges of tracking malware discovered in open source softare.