class: center, middle, inverse, title-slide # Customizing & Extending R Markdown ###
Yihui Xie, RStudio
### 2017/01/14 @ rstudio::conf, Kissimmee, FL --- # An R Markdown document --- title: "A Simple Regression" author: "Yihui Xie" *output: html_document: toc: true pdf_document: citation_package: "natbib" --- We built a linear regression model. ```{r} fit <- lm(dist ~ speed, data = cars) b <- coef(fit) plot(fit) ``` The slope of the regression is `r b[1]`. --- background-image: url(https://images.unsplash.com/photo-1455165814004-1126a7199f9b?dpr=2&auto=format&fit=crop&w=1500&h=1000&q=80&cs=tinysrgb&crop=) background-size: cover class: inverse, center, middle # Customizing R Markdown --- # Two things to do first - Check out the options in the RStudio IDE .center[![](gif/rmd-gear.png)] - Read the documentation of an output format function, or read it on http://rmarkdown.rstudio.com - If neither provides what you want, let's dig deeper --- # R Markdown output formats - Lifetime of an Rmd: `.Rmd -> knitr -> .md -> Pandoc -> output` (e.g., `.html`, `.docx`, `-> LaTeX -> PDF`) - An output format is an abstraction in **rmarkdown** as a uniform (programming) interface to deal with - **knitr** options (chunk options, hooks, package options, ...) - pandoc options (`--from`, `--to`, `--latex-engine`, ...) - pre/post-processors (e.g., process HTML widgets) - and other options (e.g., whether to keep the intermediate .md) - Can be created via `rmarkdown::output_format()` - Note the `base_format` argument: output formats are _extensible_. If you only want to modify a few options of an existing format, you can use it as the base, e.g., you can add a custom post-processor on top of the existing one. --- # Built-in formats - `beamer_presentation` - `github_document` - `html_document` - `ioslides_presentation` - `md_document` - `odt_document` - `pdf_document` - `rtf_document` - `slidy_presentation` - `word_document` --- # YAML options for output formats The YAML metadata ```yaml --- output: html_document: toc: true theme: "united" fig_height: 6 --- ``` will be translated to ```r rmarkdown::render( 'input.Rmd', html_document( toc = TRUE, theme = "united", fig_height = 6 ) ) ``` --- # Example: html_document() ```r str(rmarkdown::html_document()) ``` ``` List of 11 $ knitr :List of 5 ..$ opts_knit : NULL ..$ opts_chunk :List of 5 .. ..$ dev : chr "png" .. ..$ dpi : num 96 .. ..$ fig.width : num 7 .. ..$ fig.height: num 5 .. ..$ fig.retina: num 2 ..$ knit_hooks : NULL ..$ opts_hooks : NULL ..$ opts_template: NULL $ pandoc :List of 6 ..$ to : chr "html" ..$ from : chr "markdown+autolink_bare_uris+ascii_identifiers+tex_math_single_backslash" ..$ args : chr [1:11] "--smart" "--email-obfuscation" "none" "--self-contained" ... ..$ keep_tex : logi FALSE ..$ latex_engine: chr "pdflatex" ..$ ext : NULL $ keep_md : logi FALSE $ clean_supporting : logi TRUE $ df_print : chr "default" $ pre_knit :function (...) $ post_knit :function (...) $ pre_processor :function (...) $ intermediates_generator:function (original_input, encoding, intermediates_dir) $ post_processor :function (metadata, input_file, output_file, clean, verbose) $ on_exit :function () - attr(*, "class")= chr "rmarkdown_output_format" ``` --- # Example: html_document() Some options: - `theme`: you can set it to `NULL` to reduce the HTML file size significantly (because of Bootstrap) - `css`: tweak the styles of certain elements - `template`: a custom Pandoc template --- # Pandoc templates - Official Pandoc templates: https://github.com/jgm/pandoc-templates - **rmarkdown**'s templates: https://github.com/rstudio/rmarkdown/tree/master/inst/rmd - A minimal example ```html <html> <head> * <title>$title$</title> $for(css)$ <link rel="stylesheet" href="$css$" type="text/css" /> $endfor$ </head> <body> * $body$ </body> </html> ``` --- # Simple customization There are many options you can set in YAML. Two types of options: - Options for Pandoc: make sure you read the Pandoc manual to know the possible options (e.g., for LaTeX output: http://pandoc.org/MANUAL.html#variables-for-latex). ```yaml fontsize: 12pt documentclass: book monofont: "Source Code Pro" # for XeLaTeX output ``` - Options for an R Markdown output format under the `output` field in YAML: consult the specific R help page. You can certainly create your own template, but it may not be necessary to do so if your problem can be solved by setting a few options in YAML. --- # Deeper customization A common use case: inject a snippet of code to the HTML `<head>` (e.g., JS/CSS code), or the LaTeX preamble (e.g., load some LaTeX packages before `\begin{document}`). ```yaml output: html_document: includes: in_header: "header.html" before_body: "before.html" after_body: "after.html" pdf_document: includes: in_header: "preamble.tex" ``` Even deeper customization? Sure, write a package with custom output formats! Let's study a few relatively simple examples in **rmarkdown** first. --- # Example: odt_document ```r rmarkdown::odt_document ``` ``` function (fig_width = 5, fig_height = 4, fig_caption = TRUE, template = "default", reference_odt = "default", includes = NULL, keep_md = FALSE, md_extensions = NULL, pandoc_args = NULL) { knitr <- knitr_options(opts_chunk = list(dev = "png", dpi = 96, fig.width = fig_width, fig.height = fig_height)) args <- c() if (!is.null(template) && !identical(template, "default")) args <- c(args, "--template", pandoc_path_arg(template)) args <- c(args, includes_to_pandoc_args(includes)) if (!is.null(reference_odt) && !identical(reference_odt, "default")) { args <- c(args, "--reference-odt", pandoc_path_arg(reference_odt)) } args <- c(args, pandoc_args) output_format(knitr = knitr, pandoc = pandoc_options(to = "odt", from = from_rmarkdown(fig_caption, md_extensions), args = args), keep_md = keep_md) } <environment: namespace:rmarkdown> ``` --- background-image: url(https://images.unsplash.com/photo-1462294714784-152615923171?dpr=2&auto=format&fit=crop&w=1500&h=844&q=80&cs=tinysrgb&crop=) background-size: cover class: inverse, center, middle # Extending R Markdown --- # Some extension packages - [**flexdashboard**](https://github.com/rstudio/flexdashboard): R Markdown Format for Flexible Dashboards - [**rticles**](https://github.com/rstudio/rticles): Article Formats for R Markdown - [**tufte**](https://github.com/rstudio/tufte): Tufte's Styles for R Markdown Documents - [**rmdformats**](https://github.com/juba/rmdformats): the Material design, Read The Docs, simple and clean HTML, Docco - [**prettydoc**](https://github.com/yixuan/prettydoc): Lightweight pretty HTML --- background-image: url(https://bookdown.org/yihui/bookdown/images/cover.jpg) background-size: 40% background-position: 50% 60% .center[https://bookdown.org] --- # bookdown - Not the best example of extending R Markdown, but it is a substantial extension in two aspects: 1. Deal with multiple Rmd files (chapters);<sup>*</sup> 2. Custom output formats for (1) multi-page HTML output and PDF/EPUB books (2) extending the Markdown syntax, e.g., - `bookdown::gitbook` - `bookdown::pdf_book` - `bookdown::epub_book` - `bookdown::html_document2` - ... - To some degree, it is reinventing LaTeX for other output formats (HTML, EPUB, Word). At its technical core, it is (simply?) _regular expressions_, e.g., the syntax for labels `(\#label)` and cross-references `\@ref(label)`. .footnote[[\*] You can certainly compile a single Rmd file with **bookdown**.] --- # Sometimes you need tricks/hacks .pull-left[ ![](gif/nice-sea-pic1.jpg) ![](gif/nice-wedding-pic1.jpg) R packages: user's perspective ] -- .pull-right[ ![](gif/nice-sea-pic2.jpg) ![](gif/nice-wedding-pic2.jpg) R packages: developer's perspective ] --- background-image: url(https://upload.wikimedia.org/wikipedia/commons/b/be/Sharingan_triple.svg) background-position: 90% 10% background-size: 15% # xaringan - R Markdown slideshows based on [remark.js](https://remarkjs.com) - When I saw remark.js, I felt I finally found something I had been waiting for years -- .center[ ![](gif/quick-fox.gif) ] -- - **xaringan** is pretty much a hack;<sup>*</sup> [the key](https://github.com/yihui/xaringan/blob/732e7d4e66/R/render.R#L120) is a pre-processor .footnote[[*] The goal is to bypass Pandoc but make use of other handy components of R Markdown, such as HTML dependencies.] --- # Go, R Markdown extensions, Go! ```r knitr -> rmarkdown -> bookdown -> blogdown | +-> flexdashboard +-> rticles +-> tufte +-> prettydoc +-> xaringan +-> ... ``` -- .center[![](gif/cat-flow.gif)] ??? Now R Markdown can be used to compile single documents, create dashboards, write books, create websites, and make presentations. Have we won the world? --- background-image: url(gif/missed-shot.gif) background-size: cover ??? Technology is easy. Psychology is hard. --- background-image: url(gif/logo.png) background-position: 90% 50% background-size: 20% # Contact info - Yihui Xie - https://yihui.org - Twitter [@xieyihui](https://twitter.com/xieyihui) Github [@yihui](https://github.com/yihui) - RStudio - https://www.rstudio.com - Twitter [@rstudio](https://twitter.com/rstudio) Github [@rstudio](https://github.com/rstudio)