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

docusaurus-plugin-figure-caption

v1.0.0

Published

A remark plugin that auto-wraps images in <figure> with numbered <figcaption> and cross-reference support. Works with Docusaurus, MDX, and any unified/remark pipeline.

Readme

docusaurus-plugin-figure-caption

A remark plugin that auto-wraps images in <figure> elements with numbered <figcaption> captions and cross-reference support.

Works with Docusaurus 3+, MDX, and any unified/remark pipeline.

Features

  • Auto-numbering — Images get Figure 1:, Figure 2:, etc. automatically
  • Tags & cross-references — Tag an image with #my-tag, then reference it anywhere with fig:my-tag
  • Cross-references resolve to clickable linksfig:my-tag becomes <a href="#fig-my-tag">Figure 3</a>
  • Docusaurus-native — Handles Docusaurus's JSX image transforms out of the box
  • Smart exclusion — Skips images inside tables and links (badges, buttons)
  • Configurable — Caption source, numbering mode, position, CSS classes, ID generation
  • Dark mode ready — Included CSS supports Docusaurus dark theme
  • Dual format — Ships ESM + CJS with full TypeScript declarations

Installation

npm install docusaurus-plugin-figure-caption
# or
pnpm add docusaurus-plugin-figure-caption
# or
yarn add docusaurus-plugin-figure-caption

Quick Start

Docusaurus

// docusaurus.config.ts
import type { Config } from '@docusaurus/types';

const config: Config = {
  // ...
  presets: [
    [
      'classic',
      {
        docs: {
          remarkPlugins: [
            [require('docusaurus-plugin-figure-caption').default, { /* options */ }],
          ],
        },
        blog: {
          remarkPlugins: [
            [require('docusaurus-plugin-figure-caption').default, { /* options */ }],
          ],
        },
      },
    ],
  ],
};

Import the default styles in your docusaurus.config.ts:

const config: Config = {
  // ...
  themes: {
    customCss: [
      './src/css/custom.css',
      'docusaurus-plugin-figure-caption/styles',
    ],
  },
};

Or import in your CSS:

@import 'docusaurus-plugin-figure-caption/styles';

Generic remark / unified

import { remark } from 'remark';
import remarkHtml from 'remark-html';
import figureCaption from 'docusaurus-plugin-figure-caption';

const result = await remark()
  .use(figureCaption, { numbering: 'per-page' })
  .use(remarkHtml)
  .process('![A beautiful sunset](/img/sunset.jpg)');

console.log(String(result));
// <figure class="figure-container" id="fig-1">
//   <img src="/img/sunset.jpg" alt="A beautiful sunset">
//   <figcaption class="figure-caption">Figure 1: A beautiful sunset</figcaption>
// </figure>

Usage

Basic — Auto-numbered captions

Every standalone image gets wrapped in a <figure> with a numbered caption:

![Wind turbine at sunset](/img/turbine.jpg)

![Solar panel array](/img/solar.jpg)

Produces:

  • Figure 1: Wind turbine at sunset
  • Figure 2: Solar panel array

Tags — Label your figures

Add #tag-name at the end of the alt text to assign a referenceable label:

![Performance chart over time #perf-chart](/img/performance.jpg)

The #perf-chart tag is stripped from the visible caption. The figure gets id="fig-perf-chart".

Cross-references — Link to tagged figures

Write fig:tag-name anywhere in your text. It auto-resolves to a clickable link:

![System architecture overview #architecture](/img/arch.jpg)

As shown in fig:architecture, the system uses a microservices pattern.
The detailed data flow (fig:architecture) confirms this approach.

Renders as:

As shown in Figure 1, the system uses a microservices pattern. The detailed data flow (Figure 1) confirms this approach.

Images that are skipped

The plugin automatically skips:

  • Images inside tables — Table cells often contain small icons
  • Images inside links — Badge images, clickable buttons
  • Images matching exclude patterns — Custom exclusion rules
<!-- This image is NOT wrapped (it's in a link) -->
[![badge](https://img.shields.io/badge/status-ok-green)](https://example.com)

<!-- This image IS wrapped -->
![Dashboard overview](/img/dashboard.jpg)

Configuration

All options are optional. Pass them as the second argument:

remarkPlugins: [
  [require('docusaurus-plugin-figure-caption').default, {
    numbering: 'per-page',
    prefix: 'Figure',
    separator: ':',
    captionSource: 'alt',
    captionPosition: 'bottom',
    className: 'figure-container',
    captionClassName: 'figure-caption',
    generateId: true,
    idPrefix: 'fig',
    exclude: [],
    tagPattern: /\s#([a-zA-Z0-9_-]+)$/,
    refPrefix: 'fig:',
  }],
],

Options Reference

| Option | Type | Default | Description | |--------|------|---------|-------------| | numbering | 'per-page' \| 'per-section' \| 'continuous' \| false | 'per-page' | Numbering mode. false disables numbering entirely. | | prefix | string | 'Figure' | Text before the number (e.g., 'Fig.', 'Imagen'). | | separator | string | ':' | Character between number and caption text. | | captionSource | 'alt' \| 'title' \| 'both' | 'alt' | Where to read caption text from. 'both' joins them with . | | captionPosition | 'top' \| 'bottom' | 'bottom' | Position of the caption relative to the image. | | className | string | 'figure-container' | CSS class for <figure>. | | captionClassName | string | 'figure-caption' | CSS class for <figcaption>. | | generateId | boolean | true | Whether to add id attributes to <figure> elements. | | idPrefix | string | 'fig' | Prefix for generated IDs. 'fig'id="fig-1". | | exclude | RegExp[] | [] | URL patterns to skip (e.g., [/badge/, /\.svg$/]). | | tagPattern | RegExp | /\s#([a-zA-Z0-9_-]+)$/ | Regex to extract tags from alt text. | | refPrefix | string | 'fig:' | Prefix for cross-references in text. |

Localization Example

// Spanish captions: "Figura 1: ..."
{ prefix: 'Figura' }

// German captions: "Abbildung 1 – ..."
{ prefix: 'Abbildung', separator: ' –' }

// No numbering, just caption text
{ numbering: false }

Styling

Default Styles

Import the included stylesheet for a clean default look:

@import 'docusaurus-plugin-figure-caption/styles';

This provides:

  • Centered figures with responsive images
  • Subtle box shadow on images
  • Italic caption text with proper spacing
  • Dark mode support for Docusaurus themes

Custom Styles

Override the default classes or use your own:

.figure-container {
  display: flex;
  flex-direction: column;
  align-items: center;
  margin: 2rem auto;
}

.figure-container img {
  max-width: 100%;
  border-radius: 8px;
}

.figure-caption {
  font-size: 0.85rem;
  color: #666;
  margin-top: 0.5rem;
}

Or use entirely custom class names:

{ className: 'my-figure', captionClassName: 'my-caption' }

TypeScript

The plugin exports all types for full IntelliSense:

import type {
  FigureCaptionOptions,
  ResolvedOptions,
  NumberingMode,
  CaptionSource,
  CaptionPosition,
  FigureRef,
} from 'docusaurus-plugin-figure-caption';

For advanced use, resolveOptions is also exported to programmatically merge defaults:

import { resolveOptions } from 'docusaurus-plugin-figure-caption';

const config = resolveOptions({ prefix: 'Fig.', numbering: false });
// config is fully resolved with all defaults applied

How It Works

  1. Image detection — The plugin visits all nodes in the Markdown AST. It handles both standard MDAST image nodes and Docusaurus's JSX <img> elements (which Docusaurus creates when transforming local image paths through webpack).

  2. Figure wrapping — Each qualifying image is wrapped in a <figure> element with a <figcaption> containing the numbered caption.

  3. Tag extraction — If the alt text ends with #tag-name, the tag is extracted, removed from the visible caption, and stored in an internal registry mapping tags to figure numbers.

  4. Cross-reference resolution — A second pass scans the document for fig:tag-name references. In MDX mode, these are parsed as textDirective nodes. In pure remark mode, they're matched via regex on text nodes. Each reference is replaced with a clickable <a> link to the tagged figure.

Compatibility

| Environment | Version | Status | |-------------|---------|--------| | Docusaurus | 3.x | ✅ Fully supported | | MDX | 2.x / 3.x | ✅ Handles JSX image transforms | | remark | 15.x | ✅ Standard remark plugin | | unified | 11.x | ✅ Works in any unified pipeline | | Node.js | ≥ 18 | ✅ Required |

License

MIT © John Lopez