Guides

Plugins

Plugins bundle functionality into reusable extensions that hook into the Nizel pipeline.

Using a Plugin

import { useNizel } from 'nizel';
import { syntaxHighlightPlugin } from 'nizel-highlight';

const nizel = useNizel({
  plugins: [syntaxHighlightPlugin()],
});

Plugins are ordinary JavaScript objects. You can compose them directly:

import { alertPlugin } from 'nizel-plugin-alert';
import { mathPlugin } from 'nizel-plugin-math';

const nizel = useNizel({
  plugins: [
    alertPlugin(),
    mathPlugin(),
  ],
});

Native apps can use nizel-kit instead of importing individual packages. nizel-kit exposes a serializable supportedPlugins registry and accepts plugin IDs:

const html = await NizelKit.markdownToHtml(markdown, {
  enabledPlugins: ['sanitize', 'autolink', 'alert', 'math']
});

For Swift, iOS, macOS, and WebView integration details, read NizelKit for Native Apps.

Plugin Hooks

A plugin can implement one or more hooks:

interface NizelPlugin {
  name?: string;
  hooks?: {
    beforeParse?(markdown: string, options: NizelOptions): string;
    afterParse?(ast: NizelRootNode, options: NizelOptions): NizelRootNode | void;
    afterRender?(html: string, options: NizelOptions): string;
  };
}

Writing a Plugin

Use defineNizelPlugin() when authoring TypeScript plugins. It preserves typing while leaving the object unchanged.

import { defineNizelPlugin, type NizelPlugin } from 'nizel';

export const uppercasePlugin = (): NizelPlugin => defineNizelPlugin({
  name: 'uppercase',
  hooks: {
    afterRender(html) {
      return html.replace(/\bIMPORTANT\b/g, '<strong>IMPORTANT</strong>');
    },
  },
});

Use the lightest hook that matches the job:

  • beforeParse: syntax preprocessing, custom shorthand, or block rewrites.
  • afterParse: AST changes where structure matters.
  • afterRender: output-only decoration, sanitizing, wrappers, or post-processing.

For block-like syntax, prefer custom blocks over raw string replacement:

const notePlugin = (): NizelPlugin => ({
  name: 'note',
  blocks: {
    note: {
      name: 'note',
      parse({ content }) {
        return { content };
      },
      formats: {
        html(node, ctx) {
          return node.type === 'customBlock'
::deflist
            ? `<aside>${ctx.render(node.children ?? [])}</aside>`
            : '';
::
        },
      },
    },
  },
});

beforeParse

Receives the raw Markdown string before parsing. Return the modified string.

const plugin = {
  name: 'add-footer',
  hooks: {
    beforeParse(markdown) {
      return markdown + '\n\n---\n*Generated by Nizel*';
    },
  },
};

afterParse

Receives the AST after parsing. Return the modified AST.

const plugin = {
  name: 'external-links',
  hooks: {
    afterParse(ast) {
      // modify link nodes to open externally
      return ast;
    },
  },
};

afterRender

Receives the rendered HTML string. Return the modified HTML.

const plugin = {
  name: 'wrap-tables',
  hooks: {
    afterRender(html) {
      return html.replace(/<table>/g, '<div class="table-wrapper"><table>');
    },
  },
};

Plugin Order

Plugins run in the order they appear in the plugins array. beforeParse hooks run left to right. afterParse hooks run left to right. afterRender hooks run left to right.

Official Plugins

Nizel publishes first-party plugins from the npm workspace:

PackagePurpose
nizel-plugin-abbrAbbreviation definitions
nizel-plugin-alertGitHub-style alert custom blocks
nizel-plugin-autolinkBare URL and email autolink configuration
nizel-plugin-citationsSimple citation references and bibliography
nizel-plugin-code-copyCSP-friendly copy markup for code blocks
nizel-plugin-deflistDefinition list syntax
nizel-plugin-detailsDisclosure blocks
nizel-plugin-diagramsMermaid diagram containers
nizel-plugin-emoji:name: emoji shortcuts outside code
nizel-plugin-footnotesFootnotes
nizel-plugin-frontmatter-uiMetadata UI helpers
nizel-plugin-gfmGFM-oriented preset
nizel-plugin-heading-anchorsHeading anchor links
nizel-plugin-hidden-commentsControlled Markdown HTML comment rendering
nizel-plugin-mathInline and display math wrappers
nizel-plugin-mediaImage and figure enhancements
nizel-plugin-sanitizeOutput sanitizing
nizel-plugin-shikiWorker-compatible syntax highlighting integration
nizel-plugin-task-listTask-list checkbox rendering
nizel-plugin-tocRendered table of contents
nizel-plugin-typographyMark, subscript, and superscript extensions

All official plugins are TypeScript packages that publish dist JavaScript and .d.ts files. Plugin tests include unit coverage for package helpers and integration coverage through useNizel.

Use nizel-style when rendered plugin markup should use the standard Nizel content styles. It publishes a full stylesheet plus per-plugin CSS entrypoints, so apps can load only the styles for the plugins they enable.