diff --git a/NAMESPACE b/NAMESPACE index e75a76a..6647b3d 100644 --- a/NAMESPACE +++ b/NAMESPACE @@ -53,6 +53,7 @@ export(spec_pointrange) export(spec_popover) export(spec_tooltip) export(text_spec) +export(use_latex_packages) export(usepackage_latex) export(xml_as_kable) export(xtable2kable) diff --git a/R/kbl.R b/R/kbl.R index 7e6c7f2..84a04ee 100644 --- a/R/kbl.R +++ b/R/kbl.R @@ -1,6 +1,6 @@ #' Wrapper function of knitr::kable #' -#' @description knitr's kable function is the foundation of this package. +#' @description The `knitr::kable()` function is the foundation of this package. #' However, it has many latex/html specific arguments hidden under the ground #' unless you check its source code. This wrapper function is created to #' provide better documentation (and auto-complete yay) and at the same time, @@ -64,71 +64,39 @@ kbl <- function(x, format, digits = getOption("digits"), align <- strsplit(align, '')[[1]] } if (missing(format) || is.null(format)) { - if (knitr::is_latex_output()) { + if (knitr::is_latex_output()) format <- "latex" - out <- knitr::kable( - x = x, format = format, digits = digits, - row.names = row.names, col.names = col.names, align = align, - caption = caption, label = label, format.args = format.args, - escape = escape, - booktabs = booktabs, longtable = longtable, - valign = valign, position = position, centering = centering, - vline = vline, toprule = toprule, bottomrule = bottomrule, - midrule = midrule, linesep = linesep, caption.short = caption.short, - table.envir = table.envir, ... - ) - table_info <- magic_mirror(out) - if (is.null(col.names)) { - table_info$position_offset <- 0 - } - return(out) - } else { + else format <- "html" - out <- knitr::kable( - x = x, format = format, digits = digits, - row.names = row.names, col.names = col.names, align = align, - caption = caption, label = label, format.args = format.args, - escape = escape, - table.attr = table.attr, ... - ) - if (!"kableExtra" %in% class(out)) class(out) <- c("kableExtra", class(out)) - return(out) - } - } else { - if (format == "latex") { - out <- knitr::kable( - x = x, format = format, digits = digits, - row.names = row.names, col.names = col.names, align = align, - caption = caption, label = label, format.args = format.args, - escape = escape, - booktabs = booktabs, longtable = longtable, - valign = valign, position = position, centering = centering, - vline = vline, toprule = toprule, bottomrule = bottomrule, - midrule = midrule, linesep = linesep, caption.short = caption.short, - table.envir = table.envir, ... - ) - table_info <- magic_mirror(out) - if (is.null(col.names)) { - table_info$position_offset <- 0 - } - return(out) - } - if (format == "html") { - out <- knitr::kable( - x = x, format = format, digits = digits, - row.names = row.names, col.names = col.names, align = align, - caption = caption, label = label, format.args = format.args, - escape = escape, - table.attr = table.attr, ... - ) - if (!"kableExtra" %in% class(out)) class(out) <- c("kableExtra", class(out)) - return(out) - } - return(knitr::kable( + } + if (format == "latex") { + use_latex_packages() + out <- knitr::kable( + x = x, format = format, digits = digits, + row.names = row.names, col.names = col.names, align = align, + caption = caption, label = label, format.args = format.args, + escape = escape, + booktabs = booktabs, longtable = longtable, + valign = valign, position = position, centering = centering, + vline = vline, toprule = toprule, bottomrule = bottomrule, + midrule = midrule, linesep = linesep, caption.short = caption.short, + table.envir = table.envir, ... + ) + } else if (format == "html") { + out <- knitr::kable( + x = x, format = format, digits = digits, + row.names = row.names, col.names = col.names, align = align, + caption = caption, label = label, format.args = format.args, + escape = escape, + table.attr = table.attr, ... + ) + if (!"kableExtra" %in% class(out)) class(out) <- c("kableExtra", class(out)) + } else + out <- knitr::kable( x = x, format = format, digits = digits, row.names = row.names, col.names = col.names, align = align, caption = caption, label = label, format.args = format.args, escape = escape, ... - )) - } + ) + out } diff --git a/R/util.R b/R/util.R index c50a8b7..2de238c 100644 --- a/R/util.R +++ b/R/util.R @@ -25,6 +25,47 @@ usepackage_latex <- function(name, options = NULL) { invisible(knit_meta_add(list(latex_dependency(name, options)))) } +#' Declare LaTeX packages needed by kableExtra +#' +#' @description +#' Declares all of the LaTeX packages that +#' may be used by `kableExtra` functions so that they +#' will be loaded when the document is produced. +#' @details +#' When `kableExtra` loads, it calls this function if it +#' detects that `knitr` is running and producing +#' LaTeX output. However, sometimes `kableExtra` +#' is loaded before `knitr` runs, and then these packages +#' can end up being missed, leading to LaTeX errors such as +#' "Undefined control sequence." (See +#' Github issue #721 for an example.) +#' +#' Our `kbl()` wrapper for `knitr::kable()` calls +#' this function for LaTeX output, so an explicit call +#' is not necessary. +#' +#' @examples use_latex_packages() +#' @export +use_latex_packages <- function() { + load_packages <- getOption("kableExtra.latex.load_packages", default = TRUE) + if (load_packages) { + usepackage_latex("booktabs") + usepackage_latex("longtable") + usepackage_latex("array") + usepackage_latex("multirow") + usepackage_latex("wrapfig") + usepackage_latex("float") + usepackage_latex("colortbl") + usepackage_latex("pdflscape") + usepackage_latex("tabu") + usepackage_latex("threeparttable") + usepackage_latex("threeparttablex") + usepackage_latex("ulem", "normalem") + usepackage_latex("makecell") + usepackage_latex("xcolor") + } +} + # Find the right xml section. Since xml_child + search name will result in a # crash (at least on my machine), here is a helper function. xml_tpart <- function(x, part) { diff --git a/R/zzz.R b/R/zzz.R index 8c533aa..d3823cf 100644 --- a/R/zzz.R +++ b/R/zzz.R @@ -1,23 +1,7 @@ .onLoad <- function(libname = find.package("kableExtra"), pkgname = "kableExtra") { - if (knitr::is_latex_output()) { - load_packages <- getOption("kableExtra.latex.load_packages", default = TRUE) - if (load_packages) { - usepackage_latex("booktabs") - usepackage_latex("longtable") - usepackage_latex("array") - usepackage_latex("multirow") - usepackage_latex("wrapfig") - usepackage_latex("float") - usepackage_latex("colortbl") - usepackage_latex("pdflscape") - usepackage_latex("tabu") - usepackage_latex("threeparttable") - usepackage_latex("threeparttablex") - usepackage_latex("ulem", "normalem") - usepackage_latex("makecell") - usepackage_latex("xcolor") - } - } + if (knitr::is_latex_output()) + use_latex_packages() + # auto_format <- getOption("kableExtra.auto_format", default = FALSE) # if (auto_format) auto_set_format() diff --git a/man/kbl.Rd b/man/kbl.Rd index 56ea26d..51263c2 100644 --- a/man/kbl.Rd +++ b/man/kbl.Rd @@ -130,7 +130,7 @@ caption is provided.} \item{...}{Other arguments (see Examples and References).} } \description{ -knitr's kable function is the foundation of this package. +The \code{knitr::kable()} function is the foundation of this package. However, it has many latex/html specific arguments hidden under the ground unless you check its source code. This wrapper function is created to provide better documentation (and auto-complete yay) and at the same time, diff --git a/man/linebreak.Rd b/man/linebreak.Rd index 31ecbad..40141cf 100644 --- a/man/linebreak.Rd +++ b/man/linebreak.Rd @@ -14,7 +14,7 @@ linebreak(x, align = c("l", "c", "r"), double_escape = F, linebreaker = "\\n") \item{double_escape}{Whether special character should be double escaped. Default is FALSE.} -\item{linebreaker}{Symbol for linebreaks to replace. Default is \verb{\\\\n}.} +\item{linebreaker}{Symbol for linebreaks to replace. Default is \verb{\\n}.} } \description{ This function generates LaTeX code of \code{makecell} so that users diff --git a/man/use_latex_packages.Rd b/man/use_latex_packages.Rd new file mode 100644 index 0000000..fe10ad5 --- /dev/null +++ b/man/use_latex_packages.Rd @@ -0,0 +1,29 @@ +% Generated by roxygen2: do not edit by hand +% Please edit documentation in R/util.R +\name{use_latex_packages} +\alias{use_latex_packages} +\title{Declare LaTeX packages needed by kableExtra} +\usage{ +use_latex_packages() +} +\description{ +Declares all of the LaTeX packages that +may be used by \code{kableExtra} functions so that they +will be loaded when the document is produced. +} +\details{ +When \code{kableExtra} loads, it calls this function if it +detects that \code{knitr} is running and producing +LaTeX output. However, sometimes \code{kableExtra} +is loaded before \code{knitr} runs, and then these packages +can end up being missed, leading to LaTeX errors such as +"Undefined control sequence." (See +Github issue #721 for an example.) + +Our \code{kbl()} wrapper for \code{knitr::kable()} calls +this function for LaTeX output, so an explicit call +is not necessary. +} +\examples{ +use_latex_packages() +}