A markdown-it plugin that processes images through the eleventy-img plugin. Can be used in any projects that use markdown-it. Fully compatible with the Eleventy static site generator.
This is pre-release software. There might still be API changes. I'm pretty much developing this plugin in the open and I'm learning buckets!
Use at your own risk, but feel free to get in touch if you have questions, a comment or want to talk about your experience as a user.
Same as eleventy-img. Was tested with markdown-it v9.0.0
and Eleventy v1.0.1
.
npm install --save-dev markdown-it-eleventy-img
This plugin is zero-config by default and can be use as a regular markdown-it plugin.
const md = require('markdown-it')()
.use(require("markdown-it-eleventy-img"));
With Eleventy (11ty), use the config API setLibrary
method.
// .eleventy.js (or your config file.)
const markdownIt = require('markdown-it');
const markdownItEleventyImg = require("markdown-it-eleventy-img");
module.exports = function(config) {
config.setLibrary('md', markdownIt ({
html: true,
breaks: true,
linkify: true
})
.use(markdownItEleventyImg);
}
Using markdown-it-eleventy-img without options will run eleventy-img with default options which are:
widths: [null]
formats: ["webp", "jpeg"]
urlPath: "/img/"
outputDir: "./img/"
So using:
<!-- index.md -->
![Image alt](./img/my-image.jpg "Title text!")
Will output:
<p><picture><source type="image/webp" srcset="/img/wtdfPs-yjZ-2048.webp 2048w"><img alt="Image alt" title="Title text!" src="/img/wtdfPs-yjZ-2048.jpeg" width="2048" height="1463"></picture></p>
By default, images are rendered using the generateHTML
function from the eleventy-img plugin with the whitespaceMode
"to strip the whitespace from the output of the <picture>
element (a must-have for use in markdown files)" (reference).
You can add an options object to override eleventy-img defaults, add global attributes or provide your own custom rendering.
The options object may contain these properties:
-
imgOptions
(object). Overrides eleventy-img specific options. -
globalAttributes
(object). Adds attributes to the image output. -
renderImage
(function). Lets you render custom markup and do almost everything you like with your markdown images (see Custom image rendering). -
resolvePath
(function). Lets you decide how you want to resolve paths for images. By default,markdown-it-eleventy-img
will resolve path against project root (see Resolving path).
Here's an exemple of using the options object:
.use(markdownItEleventyImg, {
imgOptions: {
widths: [800, 500, 300],
urlPath: "/images/",
outputDir: path.join("_site", "images"),
formats: ["avif", "webp", "jpeg"]
},
globalAttributes: {
class: "markdown-image",
decoding: "async",
// If you use multiple widths,
// don't forget to add a `sizes` attribute.
sizes: "100vw"
}
});
With these options, the image ![Image alt](./img/my-image.jpg "Title text!")
, will be rendered as:
<p><picture><source type="image/avif" srcset="/images/wtdfPs-yjZ-300.avif 300w, /images/wtdfPs-yjZ-500.avif 500w, /images/wtdfPs-yjZ-800.avif 800w" sizes="100vw"><source type="image/webp" srcset="/images/wtdfPs-yjZ-300.webp 300w, /images/wtdfPs-yjZ-500.webp 500w, /images/wtdfPs-yjZ-800.webp 800w" sizes="100vw"><source type="image/jpeg" srcset="/images/wtdfPs-yjZ-300.jpeg 300w, /images/wtdfPs-yjZ-500.jpeg 500w, /images/wtdfPs-yjZ-800.jpeg 800w" sizes="100vw"><img alt="Image alt" title="Title text!" class="markdown-image" decoding="async" src="/images/wtdfPs-yjZ-300.jpeg" width="800" height="571"></picture></p>
The alt
, the src
, and the title
attributes are taken from the markdown token: ![alt](./source.ext "Title")
.
Setting alt
or src
properties in globalAttributes
will have no effect on the markdown image output. These attributes have to be set on the markdown image token instead.
A warning will be logged in the console if these properties are set in globalAttributes
.
The title
property can be set in globalAttributes
, but there's probably little insentive to do so. Attributes set on the token will always override global attributes.
You may use the renderImage
method to customize the output or to add logic to your image rendering. This function is returned inside of the image renderer so any string returned by renderImage
will render the markup for every image tokens.
renderImage(image, attributes) {
const [ src, attrs ] = attributes;
const alt = attrs.alt;
return `<img src="${src}" alt="${alt}">`;
}
renderImage
takes two parameters and each one are tuples.
renderImage(image, attributes) {
const [ Image, options ] = image;
const [ src, attrs ] = attributes;
// ...
}
We separate the src
form the rest of the attributes to facilitate the use of the Image
class. If you need to, it is simple to reunite.
const [ src, attrs ] = attributes;
const allAttributes = { ...attrs, src }
Here's an exemple of adding a <figure>
parent and an optional <figcaption>
.
.use(markdownItEleventyImg, {
imgOptions: {
widths: [600, 300],
urlPath: "/images/",
outputDir: "./_site/images/",
formats: ["avif", "webp", "jpeg"]
},
globalAttributes: {
class: "markdown-image",
decoding: "async",
sizes: "100vw"
},
renderImage(image, attributes) {
const [ Image, options ] = image;
const [ src, attrs ] = attributes;
Image(src, options);
const metadata = Image.statsSync(src, options);
const imageMarkup = Image.generateHTML(metadata, attrs, {
whitespaceMode: "inline"
});
return `<figure>${imageMarkup}${attrs.title ? `<figcaption>${attrs.title}</figcaption>` : ""}</figure>`;
}
});
Note that you have to use eleventy-img synchronous API inside
renderImage
. Unfortunately, markdown-it plugins doesn't support async code (see Limitations). It's good to know that even in the sync API, the images are generated asychronously. Got to 😍 11ty!
By default, markdown-it-eleventy-img
will resolve relative paths against current working directory (project root). Use resolvePath
to configure how paths are resolved. Returned value: the source path.
The resolvePath
method takes two arguments:
- The image source from the token.
- The
env
parameter from the Markdown-it renderer.
Here's an example of resolving path relative to the markdown file in Eleventy:
config.setLibrary("md", md.use(markdownItEleventyImg, {
resolvePath: (filepath, env) => path.join(path.dirname(env.page.inputPath), filepath)
}));
Since Eleventy is passing its supplied data to env
, this is possible. It may or may not be possible in other context. It was only tested with Eleventy.
Starting with v0.3.0
, markdown-it-eleventy-img is fully compatible with markdown-it-attrs. Setting attributes with markdown-it-attrs will be passed to the image output. Same attributes will be overridden. The attribute set on the token will prevail over globalAttributes
.
markdown-it-eleventy-img is currently not supported with remote sources. Starting with v0.7.0
, the default behavior will be to revert to native markdown-it renderer whenever remote images are encountered (local sources will still be rendered through eleventy-img).
To process remote images, use code where the eleventy-img async API is allowed. For a more technical expaination see issue#2.
markdown-it-eleventy-img tries to follow as much as possible the markdown philosophy. The idea is to keep simplicity while generating responsive image format in markdown. With markdown-it-eleventy-img, you author images in markdown the same way as usual.
Also, the aim is to stay coherent with eleventy-img defaults while allowing users to use the full feature set. So if your familiar with the eleventy-img plugin, there should be no surprises.
markdown-it-eleventy-img is not a replacement for an Eleventy shortcode. Shortcodes will give more power and control. On the other hand, markdown will trade control for easiness of reading and writing.
Admittedly, it’s fairly difficult to devise a “natural” syntax for placing images into a plain text document format. That beiing said, it's probably nicer to use markdown image syntax to include an image in a blog post than to use a shortcode. So markdown-it-eleventy-img is mainly an ergonomic solution for using eleventy-img plugin with the markdown image synthax.
I've seen it asked here and there: can I use the eleventy-img plugin with markdown token? I thought it was a good challenge and I ended-up publishing my work.