Let's say I have a package with a function that returns an S3 object:
new_myclass <- function() {
return(structure(list(a=1, b=2), class = "myclass"))
}
I also have two functions that take a myclass
object and return respectively a HTML representation and a LaTeX representation of the object.
myclass2html <- function(obj) { return("<p>MyClass object</p>")}
myclass2latex <- function(obj) { return("\begin{em}MyClass\end{em} object $x$")}
What functions/methods should I define to provide consistent and transparent knitr
and rmarkdown
support? I would like to support both .Rmd
files and .R
files with a header like:
#'---
#' title: My document
#' output: pdf_output
#'---
So far my approach goes through the knit_print
method:
knit_print.myclass <- function(x, ...) {
rmarkdown_fmt <- rmarkdown::metadata$output
knitr_fmt <- knitr::opts_knit$get("out.format")
# should I use these heuristics with both variables?
if (rmarkdownfmt == "pdf_document") {
return(knitr::asis_output(myclass2latex(x)))
}
if (knitr_fmt %in% c("html", "markdown")) {
return(knitr::asis_output(myclass2html(x)))
} else {
stop("Format not supported!")
}
}
My main issue is that there may be two variables rmarkdown::metadata$output
and knitr::opts_knit$get("out.format")
that may or may not be defined (depending on whether or not rmarkdown
is being used). I find this confusing.
knit_print
the right method to customize for this purpose?get_output_format
function that tells me the output format? To put the question in context, I am working on the condformat package that allows to visualize DataFrames with conditional formatting rules.
EDIT: So far I have been doing my own voodoo to detect the output format:
#' @importFrom rmarkdown metadata
#' @importFrom knitr opts_knit
guess_output_format <- function() {
rmd_output <- tryCatch({rmarkdown::metadata$output},
error = function(e) {NULL})
if (is.null(rmd_output)) {
rmd_output = ""
}
if (is.list(rmd_output)) {
rmd_output <- names(rmd_output)[1]
}
if (rmd_output == "pdf_document") {
return("latex")
} else if (rmd_output %in% c("html_document", "html_vignette")) {
return("html")
} else if (rmd_output != "") {
stop("Unsupported rmarkdown output format:", rmd_output)
}
# No rmarkdown, let's try with knitr:
format <- knitr::opts_knit$get("out.format")
if (format %in% c("html", "markdown")) {
return("html")
} else if (format %in% c("latex")) {
return("latex")
} else {
stop("Format not supported!")
}
}
EDIT: Further discussion here: https://github.com/rstudio/rmarkdown/issues/649
With knitr 1.18 this is much simpler:
guess_output_format <- function() {
if (knitr::is_html_output()) {
return("html")
} else if (knitr::is_latex_output()) {
return("latex")
} else {
return("unsupported")
}
}
Related issue: https://github.com/rstudio/rmarkdown/issues/649
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With