rst-renderer

HTML Rendering

Render RST to HTML with syntax highlighting, math, and directives

HTML Renderer

The HTML renderer converts RST documents to semantic HTML with support for report-oriented directive plugins.

Basic Usage

import { renderRst } from '@seqyuan/rst-renderer'

const html = renderRst(`Title
=====

This is **bold** text.

.. code:: typescript

   const x: number = 42

.. math::

   E = mc^2
`)

Complete HTML Documents

renderRst returns an HTML fragment (semantic markup with CSS classes). To produce a complete, styled document — for example a single-file report — wrap it with wrapHtmlDocument, which injects the built-in theme and a <head>:

import { renderRst, wrapHtmlDocument } from '@seqyuan/rst-renderer'

const doc = wrapHtmlDocument(renderRst(source, { headingOffset: 0 }), {
  title: 'QC Report',
})
// -> <!DOCTYPE html> … <style>/* theme */</style> … </article>

Options: title, lang (default zh-CN), css (replace the theme entirely), extraCss (append), bodyClass (default rst-report). The title defaults to the first <h1>/<h2> in the fragment.

Heading Levels

By default a level-1 RST section renders as <h2>, which keeps the fragment safe to embed in a host page. For a standalone document whose top-level title should be <h1>, pass headingOffset: 0:

renderRst(source)                  // <h2>, <h3>, …
renderRst(source, { headingOffset: 0 }) // <h1>, <h2>, …

Directive Plugins

PluginDirectivesNotes
imagePluginimage, figureImage embedding
codePlugincode, code-block, sourcecodeShiki syntax highlighting (auto-detected)
highlightPluginhighlightSetting directive; produces no output
mathPluginmathKaTeX rendering (auto-detected)
admonitionPluginnote, warning, tip, important, caution, danger, hint, attention, error, admonitionCallout boxes
csvTablePlugincsv-tableCSV table with :file: or inline body
listTablePluginlist-tableReport-friendly table syntax with :header-rows: and :widths:
rawPluginrawRaw HTML passthrough (body emitted verbatim)
replacePluginreplace, unicodeText substitution

Beyond directives, the built-in parser also understands field lists (:name: value), definition lists, option lists, and substitutions (.. |name| replace:: … + |name|). | containerPlugin | container | Custom CSS container | | contentsPlugin | contents, toctree | Lightweight heading TOC and explicit page-card navigation | | includePlugin | include | Build-time include marker; pair with include expansion for actual reuse |

Report-Oriented RST Features

This renderer intentionally prioritizes reusable report building blocks over full Sphinx compatibility.

  • .. list-table:: is supported for data-driven report tables
  • .. contents:: builds an in-document heading TOC
  • .. toctree:: renders explicit related-page entries, not a full doc graph
  • .. include:: is best treated as a preprocessing step

If you need syntax details, see RST Writing Rules.

Custom Directives

import { HtmlRenderer } from '@seqyuan/rst-renderer'

const renderer = new HtmlRenderer()

renderer.registerDirective('my-custom', (directive, ctx, renderChildren) => {
  ctx.write(`<div class="custom">`)
  renderChildren(directive.children, ctx)
  ctx.write(`</div>`)
})

Code Highlighting & Math

When shiki / katex are installed they are detected automatically and used for code blocks and math. Because loading is asynchronous, call preloadRenderers() once before rendering a batch so the first document is highlighted instead of falling back:

import { preloadRenderers, renderRst } from '@seqyuan/rst-renderer'

await preloadRenderers()
const html = renderRst(source)

Without them, code blocks render as <pre><code> with data-language, and math falls back to LaTeX source wrapped in <div class="math">.

Include Expansion

The renderer itself does not resolve files from .. include:: automatically. Use include expansion before parsing:

import { renderRst } from '@seqyuan/rst-renderer'

const html = renderRst(source, {
  includeResolver: { baseDir: process.cwd() },
})

This is designed for reusable report fragments, not full Sphinx include semantics.

On this page