npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2024 – Pkg Stats / Ryan Hefner

metalsmith-adaptive-images

v1.1.0

Published

A plugin for Metalsmith to create adaptive images via srcset and styles properties

Downloads

9

Readme

metalsmith-adaptive-images

A plugin for Metalsmith to create adaptive images via <img srcset="..." styles="..."/>. It works well along with metalsmith-project-images.

MIT License js-standard-style Build Status CodeCov Badge David David semantic-release Commitizen friendly

Introduction

Providing images on websites nowadays can be tricky. You need to consider many different device sizes with good to to very bad connection speed.

So you will end up serving multiple versions of your images with different dimensions. Also you need to tell the browser which image to pick for a breakpoint. The article Don’t ruin your <img> - by Anthony Ng explains very well, what you need to keep in mind while serving images in today's web.

This plugin will create a map of images, containing metadata to properly output images with srcset and styles attributes.

It is up to you what to do with these informations. You can generate a gallery in your layout engine or use it your javascript to provide sharp images.

For simplicity, this module also provides a replace plugin, which replaces all matching images with their adaptive clones within html files.

Install

npm install --save metalsmith-adaptive-images

Preparation

First you need to load your images into metalsmith, you could use metalsmith-project-images for this.

To resize your images, you could use one of the following plugins for this:

Also consider to compress your images. The metalsmith-imagemin plugin should be a good bet here. If you are looking for a very fast but effective JPEG compressor, I can really recommend to use mozjpeg.

Usage

If your environment does not support the import syntax, see further below.

The module consists of 2 metalsmith plugins and one method for rendering adaptive images. All of them can be used separately.

The processImages plugin expects an array of images within the metadata of a file. As soon as a matching metadata key is found, the plugin will create a new map of images with proper objects with the parsed and generated metadata.

It also provides the plugin replaceImages to replace all images with their adaptive cousins in your html.

With renderImage you will get a adaptive image based on the provided url and the given configuration.

import Metalsmith from 'metalsmith'
import images from 'metalsmith-project-images'
import AdaptiveImages from 'metalsmith-adaptive-images'

// Initialize your instance of the plugin.
// This allows you to use multiple configurations.
const adaptiveImages = AdaptiveImages({
  ... your configuration here ...
})

// Example #1: Enhance your image metadata
Metalsmith('/path/to/project')
  // Use metalsmith-project-images to locate images and add to file metadata.
  .use(images({}))
  // Use the plugin to attach metadata.
  // The default options match the ones of metalsmith-project-images.
  .use(adaptiveImages.processImages)
  .use(markdown()) // Generate html files out of your markdown
  .use(layouts(...)) // Apply layouts to your files and add adaptive images manually.
  .build()

// Example #2: Simply replace images
Metalsmith('/path/to/project')
  .use(markdown()) // Generate html files out of your markdown
  .use(adaptiveImages.replaceImages) // Replace images based on the given configuration above.
  .build()

Every document with attached images like this:

files: {
  'example.md': {
    ...,
    images: [ 'images/example.jpg', ... ]
  }
}

Will be transformed into this:

files: {
  'example.md': {
    ...,
    images: [ 'images/example.jpg', ... ]
    imagesMap: {
      'example.jpg': {
        src: 'images/example-960.jpg',
        srcset: 'images/example-1440.jpg 1440w, images/example-960.jpg 960w, images/example-480.jpg 480w',
        sizes: '(min-width: 960px) 960px, 100vw',
        name: 'example.jpg'
      },
      ...
    }
  }
}

Node 6

const AdaptiveImages = require('metalsmith-adaptive-images')

Node 4

A version for the LTS version of node is also supplied. You can require it like this:

const AdaptiveImages = require('metalsmith-adaptive-images/dist/node4')

For further examples can be found in the test directory.

Options

If you got confused and need help to pick the correct options, this article about srcset and sizes may help you.

Default options:

{
  imagesKey: 'images',
  mapKey: 'imagesMap',
  imageWidths: [1440, 960, 480],
  imageSizes: ['(min-width: 960px) 960px', '100vw'],
  defaultSize: 960,
  namingPattern: '{dir}{name}-{size}{ext}', // foo/bar-200.jpg,...
  srcsetPattern: '{url} {size}w' // foo/bar-200.jpg 200w,...
  htmlFileGlob: '**/*.html',
  htmlImageSelector: 'img'
}

imagesKey

The file metadata key where to look for images. metalsmith-project-images uses images here, so does this plugin.

imagesMap

The file metadata key where to store the map of image objects.

imageWidths

Base value for the srcset attribute. This array represents the different image sizes, you want to provide. Together with the srcsetPattern option the srcset attribute will be generated.

Make sure to define from biggest to lowest size to prevent issues with some browsers.

{
  imageWidths: [2880, 1440, 960, 480, 320]
}

imageSizes

Values for the sizes attribute. This tells the browser, which size the image will have on the site. The values will be basically just combined to one string.

{
  imageSizes: ['(min-width: 960px) 1440px', '100vw'],
}

defaultSize

Default size to select. The renderer will use this to set the src attribute and so should you. Older browsers will use this as fallback when they do not support the srcset attribute.

{
  defaultSize: 960
}

namingPattern

Naming pattern for the actual image file names.

Supported placeholders:

  • {dir}: Directory of file followed by slash
  • {base}: Full filename with extension
  • {name}: Filename without extension
  • {ext}: File extension with leading dot
  • {size}: The width of the current srcset breakpoint
{
  namingPattern: '{dir}/{name}-{size}{ext}'
}

srcsetPattern

Pattern of the generated srcset syntax. The default should fit for most usecases.

Supported placeholders:

  • {url}: The url of the image to serve for this breakpoint
  • {size}: The width of the current srcset breakpoint
{
  srcsetPattern: '{url} {size}w'
}

htmlFileGlob

Glob to match html files whose images are going to be replaced by the replaceImages plugin. All minimatch features are supported.

{
  htmlFileGlob: 'galleries/*.html'
}

htmlImageSelector

Selector to select images within the html files. Almost any jQuery selector pattern is support. See cheerio selectors documentation for more details.

{
  htmlImageSelector: 'aside.gallery img'
}

Methods

processImages(files, metalsmith, done)

Metalsmith plugin to process the images found in the metadata of your files. Transforms an array of images to a proper map (object) with all information needed for adaptive display.

Thanks to this function, you can easily access your images within your page JS or in your templates to work with them.

replaceImages(files, metalsmith, done)

Metalsmith plugin to replace the images.

It will use cheerio to scan all html files for images and add the srcset and sizes attribute to them.

Change the htmlFileGlob or htmlImageSelector option if you have special needs.

renderImage(src, attrs = {})

Renders a adaptive image with srcset and sizes attribute based on your configuration.

  • src is the path to the image.
  • attrs is an object containing extra attributes for the image tag.

I found myself often using just this feature of the plugin, since the methods above are not needed in every case.

const adaptiveImages = AdaptiveImages()
adaptiveImages.renderImage('images/example.jpg', {
  alt: 'alternative text',
  title: 'title text'
})

Output since we did not pass any options:

<img
  src="images/example-960.jpg"
  srcset="images/example-1440.jpg 1440w, images/example-960.jpg 960w, images/example-480.jpg 480w"
  sizes="(min-width: 960px) 960px, 100vw"
  alt="alternative text" title="title text"/>

Development

This project follows the standard coding and the conventional changelog commit message style. Also it is configured to never decrease the code coverage of its tests.

Also make sure you check out all available npm scripts via npm run.

Contributing

Pull requests and stars are always welcome. For bugs and feature requests, please create an issue. But before doing anything, please read the CONTRIBUTING.md guidelines.