Giter VIP home page Giter VIP logo

metalsmith-adaptive-images's Introduction

DEPRECATION NOTICE:

I am no more able to provide maintenance for this plugin. If you want to take ownership or get more information, please have a look here: #62


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.

metalsmith-adaptive-images's People

Contributors

axe312ger avatar greenkeeper[bot] avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

Forkers

stackcoder

metalsmith-adaptive-images's Issues

An in-range update of eslint is breaking the build 🚨

Version 3.14.1 of eslint just got published.

Branch Build failing 🚨
Dependency eslint
Current Version 3.14.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As eslint is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this 💪


Status Details
  • ci/circleci Your tests failed on CircleCI Details
Release Notes v3.14.1
  • 791f32b Fix: brace-style false positive for keyword method names (fixes #7974) (#7980) (Teddy Katz)
  • d7a0add Docs: Add ESLint tutorial embed to getting started (#7971) (Jamis Charles)
  • 72d41f0 Fix: no-var autofix syntax error in single-line statements (fixes #7961) (#7962) (Teddy Katz)
  • b9e5b68 Fix: indent rule crash on sparse array with object (fixes #7959) (#7960) (Gyandeep Singh)
  • a7bd66a Chore: Adding assign/redeclare tests to no-undefined (refs #7964) (#7965) (Kevin Partington)
  • 8bcbf5d Docs: typo in prefer-promise-reject-errors (#7958) (Patrick McElhaney)
Commits

The new version differs by 8 commits .

  • e544644 3.14.1
  • 1297635 Build: package.json and changelog update for 3.14.1
  • 791f32b Fix: brace-style false positive for keyword method names (fixes #7974) (#7980)
  • d7a0add Docs: Add ESLint tutorial embed to getting started (#7971)
  • 72d41f0 Fix: no-var autofix syntax error in single-line statements (fixes #7961) (#7962)
  • b9e5b68 Fix: indent rule crash on sparse array with object (fixes #7959) (#7960)
  • a7bd66a Chore: Adding assign/redeclare tests to no-undefined (refs #7964) (#7965)
  • 8bcbf5d Docs: typo in prefer-promise-reject-errors (#7958)

See the full diff.

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

An in-range update of babel-plugin-transform-object-rest-spread is breaking the build 🚨

Version 6.26.0 of babel-plugin-transform-object-rest-spread just got published.

Branch Build failing 🚨
Dependency babel-plugin-transform-object-rest-spread
Current Version 6.23.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As babel-plugin-transform-object-rest-spread is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this 💪

Status Details
  • ci/circleci Your tests failed on CircleCI Details

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

An in-range update of babel-core is breaking the build 🚨

Version 6.25.0 of babel-core just got published.

Branch Build failing 🚨
Dependency babel-core
Current Version 6.24.1
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As babel-core is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this 💪

Status Details
  • ci/circleci Your tests failed on CircleCI Details

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

An in-range update of babel-plugin-istanbul is breaking the build 🚨

Version 3.1.1 of babel-plugin-istanbul just got published.

Branch Build failing 🚨
Dependency babel-plugin-istanbul
Current Version 3.0.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As babel-plugin-istanbul is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this 💪


Status Details
  • ci/circleci Your tests failed on CircleCI Details
Commits

The new version differs by 8 commits .

  • 73a4247 chore: explicitly upgrade istanbul-lib-instrument
  • 9818c25 chore(release): 3.1.1
  • 18bbcdc chore: upgrade to version of istanbul-lib-instrument that addresses inferred function name issues
  • 2e0af61 chore(release): 3.1.0
  • e764330 fix: upgrade a bunch of core dependencies (#77)
  • 437e90b feat: accept source map input for the visitor (#75)
  • 7bd4eb8 chore(package): update standard-version to version 4.0.0 (#73)
  • dfbd0b8 chore(package): update nyc to version 10.0.0 (#72)

See the full diff.

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

An in-range update of eslint-plugin-babel is breaking the build 🚨

Version 4.1.2 of eslint-plugin-babel just got published.

Branch Build failing 🚨
Dependency eslint-plugin-babel
Current Version 4.1.1
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As eslint-plugin-babel is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this 💪

Status Details
  • ci/circleci Your tests failed on CircleCI Details

Release Notes v4.1.2

Bug Fix

babel/semi: doesn't fail when using for await (let something of {}). Includes class properties

Commits

The new version differs by 2 commits.

  • 1eab147 4.1.2
  • 9468524 Modifying semi rule to support for await (#126)

See the full diff

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

Plugin deprecation: Looking for new maintainer(s)!

Hey there,

I have to deprecate this plugin since I am no more using metalsmith in any of my projects and this plugin turned out to be very complex in usage and code.

I'll try keep the kind of related https://github.com/axe312ger/metalsmith-sharp plugin alive since it is way more simple to maintain and has more usage in the community as well.

If anyone is willing to continue, please let me know here.

May the open source be with u,
Benedikt

Provide a concrete example to understand how your plugin works?

Thank you for your plugin,
but I don't really understand how it's work,
and a little good and concrete example is often better than a long explanation.

For example, I have this structure:

projects/
|-- page-1/
|	|-- index.hbs
|	|-- images/
|		|-- image-A-small.png
|		|-- image-A-medium.png
|		|-- image-A-large.png
|		|-- image-B-small.png
|		|-- image-B-medium.png
|		|-- image-B-large.png
|-- page-2/
|	|-- index.hbs
|	|-- images/
|		|-- image-C-small.png
|		|-- image-C-medium.png
|		|-- image-C-large.png

and I don't understand how your plugin can fit my structure to generate a srcset.

Thanks for your help!

Plugin replaces all Cyrillic characters with html entities

I'm using configuration like this:

const images = AdaptiveImages({
  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',
});

...

  .use(templates({
    templateKey: 'layout',
  }))
  .use(images.replaceImages)

Charset of the source files utf-8. As result instead of Зоркий I've got &#x417;&#x43E;&#x440;&#x43A;&#x438;&#x439;

An in-range update of cross-env is breaking the build 🚨

Version 3.2.0 of cross-env just got published.

Branch Build failing 🚨
Dependency cross-env
Current Version 3.1.4
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As cross-env is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this 💪


Status Details
  • ci/circleci Your tests failed on CircleCI Details
Release Notes v3.2.0

<a name"3.2.0">

3.2.0 (2017-03-04)

Features

  • revamp: revamp the entire lib (backward compatible) (#63) (dad00c46)
Commits

The new version differs by 4 commits .

  • dad00c4 feat(revamp): revamp the entire lib (backward compatible) (#63)
  • e33a85c docs(README): Add doc for cross-var. (#58)
  • 5e590ec docs(README): added how to use cross-env to run npm sub-scripts (#53)
  • afdb2de docs(README): mention Bash on Windows (#49)

See the full diff.

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

An in-range update of eslint-plugin-promise is breaking the build 🚨

Version 3.6.0 of eslint-plugin-promise was just published.

Branch Build failing 🚨
Dependency eslint-plugin-promise
Current Version 3.5.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

eslint-plugin-promise is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ci/circleci Your tests failed on CircleCI Details

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of cz-conventional-changelog is breaking the build 🚨

Version 2.1.0 of cz-conventional-changelog was just published.

Branch Build failing 🚨
Dependency cz-conventional-changelog
Current Version 2.0.0
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

cz-conventional-changelog is a devDependency of this project. It might not break your production code or affect downstream projects, but probably breaks your build or test tools, which may prevent deploying or publishing.

Status Details
  • ci/circleci Your tests failed on CircleCI Details

Release Notes v2.1.0

<a name"2.1.0">

2.1.0 (2017-10-27)

Features

  • prompt: add confirmation fields + edit for clarity (#58) (d40ac2c5)
Commits

The new version differs by 3 commits.

  • d40ac2c feat(prompt): add confirmation fields + edit for clarity (#58)
  • f7a770e Merge pull request #57 from Epitrochoid/remove-unused-dep
  • 2d1095b Removed unused pad-right dependency

See the full diff

FAQ and help

There is a collection of frequently asked questions. If those don’t help, you can always ask the humans behind Greenkeeper.


Your Greenkeeper Bot 🌴

An in-range update of babel-register is breaking the build 🚨

Version 6.26.0 of babel-register just got published.

Branch Build failing 🚨
Dependency babel-register
Current Version 6.24.1
Type devDependency

This version is covered by your current version range and after updating it in your project the build failed.

As babel-register is “only” a devDependency of this project it might not break production or downstream projects, but “only” your build or test tools – preventing new deploys or publishes.

I recommend you give this issue a high priority. I’m sure you can resolve this 💪

Status Details
  • ci/circleci Your tests failed on CircleCI Details

Not sure how things should work exactly?

There is a collection of frequently asked questions and of course you may always ask my humans.


Your Greenkeeper Bot 🌴

Support for lazy load

Being able to use this with LazyLoad would be nice.

LazyLoad requires the attribute names to be changed from src and srcset to data-srcand data-srcset as shown in this example.

Two suggestions

  • we could pass a boolean option lazyLoad, which if true renders with data-src and data-srcset attribute names instead of regular ones. Or
  • we could pass a string option prefix, which allows adding any prefix.

Metalsmith CLI integration

Hey I like the sound of this plug-in, but I'm not sure how I could integrate it if my project uses the Metalsmith CLI.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.