Skip to content

Commit

Permalink
major changes to path handling - now can build from html slides on th…
Browse files Browse the repository at this point in the history
…e web
  • Loading branch information
jhelvy committed Feb 24, 2021
1 parent d8e5781 commit 3b3bc7a
Show file tree
Hide file tree
Showing 20 changed files with 286 additions and 216 deletions.
1 change: 1 addition & 0 deletions .Rbuildignore
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,4 @@
build.R
^\.travis\.yml$
^CRAN-RELEASE$
next_release.md
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
Package: xaringanBuilder
Title: Functions For Building Xaringan Slides To Different Outputs
Version: 0.0.4.9000
Version: 0.0.5.9000
Authors@R:
c(person(given = "John",
family = "Helveston",
Expand Down
13 changes: 13 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,16 @@
# xaringanBuilder 0.0.5

## Summary of larger updates:

* Major improvements to how paths are handled by adding the build_paths() function (not exported). Now you can use a url to build to any output types except for social and html (which both require starting from the Rmd file).
* Added build_to_pdf() function (not exported) as an internal helper to build from a Rmd or html file to the pdf.

## Summary of smaller updates:

* Added `assert_chrome_installed()` for issue #12

## Bugs

# xaringanBuilder 0.0.4

* Added `build_social()` for making a png of the first slides sized for sharing on social media.
Expand Down
38 changes: 20 additions & 18 deletions R/all.R
Original file line number Diff line number Diff line change
@@ -1,15 +1,15 @@
#' Build xaringan slides to multiple outputs.
#'
#' Build xaringan slides to multiple outputs. Options are `"html"`, `"pdf"`,
#' `"gif"`, `"pptx"`, `"thumbnail"`, and `"social"`.
#' `"gif"`, `"pptx"`, `"thumbnail"`, and `"social"`. See individual
#' build_..() functions for details about each output type.
#' @param input Path to Rmd file of xaringan slides.
#' @param include A vector of the different output types to build. Options are
#' `"html"`, `"pdf"`, `"gif"`, `"pptx"`, and `"thumbnail"` (a png image of the
#' first slide). Defaults to `c("html", "pdf", "gif", "pptx", "thumbnail")`.
#' `"html"`, `"pdf"`, `"gif"`, `"pptx"`, `"thumbnail"`, and `"social"`.
#' Defaults to `c("html", "pdf", "gif", "pptx", "thumbnail", "social")`.
#' @param exclude A vector of the different output types to NOT build. Options
#' are `"html"`, `"pdf"`, `"gif"`, `"pptx"`, and `"thumbnail"` (a png image of
#' the first slide). Defaults to `NULL`, in which case all all output types
#' are rendered.
#' are `"html"`, `"pdf"`, `"gif"`, `"pptx"`, `"thumbnail"`, and `"social"`.
#' Defaults to `NULL`, in which case all all output types are built.
#' @param complex_slides For "complex" slides (e.g. slides with panelsets or
#' other html widgets or advanced features), set `complex_slides = TRUE`.
#' Defaults to `FALSE`. This will use the {chromote} package to iterate through
Expand Down Expand Up @@ -41,10 +41,11 @@ build_all <- function(
partial_slides = FALSE,
delay = 1
) {
# Check that input file has the correct extension
assert_path_ext(input, "rmd")
input <- fs::path_abs(input)
input_html <- fs::path_ext_set(input, "html")
input_pdf <- fs::path_ext_set(input, "pdf")

# Build input and output paths
paths <- build_paths(input, output_file = NULL)

include <- match.arg(include, several.ok = TRUE)
do_htm <- ("html" %in% include) && (! "html" %in% exclude)
Expand Down Expand Up @@ -74,35 +75,36 @@ build_all <- function(
# if at some point intermediate files are removed if not requested, the
# logic here will need to be changed.

if (do_gif && (!fs::file_exists(input_pdf) || do_htm)) {
if (do_gif && (!fs::file_exists(paths$input$pdf) || do_htm)) {
# to make a gif we need the PDF file
# or if we update the HTML, we should also update the PDF for the gif
do_pdf <- TRUE
}
if (do_ppt && (!fs::file_exists(input_pdf) || do_htm)) {
if (do_ppt && (!fs::file_exists(paths$input$pdf) || do_htm)) {
# to make a pptx we need the PDF file
# or if we update the HTML, we should also update the PDF for the pptx
do_pdf <- TRUE
}
if ((do_pdf || do_thm) && !fs::file_exists(input_html)) {
if ((do_pdf || do_thm) && !fs::file_exists(paths$input$html)) {
# to make a PDF or thumbnail we need the html file
do_htm <- TRUE
}

# Do each step in order to ensure updates propagate
# (or we use the current version of the required build step)
if (do_soc) build_html(input)
if (do_htm) build_html(input)
if (do_thm) build_thumbnail(input_html)
if (do_soc) build_social(paths$input$rmd, paths$output$social)
if (do_htm) build_html(paths$input$rmd, paths$output$html)
if (do_thm) build_thumbnail(paths$input$html, paths$output$thumbnail)
if (do_pdf) {
build_pdf(
input = input_html,
input = paths$input$html,
output_file = paths$output$pdf,
complex_slides = complex_slides,
partial_slides = partial_slides,
delay = delay)
}
if (do_gif) build_gif(input_pdf)
if (do_ppt) build_pptx(input_pdf)
if (do_gif) build_gif(paths$input$pdf, paths$output$gif)
if (do_ppt) build_pptx(paths$input$pdf, paths$output$pptx)

invisible(input)
}
34 changes: 15 additions & 19 deletions R/gif.R
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#' Build xaringan slides as gif file.
#'
#' Build xaringan slides as a gif file from a Rmd, html, or pdf file. The
#' function builds to the pdf and then converts it to a gif.
#' @param input Path to Rmd, html, or pdf file of xaringan slides.
#' Build xaringan slides as a gif file. The function builds to the pdf and
#' then converts it to a gif.
#' @param input Path to a Rmd, html, or pdf file, or a url of xaringan slides.
#' If the input is a url to xaringan slides on a website, you must provide the
#' full url ending in ".html".
#' @param output_file Name of the output gif file.
#' @param density Resolution of the resulting gif file.
#' @param fps Frames per second of the resulting gif file.
Expand Down Expand Up @@ -33,28 +35,22 @@ build_gif <- function(
complex_slides = FALSE,
partial_slides = FALSE,
delay = 1
) {
) {
# Check input and output files have correct extensions
assert_path_ext(input, c("rmd", "html", "pdf"), arg = "input")
output_file <- check_output_file(input, output_file, "gif")
assert_io_paths(input, c("rmd", "html", "pdf"), output_file, "gif")

# Create full file paths from root
input <- fs::path_abs(input)
output_file <- fs::path_abs(output_file)
# Build input and output paths
paths <- build_paths(input, output_file)

# Build
if (test_path_ext(input, c("rmd", "html"))) {
build_pdf(
input = input,
output_file = fs::path_ext_set(output_file, "pdf"),
complex_slides = complex_slides,
partial_slides = partial_slides,
delay = delay)
input <- fs::path_ext_set(input, "pdf")
# Build html and / or pdf (if input is not pdf)
if (!test_path_ext(input, "pdf")) {
build_to_pdf(input, paths, complex_slides, partial_slides, delay)
}

# Build gif from pdf
input <- paths$input$pdf
output_file <- paths$output$gif
print_build_status(input, output_file)

pngs <- pdf_to_pngs(input, density)
pngs_joined <- magick::image_join(pngs)
pngs_animated <- magick::image_animate(pngs_joined, fps = fps)
Expand Down
12 changes: 6 additions & 6 deletions R/html.R
Original file line number Diff line number Diff line change
Expand Up @@ -14,14 +14,14 @@
#' }
build_html <- function(input, output_file = NULL) {
# Check input and output files have correct extensions
assert_path_ext(input, "rmd", arg = "input")
output_file <- check_output_file(input, output_file, "html")
assert_io_paths(input, "rmd", output_file, "html")

# Create full file paths from root
input <- fs::path_abs(input)
output_file <- fs::path_abs(output_file)
# Build input and output paths
paths <- build_paths(input, output_file)
input <- paths$input$rmd
output_file <- paths$output$html

# Build
# Build html from rmd
print_build_status(input, output_file)
rmarkdown::render(
input = input,
Expand Down
66 changes: 25 additions & 41 deletions R/pdf.R
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
#' Build xaringan slides as pdf file.
#'
#' Build xaringan slides to a pdf file. Requires a local installation of
#' Build xaringan slides as a pdf file. Requires a local installation of
#' Chrome. If you set `complex_slides = TRUE` or `partial_slides = TRUE`,
#' you will also need to install the {chromote} package:
#' `devtools::install_github("rstudio/chromote")`
#' @param input Path to Rmd or html file of xaringan slides.
#' you will also need to install the {chromote} and {pdftools} packages.
#' @param input Path to a Rmd file or html file / url of xaringan slides. If
#' the input is a url to xaringan slides on a website, you must provide the
#' full url ending in ".html".
#' @param output_file The name of the output file. If `NULL` (the default) then
#' the output filename will be based on filename for the input file.
#' If a filename is provided, a path to the output file can also be provided.
Expand All @@ -22,21 +23,23 @@
#' @export
#' @examples
#' \dontrun{
#' # Build simple pdf from Rmd or html file
#' # Build a pdf from a Rmd or html file
#' build_pdf("slides.Rmd")
#' build_pdf("slides.html")
#'
#' # Build simple pdf from Rmd or html file and include
#' # partial (continuation) slides
#' # Build a pdf from a url
#' build_pdf("http://www.mysite.com/myslides.html")
#'
#' # Build a pdf with partial (continuation) slides
#' build_pdf("slides.Rmd", partial_slides = TRUE)
#' build_pdf("slides.html", partial_slides = TRUE)
#'
#' # Build "complex" xaringan slides to pdf from Rmd or html file
#' # Build a pdf of "complex" xaringan slides
#' build_pdf("slides_complex.Rmd", complex_slides = TRUE)
#' build_pdf("slides_complex.html", complex_slides = TRUE)
#'
#' # Build "complex" xaringan slides to pdf from Rmd or html file and include
#' # partial (continuation) slides
#' # Build a pdf of "complex" xaringan slides and include partial
#' # (continuation) slides
#' build_pdf(input = "slides_complex.Rmd",
#' output_file = "slides_complex_partial.pdf",
#' complex_slides = TRUE,
Expand All @@ -57,26 +60,24 @@ build_pdf <- function(
assert_chrome_installed()

# Check input and output files have correct extensions
assert_path_ext(input, c("rmd", "html"), arg = "input")
output_file <- check_output_file(input, output_file, "pdf")
assert_io_paths(input, c("rmd", "html"), output_file, "pdf")

# Create full file paths from root
input <- fs::path_abs(input)
output_file <- fs::path_abs(output_file)
# Build input and output paths
paths <- build_paths(input, output_file)

# Build
# Build html (if input is rmd)
if (test_path_ext(input, "rmd")) {
build_html(
input = input,
output_file = fs::path_ext_set(output_file, "html")
)
input <- fs::path_ext_set(input, "html")
build_html(paths$input$rmd, paths$output$html)
}

# Build pdf from html
output_file <- paths$output$pdf
if (complex_slides | partial_slides) {
build_pdf_complex(input, output_file, partial_slides, delay)
build_pdf_complex(paths$input$url, output_file, partial_slides, delay)
} else {
build_pdf_simple(input, output_file)
input <- paths$input$html
if (is_url(input)) { input <- paths$input$url }
build_pdf_simple(input, output_file)
}
}

Expand All @@ -89,7 +90,7 @@ build_pdf <- function(
#' @param output_file The name of the output file. If `NULL` (the default) then
#' the output filename will be based on filename for the input file.
#' If a filename is provided, a path to the output file can also be provided.
build_pdf_simple <- function(input, output_file) {
build_pdf_simple <- function(input, output_file = NULL) {
print_build_status(input, output_file)
pagedown::chrome_print(
input = input,
Expand Down Expand Up @@ -123,23 +124,6 @@ build_pdf_complex <- function(input, output_file, partial_slides, delay) {
stop("`pdftools` is required: install.packages('pdftools')")
}

is_url <- grepl("^(ht|f)tp", tolower(input))

if (is.null(output_file)) {
if (is_url) {
output_file <- fs::path_ext_set(fs::path_file(input), "pdf")
} else {
output_file <- fs::path_ext_set(input, "pdf")
}
}

if (!is_url && !grepl("^file://", input)) {
if (!tolower(fs::path_ext(input)) %in% c("htm", "html")) {
stop("`input` must be the HTML version of the slides.")
}
input <- paste0("file://", fs::path_abs(input))
}

b <- chromote::ChromoteSession$new()
on.exit(b$close(), add = TRUE)

Expand Down
37 changes: 16 additions & 21 deletions R/pptx.R
Original file line number Diff line number Diff line change
@@ -1,9 +1,10 @@
#' Build xaringan slides as pptx file.
#'
#' Build xaringan slides as pptx file from a Rmd, html, or pdf file. The
#' function builds to the pdf and then inserts a png image of each slide
#' as a new slide in a pptx file.
#' @param input Path to Rmd, html, or pdf file of xaringan slides.
#' Build xaringan slides as a pptx file. The function builds to the pdf and
#' then inserts a png image of each slide as a new slide in a pptx file.
#' @param input Path to a Rmd, html, or pdf file, or a url of xaringan slides.
#' If the input is a url to xaringan slides on a website, you must provide the
#' full url ending in ".html".
#' @param output_file Name of the output pptx file.
#' @param density Resolution of the resulting pptx file.
#' @param complex_slides For "complex" slides (e.g. slides with panelsets or
Expand Down Expand Up @@ -32,33 +33,27 @@ build_pptx <- function(
complex_slides = FALSE,
partial_slides = FALSE,
delay = 1
) {
) {
if (!requireNamespace("officer", quietly = TRUE)) {
stop("`officer` is required: install.packages('officer')")
}

# Check input and output files have correct extensions
assert_path_ext(input, c("rmd", "html", "pdf"), arg = "input")
output_file <- check_output_file(input, output_file, "pptx")
assert_io_paths(input, c("rmd", "html", "pdf"), output_file, "pptx")

# Create full file paths from root
input <- fs::path_abs(input)
output_file <- fs::path_abs(output_file)
# Build input and output paths
paths <- build_paths(input, output_file)

# Build
if (test_path_ext(input, c("rmd", "html"))) {
build_pdf(
input = input,
output_file = fs::path_ext_set(output_file, "pdf"),
complex_slides = complex_slides,
partial_slides = partial_slides,
delay = delay)
input <- fs::path_ext_set(input, "pdf")
# Build html and / or pdf (if input is not pdf)
if (!test_path_ext(input, "pdf")) {
build_to_pdf(input, paths, complex_slides, partial_slides, delay)
}

# Build pptx from pdf
input <- paths$input$pdf
output_file <- paths$output$pptx
print_build_status(input, output_file)

pngs <- pdf_to_pngs(input, density)

doc <- officer::read_pptx()
for (i in 1:length(pngs)) {
png_path <- magick::image_write(
Expand Down
19 changes: 6 additions & 13 deletions R/social.R
Original file line number Diff line number Diff line change
Expand Up @@ -30,22 +30,15 @@ build_social <- function(input, output_file = NULL) {
assert_chrome_installed()

# Check input and output files have correct extensions
assert_path_ext(input, "rmd", arg = "input")
output_null <- is.null(output_file)
output_file <- check_output_file(input, output_file, "png")
assert_io_paths(input, "rmd", output_file, "png")

# Create full file paths from root
input <- fs::path_abs(input)
output_file <- fs::path_abs(output_file)
# Build input and output paths
paths <- build_paths(input, output_file)
input <- paths$input$rmd
output_file <- paths$output$social

# Append "_social" to output_file name if not provided by user
if (output_null) {
output_file <- append_to_file_path(output_file, "_social")
}

# Build
# Build png from rmd
print_build_status(input, output_file)

webshot2::rmdshot(
doc = input,
file = output_file,
Expand Down
Loading

0 comments on commit 3b3bc7a

Please sign in to comment.