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

@dr-ishaan/remark-callout

v1.0.0

Published

Remark plugin for GitHub/Obsidian-style callouts, literary types (epigraph/pullquote/aside/sidebar), and accordions with native exclusive expansion. Transforms [!TYPE] blockquotes into styled HTML containers with SVG icons, oklch colors, rich titles, and

Readme

remark-callout

npm version License: MIT

A remark plugin for the unified pipeline that transforms GitHub/Obsidian-style callout blockquotes into styled HTML containers — with SVG icons, oklch colors, collapsible support, rich titles, literary types (epigraph/pullquote/aside/sidebar), and a separate accordion family with native exclusive expansion.

Syntax

Callouts — [!TYPE]

> [!NOTE]
> Simple note body.

> [!WARNING] Custom title
> Multi-line content.

> [!TIP]+
> Collapsible, open by default.

> [!DANGER]-
> Collapsible, closed by default.

> [!NOTE] **Rich title** with `inline code` and [links](https://example.com)
> Body text on the next line.

Rich titles

Inline markdown on the marker line (after [!TYPE]) is rendered as HTML inside the title span:

| Input | Rendered title | |---|---| | > [!NOTE] **bold** | <strong>bold</strong> | | > [!NOTE] mixed **bold** text | mixed <strong>bold</strong> text | | > [!NOTE] [link](http://x) | <a href="http://x">link</a> | | > [!NOTE] \code`|code| |> [!NOTE] plain text|plain text| |> [!NOTE](nothing) |Note` (default from config) |

Content on subsequent lines (after a newline) is body content, not title.

Literary types — [!EPIGRAPH], [!PULLQUOTE], [!ASIDE], [!SIDEBAR]

Literary types render as semantic HTML elements (<figure> / <aside>) instead of callout boxes — no border, no icon, no colored chrome. They include automatic attribution detection (em-dash , en-dash , or double-hyphen -- on the last body line).

> [!EPIGRAPH] Charles Dickens
> "It was the best of times, it was the worst of times."

> [!PULLQUOTE]
> "Design is not just what it looks like and feels like. Design is how it works."
> — Steve Jobs

> [!ASIDE] Tangent
> A marginal note that doesn't break the main flow.

> [!SIDEBAR] Related concept
> A magazine-style sidebar with its own visual identity.
> — Author Name

| Type | Renders as | Attribution | |---|---|---| | [!EPIGRAPH] | <figure><blockquote/><figcaption/></figure> | Custom title or — Author trailing line | | [!PULLQUOTE] / [!PULL] | <figure> (smaller) | Same as epigraph | | [!ASIDE] | <aside> with optional heading + body + attribution | — Author trailing line | | [!SIDEBAR] | <aside> (wider, magazine-style) | — Author trailing line |

Accordions — [!!] (separate family)

Accordions are a separate visual family from callouts — no callout DNA (no left-border accent, no colored chrome, no type-driven color theming). The only color comes from the user-supplied icon. Adjacent panels form a group with native exclusive expansion via <details name="..."> (zero JavaScript).

> [!!] Bare accordion (no icon)
> Body content goes here.

> [! 💻 !] Laptop
> A panel with an emoji icon.

> [! 💡 !]+ Bright idea
> A panel that's open by default.

> [! <svg>...</svg> !] Custom SVG icon
> A panel with an inline SVG icon.

Multiple panels in one blockquote — separated by blank > lines, they auto-group:

> [! 😮 !] What is this?
> First panel body.
>
> [!!] Who are you?
> Second panel body.

Accordion marker forms

| Form | Syntax | Description | |---|---|---| | Bare | [!!] Title | No icon, just title | | Shorthand | [! icon !] Title | Icon (emoji or SVG) between the two !s | | Long form | [!!] [! icon !] Title | Bare marker + icon sub-token (legacy) |

All three forms support + / - foldable suffixes:

  • [!!]+ — open by default
  • [!!]- — closed by default (same as bare default)
  • [! 💡 !]+ — open with icon

Default state is collapsed.

Adjacency grouping

Adjacent accordion panels (siblings with no non-accordion content between them) form a group with native exclusive expansion — opening one panel automatically closes the others in the same group. This is implemented via the HTML <details name="..."> attribute (no JavaScript).

Different groups get unique counter-based name IDs (accordion-group-1, accordion-group-2, …).

Features

  • 210+ built-in callout types across 12 color families (note, tip, warning, danger, success, question, info, example, abstract, quote, bug, best-practice, …)
  • Literary types — epigraph, pullquote, aside, sidebar render as semantic <figure>/<aside> with attribution detection
  • Accordion family[!!] marker with native <details name="..."> exclusive expansion, zero JavaScript
  • SVG icons — Lucide-style, 24×24 viewBox, stroke-based, using currentColor
  • oklch colors — perceptually uniform, automatic dark mode via prefers-color-scheme
  • Collapsible callouts — native <details>/<summary> with + (open) / - (closed) syntax, zero JavaScript
  • Rich titles — inline markdown in the title (bold, italic, links, code) renders as HTML in the title span
  • Case-insensitive type matching — [!NOTE], [!note], [!NoTe] all work
  • Hyphenated types[!BEST-PRACTICE], [!RATE-LIMIT], [!CI-CD]
  • CRLF-compatible — Windows (\r\n), old Mac (\r), and Unix (\n) line endings all work
  • Custom callout types — define your own with callouts, icons, titles options
  • Single-pass recursive transformer — handles arbitrarily deep nesting with no cap
  • No allowDangerousHtml required — SVG icons are parsed into proper HAST elements via hast-util-from-html

Install

npm install remark-callout

Usage

import { unified } from 'unified'
import remarkParse from 'remark-parse'
import remarkCallout, { calloutToHast } from 'remark-callout'
import remarkRehype from 'remark-rehype'
import rehypeStringify from 'rehype-stringify'

// Import the default stylesheet (Astro / Vite / any CSS-aware bundler)
import 'remark-callout/styles/callout.css'

const result = unified()
  .use(remarkParse)
  .use(remarkCallout)
  .use(remarkRehype, { handlers: { callout: calloutToHast } })
  .use(rehypeStringify)
  .processSync('> [!NOTE]\n> Hello world')

console.log(String(result))

Important: You MUST pass { handlers: { callout: calloutToHast } } to remark-rehype. Without it, callouts render as empty <div>s with no header, body, or icon.

Options

remarkCallout({
  // Custom callout type definitions (keys are case-insensitive)
  callouts: {
    myType: {
      defaultTitle: 'My Type',
      icon: '<svg>...</svg>',
      colorL: 0.55,  // oklch lightness (0–1)
      colorC: 0.18,  // oklch chroma  (0–0.4)
      colorH: 300,   // oklch hue      (0–360)
    },
  },

  // Override icons for existing types (auto-creates a stub type if missing)
  icons: {
    note: '<svg>...</svg>',
  },

  // Override default titles for existing types
  titles: {
    note: 'Heads Up',
  },

  // Hide the title or icon span entirely
  showTitle: true,   // default
  showIcon:  true,   // default

  // Enable collapsible syntax (+ / -). Default: true.
  enableFoldable: true,

  // Disable all built-in types (use with `callouts` to define everything yourself)
  disableBuiltins: false,

  // Tag name for non-foldable callout container. Default: 'div'.
  // (Foldable callouts always use <details>.)
  tag: 'div',
})

Output HTML

Non-foldable callout

> [!NOTE]
> Body text.
<div class="callout callout-note" data-callout="note"
     style="--callout-l: 0.55; --callout-c: 0.18; --callout-h: 250;">
  <div class="callout-header">
    <span class="callout-icon" aria-hidden="true"><svg>...</svg></span>
    <span class="callout-title">Note</span>
  </div>
  <div class="callout-body">
    <p>Body text.</p>
  </div>
</div>

Foldable callout (open)

> [!TIP]+
> Expanded by default.
<details class="callout callout-tip callout-foldable" data-callout="tip"
         data-callout-fold="open" open
         style="--callout-l: 0.60; --callout-c: 0.17; --callout-h: 155;">
  <summary class="callout-header">
    <span class="callout-icon" aria-hidden="true"><svg>...</svg></span>
    <span class="callout-title">Tip</span>
  </summary>
  <div class="callout-body">
    <p>Expanded by default.</p>
  </div>
</details>

Epigraph (literary)

> [!EPIGRAPH]
> "It was the best of times."
> — Charles Dickens
<figure class="epigraph">
  <blockquote class="epigraph-quote">
    <p>"It was the best of times."</p>
  </blockquote>
  <figcaption class="epigraph-attribution">— Charles Dickens</figcaption>
</figure>

Accordion panel

> [! 💻 !] Laptop
> A panel with an emoji icon.
<details class="accordion" name="accordion-group-1">
  <summary class="accordion-header">
    <span class="accordion-icon" aria-hidden="true">💻</span>
    <span class="accordion-title">Laptop</span>
    <span class="accordion-chevron" aria-hidden="true"></span>
  </summary>
  <div class="accordion-body">
    <p>A panel with an emoji icon.</p>
  </div>
</details>

Styling

The default stylesheet uses CSS custom properties (oklch color components) set inline on each callout. Override any of these in your own CSS:

:root {
  --callout-radius: 0.5rem;
  --callout-padding: 1rem 1.25rem;
  --callout-margin: 1.5em 0;
  --callout-border-width: 4px;
  --callout-header-gap: 0.5rem;
  --callout-header-margin-bottom: 0.5rem;
  --callout-body-font-size: 1.05rem;
  --callout-title-font-size: 1.2rem;
  --callout-title-font-weight: 600;
  --callout-icon-size: 1.15rem;

  --callout-bg-alpha: 0.06;
  --callout-border-alpha: 1;
  --callout-icon-alpha: 1;

  /* Accordion variables */
  --accordion-radius: 12px;
  --accordion-border-color: #e5e7eb;
  --accordion-bg: #ffffff;
  --accordion-body-bg: #f9fafb;
  --accordion-title-color: #111827;
  --accordion-chevron-color: #6b7280;
  --accordion-icon-size: 1.25rem;
}

Dark mode is automatic via @media (prefers-color-scheme: dark).

Built-in Callout Types

The plugin ships with 210+ built-in callout types across 12 color families:

| Family | Hue | Examples | |---|---|---| | Blue | ~250 | note, info, example, abstract, update, figure, … | | Green | ~155 | tip, hint, success, check, done, … | | Purple | ~300 | important, quote, cite, definition, bibliography, references, citation, related, … | | Amber | ~80 | warning, attention, todo, correction, draft, … | | Orange | ~55 | question, help, faq, further-reading, discussion, … | | Red | ~25 | caution, danger, error, failure, bug, … | | Cyan | ~195 | security, accessibility, … | | Teal | ~180 | best-practice, milestone, scalability, … | | Pink | ~345 | trivia, ux-insight, … | | Indigo | ~270 | deep-dive, … | | Gray | ~0 | shortcut, environment, hardware, … | | Silver | ~0 | licensing, … |

Literary types (render as <figure>/<aside>, not callout boxes):

  • [!EPIGRAPH] — large article-opener quote
  • [!PULLQUOTE] / [!PULL] — mid-article scanner-bait quote
  • [!ASIDE] — compact marginal note
  • [!SIDEBAR] — magazine-style content box

Accordion family (separate from callouts):

  • [!!] — bare accordion panel
  • [! icon !] — accordion with emoji or SVG icon

See src/defaults.ts for the complete list with their default titles, icons, and colors.

Development

# Install dependencies
npm install

# Build TypeScript → dist/
npm run build

# Watch mode for development
npm run dev

License

MIT © dr-ishaan