diff --git a/.github/workflows/check-standard.yaml b/.github/workflows/check-standard.yaml index 8ac813e..dd0e505 100644 --- a/.github/workflows/check-standard.yaml +++ b/.github/workflows/check-standard.yaml @@ -32,6 +32,8 @@ jobs: - uses: actions/checkout@v2 - uses: r-lib/actions/setup-pandoc@v2 + - uses: quarto-dev/quarto-actions/setup@v2 + - run: 'quarto --version' - if: runner.os == 'Linux' run: | diff --git a/CRAN-SUBMISSION b/CRAN-SUBMISSION new file mode 100644 index 0000000..3e9afe4 --- /dev/null +++ b/CRAN-SUBMISSION @@ -0,0 +1,3 @@ +Version: 0.2.0 +Date: 2022-09-23 16:01:37 UTC +SHA: 16da193173108b915de47e58503aa51459bb8e1c diff --git a/DESCRIPTION b/DESCRIPTION index cd1910f..0a63276 100644 --- a/DESCRIPTION +++ b/DESCRIPTION @@ -1,6 +1,6 @@ Package: renderthis Title: Render Slides to Different Formats -Version: 0.1.0 +Version: 0.2.0 Authors@R: c(person(given = "John", family = "Helveston", @@ -32,6 +32,7 @@ Imports: magick (>= 2.7.1), pagedown, progress, + quarto, rmarkdown, withr, xaringan, @@ -48,6 +49,6 @@ Suggests: Config/testthat/edition: 3 Config/Needs/website: xaringanExtra Encoding: UTF-8 -RoxygenNote: 7.2.0 +RoxygenNote: 7.2.1 Roxygen: list(markdown = TRUE) VignetteBuilder: knitr diff --git a/NEWS.md b/NEWS.md index 94aae97..ecf121a 100644 --- a/NEWS.md +++ b/NEWS.md @@ -1,6 +1,13 @@ -# renderthis 0.1.0 +# renderthis 0.2.0 + +- Addresses several previous issues related to a note about a Crashpad file being generated from CI checks on Ubuntu. +- Implements initial support for rendering Quarto revealjs presentations. + +# renderthis 0.1.1 -# renderthis 0.0.1 +- Fixes a bug (#63) by checking that the path returned by find_chrome() actually exists. + +# renderthis 0.1.0 * Initial version, most functionality copied / modified from v0.0.9 of xaringanBuilder * Added a `NEWS.md` file to track changes to the package. diff --git a/R/all.R b/R/all.R index 72dfa41..b5aad7a 100644 --- a/R/all.R +++ b/R/all.R @@ -1,13 +1,13 @@ -#' Build xaringan slides to multiple outputs. +#' Build slides to multiple outputs. #' #' @description #' `r lifecycle::badge("deprecated")` #' -#' Build xaringan slides to multiple outputs. Options are `"html"`, `"social"` -#' `"pdf"`, `"png"`, `"gif"`, `"mp4"`, and `"pptx"`. See each individual -#' build_*() function for details about each output type. +#' Build slides to multiple outputs. Options are `"html"`, `"social"` `"pdf"`, +#' `"png"`, `"gif"`, `"mp4"`, and `"pptx"`. See each individual build_*() +#' function for details about each output type. #' -#' @param input Path to Rmd file of xaringan slides. +#' @param input Path to an `.Rmd` or `.qmd` file of slides. #' @param include A vector of the different output types to build. Options are #' `"html"`, `"social"`, `"pdf"`, `"png"`, `"gif"`, `"mp4"`, and `"pptx"`. #' Defaults to `c("html", "social", "pdf", "png", "gif", "mp4", "pptx")`. @@ -37,7 +37,7 @@ build_all <- function( lifecycle::deprecate_warn("0.1.0", "build_all()") # Check that input file has the correct extension - assert_path_ext(input, "rmd") + assert_path_ext(input, c("rmd", "qmd")) # Build hierarchy: # diff --git a/R/gif.R b/R/gif.R index 8e0c3be..b958833 100644 --- a/R/gif.R +++ b/R/gif.R @@ -1,20 +1,20 @@ -#' Render slides as a gif file. +#' Render slides as a GIF file. #' -#' Render slides as a gif video file. The function renders to the pdf, -#' converts each slide in the pdf to a png, and then converts the deck of -#' png files to a gif file. +#' Render slides as a GIF video file. The function renders to the PDF, +#' converts each slide in the PDF to a PNG, and then converts the deck of +#' PNG files to a GIF file. #' -#' @param from Path to a Rmd file, html file, pdf file, or a url. If `from` -#' is a url to slides on a website, you must provide the full url +#' @param from Path to an `.Rmd`, `.qmd`, `.html`, `.pdf` file, or a URL. If +#' `from` is a URL to slides on a website, you must provide the full URL #' ending in `".html"`. -#' @param to Name of the output gif file. -#' @param density Resolution of the resulting pngs in each slide file. Defaults +#' @param to Name of the output `.gif` file. +#' @param density Resolution of the resulting PNGs in each slide file. Defaults #' to `100`. #' @param slides A numeric or integer vector of the slide number(s) to include -#' in the gif, or one of `"all"`, `"first"`, or `"last"`. Negative integers +#' in the GIF, or one of `"all"`, `"first"`, or `"last"`. Negative integers #' select which slides _not_ to include. Defaults to `"all"`, in which case #' all slides are included. -#' @param fps Frames per second of the resulting gif file. +#' @param fps Frames per second in the animated GIF. #' @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 @@ -27,7 +27,7 @@ #' Only used if `complex_slides = TRUE` or `partial_slides = TRUE`. #' @inheritParams to_png #' -#' @return Slides are rendered as a gif file. +#' @return Slides are rendered as a `.gif` file. #' #' @example man/examples/examples_gif.R #' @@ -52,8 +52,7 @@ to_gif <- function( } # Check input and output files have correct extensions - assert_path_ext(input, c("rmd", "html", "pdf")) - assert_path_ext(output_file, "gif") + assert_path_ext(output_file, "gif", arg = "to") # Render html and / or pdf (if input is not pdf) step_pdf <- input diff --git a/R/html.R b/R/html.R index 5f967e6..33b12e8 100644 --- a/R/html.R +++ b/R/html.R @@ -1,12 +1,11 @@ #' Render slides as html file. #' -#' Render xaringan or quarto slides as an html file. For xaringan slides, it -#' is the same thing as [rmarkdown::render()] with -#' `output_format = "xaringan::moon_reader"` except that the `self_contained` -#' option is forced to `TRUE` if the HTML file is built into a directory other -#' than the one containing `from`. +#' Render xaringan or Quarto slides as an html file. In generally, it is the +#' same thing as [rmarkdown::render()] or [quarto::quarto_render()] except that +#' the `self_contained` option is forced to `TRUE` if the HTML file is built +#' into a directory other than the one containing `from`. #' -#' @param from Path to an Rmd file of xaringan slides. +#' @param from Path to an `.Rmd` or `.qmd` file. #' @param to The name of the output file. If using `NULL` then the #' output file name will be based on file name for the `from` file. If a file #' name is provided, a path to the output file can also be provided. @@ -16,14 +15,15 @@ #' you can share with others, but it may be very large. This feature is #' enabled by default when the `to` file is written in a directory other #' than the one containing the `from` R Markdown file. -#' @param rmd_args A list of arguments passed to [rmarkdown::render()]. +#' @param render_args A list of arguments passed to [rmarkdown::render()] or +#' [quarto::quarto_render()]. #' -#' @return Slides are rendered as an html file. +#' @return Slides are rendered as an `.html` file. #' #' @example man/examples/examples_html.R #' #' @export -to_html <- function(from, to = NULL, self_contained = FALSE, rmd_args = NULL) { +to_html <- function(from, to = NULL, self_contained = FALSE, render_args = NULL) { input <- from output_file <- to @@ -35,14 +35,21 @@ to_html <- function(from, to = NULL, self_contained = FALSE, rmd_args = NULL) { } # Check input and output files have correct extensions - assert_path_ext(input, "rmd") - assert_path_ext(output_file, "html") + assert_path_ext(input, c("rmd", "qmd"), arg = "from") + assert_path_ext(output_file, "html", arg = "to") input <- fs::path_abs(input) output_file <- fs::path_abs(output_file) - rmd_args <- build_html_rmd_args(input, output_file, self_contained, rmd_args) - self_contained <- rmd_args$output_options$self_contained + if (test_path_ext(input, "rmd")) { + render_args <- build_html_rmd_args(input, output_file, self_contained, render_args) + self_contained <- render_args$output_options$self_contained + render_fn <- rmarkdown::render + } else { + render_args <- build_html_qmd_args(input, output_file, self_contained, render_args) + self_contained <- "--self-contained" %in% render_args$pandoc_args + render_fn <- quarto::quarto_render + } # Render html from rmd # @@ -55,20 +62,21 @@ to_html <- function(from, to = NULL, self_contained = FALSE, rmd_args = NULL) { withr::local_dir(fs::path_dir(input)) if (self_contained) { - rmd_args$output_file <- path_from( - fs::path_file(rmd_args$output_file), "html", temporary = TRUE + render_args$output_file <- path_from( + fs::path_file(render_args$output_file), "html", temporary = TRUE ) withr::defer( - fs::file_move(rmd_args$output_file, output_file), + fs::file_move(render_args$output_file, output_file), priority = "first" ) } - - do.call(rmarkdown::render, rmd_args) + do.call(render_fn, render_args) }, error = cli_build_failed(proc) ) + + invisible(output_file) } build_html_rmd_args <- function(input, output_file, self_contained = FALSE, rmd_args = NULL) { @@ -90,6 +98,28 @@ build_html_rmd_args <- function(input, output_file, self_contained = FALSE, rmd_ rmd_args } +build_html_qmd_args <- function(input, output_file, self_contained = FALSE, qmd_args = NULL) { + qmd_args <- c(list(), qmd_args) + qmd_args$input <- fs::path_file(input) + qmd_args$output_file <- fs::path_file(output_file) + + self_contained <- + isTRUE(self_contained) || + self_contained_is_required(input, output_file) + + if (self_contained) { + # TODO: this argument is deprecated in latest pandoc, we should check + # for pandoc version and pick best version + qmd_args$pandoc_args <- c("--self-contained") + } + + if (is.null(qmd_args$quiet)) { + qmd_args$quiet <- TRUE + } + + qmd_args +} + self_contained_is_required <- function(input, output_file) { if (in_same_directory(input, output_file)) { return(FALSE) diff --git a/R/mp4.R b/R/mp4.R index 75ac028..5d16c2d 100644 --- a/R/mp4.R +++ b/R/mp4.R @@ -1,22 +1,20 @@ -#' Render slides as a mp4 video file. +#' Render slides as an MP4 video file. #' -#' Render slides as a mp4 video file. The function renders to the pdf, +#' Render slides as an MP4 video file. The function renders to the pdf, #' converts each slide in the pdf to a png, and then converts the deck of -#' png files to a mp4 video file. +#' png files to a MP4 video file. #' -#' @param from Path to a Rmd file, html file, pdf file, or a url. If `from` -#' is a url to slides on a website, you must provide the full url -#' ending in `".html"`. -#' @param to Name of the output mp4 file. +#' @param to Name of the output `.mp4` file. #' @param slides A numeric or integer vector of the slide number(s) to include #' in the mp4, or one of `"all"`, `"first"`, or `"last"`. Negative integers #' select which slides _not_ to include. Defaults to `"all"`, in which case #' all slides are included. -#' @param fps Frames per second of the resulting mp4 file. +#' @param fps Frames per second of the resulting `.mp4` file. +#' @inheritParams to_gif #' @inheritParams to_png #' @inheritParams to_pdf #' -#' @return Slides are rendered as an mp4 file. +#' @return Slides are rendered as an `.mp4` file. #' #' @example man/examples/examples_mp4.R #' @@ -44,8 +42,7 @@ to_mp4 <- function( } # Check input and output files have correct extensions - assert_path_ext(input, c("rmd", "html", "pdf")) - assert_path_ext(output_file, "mp4") + assert_path_ext(output_file, "mp4", arg = "to") # Render html and / or pdf (if input is not pdf) step_pdf <- input diff --git a/R/pdf.R b/R/pdf.R index d2b108e..d274c97 100644 --- a/R/pdf.R +++ b/R/pdf.R @@ -1,13 +1,13 @@ -#' Render slides as pdf file. +#' Render slides as PDF file. #' -#' Render slides as a pdf file. Requires a local installation of Chrome. +#' Render 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} and {pdftools} packages. #' -#' @param from Path to a Rmd file, html file, pdf file, or a url. If `from` -#' is a url to slides on a website, you must provide the full url -#' ending in `".html"`. -#' @param to The name of the output file. If `NULL` (the default) then +#' @param from Path to an `.Rmd`, `.qmd`, `.html` file, or a URL. If `from` is a +#' URL to slides on a website, you must provide the full URL ending in +#' `".html"`. +#' @param to The name of the output `.pdf` file. If `NULL` (the default) then #' the output filename will be based on filename for the `from` file. If a #' filename is provided, a path to the output file can also be provided. #' @param complex_slides For "complex" slides (e.g. slides with panelsets or @@ -25,7 +25,7 @@ #' if the `to` file is written into the same directory as the `from` argument, #' otherwise the intermediate file isn't kept. #' -#' @return Slides are rendered as a pdf file. +#' @return Slides are rendered as a `.pdf` file. #' #' @example man/examples/examples_pdf.R #' @@ -46,13 +46,21 @@ to_pdf <- function( assert_path_exists(input) + complex_slides <- complex_slides || partial_slides + + if (complex_slides && test_path_ext(input, "qmd")) { + cli::cli_abort(c( + "Complex PDF rendering is currently only available for xaringan slides in {.path .Rmd} documents.", + "x" = "{.strong input}: {.val {input}}" + )) + } + if (is.null(output_file)) { output_file <- path_from(input, "pdf") } # Check input and output files have correct extensions - assert_path_ext(input, c("rmd", "html")) - assert_path_ext(output_file, "pdf") + assert_path_ext(output_file, "pdf", arg = "to") if (is.null(keep_intermediates)) { keep_intermediates <- in_same_directory(input, output_file) @@ -60,15 +68,16 @@ to_pdf <- function( # Render html (if input is rmd) step_html <- input - if (test_path_ext(input, "rmd")) { + if (!test_path_ext(input, "html")) { step_html <- path_from(output_file, "html", temporary = !keep_intermediates) to_html(from = input, to = step_html) } # Render pdf from html - if (complex_slides | partial_slides) { + if (complex_slides) { to_pdf_complex(path_from(step_html, "url"), output_file, partial_slides, delay) } else { + assert_path_ext(input, c("qmd", "rmd", "html"), arg = "from") to_pdf_simple(step_html, output_file) } } diff --git a/R/png.R b/R/png.R index 8343593..bbd4fe8 100644 --- a/R/png.R +++ b/R/png.R @@ -1,29 +1,27 @@ -#' Render slides as png file(s). +#' Render slides as PNG file(s). #' -#' Render png image(s) of slides. The function renders to the pdf and -#' then converts it into png files of each slide. The slide numbers defined by +#' Render PNG image(s) of slides. The function renders to the PDF and +#' then converts it into PNG files of each slide. The slide numbers defined by #' the `slides` argument are saved (defaults to `1`, returning only the title -#' slide). If `length(slides) > 1`, it will return the png files in a zip file. -#' You can also get a zip file of all the slides as pngs by setting `slides = +#' slide). If `length(slides) > 1`, it will return the PNG files in a ZIP file. +#' You can also get a ZIP file of all the slides as PNGs by setting `slides = #' "all"`). #' -#' @param from Path to a Rmd file, html file, pdf file, or a url. If `from` -#' is a url to slides on a website, you must provide the full url -#' ending in `".html"`. -#' @param to Name of the output png or zip file. -#' @param density Resolution of the resulting pngs in each slide file. Defaults +#' @param to Name of the output `.png` or `.zip` file. +#' @param density Resolution of the resulting PNGs in each slide file. Defaults #' to `100`. #' @param slides A numeric or integer vector of the slide number(s) to render -#' as png files , or one of `"all"`, `"first"`, or `"last"`. Negative integers +#' as PNG files , or one of `"all"`, `"first"`, or `"last"`. Negative integers #' select which slides _not_ to include. If more than one slide are included, -#' pngs will be returned as a zip file. Defaults to `"all"`, in which case +#' PNGs will be returned as a ZIP file. Defaults to `"all"`, in which case #' all slides are included. +#' @inheritParams to_gif #' @inheritParams to_pdf #' @param keep_intermediates Should we keep the intermediate files used to #' render the final output? The default is `FALSE`. #' -#' @return Slides are rendered as a png file (single) or zip file of multiple -#' png files. +#' @return Slides are rendered as a `.png` file (single) or `.zip` file of +#' multiple `.png` files. #' #' @example man/examples/examples_png.R #' @@ -53,8 +51,7 @@ to_png <- function( slides <- slides_arg_validate(slides) # Check input and output files have correct extensions - assert_path_ext(input, c("rmd", "html", "pdf")) - assert_path_ext(output_file, c("png", "zip")) + assert_path_ext(output_file, c("png", "zip"), arg = "from") # Render html and / or pdf (if input is not pdf) step_pdf <- input diff --git a/R/pptx.R b/R/pptx.R index 6ea5ab9..87092af 100644 --- a/R/pptx.R +++ b/R/pptx.R @@ -1,17 +1,15 @@ -#' Render slides as pptx file. +#' Render slides as a PowerPoint file. #' -#' Render slides as a pptx file. The function renders to the pdf and -#' then converts it into png images that are inserted on each slide in the -#' pptx file. +#' Render slides as a `.pptx` file. The function renders to the PDF and +#' then converts it into PNG images that are inserted on each slide in the +#' PowerPoint file. #' -#' @param from Path to a Rmd file, html file, pdf file, or a url. If `from` -#' is a url to slides on a website, you must provide the full url -#' ending in `".html"`. -#' @param to Name of the output pptx file. +#' @param to Name of the output `.pptx` file. #' @param slides A numeric or integer vector of the slide number(s) to include #' in the pptx, or one of `"all"`, `"first"`, or `"last"`. Negative integers #' select which slides _not_ to include. Defaults to `"all"`, in which case #' all slides are included. +#' @inheritParams to_gif #' @inheritParams to_png #' @inheritParams to_pdf #' @@ -42,8 +40,7 @@ to_pptx <- function( } # Check input and output files have correct extensions - assert_path_ext(input, c("rmd", "html", "pdf")) - assert_path_ext(output_file, "pptx") + assert_path_ext(output_file, "pptx", arg = "to") # Render html and / or pdf (if input is not pdf) step_pdf <- input diff --git a/R/social.R b/R/social.R index a760e82..37b6aba 100644 --- a/R/social.R +++ b/R/social.R @@ -36,8 +36,8 @@ to_social <- function(from, to = NULL) { } # Check input and output files have correct extensions - assert_path_ext(input, "rmd") - assert_path_ext(output_file, "png") + assert_path_ext(input, "rmd", arg = "from") + assert_path_ext(output_file, "png", arg = "to") # Render a temporary html file for the slide snapshot # We used to use `webshot2::rmdshot()` but this way we have more control @@ -47,7 +47,7 @@ to_social <- function(from, to = NULL) { from = input, to = step_html, self_contained = TRUE, - rmd_args = list( + render_args = list( output_options = list(nature = list(ratio = "191:100")) ) ) diff --git a/R/utils.R b/R/utils.R index 7071433..31bb74e 100644 --- a/R/utils.R +++ b/R/utils.R @@ -48,10 +48,8 @@ assert_chrome_installed <- function() { check_chrome_installed <- function() { assert_chromote() - tryCatch( - !is.null(chromote::find_chrome()), - error = function(e) FALSE - ) + chrome <- tryCatch(chromote::find_chrome(), error = function(e) FALSE) + !is.null(chrome) && fs::file_exists(chrome) } assert_chromote <- function() { diff --git a/R/with_example.R b/R/with_example.R index 13280d3..85b8604 100644 --- a/R/with_example.R +++ b/R/with_example.R @@ -19,7 +19,39 @@ #' #' @keywords internal #' @export -with_example <- function(example, code, clean = TRUE) { +with_example <- function( + example, + code, + clean = TRUE, + requires_packages = NULL, + requires_chrome = FALSE +) { + if (!interactive()) { + in_pkgdown <- identical(Sys.getenv("IN_PKGDOWN"), "true") + in_ci <- nzchar(Sys.getenv("CI", "")) + if (!(in_pkgdown || in_ci)) { + return(invisible()) + } + } + + if (isTRUE(requires_chrome)) { + requires_packages <- c(requires_packages, "chromote") + } + if (!is.null(requires_packages)) { + pkg_is_avail <- vapply(requires_packages, requireNamespace, logical(1), quietly = TRUE) + pkgs_miss <- requires_packages[!pkg_is_avail] + if (length(pkgs_miss)) { + cli::cli_inform("This example requires the packages {.pkg {pkgs_miss}}.") + return(invisible()) + } + } + if (isTRUE(requires_chrome)) { + if (!check_chrome_installed()) { + cli::cli_inform("This example requires {.strong Google Chrome}.") + return(invisible()) + } + } + examples <- dir(system.file("example", package = "renderthis")) example <- match.arg(tolower(example), choices = tolower(examples)) example <- examples[tolower(example) == tolower(examples)] diff --git a/README.Rmd b/README.Rmd index 6ee6c49..56ebecf 100644 --- a/README.Rmd +++ b/README.Rmd @@ -4,6 +4,11 @@ output: html_preview: false --- +[rmarkdown]: https://rmarkdown.rstudio.com +[quarto]: https://quarto.org +[xaringan]: https://slides.yihui.org/xaringan/ +[revealjs]: https://quarto.org/docs/presentations/revealjs/ + ```{r setup, include = FALSE} @@ -26,45 +31,46 @@ IS_README <- TRUE stable](https://lifecycle.r-lib.org/articles/figures/lifecycle-stable.svg)](https://lifecycle.r-lib.org/articles/stages.html#stable) -This package contains functions for rendering xaringan slides to different formats, including html, pdf, png, gif, pptx, and mp4, as well as a 'social' output, a png of the first slide re-sized for sharing on social media. +This package contains functions for rendering [R Markdown][rmarkdown] and [Quarto][quarto] documents — priamrily [xaringan] or [revealjs] slides — to different formats, including HTML, PDF, PNG, GIF, PPTX, and MP4, as well as a 'social' output, a png of the first slide re-sized for sharing on social media. **Looking for xaringanBuilder?** The package formerly known as xaringanBuilder is now **renderthis**. -If you need to install xaringanBuilder under the previous package name, [see the instructions below](#installing-xaringanbuilder). +If you need to install xaringanBuilder under the previous package name, +[see the instructions below](#installing-xaringanbuilder). ## Installation -You can install the current version of renderthis from GitHub: +**Note**: To get the most out of renderthis, we recommend installing the +package **with dependencies** and making sure that you have a local +installation of Google Chrome. See the +[Setup](https://jhelvy.github.io/renderthis/articles/renderthis-setup.html) +page for details. + +You can install the latest version of renderthis from +[CRAN](https://cran.r-project.org/) with: ```{r} -# install.packages("remotes") -remotes::install_github("jhelvy/renderthis") +install.packages("renderthis") ``` -Some output formats require additional packages, and each format will provide instructions about how to install any missing dependencies. You can also choose to install renderthis with all of its dependencies: +And the development version from GitHub with: ```{r} # install.packages("remotes") -remotes::install_github("jhelvy/renderthis", dependencies = TRUE) +remotes::install_github("jhelvy/renderthis") ``` -**Note**: To get the most out of renderthis, we recommend installing the package **with dependencies** and making sure that you have a [local installation of Google Chrome](https://jhelvy.github.io/renderthis/articles/renderthis-setup.html#local-chrome-installation). - -Because many users will not need all output formats, -several outputs require additional packages that are suggested dependencies -and aren't installed by default unless requested as described above. -The table below lists the packages required for each output type: +Some output formats require additional packages, and each format will provide +instructions about how to install any missing dependencies. You can also +choose to install renderthis with all of its dependencies: -| Output | Requires | -|:-----|:-----| -| PDF (simple) | Google Chrome (for [pagedown](https://pagedown.rbind.io/)) | -| PDF (complex) | [chromote](https://rstudio.github.io/chromote/) | -| PNG | Requires PDF | -| GIF | Requires PDF | -| MP4 | [av](https://docs.ropensci.org/av/) | -| PPTX | [officer](https://ardata-fr.github.io/officeverse/) | -| Social | [chromote](https://rstudio.github.io/chromote/) | +```{r} +# From CRAN +install.packages("renderthis", dependencies = TRUE) +# From GitHub +remotes::install_github("jhelvy/renderthis", dependencies = TRUE) +``` ## Usage @@ -72,7 +78,8 @@ The table below lists the packages required for each output type: ``` -Learn more about renderthis in the [Get Started article](https://jhelvy.github.io/renderthis/articles/renderthis.html). +Learn more about renderthis in the +[Get Started article](https://jhelvy.github.io/renderthis/articles/renderthis.html). ## Author and License Information diff --git a/README.md b/README.md index c88010e..a1c50fd 100644 --- a/README.md +++ b/README.md @@ -12,8 +12,12 @@ status](https://www.r-pkg.org/badges/version/renderthis)](https://CRAN.R-project stable](https://lifecycle.r-lib.org/articles/figures/lifecycle-stable.svg)](https://lifecycle.r-lib.org/articles/stages.html#stable) -This package contains functions for rendering xaringan slides to -different formats, including html, pdf, png, gif, pptx, and mp4, as well +This package contains functions for rendering [R +Markdown](https://rmarkdown.rstudio.com) and +[Quarto](https://quarto.org) documents — priamrily +[xaringan](https://slides.yihui.org/xaringan/) or +[revealjs](https://quarto.org/docs/presentations/revealjs/) slides — to +different formats, including HTML, PDF, PNG, GIF, PPTX, and MP4, as well as a ‘social’ output, a png of the first slide re-sized for sharing on social media. @@ -24,7 +28,20 @@ below](#installing-xaringanbuilder). ## Installation -You can install the current version of renderthis from GitHub: +**Note**: To get the most out of renderthis, we recommend installing the +package **with dependencies** and making sure that you have a local +installation of Google Chrome. See the +[Setup](https://jhelvy.github.io/renderthis/articles/renderthis-setup.html) +page for details. + +You can install the latest version of renderthis from +[CRAN](https://cran.r-project.org/) with: + +``` r +install.packages("renderthis") +``` + +And the development version from GitHub with: ``` r # install.packages("remotes") @@ -36,38 +53,21 @@ provide instructions about how to install any missing dependencies. You can also choose to install renderthis with all of its dependencies: ``` r -# install.packages("remotes") +# From CRAN +install.packages("renderthis", dependencies = TRUE) + +# From GitHub remotes::install_github("jhelvy/renderthis", dependencies = TRUE) ``` -**Note**: To get the most out of renderthis, we recommend installing the -package **with dependencies** and making sure that you have a [local -installation of Google -Chrome](https://jhelvy.github.io/renderthis/articles/renderthis-setup.html#local-chrome-installation). - -Because many users will not need all output formats, several outputs -require additional packages that are suggested dependencies and aren’t -installed by default unless requested as described above. The table -below lists the packages required for each output type: - -| Output | Requires | -|:--------------|:-----------------------------------------------------------| -| PDF (simple) | Google Chrome (for [pagedown](https://pagedown.rbind.io/)) | -| PDF (complex) | [chromote](https://rstudio.github.io/chromote/) | -| PNG | Requires PDF | -| GIF | Requires PDF | -| MP4 | [av](https://docs.ropensci.org/av/) | -| PPTX | [officer](https://ardata-fr.github.io/officeverse/) | -| Social | [chromote](https://rstudio.github.io/chromote/) | - ## Usage Use renderthis to render slides to different formats. Here is a diagram of the render hierarchy: - Rmd + Rmd / qmd | - |--> social (png) + |--> social (png, from Rmd only) | |--> html | diff --git a/cran-comments.md b/cran-comments.md new file mode 100644 index 0000000..d5b82da --- /dev/null +++ b/cran-comments.md @@ -0,0 +1,10 @@ +## Test environments +* local R installation, R 4.1.0 +* ubuntu 16.04 (on travis-ci), R 4.0.2 +* win-builder (devel and release) + +## R CMD check results +0 errors | 0 warnings | 0 notes + +## Notes +* This is a new release. diff --git a/man/build_all.Rd b/man/build_all.Rd index d44cd4c..f2b11fc 100644 --- a/man/build_all.Rd +++ b/man/build_all.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/all.R \name{build_all} \alias{build_all} -\title{Build xaringan slides to multiple outputs.} +\title{Build slides to multiple outputs.} \usage{ build_all( input, @@ -17,7 +17,7 @@ build_all( ) } \arguments{ -\item{input}{Path to Rmd file of xaringan slides.} +\item{input}{Path to an \code{.Rmd} or \code{.qmd} file of slides.} \item{include}{A vector of the different output types to build. Options are \code{"html"}, \code{"social"}, \code{"pdf"}, \code{"png"}, \code{"gif"}, \code{"mp4"}, and \code{"pptx"}. @@ -40,16 +40,16 @@ PDF.} \item{delay}{Seconds of delay between advancing to and printing a new slide. Only used if \code{complex_slides = TRUE} or \code{partial_slides = TRUE}.} -\item{density}{Resolution of the resulting pngs in each slide file. Defaults +\item{density}{Resolution of the resulting PNGs in each slide file. Defaults to \code{100}.} \item{slides}{A numeric or integer vector of the slide number(s) to render -as png files , or one of \code{"all"}, \code{"first"}, or \code{"last"}. Negative integers +as PNG files , or one of \code{"all"}, \code{"first"}, or \code{"last"}. Negative integers select which slides \emph{not} to include. If more than one slide are included, -pngs will be returned as a zip file. Defaults to \code{"all"}, in which case +PNGs will be returned as a ZIP file. Defaults to \code{"all"}, in which case all slides are included.} -\item{fps}{Frames per second of the resulting mp4 file.} +\item{fps}{Frames per second of the resulting \code{.mp4} file.} } \value{ Builds slides to multiple output formats. @@ -57,22 +57,16 @@ Builds slides to multiple output formats. \description{ \ifelse{html}{\href{https://lifecycle.r-lib.org/articles/stages.html#deprecated}{\figure{lifecycle-deprecated.svg}{options: alt='[Deprecated]'}}}{\strong{[Deprecated]}} -Build xaringan slides to multiple outputs. Options are \code{"html"}, \code{"social"} -\code{"pdf"}, \code{"png"}, \code{"gif"}, \code{"mp4"}, and \code{"pptx"}. See each individual -build_*() function for details about each output type. +Build slides to multiple outputs. Options are \code{"html"}, \code{"social"} \code{"pdf"}, +\code{"png"}, \code{"gif"}, \code{"mp4"}, and \code{"pptx"}. See each individual build_*() +function for details about each output type. } \examples{ if (interactive()) { - # Build every output by default - with_example("slides.Rmd", { - build_all("slides.Rmd") - }) - - # Both of these build html, pdf, and gif outputs + # Both of these build html and pdf outputs # (PDF outputs require Google Chrome for {pagedown}) - with_example("slides.Rmd", { - build_all("slides.Rmd", include = c("html", "pdf", "gif")) - build_all("slides.Rmd", exclude = c("social", "png", "mp4", "pptx")) + with_example("slides.Rmd", requires_chrome = TRUE, { + build_all("slides.Rmd", include = c("html", "pdf")) }) } } diff --git a/man/examples/examples_all.R b/man/examples/examples_all.R index 27977fb..b040aec 100644 --- a/man/examples/examples_all.R +++ b/man/examples/examples_all.R @@ -1,13 +1,7 @@ if (interactive()) { - # Build every output by default - with_example("slides.Rmd", { - build_all("slides.Rmd") - }) - - # Both of these build html, pdf, and gif outputs + # Both of these build html and pdf outputs # (PDF outputs require Google Chrome for {pagedown}) - with_example("slides.Rmd", { - build_all("slides.Rmd", include = c("html", "pdf", "gif")) - build_all("slides.Rmd", exclude = c("social", "png", "mp4", "pptx")) + with_example("slides.Rmd", requires_chrome = TRUE, { + build_all("slides.Rmd", include = c("html", "pdf")) }) } diff --git a/man/examples/examples_gif.R b/man/examples/examples_gif.R index e7240e3..28c1624 100644 --- a/man/examples/examples_gif.R +++ b/man/examples/examples_gif.R @@ -1,4 +1,4 @@ -with_example("slides.Rmd", { +with_example("slides.Rmd", requires_chrome = TRUE, { # Render gif from Rmd, html, pdf, or direct URL to_gif("slides.Rmd") }) diff --git a/man/examples/examples_mp4.R b/man/examples/examples_mp4.R index 3ae1d9c..f87bfd5 100644 --- a/man/examples/examples_mp4.R +++ b/man/examples/examples_mp4.R @@ -1,6 +1,4 @@ -if (requireNamespace("av", quietly = TRUE)) { - with_example("slides.Rmd", { - # Render mp4 from Rmd, html, pdf, or direct URL - to_mp4("slides.Rmd") - }) -} +with_example("slides.Rmd", requires_chrome = TRUE, requires_packages = "av", { + # Render mp4 from Rmd, html, pdf, or direct URL + to_mp4("slides.Rmd") +}) diff --git a/man/examples/examples_pdf.R b/man/examples/examples_pdf.R index 93bb4c7..86f426d 100644 --- a/man/examples/examples_pdf.R +++ b/man/examples/examples_pdf.R @@ -1,4 +1,4 @@ -with_example("slides.Rmd", { +with_example("slides.Rmd", requires_chrome = TRUE, { # Render pdf from Rmd, html, or direct URL to_pdf("slides.Rmd") }) diff --git a/man/examples/examples_png.R b/man/examples/examples_png.R index 2be8807..20f60a1 100644 --- a/man/examples/examples_png.R +++ b/man/examples/examples_png.R @@ -1,4 +1,4 @@ -with_example("slides.Rmd", { +with_example("slides.Rmd", requires_chrome = TRUE, { # By default a png of only the first slide is built to_png("slides.Rmd", keep_intermediates = TRUE) diff --git a/man/examples/examples_pptx.R b/man/examples/examples_pptx.R index 8167e6a..245ca70 100644 --- a/man/examples/examples_pptx.R +++ b/man/examples/examples_pptx.R @@ -1,6 +1,4 @@ -if (requireNamespace("officer", quietly = TRUE)) { - with_example("slides.Rmd", { - # Render pptx from Rmd, html, pdf, or direct URL - to_pptx("slides.Rmd") - }) -} +with_example("slides.Rmd", requires_chrome = TRUE, requires_packages = "officer", { + # Render pptx from Rmd, html, pdf, or direct URL + to_pptx("slides.Rmd") +}) diff --git a/man/examples/examples_social.R b/man/examples/examples_social.R index f9ae415..7d224a1 100644 --- a/man/examples/examples_social.R +++ b/man/examples/examples_social.R @@ -1,5 +1,5 @@ -if (requireNamespace("webshot2", quietly = TRUE) && interactive()) { - with_example("slides.Rmd", { +if (interactive()) { + with_example("slides.Rmd", requires_chrome = TRUE, requires_packages = "webshot2", { # Render png image of first slide from Rmd file # sized for sharing on social media to_social("slides.Rmd") diff --git a/man/fragments/usage.Rmd b/man/fragments/usage.Rmd index 8b7cd52..2dc4c04 100644 --- a/man/fragments/usage.Rmd +++ b/man/fragments/usage.Rmd @@ -1,9 +1,9 @@ Use renderthis to render slides to different formats. Here is a diagram of the render hierarchy: ``` -Rmd +Rmd / qmd | - |--> social (png) + |--> social (png, from Rmd only) | |--> html | diff --git a/man/to_gif.Rd b/man/to_gif.Rd index f3582d3..b8cd88b 100644 --- a/man/to_gif.Rd +++ b/man/to_gif.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/gif.R \name{to_gif} \alias{to_gif} -\title{Render slides as a gif file.} +\title{Render slides as a GIF file.} \usage{ to_gif( from, @@ -17,21 +17,21 @@ to_gif( ) } \arguments{ -\item{from}{Path to a Rmd file, html file, pdf file, or a url. If \code{from} -is a url to slides on a website, you must provide the full url +\item{from}{Path to an \code{.Rmd}, \code{.qmd}, \code{.html}, \code{.pdf} file, or a URL. If +\code{from} is a URL to slides on a website, you must provide the full URL ending in \code{".html"}.} -\item{to}{Name of the output gif file.} +\item{to}{Name of the output \code{.gif} file.} -\item{density}{Resolution of the resulting pngs in each slide file. Defaults +\item{density}{Resolution of the resulting PNGs in each slide file. Defaults to \code{100}.} \item{slides}{A numeric or integer vector of the slide number(s) to include -in the gif, or one of \code{"all"}, \code{"first"}, or \code{"last"}. Negative integers +in the GIF, or one of \code{"all"}, \code{"first"}, or \code{"last"}. Negative integers select which slides \emph{not} to include. Defaults to \code{"all"}, in which case all slides are included.} -\item{fps}{Frames per second of the resulting gif file.} +\item{fps}{Frames per second in the animated GIF.} \item{complex_slides}{For "complex" slides (e.g. slides with panelsets or other html widgets or advanced features), set \code{complex_slides = TRUE}. @@ -50,15 +50,15 @@ Only used if \code{complex_slides = TRUE} or \code{partial_slides = TRUE}.} render the final output? The default is \code{FALSE}.} } \value{ -Slides are rendered as a gif file. +Slides are rendered as a \code{.gif} file. } \description{ -Render slides as a gif video file. The function renders to the pdf, -converts each slide in the pdf to a png, and then converts the deck of -png files to a gif file. +Render slides as a GIF video file. The function renders to the PDF, +converts each slide in the PDF to a PNG, and then converts the deck of +PNG files to a GIF file. } \examples{ -with_example("slides.Rmd", { +with_example("slides.Rmd", requires_chrome = TRUE, { # Render gif from Rmd, html, pdf, or direct URL to_gif("slides.Rmd") }) diff --git a/man/to_html.Rd b/man/to_html.Rd index d76557e..b75fc2b 100644 --- a/man/to_html.Rd +++ b/man/to_html.Rd @@ -4,10 +4,10 @@ \alias{to_html} \title{Render slides as html file.} \usage{ -to_html(from, to = NULL, self_contained = FALSE, rmd_args = NULL) +to_html(from, to = NULL, self_contained = FALSE, render_args = NULL) } \arguments{ -\item{from}{Path to an Rmd file of xaringan slides.} +\item{from}{Path to an \code{.Rmd} or \code{.qmd} file.} \item{to}{The name of the output file. If using \code{NULL} then the output file name will be based on file name for the \code{from} file. If a file @@ -20,17 +20,17 @@ you can share with others, but it may be very large. This feature is enabled by default when the \code{to} file is written in a directory other than the one containing the \code{from} R Markdown file.} -\item{rmd_args}{A list of arguments passed to \code{\link[rmarkdown:render]{rmarkdown::render()}}.} +\item{render_args}{A list of arguments passed to \code{\link[rmarkdown:render]{rmarkdown::render()}} or +\code{\link[quarto:quarto_render]{quarto::quarto_render()}}.} } \value{ -Slides are rendered as an html file. +Slides are rendered as an \code{.html} file. } \description{ -Render xaringan or quarto slides as an html file. For xaringan slides, it -is the same thing as \code{\link[rmarkdown:render]{rmarkdown::render()}} with -\code{output_format = "xaringan::moon_reader"} except that the \code{self_contained} -option is forced to \code{TRUE} if the HTML file is built into a directory other -than the one containing \code{from}. +Render xaringan or Quarto slides as an html file. In generally, it is the +same thing as \code{\link[rmarkdown:render]{rmarkdown::render()}} or \code{\link[quarto:quarto_render]{quarto::quarto_render()}} except that +the \code{self_contained} option is forced to \code{TRUE} if the HTML file is built +into a directory other than the one containing \code{from}. } \examples{ with_example("slides.Rmd", { diff --git a/man/to_mp4.Rd b/man/to_mp4.Rd index 3f1d7c8..57ec661 100644 --- a/man/to_mp4.Rd +++ b/man/to_mp4.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/mp4.R \name{to_mp4} \alias{to_mp4} -\title{Render slides as a mp4 video file.} +\title{Render slides as an MP4 video file.} \usage{ to_mp4( from, @@ -17,13 +17,13 @@ to_mp4( ) } \arguments{ -\item{from}{Path to a Rmd file, html file, pdf file, or a url. If \code{from} -is a url to slides on a website, you must provide the full url +\item{from}{Path to an \code{.Rmd}, \code{.qmd}, \code{.html}, \code{.pdf} file, or a URL. If +\code{from} is a URL to slides on a website, you must provide the full URL ending in \code{".html"}.} -\item{to}{Name of the output mp4 file.} +\item{to}{Name of the output \code{.mp4} file.} -\item{density}{Resolution of the resulting pngs in each slide file. Defaults +\item{density}{Resolution of the resulting PNGs in each slide file. Defaults to \code{100}.} \item{slides}{A numeric or integer vector of the slide number(s) to include @@ -31,7 +31,7 @@ in the mp4, or one of \code{"all"}, \code{"first"}, or \code{"last"}. Negative i select which slides \emph{not} to include. Defaults to \code{"all"}, in which case all slides are included.} -\item{fps}{Frames per second of the resulting mp4 file.} +\item{fps}{Frames per second of the resulting \code{.mp4} file.} \item{complex_slides}{For "complex" slides (e.g. slides with panelsets or other html widgets or advanced features), set \code{complex_slides = TRUE}. @@ -50,18 +50,16 @@ Only used if \code{complex_slides = TRUE} or \code{partial_slides = TRUE}.} render the final output? The default is \code{FALSE}.} } \value{ -Slides are rendered as an mp4 file. +Slides are rendered as an \code{.mp4} file. } \description{ -Render slides as a mp4 video file. The function renders to the pdf, +Render slides as an MP4 video file. The function renders to the pdf, converts each slide in the pdf to a png, and then converts the deck of -png files to a mp4 video file. +png files to a MP4 video file. } \examples{ -if (requireNamespace("av", quietly = TRUE)) { - with_example("slides.Rmd", { - # Render mp4 from Rmd, html, pdf, or direct URL - to_mp4("slides.Rmd") - }) -} +with_example("slides.Rmd", requires_chrome = TRUE, requires_packages = "av", { + # Render mp4 from Rmd, html, pdf, or direct URL + to_mp4("slides.Rmd") +}) } diff --git a/man/to_pdf.Rd b/man/to_pdf.Rd index 025a351..7d8572c 100644 --- a/man/to_pdf.Rd +++ b/man/to_pdf.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/pdf.R \name{to_pdf} \alias{to_pdf} -\title{Render slides as pdf file.} +\title{Render slides as PDF file.} \usage{ to_pdf( from, @@ -14,11 +14,11 @@ to_pdf( ) } \arguments{ -\item{from}{Path to a Rmd file, html file, pdf file, or a url. If \code{from} -is a url to slides on a website, you must provide the full url -ending in \code{".html"}.} +\item{from}{Path to an \code{.Rmd}, \code{.qmd}, \code{.html} file, or a URL. If \code{from} is a +URL to slides on a website, you must provide the full URL ending in +\code{".html"}.} -\item{to}{The name of the output file. If \code{NULL} (the default) then +\item{to}{The name of the output \code{.pdf} file. If \code{NULL} (the default) then the output filename will be based on filename for the \code{from} file. If a filename is provided, a path to the output file can also be provided.} @@ -41,15 +41,15 @@ if the \code{to} file is written into the same directory as the \code{from} argu otherwise the intermediate file isn't kept.} } \value{ -Slides are rendered as a pdf file. +Slides are rendered as a \code{.pdf} file. } \description{ -Render slides as a pdf file. Requires a local installation of Chrome. +Render slides as a PDF file. Requires a local installation of Chrome. If you set \code{complex_slides = TRUE} or \code{partial_slides = TRUE}, you will also need to install the {chromote} and {pdftools} packages. } \examples{ -with_example("slides.Rmd", { +with_example("slides.Rmd", requires_chrome = TRUE, { # Render pdf from Rmd, html, or direct URL to_pdf("slides.Rmd") }) diff --git a/man/to_png.Rd b/man/to_png.Rd index 7f834b5..8b2d2e8 100644 --- a/man/to_png.Rd +++ b/man/to_png.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/png.R \name{to_png} \alias{to_png} -\title{Render slides as png file(s).} +\title{Render slides as PNG file(s).} \usage{ to_png( from, @@ -16,19 +16,19 @@ to_png( ) } \arguments{ -\item{from}{Path to a Rmd file, html file, pdf file, or a url. If \code{from} -is a url to slides on a website, you must provide the full url +\item{from}{Path to an \code{.Rmd}, \code{.qmd}, \code{.html}, \code{.pdf} file, or a URL. If +\code{from} is a URL to slides on a website, you must provide the full URL ending in \code{".html"}.} -\item{to}{Name of the output png or zip file.} +\item{to}{Name of the output \code{.png} or \code{.zip} file.} -\item{density}{Resolution of the resulting pngs in each slide file. Defaults +\item{density}{Resolution of the resulting PNGs in each slide file. Defaults to \code{100}.} \item{slides}{A numeric or integer vector of the slide number(s) to render -as png files , or one of \code{"all"}, \code{"first"}, or \code{"last"}. Negative integers +as PNG files , or one of \code{"all"}, \code{"first"}, or \code{"last"}. Negative integers select which slides \emph{not} to include. If more than one slide are included, -pngs will be returned as a zip file. Defaults to \code{"all"}, in which case +PNGs will be returned as a ZIP file. Defaults to \code{"all"}, in which case all slides are included.} \item{complex_slides}{For "complex" slides (e.g. slides with panelsets or @@ -48,18 +48,18 @@ Only used if \code{complex_slides = TRUE} or \code{partial_slides = TRUE}.} render the final output? The default is \code{FALSE}.} } \value{ -Slides are rendered as a png file (single) or zip file of multiple -png files. +Slides are rendered as a \code{.png} file (single) or \code{.zip} file of +multiple \code{.png} files. } \description{ -Render png image(s) of slides. The function renders to the pdf and -then converts it into png files of each slide. The slide numbers defined by +Render PNG image(s) of slides. The function renders to the PDF and +then converts it into PNG files of each slide. The slide numbers defined by the \code{slides} argument are saved (defaults to \code{1}, returning only the title -slide). If \code{length(slides) > 1}, it will return the png files in a zip file. -You can also get a zip file of all the slides as pngs by setting \code{slides = "all"}). +slide). If \code{length(slides) > 1}, it will return the PNG files in a ZIP file. +You can also get a ZIP file of all the slides as PNGs by setting \code{slides = "all"}). } \examples{ -with_example("slides.Rmd", { +with_example("slides.Rmd", requires_chrome = TRUE, { # By default a png of only the first slide is built to_png("slides.Rmd", keep_intermediates = TRUE) diff --git a/man/to_pptx.Rd b/man/to_pptx.Rd index 5bb054f..896740d 100644 --- a/man/to_pptx.Rd +++ b/man/to_pptx.Rd @@ -2,7 +2,7 @@ % Please edit documentation in R/pptx.R \name{to_pptx} \alias{to_pptx} -\title{Render slides as pptx file.} +\title{Render slides as a PowerPoint file.} \usage{ to_pptx( from, @@ -16,13 +16,13 @@ to_pptx( ) } \arguments{ -\item{from}{Path to a Rmd file, html file, pdf file, or a url. If \code{from} -is a url to slides on a website, you must provide the full url +\item{from}{Path to an \code{.Rmd}, \code{.qmd}, \code{.html}, \code{.pdf} file, or a URL. If +\code{from} is a URL to slides on a website, you must provide the full URL ending in \code{".html"}.} -\item{to}{Name of the output pptx file.} +\item{to}{Name of the output \code{.pptx} file.} -\item{density}{Resolution of the resulting pngs in each slide file. Defaults +\item{density}{Resolution of the resulting PNGs in each slide file. Defaults to \code{100}.} \item{slides}{A numeric or integer vector of the slide number(s) to include @@ -50,15 +50,13 @@ render the final output? The default is \code{FALSE}.} Slides are rendered as a pptx file. } \description{ -Render slides as a pptx file. The function renders to the pdf and -then converts it into png images that are inserted on each slide in the -pptx file. +Render slides as a \code{.pptx} file. The function renders to the PDF and +then converts it into PNG images that are inserted on each slide in the +PowerPoint file. } \examples{ -if (requireNamespace("officer", quietly = TRUE)) { - with_example("slides.Rmd", { - # Render pptx from Rmd, html, pdf, or direct URL - to_pptx("slides.Rmd") - }) -} +with_example("slides.Rmd", requires_chrome = TRUE, requires_packages = "officer", { + # Render pptx from Rmd, html, pdf, or direct URL + to_pptx("slides.Rmd") +}) } diff --git a/man/to_social.Rd b/man/to_social.Rd index 926b18f..fb3276a 100644 --- a/man/to_social.Rd +++ b/man/to_social.Rd @@ -22,8 +22,8 @@ Requires a local installation of Chrome as well as the {webshot2} package: \code{remotes::install_github("rstudio/webshot2")}. } \examples{ -if (requireNamespace("webshot2", quietly = TRUE) && interactive()) { - with_example("slides.Rmd", { +if (interactive()) { + with_example("slides.Rmd", requires_chrome = TRUE, requires_packages = "webshot2", { # Render png image of first slide from Rmd file # sized for sharing on social media to_social("slides.Rmd") diff --git a/man/with_example.Rd b/man/with_example.Rd index 57e1625..6550f12 100644 --- a/man/with_example.Rd +++ b/man/with_example.Rd @@ -4,7 +4,13 @@ \alias{with_example} \title{Try renderthis functions with an example} \usage{ -with_example(example, code, clean = TRUE) +with_example( + example, + code, + clean = TRUE, + requires_packages = NULL, + requires_chrome = FALSE +) } \arguments{ \item{example}{The name of the example file, currently only \code{"slides.Rmd"}.} diff --git a/tests/testthat/helpers.R b/tests/testthat/helpers.R index 2090e39..754f7b2 100644 --- a/tests/testthat/helpers.R +++ b/tests/testthat/helpers.R @@ -10,6 +10,34 @@ expect_equal_images <- function(x, y) { ) } +local_test_example_dir <- function(..., copy_to = NULL) { + # Copies a test example directory into a temporary directory that is removed + # when exiting the parent environment, e.g. when the test completes + test_example <- fs::path_abs(test_path(...)) + + tmpdir <- withr::local_tempdir(.local_envir = parent.frame()) + withr::local_dir(tmpdir, .local_envir = parent.frame()) + + if (!is.null(copy_to)) { + fs::dir_create(copy_to) + fs::dir_copy(test_example, copy_to, overwrite = TRUE) + } else { + fs::dir_copy(test_example, ".", overwrite = TRUE) + } + + invisible(tmpdir) +} + skip_if_not_chrome_installed <- function() { + skip_on_cran() skip_if_not(check_chrome_installed(), "Chrome is not installed") } + +skip_if_not_pandoc <- function() { + skip_if_not(rmarkdown::pandoc_available()) +} + +skip_if_not_quarto <- function() { + skip_if_not(!is.null(quarto::quarto_path()), "quarto binary not available") + skip_if_not_pandoc() +} diff --git a/tests/testthat/slides/quarto-basic/slides.qmd b/tests/testthat/slides/quarto-basic/slides.qmd new file mode 100644 index 0000000..6ae584d --- /dev/null +++ b/tests/testthat/slides/quarto-basic/slides.qmd @@ -0,0 +1,15 @@ +--- +title: "Habits" +author: "John Doe" +format: revealjs +--- + +## Getting up + +- Turn off alarm +- Get out of bed + +## Going to sleep + +- Get in bed +- Count sheep diff --git a/tests/testthat/test-all.R b/tests/testthat/test-all.R index 19b8153..321b9b9 100644 --- a/tests/testthat/test-all.R +++ b/tests/testthat/test-all.R @@ -4,13 +4,11 @@ test_that("build_all() from basic slides.Rmd", { skip_if_not_installed("officer") skip_if_not_installed("webshot2") - tmpdir <- withr::local_tempdir() - fs::dir_copy(test_path("slides", "basic"), tmpdir, overwrite = TRUE) - - withr::local_dir(tmpdir) - + local_test_example_dir("slides", "basic") suppressMessages( - build_all("slides.Rmd", slides = NULL) + lifecycle::expect_deprecated( + build_all("slides.Rmd", slides = NULL) + ) ) expect_true(fs::file_exists("slides.html")) @@ -27,13 +25,11 @@ test_that("build_all() from basic slides.Rmd with a few excluded formats", { skip_if_not_installed("officer") skip_if_not_installed("webshot2") - tmpdir <- withr::local_tempdir() - fs::dir_copy(test_path("slides", "basic"), tmpdir, overwrite = TRUE) - - withr::local_dir(tmpdir) - + local_test_example_dir("slides", "basic") suppressMessages( - build_all("slides.Rmd", slides = NULL, exclude = c("html", "pdf", "png")) + lifecycle::expect_deprecated( + build_all("slides.Rmd", slides = NULL, exclude = c("html", "pdf", "png")) + ) ) expect_false(fs::file_exists("slides.html")) diff --git a/tests/testthat/test-gif.R b/tests/testthat/test-gif.R index f5dfcb0..9c0de3c 100644 --- a/tests/testthat/test-gif.R +++ b/tests/testthat/test-gif.R @@ -1,4 +1,5 @@ test_that("to_gif() simple from .Rmd", { + skip_if_not_pandoc() skip_if_not_chrome_installed() tmpdir <- withr::local_tempdir() @@ -45,6 +46,7 @@ test_that("to_gif() simple from pdf", { }) test_that("to_gif() keeps intermediates", { + skip_if_not_pandoc() skip_if_not_chrome_installed() tmpdir <- withr::local_tempdir() diff --git a/tests/testthat/test-html.R b/tests/testthat/test-html.R index ba5bc36..84e1400 100644 --- a/tests/testthat/test-html.R +++ b/tests/testthat/test-html.R @@ -1,4 +1,6 @@ test_that("to_html() output in input directory", { + skip_if_not_pandoc() + tmpdir <- withr::local_tempdir() fs::dir_copy(test_path("slides", "basic"), tmpdir, overwrite = TRUE) @@ -10,6 +12,8 @@ test_that("to_html() output in input directory", { }) test_that("to_html() self-contained output in input directory", { + skip_if_not_pandoc() + tmpdir <- withr::local_tempdir() fs::dir_copy(test_path("slides", "basic"), tmpdir, overwrite = TRUE) @@ -21,6 +25,8 @@ test_that("to_html() self-contained output in input directory", { }) test_that("to_html() output in sub-directory", { + skip_if_not_pandoc() + tmpdir <- withr::local_tempdir() fs::dir_copy( test_path("slides", "basic"), @@ -42,6 +48,8 @@ test_that("to_html() output in sub-directory", { }) test_that("to_html() output in parent directory", { + skip_if_not_pandoc() + tmpdir <- withr::local_tempdir() fs::dir_copy( @@ -63,6 +71,8 @@ test_that("to_html() output in parent directory", { }) test_that("to_html() output in totally different directory", { + skip_if_not_pandoc() + tmpdir <- withr::local_tempdir() fs::dir_copy( diff --git a/tests/testthat/test-mp4.R b/tests/testthat/test-mp4.R index fc7b2a1..57c541d 100644 --- a/tests/testthat/test-mp4.R +++ b/tests/testthat/test-mp4.R @@ -1,4 +1,5 @@ test_that("to_gif() builds an mp4", { + skip_on_cran() skip_if_not_installed("av") tmpdir <- withr::local_tempdir() @@ -22,6 +23,7 @@ test_that("to_gif() builds an mp4", { }) test_that("to_gif() builds a widescreen mp4", { + skip_on_cran() skip_if_not_installed("av") tmpdir <- withr::local_tempdir() diff --git a/tests/testthat/test-pdf.R b/tests/testthat/test-pdf.R index ccade74..a08c162 100644 --- a/tests/testthat/test-pdf.R +++ b/tests/testthat/test-pdf.R @@ -1,4 +1,5 @@ test_that("to_pdf() simple", { + skip_if_not_pandoc() skip_if_not_chrome_installed() tmpdir <- withr::local_tempdir() @@ -17,6 +18,7 @@ test_that("to_pdf() simple", { }) test_that("to_pdf() simple, other directory", { + skip_if_not_pandoc() skip_if_not_chrome_installed() tmpdir <- withr::local_tempdir() @@ -36,6 +38,7 @@ test_that("to_pdf() simple, other directory", { }) test_that("to_pdf() complex slides", { + skip_if_not_pandoc() skip_if_not_chrome_installed() skip_if_not_installed("pdftools") @@ -55,6 +58,7 @@ test_that("to_pdf() complex slides", { }) test_that("to_pdf() partial slides", { + skip_if_not_pandoc() skip_if_not_chrome_installed() skip_if_not_installed("pdftools") diff --git a/tests/testthat/test-png.R b/tests/testthat/test-png.R index 89d5acb..94e1ca6 100644 --- a/tests/testthat/test-png.R +++ b/tests/testthat/test-png.R @@ -10,6 +10,7 @@ test_that("to_png() handles bad inputs", { }) test_that("to_png() from .Rmd doesn't keep intermediates by default", { + skip_if_not_pandoc() skip_if_not_chrome_installed() tmpdir <- withr::local_tempdir() @@ -47,6 +48,7 @@ test_that("to_png() from basic.pdf", { }) test_that("to_png() chooses .zip even if .png is given", { + skip_if_not_pandoc() skip_if_not_chrome_installed() tmpdir <- withr::local_tempdir() diff --git a/tests/testthat/test-pptx.R b/tests/testthat/test-pptx.R index 50e07aa..013777f 100644 --- a/tests/testthat/test-pptx.R +++ b/tests/testthat/test-pptx.R @@ -23,6 +23,7 @@ test_that("to_pptx() simple from pdf", { test_that("to_pptx() simple from Rmd", { skip_if_not_installed("officer") + skip_if_not_pandoc() skip_if_not_chrome_installed() tmpdir <- withr::local_tempdir() diff --git a/tests/testthat/test-quarto.R b/tests/testthat/test-quarto.R new file mode 100644 index 0000000..f2cfce2 --- /dev/null +++ b/tests/testthat/test-quarto.R @@ -0,0 +1,133 @@ +test_that("[quarto] to_html() output in input directory", { + skip_if_not_quarto() + + local_test_example_dir("slides", "quarto-basic") + suppressMessages(to_html("slides.qmd")) + + expect_true(fs::file_exists("slides.html")) + expect_true(fs::dir_exists("slides_files")) +}) + +test_that("[quarto] to_html() self-contained output in input directory", { + skip_if_not_quarto() + + local_test_example_dir("slides", "quarto-basic") + suppressMessages(to_html("slides.qmd", self_contained = TRUE)) + + expect_true(fs::file_exists("slides.html")) + expect_false(fs::dir_exists("slides_files")) +}) + +test_that("[quarto] to_html() output in sub-directory", { + skip_if_not_quarto() + + local_test_example_dir("slides", "quarto-basic", copy_to = "slides") + + fs::dir_create("output") + suppressMessages( + expect_message( + to_html("slides/slides.qmd", "output/slides.html"), + "self_contained = TRUE" + ) + ) + + expect_true(fs::file_exists("output/slides.html")) + expect_false(fs::dir_exists("output/slides_files")) +}) + +test_that("[quarto] to_html() output in parent directory", { + skip_if_not_quarto() + + local_test_example_dir("slides", "quarto-basic", copy_to = "slides") + suppressMessages( + expect_message( + to_html("slides/slides.qmd", "slides.html"), + "self_contained = TRUE" + ) + ) + + expect_true(fs::file_exists("slides.html")) + expect_false(fs::dir_exists("slides_files")) +}) + +test_that("[quarto] to_html() output in totally different directory", { + skip_if_not_quarto() + + local_test_example_dir("slides", "quarto-basic", copy_to = "slides") + tmpdir_out <- withr::local_tempdir() + + suppressMessages( + expect_message( + to_html("slides/slides.qmd", fs::path(tmpdir_out, "slides.html")), + "self_contained = TRUE" + ) + ) + + expect_true(fs::file_exists(fs::path(tmpdir_out, "slides.html"))) +}) + +test_that("[quarto] to_pdf()", { + skip_if_not_quarto() + skip_if_not_chrome_installed() + + local_test_example_dir("slides", "quarto-basic") + suppressMessages(to_pdf("slides.qmd")) + + expect_true(fs::file_exists("slides.html")) + expect_true(fs::file_exists("slides.pdf")) +}) + +test_that("[quarto] to_pdf() with complex slides is not available", { + skip_if_not_quarto() + skip_if_not_chrome_installed() + + local_test_example_dir("slides", "quarto-basic") + expect_error(to_pdf("slides.qmd", complex_slides = TRUE)) + expect_error(to_pdf("slides.qmd", partial_slides = TRUE)) +}) + +test_that("[quarto] to_png()", { + skip_if_not_quarto() + skip_if_not_chrome_installed() + + local_test_example_dir("slides", "quarto-basic") + suppressMessages(to_png("slides.qmd", keep_intermediates = TRUE)) + + expect_true(fs::file_exists("slides.png")) + expect_true(fs::file_exists("slides.html")) + expect_true(fs::file_exists("slides.pdf")) +}) + +test_that("[quarto] to_gif()", { + skip_if_not_quarto() + skip_if_not_chrome_installed() + + local_test_example_dir("slides", "quarto-basic") + suppressMessages(to_gif("slides.qmd")) + + expect_true(fs::file_exists("slides.gif")) +}) + +test_that("[quarto] to_mp4()", { + skip_if_not_installed("av") + skip_if_not_quarto() + skip_if_not_chrome_installed() + + local_test_example_dir("slides", "quarto-basic") + suppressMessages(to_mp4("slides.qmd", keep_intermediates = TRUE)) + + expect_true(fs::file_exists("slides.mp4")) + expect_true(fs::file_exists("slides.html")) + expect_true(fs::file_exists("slides.pdf")) +}) + +test_that("[quarto] to_pptx()", { + skip_if_not_installed("officer") + skip_if_not_quarto() + skip_if_not_chrome_installed() + + local_test_example_dir("slides", "quarto-basic") + suppressMessages(to_pptx("slides.qmd")) + + expect_true(fs::file_exists("slides.pptx")) +}) diff --git a/tests/testthat/test-social.R b/tests/testthat/test-social.R index f9fdc94..7b69bdd 100644 --- a/tests/testthat/test-social.R +++ b/tests/testthat/test-social.R @@ -1,4 +1,5 @@ test_that("to_html() output in input directory", { + skip_if_not_pandoc() skip_if_not_chrome_installed() skip_if_not_installed("webshot2") diff --git a/vignettes/renderthis-setup.Rmd b/vignettes/renderthis-setup.Rmd index f2f18aa..1064da9 100644 --- a/vignettes/renderthis-setup.Rmd +++ b/vignettes/renderthis-setup.Rmd @@ -10,31 +10,52 @@ vignette: > ```{r setup, include = FALSE} knitr::opts_chunk$set( collapse = TRUE, - comment = "#>" + comment = "#>", + eval = FALSE ) ``` -To get the most out of renderthis, we recommend installing the package **with dependencies** and making sure that you have a local installation of Chrome. +To get the most out of renderthis, we recommend installing the package +**with dependencies** and making sure that you have a local installation +of Chrome. # Installation -You can install the current version of renderthis from GitHub: +You can install the latest version of renderthis from +[CRAN](https://cran.r-project.org/) with: -```{r, eval=FALSE} +```{r} +install.packages("renderthis") +``` + +And the development version from GitHub with: + +```{r} # install.packages("remotes") remotes::install_github("jhelvy/renderthis") ``` -Some output formats require additional packages, and each format will provide instructions about how to install any missing dependencies. You can also choose to install renderthis with all of its dependencies: +Some output formats require additional packages, and each format will provide +instructions about how to install any missing dependencies. You can also +choose to install renderthis with all of its dependencies: -```{r, eval=FALSE} -# install.packages("remotes") +```{r} +# From CRAN +install.packages("renderthis", dependencies = TRUE) + +# From GitHub remotes::install_github("jhelvy/renderthis", dependencies = TRUE) ``` # Local Chrome Installation -Rendering the PDF requires a local installation of Chrome. If you don't have Chrome installed, you can use other browsers based on Chromium, such as Chromium itself, Edge, Vivaldi, Brave, or Opera. In this case, you will need to set the path to the browser you want to use for the [pagedown](https://github.com/rstudio/pagedown) package as well as the [chromote](https://github.com/rstudio/chromote) package if you use the `complex_slides = TRUE` or `partial_slides = TRUE` arguments. +Rendering the PDF requires a local installation of Chrome. If you don't have +Chrome installed, you can use other browsers based on Chromium, such as +Chromium itself, Edge, Vivaldi, Brave, or Opera. In this case, you will need +to set the path to the browser you want to use for the +[pagedown](https://github.com/rstudio/pagedown) package as well as the +[chromote](https://github.com/rstudio/chromote) package if you use the +`complex_slides = TRUE` or `partial_slides = TRUE` arguments. After installing the packages, you can set the paths like this: @@ -43,7 +64,16 @@ Sys.setenv(PAGEDOWN_CHROME = "/path/to/browser") Sys.setenv(CHROMOTE_CHROME = "/path/to/browser") ``` -If you are unable to install Chrome (e.g. on a computing cluster), the recommended workflow is to render intermediate output formats and use an alternative method for rendering the PDF. +If you're not sure where Chrome lives on your machine, +try the following command to search for it: + +```{r, eval=FALSE} +pagedown::find_chrome() +``` + +If you are unable to install Chrome (e.g. on a computing cluster), the +recommended workflow is to render intermediate output formats and use an +alternative method for rendering the PDF. For example, to render a pptx from a Rmd file without Chrome, you could: @@ -51,3 +81,20 @@ For example, to render a pptx from a Rmd file without Chrome, you could: 2. Use vscode remote and vscode-preview-server extension to open the html on a local machine (preferrably with Chrome installed) 3. Save to pdf on Chrome 4. Render the pptx with `to_pptx(from = "slides.pdf")` + +# Dependencies + +Because many users will not need all output formats, +several outputs require additional packages that are suggested dependencies +and aren't installed by default unless requested as described above. +The table below lists the packages required for each output type: + +| Output | Requires | +|:-----|:-----| +| PDF (simple) | Google Chrome (for [pagedown](https://pagedown.rbind.io/)) | +| PDF (complex) | [chromote](https://rstudio.github.io/chromote/) | +| PNG | Requires PDF | +| GIF | Requires PDF | +| MP4 | [av](https://docs.ropensci.org/av/) | +| PPTX | [officer](https://ardata-fr.github.io/officeverse/) | +| Social | [webshot2](https://rstudio.github.io/webshot2/) | diff --git a/vignettes/renderthis.Rmd b/vignettes/renderthis.Rmd index 405fd79..3485870 100644 --- a/vignettes/renderthis.Rmd +++ b/vignettes/renderthis.Rmd @@ -23,18 +23,20 @@ knitr::opts_chunk$set( ## Render HTML -Render an html file from an Rmd file of xaringan slides: +Render an HTML file from an `.Rmd` file of xaringan slides or `.qmd` of Quarto revealjs slides: ```{r} to_html(from = "slides.Rmd") +to_html(from = "slides.qmd") ``` ## Render PDF -Input can be an Rmd file, html file, or url: +Input can be an `.Rmd` file, `.qmd` file, `.html` file, or url: ```{r} to_pdf(from = "slides.Rmd") +to_pdf(from = "slides.qmd") to_pdf(from = "slides.html") to_pdf(from = "https://jhelvy.github.io/renderthis/example/slides.html") ``` @@ -43,10 +45,11 @@ to_pdf(from = "https://jhelvy.github.io/renderthis/example/slides.html") ## Render GIF -Input can be an Rmd file, html file, pdf file, or url: +Input can be an `.Rmd` file, `.qmd` file, `.html` file, `.pdf` file, or url: ```{r} to_gif(from = "slides.Rmd") +to_gif(from = "slides.qmd") to_gif(from = "slides.html") to_gif(from = "slides.pdf") to_gif(from = "https://jhelvy.github.io/renderthis/example/slides.html") @@ -58,10 +61,11 @@ Example: ## Render MP4 -Input can be an Rmd file, html file, pdf file, or url: +Input can be an `.Rmd` file, `.qmd` file, `.html` file, `.pdf` file, or url: ```{r} to_mp4(from = "slides.Rmd") +to_mp4(from = "slides.qmd") to_mp4(from = "slides.html") to_mp4(from = "slides.pdf") to_mp4(from = "https://jhelvy.github.io/renderthis/example/slides.html") @@ -73,10 +77,11 @@ Creates a pptx file where each slide contains a png image of each slide. While y (See the [slidex](https://github.com/datalorax/slidex) package by @datalorax to do the opposite: pptx --> xaringan!) -Input can be an Rmd file, html file, pdf file, or url: +Input can be an `.Rmd` file, `.qmd` file, `.html` file, `.pdf` file, or url: ```{r} to_pptx(from = "slides.Rmd") +to_pptx(from = "slides.qmd") to_pptx(from = "slides.html") to_pptx(from = "slides.pdf") to_pptx(from = "https://jhelvy.github.io/renderthis/example/slides.html") @@ -86,11 +91,12 @@ to_pptx(from = "https://jhelvy.github.io/renderthis/example/slides.html") Render png image(s) of some or all slides. Use the `slides` argument to determine which slides to include (defaults to `1`, returning just the first slide). -Input can be an Rmd file, html file, pdf file, or url: +Input can be an `.Rmd` file, `.qmd` file, `.html` file, `.pdf` file, or url: ```{r} # By default, a png of only the first slide is built to_png(from = "slides.Rmd", to = "title_slide.png") +to_png(from = "slides.qmd", to = "title_slide.png") to_png(from = "slides.html", to = "title_slide.png") to_png(from = "slides.pdf", to = "title_slide.png") to_png(from = @@ -112,7 +118,7 @@ Example: ## Render Social -Render a png of the first slide from an Rmd file. Image is sized for sharing on social media (e.g. Twitter). +Render a png of the first slide from an `.Rmd` file of xaringan slides (Quarto slides not yet supported). Image is sized for sharing on social media (e.g. Twitter). ```{r} to_social(from = "slides.Rmd")