The rd2markdown package intro
Szymon Maksymiuk
2025-01-27
package_intro.Rmd
The 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.