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-dgmo

v0.3.5

Published

Remark plugin to render DGMO diagrams from fenced code blocks at build time. Framework-agnostic core shared by astro-dgmo, docusaurus-plugin-dgmo, and any unified pipeline.

Downloads

2,594

Readme

remark-dgmo

Framework-agnostic remark plugin that renders DGMO diagrams from ```dgmo fenced code blocks at build time. Powered by @diagrammo/dgmo. Zero client JavaScript by default.

sequence
Client -POST /login-> API
API -validate-> Auth
Auth -JWT-> API
API -200 OK-> Client

Drop a fenced block with the language dgmo into any markdown or MDX file processed by a unified-style pipeline — Astro, Docusaurus, Starlight, Vitepress, eleventy-with-remark, or your own custom toolchain — and it becomes an inline <svg> at build time.

By default, every diagram is rendered twice (once with the palette's light mode, once with its dark mode) and wrapped in <div class="dgmo-light"> / <div class="dgmo-dark">. A tiny shipped stylesheet hides the wrong one based on [data-theme="dark"] (the convention used by Docusaurus, Starlight, and most other docs frameworks). The result: your diagrams follow the host page's color-mode toggle without any client-side rendering.

Install

pnpm add remark-dgmo @diagrammo/dgmo
# or
npm install remark-dgmo @diagrammo/dgmo

@diagrammo/dgmo is a peer dependency.

ESM-only. Your config file must be .mjs, .ts, or .mts — or your package.json must have "type": "module".

Use — three integration patterns

Pattern 1: Astro

Use astro-dgmo — it wraps this plugin and handles the integration plumbing.

pnpm add astro-dgmo @diagrammo/dgmo
// astro.config.mjs
import { defineConfig } from 'astro/config';
import dgmo from 'astro-dgmo';

export default defineConfig({
  integrations: [dgmo()],
});

You'll also need to import the color-mode stylesheet in your global layout:

---
// src/layouts/Base.astro
import 'remark-dgmo/client.css';
---

Pattern 2: Docusaurus

Use docusaurus-plugin-dgmo — it handles getClientModules() registration for the CSS + client script.

pnpm add docusaurus-plugin-dgmo @diagrammo/dgmo
// docusaurus.config.ts
import type { Config } from '@docusaurus/types';

const config: Config = {
  // …
  plugins: ['docusaurus-plugin-dgmo'],
  presets: [
    [
      'classic',
      {
        docs: {
          remarkPlugins: [
            (await import('docusaurus-plugin-dgmo/remark')).default,
          ],
        },
        blog: {
          remarkPlugins: [
            (await import('docusaurus-plugin-dgmo/remark')).default,
          ],
        },
        pages: {
          remarkPlugins: [
            (await import('docusaurus-plugin-dgmo/remark')).default,
          ],
        },
      },
    ],
  ],
};

export default config;

The plugin registers client.css + client.js via getClientModules(). You still wire remarkPlugins into each preset slot manually — Docusaurus's plugin API has no hook to auto-inject into a sibling preset.

Pattern 3: Fumadocs (Next.js app router)

Use fumadocs-dgmo — it wraps mdxOptions for fumadocs-mdx, ships a .dark-rewritten stylesheet (Fumadocs UI's next-themes default), and provides a Client Component that re-binds on every soft navigation.

pnpm add fumadocs-dgmo @diagrammo/dgmo
// source.config.ts
import { defineConfig } from 'fumadocs-mdx/config';
import { withDgmo } from 'fumadocs-dgmo/config';

export default defineConfig({
  mdxOptions: withDgmo(),
});
/* app/global.css */
@import 'fumadocs-ui/css/preset.css';
@import 'fumadocs-dgmo/client.css';
// app/layout.tsx — add <DgmoClient /> inside <RootProvider>
import { DgmoClient } from 'fumadocs-dgmo/client';
// …
<RootProvider>
  {children}
  <DgmoClient />
</RootProvider>;

Pattern 4: Vanilla unified pipeline

import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
import remarkDgmo from 'remark-dgmo';

const out = await unified()
  .use(remarkParse)
  .use(remarkDgmo, { mode: 'showcase', palette: 'dracula' })
  .use(remarkRehype, { allowDangerousHtml: true })
  .use(rehypeStringify, { allowDangerousHtml: true })
  .process(source);

In your output HTML's <head>, add the shipped stylesheet (or inline its three rules):

<link
  rel="stylesheet"
  href="/path/to/node_modules/remark-dgmo/dist/client.css"
/>
<script
  type="module"
  src="/path/to/node_modules/remark-dgmo/dist/client.js"
></script>

The client script is optional — it tightens each diagram's viewBox to its content bounds and wires up showcase-mode copy buttons. Without it, diagrams still render but may have extra whitespace and copy buttons won't function.

Options

remarkDgmo({
  // Output mode for `dgmo` blocks. 'diagram' (default) = SVG only.
  // 'showcase' = syntax-highlighted source + diagram + copy + open-in-editor.
  mode: 'diagram',

  // Default palette name (any registered @diagrammo/dgmo palette).
  palette: 'nord',

  // Color-mode strategy. 'auto' (default) renders both light and dark and
  // toggles via CSS. 'light' or 'dark' single-renders with the matching theme.
  colorMode: 'auto',

  // Default theme when colorMode is 'light' or 'dark' (single-render). Ignored under 'auto'.
  theme: 'dark',

  // Showcase chrome — enabled automatically in showcase mode.
  showSource: undefined, // boolean; default = (mode === 'showcase')
  showCopy: undefined, // boolean; default = (mode === 'showcase')
  showOpenInEditor: undefined, // boolean; default = (mode === 'showcase')

  // Where the "Open in editor" link points.
  editorBaseUrl: 'https://online.diagrammo.app',

  // Outer wrapper element + class hook.
  wrapper: 'figure',
  className: 'dgmo',

  // Append additional class names to every emitted wrapper. Used by
  // astro-dgmo v0.3.0 to keep the legacy `astro-dgmo*` class names for one
  // minor cycle of backward compat.
  legacyClassNames: [],

  // Emit MDX-compatible output. Default: false (raw `html` mdast node).
  // Set to true when the host pipeline routes files through @mdx-js/mdx —
  // Docusaurus with `markdown.format: 'mdx'`, Astro `.mdx`, Fumadocs, etc.
  // The plugin then emits an `mdxJsxFlowElement` instead of an `html` node,
  // so MDX accepts the output without "Cannot handle unknown node `raw`".
  mdx: false,
});

Per-block overrides

Append options to the fence info string. Tokens are space-separated; values may be quoted.

```dgmo showcase title="Login flow" palette=catppuccin theme=light
sequence
A -> B
```

| Token | Effect | | ------------------------------------------------------- | ----------------------------------- | | diagram / showcase | Set mode for this block | | palette=<name> | Override palette | | theme=light / theme=dark / theme=transparent | Override theme (single-render only) | | colorMode=auto / colorMode=light / colorMode=dark | Override color-mode strategy | | title="…" | Add a caption (<figcaption>) | | source / noSource | Force source listing on/off | | copy / noCopy | Force copy button on/off | | openInEditor / noOpenInEditor | Force editor link on/off |

Working reference site

For an end-to-end example of remark-dgmo running inside a real framework, see docusaurus-plugin-dgmo's tests/fixture/ — a minimal Docusaurus 3 site that wires this plugin into every preset slot and exercises plain, tagged, showcase, and per-block-override blocks. The astro-dgmo repo has an equivalent Astro 6 fixture at tests/fixture/; the fumadocs-dgmo repo has a Next.js app-router fixture at tests/fixture/.

All three fixtures pin to link:../.. against the wrapper plugin's source, so they're the canonical reference for the smallest correct config — including the non-obvious gotchas (Docusaurus's async-function default export + markdown: { format: 'md' }, Astro's manual import 'remark-dgmo/client.css', Fumadocs's mdx: true requirement and html.dark selector mapping).

Custom color-mode selector

The shipped client.css keys on [data-theme="dark"] — the convention used by Docusaurus and Starlight. For Tailwind-style sites that signal dark mode via a .dark class on <html> (which is also what Fumadocs UI's next-themes default produces), don't import client.css directly — fumadocs-dgmo/client.css ships a build-time rewrite for that case. For any other custom selector, inline these three rules in your own CSS instead, swapping the selector:

.dgmo-dark {
  display: none;
}
html.dark .dgmo-light {
  display: none;
}
html.dark .dgmo-dark {
  display: block;
}

For data-color-scheme="dark", :root[data-mode="dark"], etc. — same three rules, swap the selector to match what your toggle sets.

How it works

  1. The remark transformer walks the mdast, finding code nodes with lang === 'dgmo'.
  2. For each block, renderDgmoBlock() calls render() from @diagrammo/dgmo — twice if colorMode: 'auto' (one light, one dark), once otherwise.
  3. Each SVG is normalized: width/height stripped, viewBox added, inline background removed.
  4. The original code node is replaced with an html node carrying the rendered wrapper(s).
  5. The optional client script (dist/client.js) tightens viewBoxes and binds showcase-mode copy buttons.

Rendering happens at build time. The browser sees only the inline SVG and the small color-mode CSS.

License

MIT