Security News
PyPI Introduces Digital Attestations to Strengthen Python Package Security
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
@microflash/remark-callout-directives
Advanced tools
remark plugin to render callouts and admonitions with directives
remark plugin to render callouts and admonitions with directives
This package is a unified (remark) plugin to add support for callouts and admonitions using the directives. It depends on remark-directive which must be included before this plugin.
Callouts and admonitions are used to provide additional information related to a topic under discussion or draw out attention to potential possibilities. They are widely used in documentation by popular libraries, frameworks, and applications (for example, Docusaurus, Obsidian, etc). Use this plugin if you need something similar.
You should import remark-directive
before this plugin for callouts to work.
This package is ESM only.
In Node.js (version 16.0+), install with npm:
npm install @microflash/remark-callout-directives
In Deno, with esm.sh:
import remarkCalloutDirectives from "https://esm.sh/@microflash/remark-callout-directives"
In browsers, with esm.sh:
<script type="module">
import remarkCalloutDirectives from "https://esm.sh/@microflash/remark-callout-directives?bundle"
</script>
Say we have the following file example.md
:
:::note
Some **content** with _Markdown_ `syntax`.
:::
And our module example.js
looks as follows:
import { read } from "to-vfile"
import { unified } from "unified"
import remarkParse from "remark-parse"
import remarkDirective from "remark-directive"
import remarkCalloutDirectives from "@microflash/remark-callout-directives"
import remarkRehype from "remark-rehype"
import rehypeStringify from "rehype-stringify"
main()
async function main() {
const file = await unified()
.use(remarkParse)
.use(remarkDirective)
.use(remarkCalloutDirectives)
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeStringify, { allowDangerousHtml: true })
.process(await read("example.md"))
console.log(String(file))
}
Running that with node example.js
yields:
<aside class="callout callout-note">
<div class="callout-indicator">
<div class="callout-hint">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M12 8h.01M12 12v4"/>
<circle cx="12" cy="12" r="10"/>
</svg>
</div>
<div class="callout-title">Note</div>
</div>
<div class="callout-content">
<p>Some <strong>content</strong> with <em>Markdown</em> <code>syntax</code>.
</p>
</div>
</aside>
The default export is remarkCalloutDirectives
.
The following options are available. All of them are optional.
aliases
: a list of aliases for the callouts
callouts
: an object containing the callout definitionstagName
: global custom element type. If specified, it'll override the default aside
element type. This can be overridden by callout specific configuration (callouts.<calloutName>.tagName
).By default, the following callouts and aliases are preconfigured.
{
aliases: {},
callouts: {
note: {
title: "Note",
hint: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M12 8h.01M12 12v4"/><circle cx="12" cy="12" r="10"/></svg>`
},
commend: {
title: "Success",
hint: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="m8 12 2.7 2.7L16 9.3"/><circle cx="12" cy="12" r="10"/></svg>`
},
warn: {
title: "Warning",
hint: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M12 9v4m0 4h.01M8.681 4.082C9.351 2.797 10.621 2 12 2s2.649.797 3.319 2.082l6.203 11.904a4.28 4.28 0 0 1-.046 4.019C20.793 21.241 19.549 22 18.203 22H5.797c-1.346 0-2.59-.759-3.273-1.995a4.28 4.28 0 0 1-.046-4.019L8.681 4.082Z"/></svg>`
},
deter: {
title: "Danger",
hint: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M12 12s-5.6 4.6-3.6 8c1.6 2.6 5.7 2.7 7.2 0 2-3.7-3.6-8-3.6-8Z"/><path d="M13.004 2 8.5 9 6.001 6s-4.268 7.206-1.629 11.8c3.016 5.5 11.964 5.7 15.08 0C23.876 10 13.004 2 13.004 2Z"/></svg>`
},
assert: {
title: "Info",
hint: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M12.5 7.5h.01m-.01 4v4m-7.926.685L2 21l6.136-1.949c1.307.606 2.791.949 4.364.949 5.243 0 9.5-3.809 9.5-8.5S17.743 3 12.5 3 3 6.809 3 11.5c0 1.731.579 3.341 1.574 4.685"/></svg>`
}
}
}
To style the callouts, import a theme from themes
folder.
For more advanced customizations, take a look at the existing themes and remix your own.
Say we have the following file example.md
:
:::warn{title="Hold on there"}
Some **content** with _Markdown_ `syntax`.
:::
Running example.js
will yield:
<aside class="callout callout-warn">
<div class="callout-indicator">
<div class="callout-hint">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M12 9v4m0 4h.01M8.681 4.082C9.351 2.797 10.621 2 12 2s2.649.797 3.319 2.082l6.203 11.904a4.28 4.28 0 0 1-.046 4.019C20.793 21.241 19.549 22 18.203 22H5.797c-1.346 0-2.59-.759-3.273-1.995a4.28 4.28 0 0 1-.046-4.019L8.681 4.082Z"/>
</svg>
</div>
<div class="callout-title">Hold on there</div>
</div>
<div class="callout-content">
<p>Some <strong>content</strong> with <em>Markdown</em> <code>syntax</code>.</p>
</div>
</aside>
Say we have the following file example.md
:
:::warn{title="**Hold** on _there_!"}
Some **content** with _Markdown_ `syntax`.
:::
Running example.js
will yield:
<aside class="callout callout-warn">
<div class="callout-indicator">
<div class="callout-hint">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M12 9v4m0 4h.01M8.681 4.082C9.351 2.797 10.621 2 12 2s2.649.797 3.319 2.082l6.203 11.904a4.28 4.28 0 0 1-.046 4.019C20.793 21.241 19.549 22 18.203 22H5.797c-1.346 0-2.59-.759-3.273-1.995a4.28 4.28 0 0 1-.046-4.019L8.681 4.082Z"/>
</svg>
</div>
<div class="callout-title">
<strong>Hold</strong> on <em>there</em>!
</div>
</div>
<div class="callout-content">
<p>Some <strong>content</strong> with <em>Markdown</em> <code>syntax</code>.</p>
</div>
</aside>
You can add your own callouts as well. Say we have the following file example.md
:
:::shoutout{title="Well done!"}
Some **content** with _Markdown_ `syntax`.
:::
And our module example.js
looks as follows:
import { read } from "to-vfile"
import { unified } from "unified"
import remarkParse from "remark-parse"
import remarkDirective from "remark-directive"
import remarkCalloutDirectives from "@microflash/remark-callout-directives"
import remarkRehype from "remark-rehype"
import rehypeStringify from "rehype-stringify"
main()
async function main() {
const file = await unified()
.use(remarkParse)
.use(remarkDirective)
.use(remarkCalloutDirectives, {
callouts: {
shoutout: {
title: "Shoutout",
hint: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M4.7 6.5h.01m8.49-2.8h.01m4.29 15.6h.01m2.79-8.5h.01m-6.41-.7 2.2-.7V6.5h2.8V3.7L21 3m-6.253 10.767c1.676-.175 2.93-.38 3.739-.064 1.234.483 1.497 1.529 1.409 3.008m-9.723-7.519c.175-1.676.38-2.93.064-3.739-.483-1.234-1.529-1.497-3.008-1.409M6.5 10.4l7.1 7.1L3 21z"/></svg>`
}
}
})
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeStringify, { allowDangerousHtml: true })
.process(await read("example.md"))
console.log(String(file))
}
Running example.js
will yield:
<aside class="callout callout-shoutout">
<div class="callout-indicator">
<div class="callout-hint">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M4.7 6.5h.01m8.49-2.8h.01m4.29 15.6h.01m2.79-8.5h.01m-6.41-.7 2.2-.7V6.5h2.8V3.7L21 3m-6.253 10.767c1.676-.175 2.93-.38 3.739-.064 1.234.483 1.497 1.529 1.409 3.008m-9.723-7.519c.175-1.676.38-2.93.064-3.739-.483-1.234-1.529-1.497-3.008-1.409M6.5 10.4l7.1 7.1L3 21z"/>
</svg>
</div>
<div class="callout-title">Well done!</div>
</div>
<div class="callout-content">
<p>Some <strong>content</strong> with <em>Markdown</em> <code>syntax</code>.</p>
</div>
</aside>
Say we have the following file example.md
:
:::danger
Some **content** with _Markdown_ `syntax`.
:::
And our module example.js
looks as follows:
import { read } from "to-vfile"
import { unified } from "unified"
import remarkParse from "remark-parse"
import remarkDirective from "remark-directive"
import remarkCalloutDirectives from "@microflash/remark-callout-directives"
import remarkRehype from "remark-rehype"
import rehypeStringify from "rehype-stringify"
main()
async function main() {
const file = await unified()
.use(remarkParse)
.use(remarkDirective)
.use(remarkCalloutDirectives, {
aliases: {
danger: "deter"
}
})
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeStringify, { allowDangerousHtml: true })
.process(await read("example.md"))
console.log(String(file))
}
Running that with node example.js
yields:
<aside class="callout callout-deter">
<div class="callout-indicator">
<div class="callout-hint">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M12 12s-5.6 4.6-3.6 8c1.6 2.6 5.7 2.7 7.2 0 2-3.7-3.6-8-3.6-8Z"/>
<path d="M13.004 2 8.5 9 6.001 6s-4.268 7.206-1.629 11.8c3.016 5.5 11.964 5.7 15.08 0C23.876 10 13.004 2 13.004 2Z"/>
</svg>
</div>
<div class="callout-title">Danger</div>
</div>
<div class="callout-content">
<p>Some <strong>content</strong> with <em>Markdown</em> <code>syntax</code>.</p>
</div>
</aside>
By default, a callout is rendered as an aside
. You can override this behavior by providing a tagName
for the callout.
Say we have the following file example.md
:
:::assert
Some **content** with _Markdown_ `syntax`.
:::
And our module example.js
looks as follows:
import { read } from "to-vfile"
import { unified } from "unified"
import remarkParse from "remark-parse"
import remarkDirective from "remark-directive"
import remarkCalloutDirectives from "@microflash/remark-callout-directives"
import remarkRehype from "remark-rehype"
import rehypeStringify from "rehype-stringify"
main()
async function main() {
const file = await unified()
.use(remarkParse)
.use(remarkDirective)
.use(remarkCalloutDirectives, {
callouts: {
assert: {
tagName: "div"
}
}
})
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeStringify, { allowDangerousHtml: true })
.process(await read("example.md"))
console.log(String(file))
}
Running that with node example.js
yields:
<div class="callout callout-assert">
<div class="callout-indicator">
<div class="callout-hint">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M12.5 7.5h.01m-.01 4v4m-7.926.685L2 21l6.136-1.949c1.307.606 2.791.949 4.364.949 5.243 0 9.5-3.809 9.5-8.5S17.743 3 12.5 3 3 6.809 3 11.5c0 1.731.579 3.341 1.574 4.685"/>
</svg>
</div>
<div class="callout-title">Info</div>
</div>
<div class="callout-content">
<p>Some <strong>content</strong> with <em>Markdown</em> <code>syntax</code>.</p>
</div>
</div>
You can override the element type of all callouts by providing a tagName
.
Say we have the following file example.md
:
:::assert
Some **content** with _Markdown_ `syntax`.
:::
And our module example.js
looks as follows:
import { read } from "to-vfile"
import { unified } from "unified"
import remarkParse from "remark-parse"
import remarkDirective from "remark-directive"
import remarkCalloutDirectives from "@microflash/remark-callout-directives"
import remarkRehype from "remark-rehype"
import rehypeStringify from "rehype-stringify"
main()
async function main() {
const file = await unified()
.use(remarkParse)
.use(remarkDirective)
.use(remarkCalloutDirectives, {
tagName: "section"
})
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeStringify, { allowDangerousHtml: true })
.process(await read("example.md"))
console.log(String(file))
}
Running that with node example.js
yields:
<section class="callout callout-assert">
<div class="callout-indicator">
<div class="callout-hint">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M12.5 7.5h.01m-.01 4v4m-7.926.685L2 21l6.136-1.949c1.307.606 2.791.949 4.364.949 5.243 0 9.5-3.809 9.5-8.5S17.743 3 12.5 3 3 6.809 3 11.5c0 1.731.579 3.341 1.574 4.685"/>
</svg>
</div>
<div class="callout-title">Info</div>
</div>
<div class="callout-content">
<p>Some <strong>content</strong> with <em>Markdown</em> <code>syntax</code>.</p>
</div>
</section>
You can mix the tagName
configurations globally and specifically for a callout.
Say we have the following file example.md
:
:::assert
Some **content** with _Markdown_ `syntax`.
:::
:::note
Some **content** with _Markdown_ `syntax`.
:::
And our module example.js
looks as follows:
import { read } from "to-vfile"
import { unified } from "unified"
import remarkParse from "remark-parse"
import remarkDirective from "remark-directive"
import remarkCalloutDirectives from "@microflash/remark-callout-directives"
import remarkRehype from "remark-rehype"
import rehypeStringify from "rehype-stringify"
main()
async function main() {
const file = await unified()
.use(remarkParse)
.use(remarkDirective)
.use(remarkCalloutDirectives, {
tagName: "section",
callouts: {
assert: {
tagName: "div"
}
}
})
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeStringify, { allowDangerousHtml: true })
.process(await read("example.md"))
console.log(String(file))
}
Running that with node example.js
yields:
<div class="callout callout-assert">
<div class="callout-indicator">
<div class="callout-hint">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M12.5 7.5h.01m-.01 4v4m-7.926.685L2 21l6.136-1.949c1.307.606 2.791.949 4.364.949 5.243 0 9.5-3.809 9.5-8.5S17.743 3 12.5 3 3 6.809 3 11.5c0 1.731.579 3.341 1.574 4.685"/>
</svg>
</div>
<div class="callout-title">Info</div>
</div>
<div class="callout-content">
<p>Some <strong>content</strong> with <em>Markdown</em> <code>syntax</code>.</p>
</div>
</div>
<section class="callout callout-note">
<div class="callout-indicator">
<div class="callout-hint">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M12 8h.01M12 12v4"/>
<circle cx="12" cy="12" r="10"/>
</svg>
</div>
<div class="callout-title">Note</div>
</div>
<div class="callout-content">
<p>Some <strong>content</strong> with <em>Markdown</em> <code>syntax</code>.
</p>
</div>
</section>
You can override the defaults by passing your own preferences; they will be merged on top of the default values.
Say we have the following file example.md
:
:::commend
Some **content** with _Markdown_ `syntax`.
:::
And our module example.js
looks as follows:
import { read } from "to-vfile"
import { unified } from "unified"
import remarkParse from "remark-parse"
import remarkDirective from "remark-directive"
import remarkCalloutDirectives from "@microflash/remark-callout-directives"
import remarkRehype from "remark-rehype"
import rehypeStringify from "rehype-stringify"
main()
async function main() {
const file = await unified()
.use(remarkParse)
.use(remarkDirective)
.use(remarkCalloutDirectives, {
callouts: {
commend: {
title: "Tip",
hint: `<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2"><path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/><path d="M22 4 12 14.01l-3-3"/></svg>`
}
}
})
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeStringify, { allowDangerousHtml: true })
.process(await read("example.md"))
console.log(String(file))
}
Running that with node example.js
yields:
<aside class="callout callout-commend">
<div class="callout-indicator">
<div class="callout-hint">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-linecap="round" stroke-linejoin="round" stroke-width="2">
<path d="M22 11.08V12a10 10 0 1 1-5.93-9.14"/>
<path d="M22 4 12 14.01l-3-3"/>
</svg>
</div>
<div class="callout-title">Tip</div>
</div>
<div class="callout-content">
<p>Some <strong>content</strong> with <em>Markdown</em> <code>syntax</code>.</p>
</div>
</aside>
You can remove the indicator using the showIndicator="false"
property on a callout.
Say we have the following file example.md
:
::note{showIndicator="false"}
Some **content** with _Markdown_ `syntax`.
:::
And our module example.js
looks as follows:
import { read } from "to-vfile"
import { unified } from "unified"
import remarkParse from "remark-parse"
import remarkDirective from "remark-directive"
import remarkCalloutDirectives from "@microflash/remark-callout-directives"
import remarkRehype from "remark-rehype"
import rehypeStringify from "rehype-stringify"
main()
async function main() {
const file = await unified()
.use(remarkParse)
.use(remarkDirective)
.use(remarkCalloutDirectives)
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeStringify, { allowDangerousHtml: true })
.process(await read("example.md"))
console.log(String(file))
}
Running that with node example.js
yields:
<aside class="callout callout-note">
<div class="callout-content">
<p>Some <strong>content</strong> with <em>Markdown</em> <code>syntax</code>.</p>
</div>
</aside>
Say, you want to use the GitHub theme.
First, import the options for this theme and pass it to the plugin as follows.
import { read } from "to-vfile"
import { unified } from "unified"
import remarkParse from "remark-parse"
import remarkDirective from "remark-directive"
import remarkCalloutDirectives from "@microflash/remark-callout-directives"
import githubCalloutOptions from "@microflash/remark-callout-directives/config/github"
import remarkRehype from "remark-rehype"
import rehypeStringify from "rehype-stringify"
main()
async function main() {
const file = await unified()
.use(remarkParse)
.use(remarkDirective)
.use(remarkCalloutDirectives, githubCalloutOptions)
.use(remarkRehype, { allowDangerousHtml: true })
.use(rehypeStringify, { allowDangerousHtml: true })
.process(await read("example.md"))
console.log(String(file))
}
Finally, import the CSS file. If you've an entrypoint file in your application, you can import the CSS as follows.
import "@microflash/remark-callout-directives/theme/github"
// or using URL import
import "https://unpkg.com/@microflash/remark-callout-directives/themes/github/index.css"
If you're bundling the CSS files using a bundler, you can import the CSS in your main CSS file containing other imports.
/* other imports... */
@import "@microflash/remark-callout-directives/theme/github";
If you're using Sass, you can import the CSS in your main Sass file.
// other Sass imports
@use "@microflash/remark-callout-directives/theme/github";
You can also import the CSS file directly in browsers, with unpkg.com or jsdelivr.net:
<link rel="stylesheet" href="https://unpkg.com/@microflash/remark-callout-directives/themes/github/index.css">
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@microflash/remark-callout-directives/themes/github/index.css">
FAQs
remark plugin to render callouts and admonitions with directives
We found that @microflash/remark-callout-directives demonstrated a healthy version release cadence and project activity because the last version was released less than a year ago. It has 0 open source maintainers 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
PyPI now supports digital attestations, enhancing security and trust by allowing package maintainers to verify the authenticity of Python packages.
Security News
GitHub removed 27 malicious pull requests attempting to inject harmful code across multiple open source repositories, in another round of low-effort attacks.
Security News
RubyGems.org has added a new "maintainer" role that allows for publishing new versions of gems. This new permission type is aimed at improving security for gem owners and the service overall.