1#' Convert to a Beamer presentation 2#' 3#' Format for converting from R Markdown to a Beamer presentation. 4#' 5#' @inheritParams output_format 6#' @inheritParams pdf_document 7#' @inheritParams html_document 8#' 9#' @param toc \code{TRUE} to include a table of contents in the output (only 10#' level 1 headers will be included in the table of contents). 11#' @param slide_level The heading level which defines individual slides. By 12#' default this is the highest header level in the hierarchy that is followed 13#' immediately by content, and not another header, somewhere in the document. 14#' This default can be overridden by specifying an explicit 15#' \code{slide_level}. 16#' @param incremental \code{TRUE} to render slide bullets incrementally. Note 17#' that if you want to reverse the default incremental behavior for an 18#' individual bullet you can precede it with \code{>}. For example: 19#' \emph{\code{> - Bullet Text}} 20#' @param theme Beamer theme (e.g. "AnnArbor"). 21#' @param colortheme Beamer color theme (e.g. "dolphin"). 22#' @param fonttheme Beamer font theme (e.g. "structurebold"). 23#' @param self_contained Whether to generate a full LaTeX document (\code{TRUE}) 24#' or just the body of a LaTeX document (\code{FALSE}). Note the LaTeX 25#' document is an intermediate file unless \code{keep_tex = TRUE}. 26#' 27#' @return R Markdown output format to pass to \code{\link{render}} 28#' 29#' @details 30#' 31#' See the 32#' \href{http://rmarkdown.rstudio.com/beamer_presentation_format.html}{online 33#' documentation} for additional details on using the \code{beamer_presentation} 34#' format. 35#' 36#' Creating Beamer output from R Markdown requires that LaTeX be installed. 37#' 38#' R Markdown documents can have optional metadata that is used to generate a 39#' document header that includes the title, author, and date. For more details 40#' see the documentation on R Markdown \link[=rmd_metadata]{metadata}. 41#' 42#' R Markdown documents also support citations. You can find more information on 43#' the markdown syntax for citations in the 44#' \href{http://rmarkdown.rstudio.com/authoring_bibliographies_and_citations.html}{Bibliographies 45#' and Citations} article in the online documentation. 46#' 47#' @examples 48#' \dontrun{ 49#' 50#' library(rmarkdown) 51#' 52#' # simple invocation 53#' render("pres.Rmd", beamer_presentation()) 54#' 55#' # specify an option for incremental rendering 56#' render("pres.Rmd", beamer_presentation(incremental = TRUE)) 57#' } 58#' 59#' @export 60beamer_presentation <- function(toc = FALSE, 61 slide_level = NULL, 62 incremental = FALSE, 63 fig_width = 10, 64 fig_height = 7, 65 fig_crop = TRUE, 66 fig_caption = TRUE, 67 dev = 'pdf', 68 df_print = "default", 69 theme = "default", 70 colortheme = "default", 71 fonttheme = "default", 72 highlight = "default", 73 template = "default", 74 keep_tex = FALSE, 75 latex_engine = "pdflatex", 76 citation_package = c("none", "natbib", "biblatex"), 77 self_contained = TRUE, 78 includes = NULL, 79 md_extensions = NULL, 80 pandoc_args = NULL) { 81 82 # base pandoc options for all beamer output 83 args <- c() 84 85 # template path and assets 86 if (!is.null(template)) { 87 if (identical(template, "default")) template <- patch_beamer_template() 88 if (!is.null(template)) 89 args <- c(args, "--template", pandoc_path_arg(template)) 90 } 91 92 # table of contents 93 if (toc) 94 args <- c(args, "--table-of-contents") 95 96 # slide level 97 if (!is.null(slide_level)) 98 args <- c(args, "--slide-level", as.character(slide_level)) 99 100 # incremental 101 if (incremental) 102 args <- c(args, "--incremental") 103 104 # themes 105 if (!identical(theme, "default")) 106 args <- c(args, pandoc_variable_arg("theme", theme)) 107 if (!identical(colortheme, "default")) 108 args <- c(args, pandoc_variable_arg("colortheme", colortheme)) 109 if (!identical(fonttheme, "default")) 110 args <- c(args, pandoc_variable_arg("fonttheme", fonttheme)) 111 112 # highlighting 113 if (!is.null(highlight)) 114 highlight <- match.arg(highlight, highlighters()) 115 args <- c(args, pandoc_highlight_args(highlight)) 116 117 # latex engine 118 latex_engine = match.arg(latex_engine, c("pdflatex", "lualatex", "xelatex")) 119 args <- c(args, pandoc_latex_engine_args(latex_engine)) 120 121 # citation package 122 citation_package <- match.arg(citation_package) 123 if (citation_package != "none") args <- c(args, paste0("--", citation_package)) 124 125 # generate a self-contained LaTeX document (including preamble) 126 if (self_contained) args <- c(args, "--self-contained") 127 128 # content includes 129 args <- c(args, includes_to_pandoc_args(includes)) 130 131 # make sure the graphics package is always loaded 132 if (identical(template, "default")) args <- c(args, "--variable", "graphics=yes") 133 134 # custom args 135 args <- c(args, pandoc_args) 136 137 # initialize saved files dir 138 saved_files_dir <- NULL 139 140 pre_processor <- function(metadata, input_file, runtime, knit_meta, 141 files_dir, output_dir) { 142 # save files dir (for generating intermediates) 143 saved_files_dir <<- files_dir 144 145 # no-op other than caching dir location 146 invisible(NULL) 147 } 148 149 # generate intermediates (required to make resources available for publish) 150 intermediates_generator <- function(original_input, encoding, 151 intermediates_dir) { 152 return(pdf_intermediates_generator(saved_files_dir, original_input, 153 encoding, intermediates_dir)) 154 } 155 156 # return format 157 output_format( 158 knitr = knitr_options_pdf(fig_width, fig_height, fig_crop, dev), 159 pandoc = pandoc_options(to = "beamer", 160 from = from_rmarkdown(fig_caption, md_extensions), 161 args = args, 162 latex_engine = latex_engine, 163 keep_tex = keep_tex), 164 pre_processor = pre_processor, 165 intermediates_generator = intermediates_generator, 166 clean_supporting = !keep_tex, 167 df_print = df_print 168 ) 169} 170 171 172patch_beamer_template_pagenumber <- function(template) { 173 174 patch <- paste( 175 "% Comment these out if you don't want a slide with just the", 176 "% part/section/subsection/subsubsection title:", "\\AtBeginPart{", 177 " \\let\\insertpartnumber\\relax", " \\let\\partname\\relax", 178 " \\frame{\\partpage}", "}", "\\AtBeginSection{", 179 " \\let\\insertsectionnumber\\relax", " \\let\\sectionname\\relax", 180 " \\frame{\\sectionpage}", "}", "\\AtBeginSubsection{", 181 " \\let\\insertsubsectionnumber\\relax", " \\let\\subsectionname\\relax", 182 " \\frame{\\subsectionpage}", "}", 183 sep = "\n" 184 ) 185 186 pasted <- paste(template, collapse = "\n") 187 patched <- sub(patch, "", pasted, fixed = TRUE) 188 strsplit(patched, "\n", fixed = TRUE)[[1]] 189} 190 191patch_beamer_template_paragraph_spacing <- function(template) { 192 193 patch <- c( 194 "\\setlength{\\parindent}{0pt}", 195 "\\setlength{\\parskip}{6pt plus 2pt minus 1pt}" 196 ) 197 198 lines <- unlist(lapply(patch, function(line) { 199 index <- grep(line, template, fixed = TRUE) 200 if (length(index) == 1) index else -1 201 })) 202 203 # bail if we already have these lines in the document 204 if (all(lines >= 0) && lines[[1]] == lines[[2]] - 1) 205 return(template) 206 207 # find patch location -- we insert before this line 208 targetLine <- "\\setlength{\\emergencystretch}{3em} % prevent overfull lines" 209 targetIdx <- grep(targetLine, template, fixed = TRUE) 210 if (!length(targetIdx)) 211 return(template) 212 213 # insert patch 214 c( 215 utils::head(template, n = targetIdx - 1), 216 patch, 217 utils::tail(template, n = -(targetIdx - 1)) 218 ) 219} 220 221patch_beamer_template <- function() { 222 pandoc_available(error = TRUE) 223 224 # invoke pandoc to read default template 225 command <- paste(quoted(pandoc()), "-D beamer") 226 template <- with_pandoc_safe_environment({ 227 tryCatch( 228 system(command, intern = TRUE), 229 error = function(e) NULL 230 ) 231 }) 232 233 # make failure to read template non-fatal 234 if (is.null(template)) 235 return(NULL) 236 237 # trim whitespace 238 template <- gsub("^\\s+|\\s+$", "", template, perl = TRUE) 239 240 # apply patches (store original version of template so we can 241 # compare after applying patches) 242 original <- template 243 version <- pandoc_version() 244 245 if (version < "1.15.2") 246 template <- patch_beamer_template_pagenumber(template) 247 248 if (version > "1.15.2" && version < "1.17.3") 249 template <- patch_beamer_template_paragraph_spacing(template) 250 251 # if the template hasn't changed, return NULL (we don't need 252 # to apply a custom template) 253 if (identical(template, original)) 254 return(NULL) 255 256 # write and return path to template 257 as_tmpfile(enc2utf8(template)) 258} 259