or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

docs

index.md
tile.json

tessl/npm-remark-rehype

remark plugin that turns markdown into HTML to support rehype

Workspace
tessl
Visibility
Public
Created
Last updated
Describes
npmpkg:npm/remark-rehype@11.1.x

To install, run

npx @tessl/cli install tessl/npm-remark-rehype@11.1.0

index.mddocs/

remark-rehype

remark-rehype is a unified plugin that bridges the markdown ecosystem (remark/mdast) and the HTML ecosystem (rehype/hast). It transforms markdown syntax trees into HTML syntax trees, enabling users to process markdown with remark plugins and then continue processing the resulting HTML with rehype plugins.

Package Information

  • Package Name: remark-rehype
  • Package Type: npm
  • Language: TypeScript (compiled to JavaScript)
  • Installation: npm install remark-rehype

Core Imports

import remarkRehype from "remark-rehype";

For CommonJS:

const remarkRehype = require("remark-rehype");

Re-exported utilities from mdast-util-to-hast:

import { 
  defaultFootnoteBackContent, 
  defaultFootnoteBackLabel, 
  defaultHandlers 
} from "remark-rehype";

Basic Usage

import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkRehype from "remark-rehype";
import rehypeStringify from "rehype-stringify";

// Basic markdown to HTML transformation
const file = await unified()
  .use(remarkParse)          // Parse markdown
  .use(remarkRehype)         // Transform to HTML
  .use(rehypeStringify)      // Serialize HTML
  .process("# Hello World"); // Process markdown

console.log(String(file)); // "<h1>Hello World</h1>"

Architecture

remark-rehype operates in two distinct modes:

  • Mutate Mode (default): Returns a hast tree that can be processed by subsequent rehype plugins
  • Bridge Mode: Runs a provided processor with the hast tree, then discards the result and continues with the original mdast tree

The plugin relies on mdast-util-to-hast for the core transformation logic and provides unified plugin integration with comprehensive options for customization.

Capabilities

Plugin Function

The main plugin function that transforms markdown (mdast) syntax trees into HTML (hast) syntax trees.

/**
 * Turn markdown into HTML.
 * 
 * @param destination - Processor for bridge mode, or options for mutate mode
 * @param options - Configuration options when processor is provided
 * @returns Transform function for the unified pipeline
 */
function remarkRehype(
  destination?: Processor | Options, 
  options?: Options
): TransformMutate | TransformBridge;

// Mutate mode - returns hast tree for further processing
type TransformMutate = (tree: MdastRoot, file: VFile) => HastRoot;

// Bridge mode - runs processor and discards result
type TransformBridge = (tree: MdastRoot, file: VFile) => Promise<undefined>;

Usage Examples:

import { unified } from "unified";
import remarkParse from "remark-parse";
import remarkRehype from "remark-rehype";
import rehypeStringify from "rehype-stringify";

// Mutate mode (default)
const processor = unified()
  .use(remarkParse)
  .use(remarkRehype)
  .use(rehypeStringify);

// Mutate mode with options
const processorWithOptions = unified()
  .use(remarkParse)
  .use(remarkRehype, {
    allowDangerousHtml: true,
    handlers: { /* custom handlers */ }
  })
  .use(rehypeStringify);

// Bridge mode
const bridgeProcessor = unified()
  .use(remarkParse)
  .use(remarkRehype, unified().use(rehypeStringify))
  .use(remarkStringify); // Continue with markdown processing

Configuration Options

Comprehensive configuration options for customizing the transformation behavior.

interface Options {
  /** Allow raw HTML in markdown to be passed through */
  allowDangerousHtml?: boolean;
  
  /** Custom handlers for specific node types */
  handlers?: Partial<Record<string, Handler>>;
  
  /** Node types to pass through unchanged */
  passThrough?: string[];
  
  /** Handler for unknown node types */
  unknownHandler?: Handler;
  
  /** Function to generate footnote back-reference labels */
  footnoteBackLabel?: (referenceIndex: number, rereferenceIndex: number) => string;
  
  /** Function to generate footnote back-reference content */
  footnoteBackContent?: (referenceIndex: number, rereferenceIndex: number) => ElementContent[];
  
  /** Label to use for the footnotes section (affects screen readers) */
  footnoteLabel?: string;
  
  /** Properties for footnote label elements */
  footnoteLabelProperties?: Properties;
  
  /** Tag name for footnote label elements */
  footnoteLabelTagName?: string;
  
  /** Prefix for DOM clobbering prevention */
  clobberPrefix?: string;
}

type Handler = (state: State, node: Node) => Element | ElementContent[] | void;

Usage Examples:

// Custom footnote labels for non-English languages
const germanOptions = {
  footnoteBackLabel(referenceIndex, rereferenceIndex) {
    return 'Zurück zu Referenz ' + (referenceIndex + 1) +
      (rereferenceIndex > 1 ? '-' + rereferenceIndex : '');
  }
};

// Allow raw HTML processing
const htmlOptions = {
  allowDangerousHtml: true
};

// Custom node handlers
const customOptions = {
  handlers: {
    // Override heading transformation
    heading(state, node) {
      return {
        type: 'element',
        tagName: 'h' + node.depth,
        properties: { className: ['custom-heading'] },
        children: state.all(node)
      };
    }
  }
};

Footnote Utilities

Pre-built utilities for GitHub-compatible footnote handling.

/**
 * Generate default content for footnote back-references
 * @param referenceIndex - Index of the definition's first reference (0-indexed)
 * @param rereferenceIndex - Index of calls to the same definition (0-indexed)
 * @returns Array of hast element content nodes
 */
function defaultFootnoteBackContent(
  referenceIndex: number, 
  rereferenceIndex: number
): ElementContent[];

/**
 * Generate default accessibility labels for footnote back-references
 * @param referenceIndex - Index of the definition's first reference (0-indexed)
 * @param rereferenceIndex - Index of calls to the same definition (0-indexed)
 * @returns Label string for screen readers
 */
function defaultFootnoteBackLabel(
  referenceIndex: number, 
  rereferenceIndex: number
): string;

Usage Examples:

import { defaultFootnoteBackContent, defaultFootnoteBackLabel } from "remark-rehype";

// Use default functions as templates for customization
function customFootnoteBackContent(refIndex, rerefIndex) {
  const defaultContent = defaultFootnoteBackContent(refIndex, rerefIndex);
  // Modify the default content as needed
  return defaultContent;
}

// Check what the defaults generate
console.log(defaultFootnoteBackLabel(0, 1)); // "Back to reference 1"
console.log(defaultFootnoteBackLabel(1, 2)); // "Back to reference 2-2"

Default Node Handlers

Complete set of default handlers for transforming all standard markdown node types to HTML.

/**
 * Default handlers for transforming mdast nodes to hast nodes
 * Includes handlers for all standard CommonMark and GFM node types
 */
const defaultHandlers: Partial<Record<string, Handler>>;

Available Handlers:

  • blockquote - Block quotes (> text)
  • break - Hard line breaks ( \n)
  • code - Code blocks (```)
  • delete - Strikethrough text (~~text~~)
  • emphasis - Italic text (*text*)
  • footnoteReference - Footnote references ([^ref])
  • heading - Headings (# text)
  • html - Raw HTML
  • image - Images (![alt](src))
  • imageReference - Image references (![alt][ref])
  • inlineCode - Inline code (`code`)
  • link - Links ([text](url))
  • linkReference - Link references ([text][ref])
  • list - Lists (- item)
  • listItem - List items
  • paragraph - Paragraphs
  • root - Document root
  • strong - Bold text (**text**)
  • table - Tables
  • tableCell - Table cells
  • tableRow - Table rows
  • text - Plain text
  • thematicBreak - Horizontal rules (---)

Usage Examples:

import { defaultHandlers } from "remark-rehype";

// Extend default handlers with custom ones
const customHandlers = {
  ...defaultHandlers,
  heading(state, node) {
    const result = defaultHandlers.heading(state, node);
    // Add custom attributes to all headings
    if (result && result.properties) {
      result.properties.className = ['custom-heading'];
    }
    return result;
  },
  customNode(state, node) {
    // Handle custom node types
    return {
      type: 'element',
      tagName: 'div',
      properties: { className: ['custom-node'] },
      children: state.all(node)
    };
  }
};

const processor = unified()
  .use(remarkParse)
  .use(remarkRehype, { handlers: customHandlers })
  .use(rehypeStringify);

Types

import type { Root as MdastRoot, Node as MdastNode } from "mdast";
import type { Root as HastRoot, Element, ElementContent, Properties } from "hast";
import type { VFile } from "vfile";
import type { Processor } from "unified";
import type { State } from "mdast-util-to-hast";

interface Options {
  allowDangerousHtml?: boolean;
  handlers?: Partial<Record<string, Handler>>;
  passThrough?: string[];
  unknownHandler?: Handler;
  footnoteBackLabel?: (referenceIndex: number, rereferenceIndex: number) => string;
  footnoteBackContent?: (referenceIndex: number, rereferenceIndex: number) => ElementContent[];
  footnoteLabel?: string;
  footnoteLabelProperties?: Properties;
  footnoteLabelTagName?: string;
  clobberPrefix?: string;
}

type Handler = (state: State, node: MdastNode) => Element | ElementContent[] | void;

type TransformMutate = (tree: MdastRoot, file: VFile) => HastRoot;
type TransformBridge = (tree: MdastRoot, file: VFile) => Promise<undefined>;

Error Handling

The plugin handles several edge cases and error conditions:

  • Unknown Node Types: Uses unknownHandler or falls back to creating <div> elements
  • Raw HTML: Requires allowDangerousHtml: true option to process embedded HTML
  • DOM Clobbering: Uses clobberPrefix to prevent ID-based security issues with footnotes
  • Invalid Footnotes: Gracefully handles malformed footnote references and definitions

Common Patterns

Processing Raw HTML

// Enable raw HTML processing (use with caution)
const processor = unified()
  .use(remarkParse)
  .use(remarkRehype, { allowDangerousHtml: true })
  .use(rehypeRaw) // Parse raw HTML into proper hast nodes
  .use(rehypeStringify);

Multi-language Footnotes

// Customize footnote labels for different languages  
const frenchProcessor = unified()
  .use(remarkParse)
  .use(remarkRehype, {
    footnoteBackLabel(refIndex) {
      return `Retour à la référence ${refIndex + 1}`;
    }
  })
  .use(rehypeStringify);

Custom Node Processing

// Handle custom markdown extensions
const processor = unified()
  .use(remarkParse)
  .use(remarkRehype, {
    handlers: {
      // Handle custom admonition blocks
      admonition(state, node) {
        return {
          type: 'element',
          tagName: 'div',
          properties: { 
            className: ['admonition', node.type] 
          },
          children: state.all(node)
        };
      }
    }
  })
  .use(rehypeStringify);