API reference

The complete public API surface of @rho/md — build-time exports, runtime exports, helpers, types.


Overview

import {
  // === Build-time: Remark plugins ===
  remarkPlugins,            // array (collection of 7 plugins)
  remarkCallout,
  remarkLayout,
  remarkAnnotate,
  remarkTabs,
  remarkStepper,
  remarkTimeline,
  remarkModal,

  // === Build-time: Inner processor (nested DSL) ===
  registerInnerPlugin,
  registerAllInnerPlugins,
  parseInner,

  // === Runtime: Hydration ===
  hydrateAll,
  renderInteractBlocks,
  renderTabsBlocks,
  renderStepperBlocks,
  renderModalBlocks,

  // === Highlight.js / lowlight grammar ===
  stlLanguage,
} from '@rho/md';

// === CSS ===
import '@rho/md/css';

Build-time API

remarkPlugins

Type: Array<RemarkPlugin>

An array of 7 Rho remark plugins — easiest to register all at once:

import { unified } from 'unified';
import remarkParse from 'remark-parse';
import { remarkPlugins } from '@rho/md';

const processor = unified().use(remarkParse);
remarkPlugins.forEach((p) => processor.use(p));

Equivalent to:

processor
  .use(remarkCallout)
  .use(remarkLayout)
  .use(remarkAnnotate)
  .use(remarkTabs)
  .use(remarkStepper)
  .use(remarkTimeline)
  .use(remarkModal);

remarkCallout / remarkLayout / remarkAnnotate / remarkTabs / remarkStepper / remarkTimeline / remarkModal

Type: RemarkPlugin

Reference each remark plugin individually. Each handles one DSL:

Plugin DSL Trigger
remarkCallout Callout > [!INFO] blockquote
remarkLayout Layout ```layout grid cols=N fenced block
remarkAnnotate Annotate ```annotate fenced block
remarkTabs Tabs ```tabs fenced block
remarkStepper Stepper ```stepper fenced block
remarkTimeline Timeline ```timeline fenced block
remarkModal Modal ```modal fenced block

Interact / Vega-Lite / SVG / Computed / Timer aren't in the remark plugin list — they're handled at hydration (the fenced ```interact block emits a marker class at build-time; runtime takes over).

See Remark plugins.


Build-time: Inner processor

registerInnerPlugin(plugin)

Type: (plugin: RemarkPlugin) => void

Register a remark plugin with the inner processor — it will be invoked when parsing nested DSLs.

import { registerInnerPlugin, remarkCallout } from '@rho/md';
registerInnerPlugin(remarkCallout);

→ After this, > [!INFO] inside containers (layout / tabs / stepper / etc.) is recognized as a callout.

registerAllInnerPlugins()

Type: () => void

Register all 7 plugins at once. Most common:

import { registerAllInnerPlugins } from '@rho/md';
registerAllInnerPlugins();

Almost always called when integrating @rho/md — unless you explicitly know you won't use nested DSLs.

parseInner(content, options?)

Type: (content: string, options?: ParseInnerOptions) => string

Advanced API — manually call the inner processor on a chunk of nested content. Normal integration doesn't need it.

See Inner processor.


Runtime: Hydration

hydrateAll(container)

Type: (container: HTMLElement) => void

Scans the container for all Rho marker classes; turns static HTML into interactive components. The most-used hydration API:

import { hydrateAll } from '@rho/md';

const container = document.getElementById('root');
container.innerHTML = await renderRho(markdownSource);
hydrateAll(container);

Idempotent — calling multiple times only hydrates once (each block is marked, subsequent calls skip it).

Equivalent to:

renderInteractBlocks(container);
renderTabsBlocks(container);
renderStepperBlocks(container);
renderModalBlocks(container);

renderInteractBlocks(container)

Type: (container: HTMLElement) => void

Hydrate only interact blocks (slider / input / select / toggle / button / template / computed / timer / svg / vega-lite).

Useful for fine-grained hydration timing — e.g., lazy-loading expensive charts:

container.innerHTML = html;
renderTabsBlocks(container);   // Hydrate static structure immediately
// ... when user scrolls to chart ...
renderInteractBlocks(container);

renderTabsBlocks(container) / renderStepperBlocks(container) / renderModalBlocks(container)

Same signature. Each only hydrates its corresponding container type.

Layout / Callout / Annotate / Timeline are purely static — no hydration needed; HTML is final.

See Hydration utilities.


Highlight.js / lowlight grammar

stlLanguage

Type: (hljs: HLJSApi) => Language

The STL language grammar — for highlight.js or lowlight:

highlight.js

import hljs from 'highlight.js';
import { stlLanguage } from '@rho/md';

hljs.registerLanguage('stl', stlLanguage);

// After this, ```stl code blocks get 6-color highlighting automatically

lowlight (server-side / build-time)

import { common } from 'lowlight';
import { stlLanguage } from '@rho/md';
import rehypeHighlight from 'rehype-highlight';

unified()
  // ... markdown pipeline ...
  .use(rehypeHighlight, {
    plainText: ['mermaid', 'vega-lite', 'vega', 'interact', 'tabs', 'stepper', 'timeline', 'modal', 'layout', 'annotate'],
    languages: { ...common, stl: stlLanguage },
  });

The plainText: [...] array is important — tells rehype-highlight not to colorize Rho's fenced block lang labels (avoids double processing).

See STL syntax highlighting (writer side).


CSS

import '@rho/md/css'

Imports Rho's built-in CSS. Includes:

  • All DSL styles (callout / layout / tabs / stepper / etc.)
  • CSS variables for theming
  • .markdown-body container class (GitHub-compatible convention)
  • Light + dark theme support
import '@rho/md/css';

Or:

<link rel="stylesheet" href="path/to/@rho/md/css/stl-md.css">

CSS variables (theming)

.markdown-body {
  --bg-color: #ffffff;
  --text-color: #1a1a2e;
  --code-bg: #f8f8f8;
  --border-color: #e5e7eb;
  --accent-blue: #2563eb;
  --accent-red: #dc2626;
  --accent-green: #16a34a;
  --accent-yellow: #ca8a04;
  --accent-purple: #9333ea;
  --accent-gray: #6b7280;
}

.markdown-body[data-theme="dark"] {
  --bg-color: #0f1115;
  --text-color: #e8ecf1;
  /* ... */
}

See CSS theming.


TypeScript types

Public types

import type {
  // Plugin types
  RemarkPlugin,           // Standard unified plugin signature
  ProcessorOptions,       // Integration-layer options

  // Hydration types
  HydrationOptions,       // Optional config for hydrate calls
  HydrationResult,        // Hydrate return info

  // Inner processor
  InnerPluginOptions,
} from '@rho/md';

Custom hydrate hooks

import type { HydrationOptions } from '@rho/md';

const options: HydrationOptions = {
  onBlockHydrated: (block, type) => {
    console.log(`Hydrated ${type} block`, block);
  },
  errorBoundary: (block, error) => {
    console.error('Hydration failed:', error);
    block.innerHTML = '<p>Render error</p>';
  },
};

hydrateAll(container, options);

Complete integration reference

import { unified } from 'unified';
import remarkParse from 'remark-parse';
import remarkGfm from 'remark-gfm';
import remarkRehype from 'remark-rehype';
import rehypeStringify from 'rehype-stringify';
import rehypeHighlight from 'rehype-highlight';
import { common } from 'lowlight';

import {
  registerAllInnerPlugins,
  remarkPlugins,
  hydrateAll,
  stlLanguage,
} from '@rho/md';
import '@rho/md/css';

// === Build-time setup ===
registerAllInnerPlugins();

const processor = unified()
  .use(remarkParse)
  .use(remarkGfm);

remarkPlugins.forEach((p) => processor.use(p));

processor
  .use(remarkRehype, { allowDangerousHtml: true })
  .use(rehypeHighlight, {
    plainText: ['interact', 'tabs', 'stepper', 'timeline', 'modal', 'layout', 'annotate'],
    languages: { ...common, stl: stlLanguage },
  })
  .use(rehypeStringify, { allowDangerousHtml: true });

// === Render ===
async function renderRho(markdown: string): Promise<string> {
  const result = await processor.process(markdown);
  return String(result);
}

// === Browser hydration ===
function mount(container: HTMLElement, html: string) {
  container.innerHTML = html;
  hydrateAll(container);
}

// === Usage ===
const html = await renderRho('# Hello\n\n> [!INFO]\n> Test');
mount(document.getElementById('root')!, html);

Non-public / internal API

⚠️ The following are not public API — don't depend on them:

  • Anything named _internal*
  • Deep imports inside dist/ (e.g., @rho/md/dist/internal/foo)
  • Methods not documented on this page

The public stable API is only what's listed above.


See also