Skip to content
/ rd2qmd Public

A fast Rd-to-Quarto Markdown converter written in Rust, with intelligent link resolution.

License

Notifications You must be signed in to change notification settings

eitsupi/rd2qmd

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

78 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

rd2qmd

A fast Rd-to-Quarto Markdown converter written in Rust, with intelligent link resolution.

Features

  • Blazing fast: Converts 228 ggplot2 docs in ~0.13s with parallel processing
  • Smart link resolution: Automatically resolves \link{} references to correct output files
  • External package links: Resolves cross-package links using pkgdown URL conventions (e.g., \link[dplyr]{mutate}https://dplyr.tidyverse.org/reference/mutate.html)
  • Topic index generation: Outputs JSON index with topic metadata (name, title, aliases, lifecycle) for building reference sites
  • Quarto-ready: Generates .qmd files with {r} executable code blocks and YAML frontmatter
  • Grid Table support: Uses Pandoc-compatible Grid Tables for Arguments section, supporting lists and block elements in cells
  • pkgdown-compatible metadata: Adds pagetitle in pkgdown style ("<title> — <name>") for SEO
  • No R required: Pure Rust binary with no runtime R dependency

Installation

From source

cargo install --git https://github.com/eitsupi/rd2qmd

Build locally

git clone https://github.com/eitsupi/rd2qmd
cd rd2qmd
cargo build --release

The binary will be available at target/release/rd2qmd.

Usage

Basic usage

# Convert a single file (outputs to same directory)
rd2qmd file.Rd

# Convert to a specific output file
rd2qmd file.Rd -o output.qmd

# Convert to standard Markdown instead of Quarto
rd2qmd file.Rd -f md

Directory conversion

When converting a directory, rd2qmd builds an alias index for internal link resolution:

# Convert all .Rd files in a directory
rd2qmd man/ -o docs/

# Process subdirectories recursively
rd2qmd man/ -o docs/ -r

# Use parallel processing with 4 jobs
rd2qmd man/ -o docs/ -j4

Options

Option Description
-o, --output <PATH> Output file or directory
-f, --format <FORMAT> Output format: qmd (default), md, or rmd
-j, --jobs <N> Number of parallel jobs (defaults to CPU count)
-r, --recursive Process directories recursively
--no-frontmatter Disable YAML frontmatter
--no-pagetitle Skip pkgdown-style pagetitle metadata ("<title> — <name>")
--quarto-code-blocks <BOOL> Use {r} code blocks (auto-set based on format)
--arguments-table <FORMAT> Arguments table format: grid (default) or pipe
-v, --verbose Verbose output
-q, --quiet Only show errors

Link resolution options

Option Description
--unresolved-link-url <URL> URL pattern for unresolved links. Default: https://rdrr.io/r/base/{topic}.html
--no-unresolved-link-url Disable fallback URL for unresolved links

External link options

These options require the external-links feature (enabled by default):

Option Description
--r-lib-path <PATH> R library path to search for packages (repeatable)
--cache-dir <DIR> Cache directory for pkgdown.yml files
--no-external-links Disable external package link resolution
--external-package-fallback <URL> Fallback URL for packages without pkgdown sites. Default: https://rdrr.io/pkg/{package}/man/{topic}.html

You can get your R library paths by running .libPaths() in R:

.libPaths()
#> [1] "/home/user/R/x86_64-pc-linux-gnu-library/4.4"
#> [2] "/usr/local/lib/R/site-library"
#> [3] "/usr/lib/R/library"

Topic index generation

Generate a JSON index of all topics with metadata for building reference sites:

# Generate index to stdout (pipe to jq for filtering)
rd2qmd index man/
rd2qmd index man/ | jq '.topics[] | select(.lifecycle)'

# Generate index while converting
rd2qmd man/ -o docs/ --topic-index index.json

The index includes topic name, output file, title, aliases, and lifecycle stage:

{
  "topics": [
    {
      "name": "my_func",
      "file": "my_func.qmd",
      "title": "My Function",
      "aliases": ["my_func", "myFunc"],
      "lifecycle": "deprecated"
    }
  ]
}

The lifecycle field is omitted for topics without a lifecycle badge. Supported stages: experimental, stable, superseded, deprecated, and legacy stages (maturing, questioning, soft_deprecated, defunct, retired).

Example control options

These options control how \dontrun{} and \donttest{} example code is handled:

Option Description
--exec-dontrun Make \dontrun{} code executable ({r} blocks)
--no-exec-donttest Make \donttest{} code non-executable (```r blocks)

Default behavior (pkgdown-compatible):

  • \dontrun{} → non-executable (```r), because it means "never run this code"
  • \donttest{} → executable ({r}), because it means "don't run during testing" but should run normally

Use --exec-dontrun to make \dontrun{} code executable, or --no-exec-donttest to make \donttest{} code non-executable.

Output formats

Quarto Markdown (.qmd)

The default format produces Quarto-compatible markdown with:

  • YAML frontmatter with title and pagetitle (pkgdown style: "<title> — <name>")
  • Executable R code blocks using {r} syntax
  • Internal links resolved to .qmd files

Use -f rmd for R Markdown (.Rmd) output with identical content.

Standard Markdown (.md)

Use -f md for standard markdown with:

  • YAML frontmatter with title and pagetitle
  • Plain r code blocks (non-executable)
  • Internal links resolved to .md files

Arguments table format

The Arguments section is rendered as a table. By default, rd2qmd uses Pandoc Grid Tables which support block elements (lists, multiple paragraphs) within cells:

+----------+-------------------------------------+
| Argument | Description                         |
+==========+=====================================+
| `x`      | A simple description.               |
+----------+-------------------------------------+
| `opts`   | Available options:                  |
|          |                                     |
|          | - option A                          |
|          | - option B                          |
+----------+-------------------------------------+

For Markdown environments that don't support Grid Tables, use --arguments-table pipe for pipe tables:

| Argument | Description |
|:---|:---|
| `x` | A simple description. |
| `opts` | Available options: <br>- option A <br>- option B |

Note: GFM tables cannot contain true block elements; lists are flattened with <br> separators.

Examples

Convert ggplot2 documentation to Quarto:

rd2qmd ggplot2/man/ -o docs/reference/ -v

Convert a single function's documentation:

rd2qmd ggplot2/man/geom_point.Rd -o geom_point.qmd

Convert to standard Markdown for a static site:

rd2qmd ggplot2/man/ -o docs/ -f md

Performance

rd2qmd is designed to be fast. Here are benchmark results converting ggplot2's documentation (228 Rd files, 734 aliases, 16 external package references):

Configuration 1 job 2 jobs 4 jobs
Without external link resolution ~0.2s ~0.2s ~0.2s
With external links (warm cache) ~1.0s ~0.9s ~0.8s
With external links (cold cache) ~1.0s - -

Notes:

  • External link resolution fetches pkgdown.yml from package websites on first run (cold cache)
  • Cached results are reused on subsequent runs (warm cache)
  • Actual times vary by environment; parallel speedup depends on I/O characteristics

Run your own benchmark:

git clone --depth 1 https://github.com/tidyverse/ggplot2 /tmp/ggplot2
cargo run --release --example benchmark -- /tmp/ggplot2/man \
  $(Rscript -e 'cat(paste("--r-lib-path", .libPaths(), collapse=" "))')

Roadmap

  • Integration with tree-sitter-qmd for syntax-aware Quarto document manipulation

Related projects

This project is built on:

  • markdown-rs - Markdown parser in Rust. rd2qmd uses its mdast (Markdown AST) types for intermediate representation.
  • r-description-rs - R DESCRIPTION file parser in Rust, used for reading package metadata.

This project was inspired by:

  • pkgdown - The standard tool for building R package documentation websites. rd2qmd follows pkgdown's URL conventions for external links and its semantics for \dontrun{}/\donttest{} example handling.
  • altdoc - A lightweight alternative to pkgdown supporting Quarto, Docsify, Docute, and MkDocs. Converts Rd to qmd via R's tools::Rd2HTML().
  • pkgsite - A Quarto-based R package documentation generator that converts Rd files to Quarto documents.
  • downlit - Syntax highlighting and automatic linking for R code, used by pkgdown.
  • rd2md - A Python-based Rd to Markdown converter.
  • rd2markdown - An R package for Rd to Markdown conversion.

License

MIT

About

A fast Rd-to-Quarto Markdown converter written in Rust, with intelligent link resolution.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Contributors 2

  •  
  •  

Languages