Skip to content

Commit

Permalink
Generate a PDF with Chrome using the Knit button of RStudio IDE (#155)
Browse files Browse the repository at this point in the history
* create a function to be passed to the knit parameter

* update documentation

* add a section for using chrome_print() on a server

* add a NEWS entry

* update templates

* modify chrome_print() instead following @yihui's suggestion in #155 (review)

* Update inst/examples/index.Rmd
  • Loading branch information
RLesur authored Dec 3, 2019
1 parent ee10157 commit e242027
Show file tree
Hide file tree
Showing 10 changed files with 81 additions and 11 deletions.
2 changes: 1 addition & 1 deletion DESCRIPTION
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,4 @@ BugReports: https://github.com/rstudio/pagedown/issues
SystemRequirements: Pandoc (>= 2.2.3)
Encoding: UTF-8
LazyData: true
RoxygenNote: 7.0.0
RoxygenNote: 7.0.2
2 changes: 2 additions & 0 deletions NEWS.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

- **reveal.js** presentations can be printed to PDF using `chrome_print()`.

- Using RStudio, any R Markdown HTML output formats can be directly printed to PDF by adding the line `"knit: pagedown::chrome_print"` to the YAML header: this line modifies the behavior of the "Knit" button of RStudio and produce both HTML and PDF documents.

# CHANGES IN pagedown VERSION 0.6

## MINOR CHANGES
Expand Down
24 changes: 18 additions & 6 deletions R/chrome.R
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
#' may need to wait for a longer time).
#' @param browser Path to Google Chrome or Chromium. This function will try to
#' find it automatically via \code{\link{find_chrome}()} if the path is not
#' explicitly provided.
#' explicitly provided and the environment variable \code{PAGEDOWN_CHROME} is
#' not set.
#' @param format The output format.
#' @param options A list of page options. See
#' \code{https://chromedevtools.github.io/devtools-protocol/tot/Page#method-printToPDF}
Expand All @@ -42,6 +43,7 @@
#' @param async Execute \code{chrome_print()} asynchronously? If \code{TRUE},
#' \code{chrome_print()} returns a \code{\link[promises]{promise}} value (the
#' \pkg{promises} package has to be installed in this case).
#' @param encoding Not used. This argument is required by RStudio IDE.
#' @references
#' \url{https://developers.google.com/web/updates/2017/04/headless-chrome}
#' @return Path of the output file (invisibly). If \code{async} is \code{TRUE}, this
Expand All @@ -51,9 +53,16 @@ chrome_print = function(
input, output = xfun::with_ext(input, format), wait = 2, browser = 'google-chrome',
format = c('pdf', 'png', 'jpeg'), options = list(), selector = 'body',
box_model = c('border', 'content', 'margin', 'padding'), scale = 1, work_dir = tempfile(),
timeout = 30, extra_args = c('--disable-gpu'), verbose = 0, async = FALSE
timeout = 30, extra_args = c('--disable-gpu'), verbose = 0, async = FALSE, encoding
) {
if (missing(browser)) browser = find_chrome() else {
is_rstudio_knit =
!interactive() && !is.na(Sys.getenv('RSTUDIO', NA)) &&
!missing(encoding) && length(match.call()) == 3
if (is_rstudio_knit) verbose = 1

if (missing(browser) && is.na(browser <- Sys.getenv('PAGEDOWN_CHROME', NA))) {
browser = find_chrome()
} else {
if (!file.exists(browser)) browser = Sys.which(browser)
}
if (!utils::file_test('-x', browser)) stop('The browser is not executable: ', browser)
Expand Down Expand Up @@ -114,9 +123,10 @@ chrome_print = function(
svr = NULL # init svr variable
if (file.exists(input)) {
is_html = function(x) grepl('[.]html?$', x)
url = if (is_html(input)) input else rmarkdown::render(
with_msg_maybe = if (is_rstudio_knit) suppressMessages else identity
url = if (is_html(input)) input else with_msg_maybe(rmarkdown::render(
input, envir = parent.frame(), encoding = 'UTF-8'
)
))
if (!is_html(url)) stop(
"The file '", url, "' should have the '.html' or '.htm' extension."
)
Expand Down Expand Up @@ -183,6 +193,7 @@ chrome_print = function(
later::run_now(); if (!is.null(svr)) run_servr()
}

if (is_rstudio_knit) message('\nOutput created: ', basename(output))
invisible(output)
})
}
Expand All @@ -206,7 +217,8 @@ find_chrome = function() {
res = head(res[file.exists(res)], 1)
if (length(res) != 1) stop(
'Cannot find Google Chrome automatically from the Windows Registry Hive. ',
"Please pass the full path of chrome.exe to the 'browser' argument."
"Please pass the full path of chrome.exe to the 'browser' argument",
"or to the environment variable 'PAGEDOWN_CHROME'."
)
res
},
Expand Down
46 changes: 44 additions & 2 deletions inst/examples/index.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -84,8 +84,51 @@ Note that this overriding mechanism also works for other output formats in **pag

## Print to PDF

You can print HTML pages to PDF using Google Chrome or Chromium using the menu "Print" or by pressing `Ctrl + P` (or `Command + P` on macOS). Remember to allow background graphics to be printed. You may also consider using the function `pagedown::chrome_print()`, but currently it is experimental and you may get an incomplete PDF, so we recommend that you open the page in a real browser and print to PDF there instead.
There are three ways to print to PDF:

1. with Google Chrome or Chromium using the menu "Print" or by pressing `Ctrl + P` (or `Command + P` on macOS). Remember to allow background graphics to be printed.

1. using the function `pagedown::chrome_print()`. Its first argument (`input`) accepts a path to a local Rmd or HTML file or an URL. Google Chrome or Chromium must be installed on your system.

1. in RStudio, adding the following line in the YAML header of your Rmd file:

```yaml
knit: pagedown::chrome_print
```

With this metadata parameter, the behavior of the "Knit" button of RStudio is modified: it produces both the HTML document and the PDF with Chrome. This functionality is suitable for any R Markdown HTML output format and is mainly convenient for small documents like presentations or notes.
If `chrome_print()` cannot find Chrome or Chromium automatically, set the `PAGEDOWN_CHROME` environment variable to the path to Chrome or Chromium executable.

### Print to PDF on a server

If you want to use `chrome_print()` on a server (an RStudio server, for instance), Chromium or Chrome has to be present on this server and available from the `PATH` or `PAGEDOWN_CHROME` environment variables.

Be sure that the local IP address `127.0.0.1` is referenced in the `no_proxy` environment variable. Otherwise the R session won't be able to connect to Chrome.

### Print to PDF with CI/CD services

It is possible to produce a PDF with Chrome using a continuous integration service.

With Travis, activate the Chrome addon by adding theses lines in `.travis.yml` file:

```yaml
addons:
chrome: stable
```

With GitLab CI, you have to use a Docker image with R, Pandoc, **pagedown** and Chromium or Chrome. Depending on the base image, you may have to install some extra fonts.

Travis and GitLab CI are container-based environments running as root. As explained in the [Travis documentation](https://docs.travis-ci.com/user/chrome#sandboxing), you have to pass the `--no-sandbox` argument to `chrome_print()` (this is required for both Travis and GitLab CI):

```{r, eval=FALSE}
chrome_print(
...,
extra_args = c("--disable-gpu",
"--no-sandbox")
)
```

Since the `--no-sandbox` option can lead to major security threats, do not use these CI/CD services to print untrusted web pages.

# Applications

Expand Down Expand Up @@ -803,4 +846,3 @@ knitr::write_bib(c(.packages(), 'pagedown', 'xaringan', 'servr'), 'index.bib')
// this is because FF handles lists differently
document.querySelector('#TOC h1').insertAdjacentHTML('afterend', '<wbr>');
```

2 changes: 2 additions & 0 deletions inst/rmarkdown/templates/html-letter/skeleton/skeleton.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ output:
self_contained: false
links-to-footnotes: true
paged-footnotes: true
# uncomment this line to produce HTML and PDF in RStudio:
#knit: pagedown::chrome_print
---

![The RStudio logo](https://www.rstudio.com/wp-content/uploads/2016/09/RStudio-Logo-Blue-Gray-250.png){.logo}
Expand Down
2 changes: 2 additions & 0 deletions inst/rmarkdown/templates/html-paged/skeleton/skeleton.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,8 @@ output:
toc: true
# change to true for a self-contained document, but it'll be a litte slower for Pandoc to render
self_contained: false
# uncomment this line to produce HTML and PDF in RStudio:
#knit: pagedown::chrome_print
---

```{r setup, include=FALSE}
Expand Down
2 changes: 2 additions & 0 deletions inst/rmarkdown/templates/html-resume/skeleton/skeleton.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@ output:
pagedown::html_resume:
# set it to true for a self-contained HTML page but it'll take longer to render
self_contained: false
# uncomment this line to produce HTML and PDF in RStudio:
#knit: pagedown::chrome_print
---

Aside
Expand Down
2 changes: 2 additions & 0 deletions inst/rmarkdown/templates/jss-paged/skeleton/skeleton.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ bibliography: index.bib
output:
pagedown::jss_paged:
self_contained: false
# uncomment this line to produce HTML and PDF in RStudio:
#knit: pagedown::chrome_print
---

# Introduction
Expand Down
2 changes: 2 additions & 0 deletions inst/rmarkdown/templates/thesis-paged/skeleton/skeleton.Rmd
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,8 @@ output:
self_contained: no
bibliography: packages.bib
link-citations: yes
# uncomment this line to produce HTML and PDF in RStudio:
#knit: pagedown::chrome_print
---

```{r setup, include=FALSE}
Expand Down
8 changes: 6 additions & 2 deletions man/chrome_print.Rd

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

0 comments on commit e242027

Please sign in to comment.