Including Images in R-Package Documentation (.Rd) Files

Including images in R-package documentation (.Rd) files

Untested, but look at the R source on GitHub, it would appear they add an image to ?par documentation file in the following manner:

 \item{\code{mai}}{A numerical vector of the form \code{c(bottom,
left, top, right)} which gives the margin size specified in
inches.\cr
\if{html}{\figure{mai.png}{options: width="35\%" alt="Figure: mai.png"}}
\if{latex}{\figure{mai.pdf}{options: width=7cm}}
}

The figure appears to be saved in /man/figures.

For more details see the Writing R Extensions section on the topic.

How to include and display images in R package?

...and almost a year later, I found the answer to my question while working on an actual package that needs to include image assets! According to the official R package documentation section on the inst folder:

To find a file in inst/ from code use system.file(). For example, to find inst/extdata/mydata.csv, you’d call system.file("extdata", "mydata.csv", package = "mypackage"). Note that you omit the inst/ directory from the path. This will work if the package is installed, or if it’s been loaded with devtools::load_all().

In this case, assuming my package is called "testpackage":

testUI <- function(id) {
ns <- NS(id)

shiny::showModal(
modalDialog(
title = img(
src=system.file("www/logo.png", package = "testpackage"),
style="display:block; margin-left:auto; margin-right:auto;"
),
br(),
fluidRow(
column(6, align="center", offset = 3,
textInput(ns("username"), label = NULL, placeholder = "Username"),
passwordInput(ns("password"), label = NULL, placeholder = "Password")
)
),
footer = (
fluidRow(
column(6, align="center", offset = 3,
actionButton(ns("signin"),"Sign in")
)
)
)
)
)
}

Note that I didn't use the comma separated directory structure as shown in the official example as I found that it's more intuitive to enter the full relative path, keeping in mind that:

When a package is installed, everything in inst/ is copied into the top-level package directory. In some sense inst/ is the opposite of .Rbuildignore - where .Rbuildignore lets you remove arbitrary files and directories from the top level, inst/ lets you add them. You are free to put anything you like in inst/ with one caution: because inst/ is copied into the top-level directory, you should never use a subdirectory with the same name as an existing directory. This means that you should avoid inst/build, inst/data, inst/demo, inst/exec, inst/help, inst/html, inst/inst, inst/libs, inst/Meta, inst/man, inst/po, inst/R, inst/src, inst/tests, inst/tools and inst/vignettes.

Hope this helps anyone else that's facing the same issue :)

Including an image using roxygen documentation

As per the change list from the announcement of R 2.14:

Rd markup has a new \figure tag so that figures can be included in
help pages when converted to HTML or LaTeX. There are examples on
the help pages for par() and points().

From: http://cran.r-project.org/doc/manuals/R-exts.html#Figures

To include figures in help pages, use the \figure markup. There are three forms.

The two commonly used simple forms are \figure{filename} and \figure{filename}{alternate text}. This will include a copy of the figure in either HTML or LaTeX output. In text output, the alternate text will be displayed instead. (When the second argument is omitted, the filename will be used.) Both the filename and the alternate text will be parsed verbatim, and should not include special characters that are significant in HTML or LaTeX.

The expert form is \figure{filename}{options: string}. (The word ‘options:’ must be typed exactly as shown and followed by at least one space.) In this form, the string is copied into the HTML img tag as attributes following the src attribute, or into the second argument of the \Figure macro in LaTeX, which by default is used as options to an \includegraphics call. As it is unlikely that any single string would suffice for both display modes, the expert form would normally be wrapped in conditionals. It is up to the author to make sure that legal HTML/LaTeX is used. For example, to include a logo in both HTML (using the simple form) and LaTeX (using the expert form), the following could be used:

 \if{html}{\figure{logo.jpg}{Our logo}}
\if{latex}{\figure{logo.jpg}{options: width=0.5in}}

The files containing the figures should be stored in the directory man/figures. Files with extensions .jpg, .pdf, .png and .svg from that directory will be copied to the help/figures directory at install time. (Figures in PDF format will not display in most HTML browsers, but might be the best choice in reference manuals.) Specify the filename relative to man/figures in the \figure directive.

Writing symbols in R package documentation files (.Rd files)

Doing it from Rstudio (Version 0.99.467):

  1. create .Rd file

Rd file creation


  1. insert desired character (see description field)

Sample Image


  1. save doc
  2. select encoding standard as prompted

Sample Image


  1. preview the file

Sample Image

Does this work for you?

R package documentation: link to a whole package, not function

You cannot link to the page that comes up when you click on the name of a package in RStudio's Packages pane. RStudio invisibly calls help(package = "<name>"), which renders the package's index.

From the R-exts manual:

The markup \link{foo} (usually in the combination \code{\link{foo}}) produces a hyperlink to the help for foo. Here foo is a topic, that is the argument of \alias markup in another Rd file (possibly in another package).

Hence \link and the equivalent Markdown markup supported by roxygen2 can only link to topics. A package index is not a topic in this sense because there is no corresponding Rd file.

It might be best just to remind users that they can use help to access the index of the package to which you are referring.

Adding automatically/manually sections to package documentation

I have written an Rscript that'll take care of all the edits to be made.

Explanation of the solution

Basically the devtools::build_manual calls the R CMD Rd2pdf script and this script basically bundles the args to call tools:::..Rd2pdf.

So what I did was overload the tools:::..Rd2pdf function and add a --toc param to change the toc title, and add another function tex.mod that'll modify the latex before it's rendered these two function are saved to ${R_HOME}/bin/Rd2pdf.overload.R so they could be used by the modified Rd2pdf, modify the Rd2pdf script basically execute Rd2pdf.overload.R instead of running tools:::Rd2pdf() and overload the devtools::build_manual to accept a toc param that'll be passed to the Rd2pdf script.

tex.mod reorders the descriptions and adds the sections to the toc using myaddcontentsline macro defined in the Rd latex package which is a wrapper to the latex macro addcontentsline.

Note: the functions that are not contained in the sections are shown first.

How sections will be defined

Section will be defined by documenting the package.

ie create an R file with the name ur.pkg.name.R and add the description of the package like this:

#' name.of.ur.pkg : A package for doing awesome things.
#'
#' The name.of.ur.pkg package provides two categories of important functions:
#' foo and baz.
#'
#' @section Foo functions:
#' first.fun
#' second.fun
#'
#' @section baz functions:
#' third.fun
#' fourth.fun
#'
#' @docType package
#' @name name.of.ur.pkg
NULL

the Rscript:

# modifies the latex of the converted .Rd files
# in order to add sections to the toc
tex.mod <- function(pkg='.', file='Rd2.tex', tocTi = "R{} topics documented:"){

library(stringr)
#get the package name
pkg <- devtools::as.package(pkg)$package
#reads the latex file
out <- readLines(file)
# modifies the Table of contents title
out[rdcont] <- sub("(?<=\\\\Rdcontents\\{).+(?=}$)", tocTi, out[rdcont <- grep('\\\\Rdcontents', out)], perl=T)
# Gets the defined sections
sections <- str_replace_all(strcapture(paste0("(?s)^.+?\\\\HeaderA\\{",pkg,"\\}.+?(\\\\begin\\{Section\\}.+\\\\end{Section})\n(?:\\\\inputencoding\\{|\n?\\\\printindex).+$"), paste0(out, collapse='\n'), data.frame(v=character(0)), perl=T)[1,1], c('\\\\begin\\{Section\\}\\{(.+?) *\\}\n'='\\1\n', '^\n'='', '\n$'='', '\n%?\n'='\n'))

# splits sections
spl <- str_split(sections, '\n?\\\\end.+?(\n|$)')[[1]]
spl <- str_split(spl[nchar(spl)>0], '\n')

#gets the package description
pkgdesc <- out[1:rdcont]
# gets the trailing lines
trailing <- out[length(out)+(-1:0)]
# get the descriptions
outi<- str_split(paste0(out[(rdcont+2):(length(out)-2)], collapse='\n'), '\\\\inputencoding.+\n')[[1]]
# sets the names to th name of the function/package described
names(outi) <- str_extract(outi, '(?<=\\\\HeaderA\\{).+?(?=\\})')
# adds lines to add to the toc file if you want more indentation put section instead of chapter
outi <- c(outi, sapply(spl, function(x) {v<-paste0("\\myaddcontentsline{toc}{chapter}{\\protect\\textbf{", x[1],"}}"); names(v)<-x[1]; v}))
# unlists the names of the sections with their functions
spl <- unlist(spl)
# orders them so that the functions that have no section are shown first
outi <- c(pkgdesc, outi[!(names(outi) %in% c(spl, pkg))], outi[spl], trailing)
# writes to file
if (require(data.table)){
# the data.table way
fwrite(list( outi), quote=F, sep='\n', file=file, append=F)
} else {
# the baseR way
fileConn<-file(file, open='w')
writeLines(outi, fileConn)
close(fileConn)
}

}

write.fun <- function(fun, path){
fun.src <- capture.output(fun)
fun.name <- as.character(substitute(fun))
fun.src[1] <- paste0(fun.name[length(fun.name)],' <- ', fun.src[1])
fun.src<-fun.src[!grepl('^<.+?>$',fun.src)]
if (require(data.table)){
# the data.table way
fwrite(list(fun.src), quote=F, sep='\n', file=path, append=T)
} else {
# the baseR way
fileConn<-file(path, open='a')
writeLines(fun.src, fileConn)
close(fileConn)
}
}
# get the location of R_HOME
Rh <- Sys.getenv('R_HOME')
f <- file.path(Rh, 'bin', 'Rd2pdf.overload.R')
file.create(f)

# adds the function to the file
write.fun(tex.mod,f)
write.fun(tools:::..Rd2pdf,f)

# reads the file
out <- readLines(f)
# forces all functions to be loaded from tools
out <- gsub('(?=(.DESCRIPTION_to_latex|.Rdfiles2tex|latex_canonical_encoding|texi2pdf|.Rd2pdf)\\()', "tools:::", out, perl=T)
# add param description to usage
out[i] <- paste(out[i <- grep('--title=NAME', out, fixed=T)], ' " --toc=NAME\tuse NAME as the title of the Table of contents", ', sep='\n' )
# parses param
out[grep('substr(a, 1, 8) == "--title="', out, fixed=T)+2] <- paste(' }', ' else if (substr(a, 1, 6) == "--toc=") {', ' tocTi <- sub("--toc=", "", a)', ' }', sep='\n')
# adds definition
out[grep(' title <- ""', out, fixed=T)] <- ' title <- ""\n tocTi <- ""'
# adds call to tex.mod to force modification
out[i] <- paste0(out[i<-grep('setwd\\(build_dir\\)', out)], '\n\ttocTi <- if(nchar(tocTi)>0) tocTi else "\\\\R{} topics documented:"\n\ttex.mod(pkg=files[1L], file="Rd2.tex", tocTi=tocTi)')
# adds call to ..Rd2pdf at the end
out <- c(out, '..Rd2pdf()')
# rewrites the file
fileConn<-file(f, open='w')
writeLines(out, fileConn)
close(fileConn)

# overloading devtools::build_manual
build_manual <- function (pkg = ".", path = NULL, toc=NULL)
{
pkg <- devtools::as.package(pkg)
path <- rlang::`%||%`(path, dirname(pkg$path))

name <- paste0(pkg$package, "_", pkg$version, ".pdf", collapse = " ")
tryCatch(msg <- callr::rscript(file.path(Sys.getenv("R_HOME"), "bin", "Rd2pdf.overload.R"), cmdargs = paste0('nextArg', paste0(c("--force",
paste0("--output=", path, "/", name), pkg$path, if(!is.null(toc)) paste0("--toc=",toc)), collapse='nextArg')), fail_on_status = TRUE),
error = function(e) {
cat(e$stderr)
stop("Failed to build manual", call. = FALSE)
})
cat(msg$stdout)
invisible(msg)
}

write.fun(build_manual, file.path(path.expand('~'), '.Rprofile'))

It automatically adds the new definition of build_manual to ~/.Rprofile.

After running devtools::document() you can

  • Now to build your manual run build_manual()
  • Now to build your manual with a custom Table of contents title pass a toc argument to the call


Related Topics



Leave a reply



Submit