npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

remark-admonition-to-blockquote-callout

v1.0.0

Published

Remark plugin for converting Python-Markdown and MkDocs Material admonitions to blockquote callouts.

Readme

remark-admonition-to-blockquote-callout

version codecov npm downloads jsDocs.io

A remark plugin for converting Python-Markdown admonitions and MkDocs Material admonitions to blockquote callouts.

What is this?

This plugin lets source files keep Python-Markdown and MkDocs Material admonition syntax while converting it to blockquote callout syntax:

  • Basic and titled admonitions: !!! note -> > [!note], !!! note "Title" -> > [!note] Title.
  • Markdown titles are preserved: !!! note "A **bold** title" -> > [!note] A **bold** title.
  • Explicit empty titles are treated the same as omitted titles: !!! note "" -> > [!note].
  • Collapsible blocks: ??? note -> > [!note]-, ???+ note -> > [!note]+.
  • Nested admonitions become nested blockquotes: !!! note -> > > [!note].
  • Extra classes are ignored after the type: !!! danger highlight blink "Title" -> > [!danger] Title.
  • Inline modifiers are ignored: !!! info inline "Title" -> > [!info] Title, !!! info inline end "Title" -> > [!info] Title.
  • MkDocs Material and custom types are kept as callout types.
  • Fenced code blocks inside admonitions are preserved.
  • Admonitions inside list items keep their list-item indentation.

When should I use this?

Use this plugin when your Markdown content is written with Python-Markdown or MkDocs Material admonition syntax, but the rest of your unified pipeline expects blockquote-based callouts.

This is especially useful when migrating documentation to a Markdown/MDX site powered by frameworks such as Astro or Next.js: keep Python-Markdown admonition syntax in source files, convert it in remark, and consider rehype-callouts if you also need to render the generated blockquote-based callouts as HTML.

Installation

This package is ESM only. In Node.js (version 16+), install with your package manager:

npm install remark-admonition-to-blockquote-callout
yarn add remark-admonition-to-blockquote-callout
pnpm add remark-admonition-to-blockquote-callout

In Deno with esm.sh:

import remarkAdmonitionToBlockquoteCallout from 'https://esm.sh/remark-admonition-to-blockquote-callout'

In browsers with esm.sh:

<script type="module">
  import remarkAdmonitionToBlockquoteCallout from 'https://esm.sh/remark-admonition-to-blockquote-callout?bundle'
</script>

Usage

Import and use the plugin before other remark plugins whose mdast changes must be preserved.

Say example.md contains:

!!! note
    Basic content.

!!! info "Custom **title**"
    Markdown title content.

???+ tip inline "Open"
    Open by default.

    ```js
    const marker = "!!! note";
    ```

    !!! success ""
        Nested empty-title admonition.

??? failure inline end "Closed"
    Closed by default.

* In a list item:

    !!! custom highlight
        Extra classes are ignored.

And module example.js contains:

import { remark } from 'remark'
import remarkAdmonitionToBlockquoteCallout from 'remark-admonition-to-blockquote-callout'
import { read } from 'to-vfile'

const file = await remark()
  .use(remarkAdmonitionToBlockquoteCallout)
  .process(await read('example.md'))

// `remark` escapes callout markers as `\[!type]` for safe Markdown output,
// preventing `[!type]` from being parsed as a link reference. Restore only
// blockquote callouts for Markdown text; AST-based unified transforms do not need it.
const output = String(file).replaceAll(
  /^(\s*>(?: >)*\s*)\\(\[![^\]\n]+])/gm,
  '$1$2'
)

console.log(output)

Then running node example.js yields:

> [!note]
> Basic content.

> [!info] Custom **title**
> Markdown title content.

> [!tip]+ Open
> Open by default.
>
> ```js
> const marker = "!!! note";
> ```
>
> > [!success]
> > Nested empty-title admonition.

> [!failure]- Closed
> Closed by default.

* In a list item:

  > [!custom]
  > Extra classes are ignored.

[!warning] When this plugin converts admonitions, it reparses the transformed Markdown and replaces the current mdast root. Place it before remark plugins that mutate mdast if those mutations must be preserved.

When writing admonitions, avoid mixing spaces and tabs for indentation. Mixed indentation can make admonition boundaries ambiguous and may prevent correct conversion.

[!note] This plugin is intentionally lenient when collecting admonition bodies. After an opening marker is found, following lines with deeper indentation are treated as body content, even if they do not follow the indentation rules required by Python-Markdown.

For example, both of these inputs are converted:

!!! note
  This is a note.

!!! note
       This is a note.
> [!note]
> This is a note.

> [!note]
> This is a note.

API

This package exports no identifiers. The default export is remarkAdmonitionToBlockquoteCallout.

unified().use(remarkAdmonitionToBlockquoteCallout)

Used to convert Python-Markdown and MkDocs Material admonitions to blockquote callouts.

Parameters

There are no options.

Returns

Transform (Transformer).

Example

Example: Render Python-Markdown Admonitions as HTML

This plugin only converts admonition Markdown syntax to blockquote callouts; use rehype-callouts later in the pipeline when those callouts should be rendered as HTML.

Module example.js contains:

import { unified } from 'unified'
import remarkParse from 'remark-parse'
import remarkAdmonitionToBlockquoteCallout from 'remark-admonition-to-blockquote-callout'
import remarkRehype from 'remark-rehype'
import rehypeCalloouts from 'rehype-callouts'
import rehypeStringify from 'rehype-stringify'
import { readSync } from 'to-vfile'

const processor = unified()
  .use(remarkParse)
  .use(remarkAdmonitionToBlockquoteCallout)
  .use(remarkRehype)
  .use(rehypeCalloouts, {
    callouts: {
      custom: { title: 'Custom Type' },
    },
  })
  .use(rehypeStringify)

const output = String(
  processor.processSync(readSync('example.md'))
)

console.log(output)

Then running node example.js yields:

<div class="callout" data-callout="note" data-collapsible="false">
  <div class="callout-title">
    <div class="callout-title-icon" aria-hidden="true">
      <!-- svg icon-->
    </div>
    <div class="callout-title-text">Note</div>
  </div>
  <div class="callout-content"><p>Basic content.</p></div>
</div>
<div class="callout" data-callout="info" data-collapsible="false">
  <div class="callout-title">
    <div class="callout-title-icon" aria-hidden="true">
      <!-- svg icon-->
    </div>
    <div class="callout-title-text">Custom <strong>title</strong></div>
  </div>
  <div class="callout-content"><p>Markdown title content.</p></div>
</div>
<details class="callout" data-callout="tip" data-collapsible="true" open>
  <summary class="callout-title">
    <div class="callout-title-icon" aria-hidden="true">
      <!-- svg icon-->
    </div>
    <div class="callout-title-text">Open</div>
    <div class="callout-fold-icon" aria-hidden="true">
      <!-- svg icon-->, 
    </div>
  </summary>
  <div class="callout-content">
    <p>Open by default.</p>
    <pre><code class="language-js">const marker = "!!! note";</code></pre>
    <div class="callout" data-callout="success" data-collapsible="false">
      <div class="callout-title">
        <div class="callout-title-icon" aria-hidden="true">
          <!-- svg icon-->
        </div>
        <div class="callout-title-text">Success</div>
      </div>
      <div class="callout-content"><p>Nested empty-title admonition.</p></div>
    </div>
  </div>
</details>
<details class="callout" data-callout="failure" data-collapsible="true">
  <summary class="callout-title">
    <div class="callout-title-icon" aria-hidden="true">
      <!-- svg icon-->
    </div>
    <div class="callout-title-text">Closed</div>
    <div class="callout-fold-icon" aria-hidden="true">
      <!-- svg icon-->
    </div>
  </summary>
  <div class="callout-content"><p>Closed by default.</p></div>
</details>
<ul>
  <li>
    <p>In a list item:</p>
    <div class="callout" data-callout="custom" data-collapsible="false">
      <div class="callout-title">
        <div class="callout-title-text">Custom Type</div>
      </div>
      <div class="callout-content"><p>Extra classes are ignored.</p></div>
    </div>
  </li>
</ul>

Types

This package is fully typed with TypeScript. It exports no additional public types.

Contribution

If you see any errors or room for improvement on this plugin, feel free to open an issues or pull request . Thank you in advance for contributing!

License

MIT © 2026-PRESENT Stephanie Lin