
Security News
Attackers Are Hunting High-Impact Node.js Maintainers in a Coordinated Social Engineering Campaign
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.
remark-code-figure
Advanced tools
A remark plugin that wraps code blocks with a figure and adds an optional figcaption.
A remark plugin that wraps code blocks in figure elements with an optional figcaption.
npm install remark-code-figure
remark-code-figure can be used with remark or with unifiedjs.
We have the following test.md file.
# Example markdown
```js My caption text
console.log("Hello, world!");
```
Let's look at a few ways this can be processed with tools in the unified collective.
You can process markdown input and return the transformed markdown output (the figure element will be written directly into markdown):
import report from 'vfile-reporter'; // for reporting errors
import {readSync, writeSync} from 'to-vfile'; // for reading our markdown file
import { remark } from 'remark';
import remarkStringify from 'remark-stringify';
import codeCaption from 'remark-code-caption';
// our processing function
async function mdToRemark(buffer) {
return await remark()
.use(codeFigure)
.use(remarkStringify)
.process(readSync('./test.md'))
.then(async (file) => {
console.error(report(file));
writeSync({path: './marked-test.md', value: String(await file)});
})
}
mdToRemark();
This will write marked-test.md to the file system for us. That file will look like:
# Example markdown
<figure class="code-figure">
<pre>
<code class="language-js">
console.log("Hello, world!");
</code>
</pre>
<figcaption class="code-caption">
My caption text
</figcaption>
</figure>
You can also process markdown input into partial html output. Make sure to use {sanitize: false} in the remarkHtml options or the figure element and its children will be stripped from the document. After that, though, you'll want to use rehype-sanitize to protect yourself from xss attacks.
async function mdHTML() {
return await unified() // you can also use remark!
.use(remarkParse) // but leave this line out if you do
.use(codeFigure)
.use(remarkHtml, {sanitize: false}) // important!
.use(rehypeSanitize)
.process(readSync('./test.md'))
.then(async (file) => {
console.error(report(file));
writeSync({path: './html-test.html', value: String(await file)});
});
}
mdHTML();
Which will give you:
<h1>Test Markdown file</h1>
<figure class="code-figure">
<pre>
<code class="language-js">
console.log("Hello, world");
</code>
</pre>
<figcaption class=code-caption>
My caption text
</figcaption>
</figure>
At the moment, this plugin will work with remark-shiki, but will not work with remark-prism.
This plugin will work with @mapbox/rehype-prism though, you'll just need to call things in the correct order, it's also recommended to use rehype-sanitize to help ensure your final output is safe from XSS attacks:
import prism from '@mapbox/rehype-prism';
async function mdPrism() {
return await remark()
.use(remarkRehype, {allowDangerousHtml: true})
.use(prism)
.use(codeFigure)
.use(rehypeRaw)
.use(rehypeSanitize)
.use(rehypeDocument)
.use(rehypeFormat) // make your html output look nice!
.use(rehypeStringify)
.process(readSync('./test.md'))
.then(async (file) => {
console.error(report(file));
writeSync({path: './mdPrism.html', value: String(await file)});
})
}
mdPrism();
If you want to highlight with remark-shiki, you need to install shiki as a separate dependency.
You'll also need to call the shiki.getHighlighter function:
async function mdShiki() {
const highlighter = await shiki.getHighlighter({theme: 'nord'});
return remark()
.use(remarkShiki, {highlighter})
.use(codeFigure)
.use(remarkRehype, {allowDangerousHtml: true})
.use(rehypeRaw)
.use(rehypeSanitize)
.use(rehypeDocument)
.use(rehypeFormat)
.use(rehypeStringify)
.process(readSync('./test.md'))
.then(async(file) => {
console.error(report(file));
writeSync({path: './mdShiki.html', value: String(await file)});
});
}
mdShiki();
Options are passed to codeFigure as an object. By default, that object looks like this:
{
className: 'code-figure',
captionOptions: {
disable: false,
position: 'after',
className: 'code-caption'
}
}
options.classNameSpecifies the class name of the figure element. Defaults to code-figure.
{
type: string,
default: 'code-figure'
}
options.captionOptions.disableSpecifies whether to disable the figcaption element.
{
type: boolean,
default: false
}
options.captionOptions.positionSpecifies the position of the figcaption element. Can be either "before" or "after".
{
type: string,
default: 'after'
}
options.captionOptions.classNameSpecifies the class name for the figcaption element. Defaults to code-caption.
{
type: string,
default: 'code-caption'
}
FAQs
A remark plugin that wraps code blocks with a figure and adds an optional figcaption.
We found that remark-code-figure demonstrated a not healthy version release cadence and project activity because the last version was released a year ago. It has 1 open source maintainer 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.

Security News
Multiple high-impact npm maintainers confirm they have been targeted in the same social engineering campaign that compromised Axios.

Security News
Axios compromise traced to social engineering, showing how attacks on maintainers can bypass controls and expose the broader software supply chain.

Security News
Node.js has paused its bug bounty program after funding ended, removing payouts for vulnerability reports but keeping its security process unchanged.