rst-renderer

Vite Plugin

Import .rst files in Vite projects as HTML, Markdown, React components, or metadata

Vite Plugin

@seqyuan/vite-plugin-rst lets you import .rst files the same way you import .md or .svg — Vite transforms them at build time using @seqyuan/rst-renderer.

Installation

pnpm add -D @seqyuan/vite-plugin-rst
pnpm add @seqyuan/rst-renderer

@seqyuan/rst-renderer is a peer dependency resolved at transform time.

Setup

// vite.config.ts
import { defineConfig } from 'vite'
import rst from '@seqyuan/vite-plugin-rst'

export default defineConfig({
  plugins: [rst()],
})

Import Formats

ImportOutput
import { html } from './doc.rst'HTML string (named + default export)
import html from './doc.rst?html'HTML string (explicit query)
import md from './doc.rst?md'Markdown string (headingOffset: 1)
import meta from './doc.rst?meta'{ title, headings[] } metadata
import RstPage from './doc.rst?react'React component (default export)

HTML Import

import { html } from './changelog.rst'

function ChangelogPanel() {
  return <div dangerouslySetInnerHTML={{ __html: html }} />
}

Markdown Import

import md from './guide.rst?md'
import { marked } from 'marked' // or your preferred MD renderer

function GuidePanel() {
  return <div dangerouslySetInnerHTML={{ __html: marked.parse(md) }} />
}

React Component Import

The ?react query generates a self-contained module:

import RstPage from './documentation.rst?react'

function App() {
  return (
    <main>
      <RstPage />
    </main>
  )
}

Generated module structure:

import { ReactRenderer } from '@seqyuan/rst-renderer/react'

const document = { /* parsed AST */ }
const renderer = new ReactRenderer()

export default function RstPage() {
  return renderer.render(document)
}

Override components by importing the AST and using ReactRenderer directly — see React Rendering.

Metadata Import

import { meta } from './doc.rst?meta'

console.log(meta.title)     // first RST heading text
console.log(meta.headings)  // all heading texts in document order

Useful for building sidebars, breadcrumbs, or page titles without parsing RST twice in application code.

Plugin Options

export default defineConfig({
  plugins: [
    rst({
      defaultFormat: 'html', // 'html' | 'md' | 'react'
    }),
  ],
})
OptionTypeDefaultDescription
defaultFormat'html' | 'md' | 'react''html'Output when no ?query param is present

Hot Module Replacement

When any .rst file changes during vite dev, the plugin triggers a full page reload. RST parsing runs at transform time, so partial HMR for individual nodes is not supported yet.

Full Example: Docs Page Component

// src/pages/ReleaseNotes.tsx
import { html } from '../../content/release-notes.rst'
import { meta } from '../../content/release-notes.rst?meta'

export function ReleaseNotes() {
  return (
    <article>
      <h1>{meta.title}</h1>
      <nav>
        <ul>
          {meta.headings.slice(1).map((h) => (
            <li key={h}>{h}</li>
          ))}
        </ul>
      </nav>
      <div className="rst-content" dangerouslySetInnerHTML={{ __html: html }} />
    </article>
  )
}

Comparison with React Renderer

ApproachBest for
?react importDrop-in page component, zero setup
ReactRenderer + custom componentsDesign-system integration, styled primitives
?html importQuick preview, legacy HTML/CSS styling
?md importPiping RST content into an existing Markdown stack

For programmatic rendering outside Vite, use HTML, React, or Markdown renderers directly.

On this page