The rd2markdown package intro
Szymon Maksymiuk
2025-02-27
package_intro.RmdThe rd2markdown package
Markdown has become a staple markup syntax and is commonly used as an interface in modern developer tools. Markdown is used for READMEs, for static content generation and as a rich text interchange format for language servers. As these use cases become more common, it becomes increasingly important that R provides an interface to its documentation to more seamlessly integrate with these tools.
The rd2markdown itself is a dependency-less, base R
centric package that converts .Rd documentation objects
into markdown files. This isn’t the first package to attempt to solve
this problem, but we feel this approach is more robust, extensible and
maintainable. We aim to provide a solution that, with a help of the R
community, will satisfy requirements set by various use cases and
groups.
Functionalities
The rd2markdown package provides tools to conveniently
extract the documentation objects and then convert them into standard
markdown files. Right now, those functionalities are provided by three
functions exported for the end-user.
rd2markdown
Overview
The rd2markdown is the core of the
rd2markdown package. This interface is modelled after the
tools::Rd2* family of functions, filling the gap in this
family of functions to target markdown. It is here, that the actual
conversion from .Rd into .md happens. It uses
the innovative idea of treating particular Rd tags as classes and
dispatching to particular methods accordingly. Thanks to that, most of
the common tags have dedicated treatment and can be formatted in various
ways. On top of that, such a design ensures trouble-free extensibility
of the package, should new tags need to be covered.
rd2markdown can work in various types. It accepts .Rd
objects extracted with get_rd option but also can directly
fetch documentation topics based on the file path or the package.
rd2markdown will leverage this functionality when needed to
flexibly convert provided Rd files provided as text, file paths or help
aliases. It is worth pointing out that the actual output of
rd2markdown function is a character vector of length one
that uses special signs to format the document. Use
writeLines function to create an actual markdown file using
this output.
At the beginning, lets set up the paths for examples files we are going to use throughout the vignette.
rd_files <- c("rd_file_sample.Rd", "rd_file_sample_2.Rd")
rd_examples_path <- system.file("examples", package = "rd2markdown")
rd_examples_macro <- file.path(rd_examples_path, "macros", "macros.Rd")
rd_examples <- file.path(rd_examples_path, rd_files)Examples
Basic usage with previously extracted documentation
rd <- rd2markdown::get_rd(file = rd_examples[[1]])
md <- rd2markdown::rd2markdown(rd)
cat(md)## # Rd sampler title
##
## ```r
## rd_sampler(x, y = TRUE, ...)
## ```
##
## ## Arguments
##
## - `x`: Rd sampler param
## - `y`: Rd sampler param with default
## - `...`: Rd sampler ellipsis param
##
## ## Returns
##
## Rd sampler return
##
## ## Description
##
## Rd sampler description with [Rd sampler link](www.example.com), `Rd sampler in-line code`. And Rd dynamic content, **italics text**, **emphasis text**.
##
## ## Details
##
## Rd sampler details
##
## Rd sampler enumerated list
##
## 1. One
## 2. Two
## 3. Three
##
## Rd sampler itemized list
##
## * One
## * Two
## * Three
##
## ||||
## |:--|:--|:--|
## |Rd|Sampler|Table|
## |rd|sampler|table|
##
## `Rd + sampler + inline + equation`
##
## `Rd * sampler * block * equation`
##
## ## Note
##
## Rd sampler note
##
## ## Rd sampler subsection
##
## Rd sampler subsection text
##
## ### Rd sampler sub-subsection
##
## Rd sampler sub-subsection text
##
## ## Examples
##
## ```r
## rd_sampler()
## ```
##
## ## References
##
## R.D. Sampler. (2021)
##
## ## See Also
##
## base::print
##
## ## Author(s)
##
## R.D. Sampler.
The content of the document object can be trimmed to particular
sections with fragments parameter. It corresponds to actual
R package documentation sections
rd <- rd2markdown::get_rd(file = rd_examples[[1]])
md <- rd2markdown::rd2markdown(rd, fragments = c("description", "usage"))
cat(md)## ```r
## rd_sampler(x, y = TRUE, ...)
## ```
##
## ## Description
##
## Rd sampler description with [Rd sampler link](www.example.com), `Rd sampler in-line code`. And Rd dynamic content, **italics text**, **emphasis text**.
rd2markdown function can also work with a path to the
file taking advantage of the hidden parameter file (and
macros if necessary)
md <- rd2markdown::rd2markdown(file = rd_examples[[1]])
cat(md)## # Rd sampler title
##
## ```r
## rd_sampler(x, y = TRUE, ...)
## ```
##
## ## Arguments
##
## - `x`: Rd sampler param
## - `y`: Rd sampler param with default
## - `...`: Rd sampler ellipsis param
##
## ## Returns
##
## Rd sampler return
##
## ## Description
##
## Rd sampler description with [Rd sampler link](www.example.com), `Rd sampler in-line code`. And Rd dynamic content, **italics text**, **emphasis text**.
##
## ## Details
##
## Rd sampler details
##
## Rd sampler enumerated list
##
## 1. One
## 2. Two
## 3. Three
##
## Rd sampler itemized list
##
## * One
## * Two
## * Three
##
## ||||
## |:--|:--|:--|
## |Rd|Sampler|Table|
## |rd|sampler|table|
##
## `Rd + sampler + inline + equation`
##
## `Rd * sampler * block * equation`
##
## ## Note
##
## Rd sampler note
##
## ## Rd sampler subsection
##
## Rd sampler subsection text
##
## ### Rd sampler sub-subsection
##
## Rd sampler sub-subsection text
##
## ## Examples
##
## ```r
## rd_sampler()
## ```
##
## ## References
##
## R.D. Sampler. (2021)
##
## ## See Also
##
## base::print
##
## ## Author(s)
##
## R.D. Sampler.
md <- rd2markdown::rd2markdown(
file = rd_examples[[2]],
macros = rd_examples_macro # Use macros = NA to automatically discover macros
)
cat(md)## # Rd data sampler
##
## ## Format
##
## A data.frame with 3 rows and 2 variables:
##
## - **x**: Numeric values
## - **y**: Character values
##
## ## Source
##
## <r.d.sampler/>
##
## ```r
## rd_data_sampler
## ```
##
## ## Description
##
## An example of dataset documentation and linking to others `rnorm()`
##
## ## Examples
##
## ```r
## rd_data_sampler
## ```
or take documentation object directly from the package with a help of
topic and package
md <- rd2markdown::rd2markdown(
topic = "rnorm",
package = "stats",
fragments = c("description", "usage")
)
cat(md)## ## Description
##
## Density, distribution function, quantile function and random generation for the normal distribution with mean equal to `mean` and standard deviation equal to `sd`.
##
## ```r
## dnorm(x, mean = 0, sd = 1, log = FALSE)
## pnorm(q, mean = 0, sd = 1, lower.tail = TRUE, log.p = FALSE)
## qnorm(p, mean = 0, sd = 1, lower.tail = TRUE, log.p = FALSE)
## rnorm(n, mean = 0, sd = 1)
## ```
get_rd
Overview
The get_rd function actually extracts the .Rd file from
the file or directly from the package. It can be used on its own, but
also rd2markdown function u ses it internally. The function
itself is using the base function tools::parse_Rd and
base::help to extract the documentation while escaping
errors with graceful exceptions handling. The function is passing
file and macros parameters directly to
tools::parse_Rd with one small addition to how
macros work. If it is NA, then the
get_rd will try to locate macros directory in the same
directory the file is and take the first .Rd file in
alphabetical order, as tools::parse_Rd accepts only a
single file as a macro.
Examples
Extracting documentation directly from the .Rd file and
file parameter
rd2markdown::get_rd(file = rd_examples[[1]])## % Generated by roxygen2: do not edit by hand
## % Please edit documentation in R/rd_sampler.R
## \name{rd_sampler}
## \alias{rd_sampler}
## \title{Rd sampler title}
## \usage{
## rd_sampler(x, y = TRUE, ...)
## }
## \arguments{
## \item{x}{Rd sampler param}
##
## \item{y}{Rd sampler param with default}
##
## \item{...}{Rd sampler ellipsis param}
## }
## \value{
## Rd sampler return
## }
## \description{
## Rd sampler description with \href{www.example.com}{Rd sampler link}, \verb{Rd sampler in-line code}. And Rd dynamic content, \emph{italics text},
## \emph{emphasis text}.
## }
## \details{
## Rd sampler details
##
## Rd sampler enumerated list
## \enumerate{
## \item One
## \item Two
## \item Three
## }
##
## Rd sampler itemized list
## \itemize{
## \item One
## \item Two
## \item Three
## }\tabular{lll}{
## Rd \tab Sampler \tab Table \cr
## rd \tab sampler \tab table \cr
## }
##
##
## \eqn{Rd + sampler + inline + equation}
##
## \deqn{Rd * sampler * block * equation}
## }
## \note{
## Rd sampler note
## }
## \section{Rd sampler subsection}{
## Rd sampler subsection text
## \subsection{Rd sampler sub-subsection}{
##
## Rd sampler sub-subsection text
## }
## }
##
## \examples{
## rd_sampler()
##
## }
## \references{
## R.D. Sampler. (2021)
## }
## \seealso{
## base::print
## }
## \author{
## R.D. Sampler.
## }
## \concept{rd_samplers}
reaching out to the installed package to fetch documentation using
topic and package parameters while keeping
file as NULL
rd2markdown::get_rd(topic = "rnorm", package = "stats")## \title{The Normal Distribution}\name{Normal}\alias{Normal}\alias{dnorm}\alias{pnorm}\alias{qnorm}\alias{rnorm}\concept{error function}\concept{erf}\concept{erfc}\concept{erfinv}\concept{erfcinv}\keyword{distribution}\description{
## Density, distribution function, quantile function and random
## generation for the normal distribution with mean equal to \code{mean}
## and standard deviation equal to \code{sd}.
## }\usage{
## dnorm(x, mean = 0, sd = 1, log = FALSE)
## pnorm(q, mean = 0, sd = 1, lower.tail = TRUE, log.p = FALSE)
## qnorm(p, mean = 0, sd = 1, lower.tail = TRUE, log.p = FALSE)
## rnorm(n, mean = 0, sd = 1)
## }\arguments{
## \item{x, q}{vector of quantiles.}
## \item{p}{vector of probabilities.}
## \item{n}{number of observations. If \code{length(n) > 1}, the length
## is taken to be the number required.}
## \item{mean}{vector of means.}
## \item{sd}{vector of standard deviations.}
## \item{log, log.p}{logical; if TRUE, probabilities p are given as log(p).}
## \item{lower.tail}{logical; if TRUE (default), probabilities are
## \eqn{P[X \le x]} otherwise, \eqn{P[X > x]}.}
## }\details{
## If \code{mean} or \code{sd} are not specified they assume the default
## values of \code{0} and \code{1}, respectively.
##
## The normal distribution has density
## \deqn{
## f(x) =
## \frac{1}{\sqrt{2\pi}\sigma} e^{-(x-\mu)^2/2\sigma^2}}{
## f(x) = 1/(\sqrt(2 \pi) \sigma) e^-((x - \mu)^2/(2 \sigma^2))
## }
## where \eqn{\mu} is the mean of the distribution and
## \eqn{\sigma} the standard deviation.
## }\value{
## \code{dnorm} gives the density,
## \code{pnorm} gives the distribution function,
## \code{qnorm} gives the quantile function, and
## \code{rnorm} generates random deviates.
##
## The length of the result is determined by \code{n} for
## \code{rnorm}, and is the maximum of the lengths of the
## numerical arguments for the other functions.
##
## The numerical arguments other than \code{n} are recycled to the
## length of the result. Only the first elements of the logical
## arguments are used.
##
## For \code{sd = 0} this gives the limit as \code{sd} decreases to 0, a
## point mass at \code{mu}.
## \code{sd < 0} is an error and returns \code{NaN}.
## }\source{
## For \code{pnorm}, based on
##
## Cody, W. D. (1993)
## Algorithm 715: SPECFUN -- A portable FORTRAN package of special
## function routines and test drivers.
## \emph{ACM Transactions on Mathematical Software} \bold{19}, 22--32.
##
## For \code{qnorm}, the code is based on a C translation of
##
## Wichura, M. J. (1988)
## Algorithm AS 241: The percentage points of the normal distribution.
## \emph{Applied Statistics}, \bold{37}, 477--484; \ifelse{text}{doi:10.2307/2347330 <https://doi.org/10.2307/2347330>}{\ifelse{latex}{\href{https://doi.org/10.2307/2347330}{doi:10.2307\out{\slash{}}2347330}}{\href{https://doi.org/10.2307/2347330}{doi:10.2307/2347330}}}.
##
## which provides precise results up to about 16 digits for
## \code{log.p=FALSE}. For log scale probabilities in the extreme tails,
## since \R version 4.1.0, extensively since 4.3.0, asymptotic expansions
## are used which have been derived and explored in
##
## Maechler, M. (2022)
## Asymptotic tail formulas for gaussian quantiles; \href{https://CRAN.R-project.org/package=DPQ}{\pkg{DPQ}} vignette
## \url{https://CRAN.R-project.org/package=DPQ/vignettes/qnorm-asymp.pdf}.
##
## For \code{rnorm}, see \link{RNG} for how to select the algorithm and
## for references to the supplied methods.
## }\references{
## Becker, R. A., Chambers, J. M. and Wilks, A. R. (1988)
## \emph{The New S Language}.
## Wadsworth & Brooks/Cole.
##
## Johnson, N. L., Kotz, S. and Balakrishnan, N. (1995)
## \emph{Continuous Univariate Distributions}, volume 1, chapter 13.
## Wiley, New York.
## }\seealso{
## \link{Distributions} for other standard distributions, including
## \code{\link{dlnorm}} for the \emph{Log}normal distribution.
## }\examples{
## require(graphics)
##
## dnorm(0) == 1/sqrt(2*pi)
## dnorm(1) == exp(-1/2)/sqrt(2*pi)
## dnorm(1) == 1/sqrt(2*pi*exp(1))
##
## ## Using "log = TRUE" for an extended range :
## par(mfrow = c(2,1))
## plot(function(x) dnorm(x, log = TRUE), -60, 50,
## main = "log { Normal density }")
## curve(log(dnorm(x)), add = TRUE, col = "red", lwd = 2)
## mtext("dnorm(x, log=TRUE)", adj = 0)
## mtext("log(dnorm(x))", col = "red", adj = 1)
##
## plot(function(x) pnorm(x, log.p = TRUE), -50, 10,
## main = "log { Normal Cumulative }")
## curve(log(pnorm(x)), add = TRUE, col = "red", lwd = 2)
## mtext("pnorm(x, log=TRUE)", adj = 0)
## mtext("log(pnorm(x))", col = "red", adj = 1)
##
## ## if you want the so-called 'error function'
## erf <- function(x) 2 * pnorm(x * sqrt(2)) - 1
## ## (see Abramowitz and Stegun 29.2.29)
## ## and the so-called 'complementary error function'
## erfc <- function(x) 2 * pnorm(x * sqrt(2), lower = FALSE)
## ## and the inverses
## erfinv <- function (x) qnorm((1 + x)/2)/sqrt(2)
## erfcinv <- function (x) qnorm(x/2, lower = FALSE)/sqrt(2)
## }
using macros parameter to pass a custom macro that is
used while extracting the documentation
rd2markdown::get_rd(
file = rd_examples[[2]],
macros = rd_examples_macro
)## % Generated by roxygen2: do not edit by hand
## % Please edit documentation in R/rd_data_sampler.R
## \name{rd_data_sampler}
## \alias{rd_data_sampler}
## \title{Rd data sampler}
## \format{
## A data.frame with 3 rows and 2 variables:
## \describe{
## \item{x}{Numeric values}
## \item{y}{Character values}
## }
## }
## \source{
## <r.d.sampler/>
## }
## \usage{
## rd_data_sampler
## }
## \description{
## An example of dataset documentation and linking to others \code{\link[=rnorm]{rnorm()}}
## }
## \examples{
## rd_data_sampler
##
## }
## \keyword{datasets}
or macros to try to automatically discover macros
rd2markdown::get_rd(
file = rd_examples[[2]],
macros = NA
)## % Generated by roxygen2: do not edit by hand
## % Please edit documentation in R/rd_data_sampler.R
## \name{rd_data_sampler}
## \alias{rd_data_sampler}
## \title{Rd data sampler}
## \format{
## A data.frame with 3 rows and 2 variables:
## \describe{
## \item{x}{Numeric values}
## \item{y}{Character values}
## }
## }
## \source{
## <r.d.sampler/>
## }
## \usage{
## rd_data_sampler
## }
## \description{
## An example of dataset documentation and linking to others \function{rnorm}
## }
## \examples{
## rd_data_sampler
##
## }
## \keyword{datasets}
documentation_to_markdown
Overview
The documentation_to_markdown function merges both and
rd2markdown and get_rd, providing a vectorized
way of parsing multiple documentation files at once. Simply pass a
vector of paths and the function will return a named list of markdown
documents created with rd2markdown function.
Examples
It is enough to pass the vector of file paths to get a list of parsed markdown files
rd2markdown::documentation_to_markdown(rd_examples)## $rd_file_sample.Rd
## [1] "# Rd sampler title\n\n```r\nrd_sampler(x, y = TRUE, ...)\n```\n\n## Description\n\nRd sampler description with [Rd sampler link](www.example.com), `Rd sampler in-line code`. And Rd dynamic content, **italics text**, **emphasis text**.\n\n## Details\n\nRd sampler details\n\nRd sampler enumerated list\n\n1. One\n2. Two\n3. Three\n\nRd sampler itemized list\n\n * One\n * Two\n * Three\n\n||||\n|:--|:--|:--|\n|Rd|Sampler|Table|\n|rd|sampler|table|\n\n`Rd + sampler + inline + equation`\n\n`Rd * sampler * block * equation`"
##
## $rd_file_sample_2.Rd
## [1] "# Rd data sampler\n\n```r\nrd_data_sampler\n```\n\n## Description\n\nAn example of dataset documentation and linking to others `rnorm()`"
The documentation_to_markdown function also allows
extracting only particular parts of the documentation, using
fragments parameter. If a given documentation file does not
have a specific section, it will become an empty string.
rd2markdown::documentation_to_markdown(rd_examples, fragments = "details")## $rd_file_sample.Rd
## [1] "## Details\n\nRd sampler details\n\nRd sampler enumerated list\n\n1. One\n2. Two\n3. Three\n\nRd sampler itemized list\n\n * One\n * Two\n * Three\n\n||||\n|:--|:--|:--|\n|Rd|Sampler|Table|\n|rd|sampler|table|\n\n`Rd + sampler + inline + equation`\n\n`Rd * sampler * block * equation`"
##
## $rd_file_sample_2.Rd
## [1] ""
Summary
The rd2markdown package is an attempt to solve the issue
of converting R package documentation objects into readable markdown
documents. It is still in early development, so not every single aspect
or nuance is covered. Therefore, we would like to welcome community
contribution by reporting gaps by opening issues on https://github.com/genentech/rd2markdown and describing
the problem or missing functionality. We value any type of input as we
aim to provide a tool that will be possible to use in various R
applications.