Gathering detailed insights and metrics for rehype-image-toolkit
Gathering detailed insights and metrics for rehype-image-toolkit
Gathering detailed insights and metrics for rehype-image-toolkit
Gathering detailed insights and metrics for rehype-image-toolkit
npm install rehype-image-toolkit
Typescript
Module System
Node Version
NPM Version
TypeScript (99.27%)
JavaScript (0.73%)
Total Downloads
0
Last Day
0
Last Week
0
Last Month
0
Last Year
0
MIT License
1 Stars
206 Commits
1 Branches
1 Contributors
Updated on Jun 10, 2025
Latest Version
1.0.3
Package Id
rehype-image-toolkit@1.0.3
Unpacked Size
168.77 kB
Size
33.15 kB
File Count
16
NPM Version
10.8.2
Node Version
20.19.2
Published on
Jun 09, 2025
Cumulative downloads
Total Downloads
Last Day
0%
NaN
Compared to previous day
Last Week
0%
NaN
Compared to previous week
Last Month
0%
NaN
Compared to previous month
Last Year
0%
NaN
Compared to previous year
8
1
29
This package is a unified (rehype) plugin that enhances Markdown image syntax ![]()
and Markdown/MDX media elements (<img>
, <audio>
, <video>
) by auto-linking bracketed or parenthesized image URLs, wrapping them in <figure>
with optional captions, unwrapping images/videos/audio from paragraph, parsing directives in title for styling and adding attributes, and dynamically converting images into <video>
or <audio>
elements based on file extension.
unified is a project that transforms content with abstract syntax trees (ASTs) using the new parser micromark. remark adds support for markdown to unified. mdast is the Markdown Abstract Syntax Tree (AST) which is a specification for representing markdown in a syntax tree. rehype is a tool that transforms HTML with plugins. hast stands for HTML Abstract Syntax Tree (HAST) that rehype uses.
Markdown natively supports images but lacks built-in syntax for videos and audio. rehype-image-toolkit
extends image syntax, automatically transforming it into <video>
or <audio>
elements based on file extensions, supporting additional attributes, providing custom directives for autolink to originals, wrapping media with figure
and adding caption, and unwrapping media from paragraph.
From what I’ve seen, most Remark and Rehype plugins that handle Markdown images apply their features globally, without offering much flexibility. In some cases, I need more control—certain images should be excluded from these transformations. For example, I might NOT want every image to be wrapped in a <figure>
, include a caption, be automatically linked to its source, or unwrapping from paragraph.
That's why each feature in rehype-image-toolkit
is individually controllable via directives. Its most distinct advantage over other remark/rehype plugins.
I designed rehype-image-toolkit
as an all-in-one solution, bringing together all essential image-related features for markdown and MDX in a single toolkit.
rehype-image-toolkit
is ideal for:
<figure>
and caption – Easily wrap in a <figure>
element with an optional caption.This package is suitable for ESM only. In Node.js (version 16+), install with npm:
1npm install rehype-image-toolkit
or
1yarn add rehype-image-toolkit
Say we have the following markdown file, example.md
:
(pay attention to directives)
1It ensures adding videos/audio using image syntax.  2 3It adds autolink to original.  4 5It adds figure and caption.  6 7It unwraps images from paragraph  8 9It adds attributes. 
Our module, example.js
, looks as follows:
1import { read } from "to-vfile"; 2import { unified } from "unified"; 3import remarkParse from "remark-parse"; 4import remarkRehype from "remark-rehype"; 5import rehypeImageToolkit from "rehype-image-toolkit"; 6import rehypeStringify from "rehype-stringify"; 7 8main(); 9 10async function main() { 11 const file = await unified() 12 .use(remarkParse) 13 .use(remarkRehype) 14 .use(rehypeImageToolkit) 15 .use(rehypeStringify) 16 .process(await read("example.md")); 17 18 console.log(String(file)); 19}
Now, running node example.js
you will see.
1<p>It ensures adding videos/audio using image syntax.</p> 2<video> 3 <source src="video.mp4" type="video/mp4" /> 4</video> 5<p> 6 It adds autolink to original. 7 <a href="https://example.com/image.png" target="_blank"> 8 <img src="https://example.com/image.png" alt="alt"/> 9 </a> 10</p> 11<p>It adds figure and caption.</p> 12<figure> 13 <img src="image.png" alt="Image Caption" /> 14 <figcaption>Image Caption</figcaption> 15</figure> 16<p>It unwraps images from paragraph</p> 17<img src="image.png" alt="alt" /> 18<p>It adds attributes.</p> 19<video title="title" width="640" height="480" autoplay> 20 <source src="video.mp4" type="video/mp4" /> 21</video>
Without rehype-image-toolkit
the output would be:
1<p>It ensures adding videos/audio using image syntax. <img src="video.mp4" alt=""></p> 2<p>It adds autolink to original. <img src="%5Bhttps://example.com/image.png%5D" alt="alt"></p> 3<p>It adds figure and caption. <img src="image.png" alt="^Image Caption"></p> 4<p>It unwraps images from paragraph <img src="image.png" alt="&alt"></p> 5<p>It adds attributes. <img src="video.mp4" alt="" title="title > 640x480 autoplay"></p>
rehype-image-toolkit
also works with references in markdown.
1![cat image][reference-image] meows ![~][reference-audio] 2 3[reference-image]: [image.png] "cat image" 4[reference-audio]: audio.mp3 "> autoplay"
will produce (pay attention to brackets around the src of the image; and title directive and tilda ~
inline directive for the audio):
1<p> 2 <a href="image.png" target="_blank"> 3 <img src="image.png" alt="cat image" /> 4 </a> meows 5 <audio autoplay> 6 <source src="audio.mp3" type="audio/mpeg" /> 7 </audio> 8</p>
Actually, you don't need to use rehype-image-toolkit
for html sources since you can write direct html structure for adding figure and caption, adding attributes and wrapping assets with an anchor link. But anyway, I've wanted to support that features for html sources as well.
Say example.html
looks as follows:
(pay attention to directives)
1<p> 2 It adds autolink to original. 3 <img src="[https://example.com/image.png]" alt="alt"/> 4</p> 5<p> 6 It adds figure and caption. 7 <img src="image.png" alt="^Image Caption"/> 8</p> 9<p> 10 It adds attributes. 11 <img src="image.png" title="title > 60x60"/> 12</p> 13<p> 14 It unwraps videos/audio from paragraph by default. 15 <video src="video.mp4"></video> 16</p> 17<p> 18 It keeps videos/audio in paragraph via tilda directive. 19 <video src="video.mp4" alt="~"></video> 20</p>
Our module, example.js
, looks as follows:
1import { read } from "to-vfile"; 2import { unified } from "unified"; 3import rehypeParse from "rehype-parse"; 4import rehypeImageToolkit from "rehype-image-toolkit"; 5import rehypeStringify from "rehype-stringify"; 6 7main(); 8 9async function main() { 10 const file = await unified() 11 .use(rehypeParse, { fragment: true }) 12 .use(rehypeImageToolkit) 13 .use(rehypeStringify) 14 .process(await read("example.md")); 15 16 console.log(String(file)); 17}
Now, running node example.js
you will see.
1<p> 2 It adds autolink to original. 3 <a href="https://example.com/image.png" target="_blank"> 4 <img src="https://example.com/image.png" alt="alt"> 5 </a> 6</p> 7<p> 8 It adds figure and caption. 9</p> 10<figure> 11 <img src="image.png" alt="Image Caption"> 12 <figcaption>Image Caption</figcaption> 13</figure> 14<p> 15 It adds attributes. 16 <img src="image.png" title="title" width="60" height="60"> 17</p> 18<p> 19 It unwraps videos/audio from paragraph by default. 20</p> 21<video src="video.mp4"></video> 22<p> 23 It keeps videos/audio in paragraph via tilda directive. 24 <video src="video.mp4"></video> 25</p>
Markdown lacks built-in support for video and audio, only providing image syntax. rehype-image-toolkit
repurposes the image syntax to render video/audio elements based on file extensions.

is transformed into <video>
element1<video> 2 <source src="example.mp4" type="video/mp4"> 3</video>

is transformed into <audio>
element1<audio> 2 <source src="example.mp3" type="audio/mpeg"> 3</audio>
Since <video>
and <audio>
are block-level elements by default, rehype-image-toolkit
unwraps them from paragraphs, splitting the text or other content around their original positions. If you don't want a video/audio to be extracted from paragraph use tilda ~
in the begining of alt text 
. It may be useful if you want an audio to be an inline element within paragraph in support of CSS.
title
attribute to customize images, videos, and audioAs you know, Markdown’s image syntax supports an optional title
attribute: 
rehype-image-toolkit
extends this by recognizing custom directives after greater operator (>
) in title.
1
width
and hight
attributes must be in pixel unit
You can use px
or just number for example 320
or 320px
. The CSS units other than pixel will go to the style attribute.
1 2 3 --> this will set the style attribute rather than width and height
If no title is needed, start with just greater operator (>
).
1
Directives must be separated by a single space, with no spaces within attribute values and no quotes.
1 2 3
There is a simple syntax for width and hight, using lowercase "x" character in the middle.
In this syntax, the pixel units should be a number, do not use px
.
1// Both dimension 2 3 4// Both dimension WRONG! 5 X WRONG! 6 7// Only width 8 9 10// Only height 11 12 13// Both dimension, other than px unit will go to the style attribute 14
The width and height attributes on images are treated specially. When used without a unit, the unit is assumed to be pixels. However, any of the CSS unit identifiers can be used. There shouldn't be any space between the number and the unit.
Wrap the link of the source in brackets or parentheses. It is valid for only if the image source starts with protokol-like links like http://
, web sites start with www.
, root relative links start with a slash /
and if just an image name like image.png
.
1### pay attention to additional brackets around the link 2 3 4### pay attention to additional parentheses around the link 5 "title")
will produce the same output below:
1<p> 2 <a href="http://example.com/image.png"> 3 <img src="http://example.com/image.png" alt="alt" title="title"> 4 </a> 5</p>
Wrapping the source attribute with brackets or parentheses produces mostly the same behavior/output, but only differs in case the image is wrapped in a <figure>
element.
<figure>
element including caption.<img>
element in the <figure>
.1 2)
will produce:
1<a href="image.png" target="_blank"> 2 <figure> 3 <img src="image.png" alt="caption"> 4 <figcaption>caption</figcaption> 5 </figure> 6</a> 7<figure> 8 <a href="image.png" target="_blank"> 9 <img src="image.png" alt="caption"> 10 </a> 11 <figcaption>caption</figcaption> 12</figure>
if you want to set different target for the <figure>
and for the <img>
inside, you can wrap the src
attribute with parentheses, not brackets, and use the formal link syntax of markdown together:
1[)](https://example.com)
will produce:
1<a href="https://example.com"> 2 <figure> 3 <a href="image.png" target="_blank"> 4 <img src="image.png" alt="Caption" /> 5 </a> 6 <figcaption>Caption</figcaption> 7 </figure> 8</a>
According to the HTML specification, anchor elements cannot be nested. Despite being invalid, browsers try to render this gracefully. The actual behavior can differ slightly between browsers, but in most modern browsers like Chrome, Firefox, and Safari:
<a href="image.png" target="_blank">
wrapping the <img>
will take precedence when clicking directly on the image.<img>
will open image.png
in a new tab (because of target="_blank"
).<a>
(e.g., on the figcaption
) will follow the outer link (https://example.com
).Add a caret ^
special directive at the start of the alt attribute in order to wrap the media asset with <figure>
element and add a caption.
Since <figure>
is block-level element by default, rehype-image-toolkit
unwraps it from paragraphs, splitting the text or other content around their original position. There is no choice not to be extracted !
1
will produce the html output:
1<figure> 2 <img src="image.png" alt="Caption of the image" title="title" /> 3 <figcaption>Caption of the image</figcaption> 4</figure>
Add a double caret ^^
special directive at the start of the alt attribute in order to only wrap the asset with <figure>
element but NOT to include a caption.
1 2 3
will produce the html output (notice there is no caption):
1<figure> 2 <img src="image.png" alt="alt" title="title" /> 3</figure> 4<figure> 5 <video title="title"> 6 <source src="video.mp4" type="video/mp4"> 7 </video> 8</figure>
If you want just a regular inline image, do not use any ^
directive in the begining of alt attribute.
1
There is an option implicitFigure
for adding an image/video/audio into <figure>
and adding a caption. If you set {implicitFigure: true}
in the options, an image will be rendered as a figure without any directive in the content if it is alone in the paragraph . The image’s alt text will be used as the caption. This feature is aligned with pandoc markdown implicit figure.
1## Assume you set `{implicitFigure: true}` 2 3
If you just want a regular inline image, when you set {implicitFigure: true}
, just make sure it is not the only thing in the paragraph or put a tilda ~
or ampersand &
directives in the start of alt attribute, since these directives have priority:
1## Assume you set `{implicitFigure: true}` 2 3### This image won't be a `<figure>` and stay in the paragraph as inline content 4 5 6 7### This image won't be a `<figure>`, but it is going to be unwrapped from paragraph 8 9
Just I want to stress again that if you want the image be in a <figure>
you can use directive caret ^
in the start of alt for explicit figure, as explained in the previous. No matter what the image is alone or not.
Add a ampersand &
special directive at the start of the alt attribute in order to unwrap the image from paragraph. Sometime you may want to unwrap images without adding it in a <figure>
. This directive ensures the image is extracted without adding it in a figure.
1 2 3
Add a tilda ~
special directive at the start of the alt attribute in order to keep videos/audio in a paragraph. This is helpful when you want these elements to remain inline in the paragraph. Normally, rehype-image-toolkit
unwraps videos/audio from paragraph by default.
1Here is the cat voice . So nice !
to be created (a PR is welcome).
All options are optional and have default values.
1type ImageToolkitOptions = { 2 explicitAutolink?: boolean; // default is "true" 3 explicitFigure?: boolean, // default is "true" 4 implicitFigure?: boolean; // default is "false" 5 figureCaptionPosition?: "above" | "below"; // default is "below" 6 addControlsForVideos?: boolean; // default is "false" 7 addControlsForAudio?: boolean; // default is "false" 8 enableMdxJsx?: boolean; // default is "true" 9}; 10 11use(rehypeImageToolkit, ImageToolkitOptions);
It is a boolean option which is for enabling or disabling ExplicitAutolink feature.
By default, it is true
. See more explanation about ExplicitAutolink here.
1use(rehypeImageToolkit, { 2 explicitAutolink: false, 3});
This will disable autolinking to original, removing the directive brackets or parentheses in the src attribute.
1
will produce standard image element without wrapping with an anchor <image src="image.png" alt="alt">
.
It is a boolean option which is for enabling or disabling ExplicitFigure feature.
By default, it is true
. See more explanation about ExplicitFigure here.
1use(rehypeImageToolkit, { 2 explicitFigure: false, 3});
This will disable adding <figure>
and caption, removing the directive caret ^
in the alt attribute.
1
will produce standard image element without figure and caption <image src="image.png" alt="caption">
.
It is a boolean option which is for enabling or disabling ImplicitFigure feature.
By default, it is false
. See more explanation about ImplicitFigure here.
1## Assume you set `{implicitFigure: true}` 2 3
It is a "above" | "below" union string option which is for placing the caption below or above of the asset.
By default, it is below
.
1use(rehypeImageToolkit, { 2 figureCaptionPosition: "above", 3});
Now, the caption will be the above of the asset.
It is a boolean option which is for adding controls
property to video
elements by default.
By default, it is false
.
1use(rehypeImageToolkit, { 2 addControlsForVideos: true, 3});
Now, video elements, like 
, will have controls
attribute by default.
1<video controls> 2 <source src="example.mp4" type="video/mp4"> 3</video>
It is a boolean option which is for adding controls
property to audio
elements by default.
By default, it is false
.
1use(rehypeImageToolkit, { 2 addControlsForAudio: true, 3});
Now, audio elements, like 
, will have controls
attribute by default.
1<audio controls> 2 <source src="example.mp3" type="audio/mpeg"> 3</audio>
It is a boolean option which is for enabling or disabling MdxJsx Elements within MDX.
As you know, the html-like (jsx) syntax in MDX contents are not HTML
elements, actually MdxJsx
elements. If you don't want the plugin process html-like (jsx) syntax in the MDX document, set the enableMdxJsx
to {enableMdxJsx: false}
.
Another consideration: if your content is pure Markdown (markdown + HTML syntax) and not MDX, set
enableMdxJsx
to{enableMdxJsx: false}
. This prevents the plugin from searching forMdxJsx
elements, resulting in faster rendering.
By default, it is true
.
1use(rehypeImageToolkit, { 2 enableMdxJsx: false, 3});
This will cause the plugin doesn't touch MdxJsx
elements within MDX contents.
1 2 3<img src="image.png" alt="^caption"/>
will produce only first one is processed:
1<figure> 2 <img src="image.png" alt="caption"/> 3 <figcaption>caption</figcaption> 4</figure> 5<img src="image.png" alt="^caption"/>
if you keep enableMdxJsx
is true
, the result would be:
1<figure> 2 <img src="image.png" alt="caption"/> 3 <figcaption>caption</figcaption> 4</figure> 5<figure> 6 <img src="image.png" alt="caption"/> 7 <figcaption>caption</figcaption> 8</figure>
This plugin modifies the hast
(HTML abstract syntax tree).
This package is fully typed with TypeScript. The plugin exports the type ImageToolkitOptions
.
This plugin works with rehype-parse
version 1+, rehype-stringify
version 1+, rehype
version 1+, and unified version 4+
.
Use of rehype-image-toolkit
involves rehype (hast), but doesn't lead to cross-site scripting (XSS) attacks.
I like to contribute the Unified / Remark / MDX ecosystem, so I recommend you to have a look my plugins.
remark-flexible-code-titles
– Remark plugin to add titles or/and containers for the code blocks with customizable propertiesremark-flexible-containers
– Remark plugin to add custom containers with customizable properties in markdownremark-ins
– Remark plugin to add ins
element in markdownremark-flexible-paragraphs
– Remark plugin to add custom paragraphs with customizable properties in markdownremark-flexible-markers
– Remark plugin to add custom mark
element with customizable properties in markdownremark-flexible-toc
– Remark plugin to expose the table of contents via vfile.data
or via an option referenceremark-mdx-remove-esm
– Remark plugin to remove import and/or export statements (mdxjsEsm)rehype-pre-language
– Rehype plugin to add language information as a property to pre
elementrehype-highlight-code-lines
– Rehype plugin to add line numbers to code blocks and allow highlighting of desired code linesrehype-code-meta
– Rehype plugin to copy code.data.meta
to code.properties.metastring
rehype-image-toolkit
– Rehype plugin to enhance Markdown image syntax ![]()
and Markdown/MDX media elements (<img>
, <audio>
, <video>
) by auto-linking bracketed or parenthesized image URLs, wrapping them in <figure>
with optional captions, unwrapping images/videos/audio from paragraph, parsing directives in title for styling and adding attributes, and dynamically converting images into <video>
or <audio>
elements based on file extension.recma-mdx-escape-missing-components
– Recma plugin to set the default value () => null
for the Components in MDX in case of missing or not provided so as not to throw an errorrecma-mdx-change-props
– Recma plugin to change the props
parameter into the _props
in the function _createMdxContent(props) {/* */}
in the compiled source in order to be able to use {props.foo}
like expressions. It is useful for the next-mdx-remote
or next-mdx-remote-client
users in nextjs
applications.recma-mdx-change-imports
– Recma plugin to convert import declarations for assets and media with relative links into variable declarations with string URLs, enabling direct asset URL resolution in compiled MDX.recma-mdx-import-media
– Recma plugin to turn media relative paths into import declarations for both markdown and html syntax in MDX.recma-mdx-import-react
– Recma plugin to ensure getting React
instance from the arguments and to make the runtime props {React, jsx, jsxs, jsxDev, Fragment}
is available in the dynamically imported components in the compiled source of MDX.recma-mdx-html-override
– Recma plugin to allow selected raw HTML elements to be overridden via MDX components.recma-mdx-interpolate
– Recma plugin to enable interpolation of identifiers wrapped in curly braces within the alt
, src
, href
, and title
attributes of markdown link and image syntax in MDX.MIT License © ipikuka
No vulnerabilities found.
No security vulnerabilities found.