1#' Convert to a PowerPoint presentation
2#'
3#' Format for converting from R Markdown to a PowerPoint presentation. Pandoc
4#' v2.0.5 or above is required.
5#' @inheritParams pdf_document
6#' @inheritParams html_document
7#' @inheritParams beamer_presentation
8#' @param reference_doc Path to a PowerPoint template.
9#' @export
10#' @return R Markdown output format to pass to \code{\link{render}}
11powerpoint_presentation <- function(
12  toc = FALSE, toc_depth = 2, number_sections = FALSE,
13  fig_width = 5, fig_height = 4, fig_caption = TRUE,
14  df_print = 'default', keep_md = FALSE, md_extensions = NULL,
15  slide_level = NULL, reference_doc = 'default', pandoc_args = NULL
16) {
17
18  # PowerPoint has been supported since Pandoc 2.0.5
19  pandoc_available('2.0.5', error = TRUE)
20
21  # knitr options and hooks
22  knitr <- knitr_options(opts_chunk = list(
23    dev = 'png', dpi = 96, fig.width = fig_width, fig.height = fig_height
24  ))
25
26  # base pandoc options for all pptx output
27  args <- c()
28
29  # table of contents
30  args <- c(args, pandoc_toc_args(toc, toc_depth))
31
32  # ppt template
33  args <- c(args, reference_doc_args("doc", reference_doc))
34
35  # slide level
36  if (!is.null(slide_level))
37    args <- c(args, '--slide-level', as.character(slide_level))
38
39  # TODO: syntax highlighting
40
41  # pandoc args
42  args <- c(args, pandoc_args)
43
44  saved_files_dir <- NULL
45
46  pre_processor <- function(metadata, input_file, runtime, knit_meta, files_dir, output_dir) {
47    saved_files_dir <<- files_dir
48    NULL
49  }
50
51  intermediates_generator <- function(...) {
52    reference_intermediates_generator(saved_files_dir, ..., reference_doc)
53  }
54
55  # return output format
56  output_format(
57    knitr = knitr,
58    pandoc = pandoc_options(
59      to = 'pptx',
60      from = from_rmarkdown(fig_caption, md_extensions),
61      args = args,
62      lua_filters = if (number_sections) pkg_file_lua("number-sections.lua")
63    ),
64    keep_md = keep_md,
65    df_print = df_print,
66    pre_processor = pre_processor,
67    intermediates_generator = intermediates_generator
68  )
69}
70
71# copy the reference doc to the intermediate dir when the dir is specified
72reference_intermediates_generator <- function(
73  saved_files_dir, original_input, intermediates_dir, reference_doc
74) {
75  res <- general_intermediates_generator(saved_files_dir,  original_input, intermediates_dir)
76  if (is.null(reference_doc) || identical(reference_doc, 'default')) return(res)
77  if (!is_relative(reference_doc)) return(res)  # an absolute path was provided; no need to copy
78  doc  <- normalize_path(reference_doc, mustWork = TRUE)
79  doc2 <- relative_to(normalize_path('.'), doc)
80  if (doc2 == doc) stop(
81    'The path of the reference document ', reference_doc, 'must be a relative ',
82    'path under the directory ', getwd()
83  )
84  doc3 <- file.path(intermediates_dir, doc2)
85  dir.create(dirname(doc3), FALSE, recursive = TRUE)
86  file.copy(doc2, doc3)
87  c(res, doc3)
88}
89