---
title: "An Introduction to ymlthis"
output: 
  prettydoc::html_pretty:
    theme: tactile
vignette: |-
  >
  %\VignetteIndexEntry{An Introduction to ymlthis}
  %\VignetteEngine{knitr::rmarkdown}
  %\VignetteEncoding{UTF-8}
---

```{r setup, echo=FALSE}
library(ymlthis)
oldoption <- options(devtools.name = "Malcolm Barrett", crayon.enabled = FALSE)
knitr::opts_chunk$set(
  collapse = TRUE,
  comment = "#>", 
  warning = FALSE
)

check <- function() "<span style='color:green'>\u2713</span>"
cross <- function() "<span style='color:red'>\u2717</span>"
knit_print.yml <- function(x, ...) {
  ymlthis::asis_yaml_output(x)
}
```

```{r pandoc_check, echo=FALSE}
if (!rmarkdown::pandoc_available()) {
  cat("pandoc is required to use ymlthis. Please visit https://pandoc.org/ for more information.")
  knitr::knit_exit()
}
```


**ymlthis** is a package to help you write YAML metadata for **R Markdown** documents and related tools like **blogdown**, **bookdown**, and **pkgdown**. YAML serves two main roles: to pass information to be printed in the document, such as the title and author, and to control how the document is rendered, anything from the output type (HTML vs. PDF) and typesetting options to what should happen with files created while rendering. See the [YAML: An Overview](yaml-overview.html) for a more general introduction to YAML and the [YAML Fieldguide](yaml-fieldguide.html) for YAML field documentation.

# Writing YAML with **ymlthis**

**ymlthis** makes it easy to write valid YAML by handling the syntax and documenting the majority of YAML fields in one place. `yml()` creates a `yml` object that, by default, sets the author name and date. **ymlthis** uses name options in **devtools** and **usethis** (`options(devtools.name = "name")` and `options(usethis.full_name = "name")`, respectively), as well as the **whoami** package, to try to find the author's name. By default, the date is set to `` `r knitr::inline_expr('format(Sys.Date())')` ``, which will update the date when knitting.

```{r}
yml()
```


Functions that start with `yml_*()` take and return `yml` objects, so they can be used to add or modify YAML fields. For instance, to add a title, use `yml_title()`

```{r }
yml() %>% 
  yml_title("An introduction to ymlthis")
```

An essential use of YAML in **R Markdown** is to set the output type. By default, the `output` YAML field looks like

``` yaml
output: html_document
```

which calls `rmarkdown::html_document()` when knitting. All of the nested fields passed to `output` come from the output function you are using (so you can check `?pkg::output_function()` to see what the options are). **ymlthis** writes and validates output YAML by parsing calls to these functions. We can, for example, nest **R Markdown**'s `pdf_document()` inside `yml_output()`:

```{r}
yml() %>% 
  yml_output(pdf_document())
```

Passing arguments to the output functions will nest them correctly for YAML.

```{r, warning = FALSE}
yml() %>% 
  yml_output(pdf_document(toc = TRUE))
```

And we can pass multiple output functions to facilitate rendering R Markdown files to multiple formats:

```{r}
yml() %>% 
  yml_output(
    pdf_document(toc = TRUE),
    html_document()
  )
```

YAML fields can come from a variety of places: **R Markdown** itself, the output function, Pandoc (for example, as options used in LaTeX), and custom templates. Many of these fields are documented in `yml_*()` functions.

```{r}
yml() %>%
  yml_author(
    c("Yihui Xie", "Hadley Wickham"),
    affiliation = "RStudio"
  ) %>%
  yml_date("07/04/2019") %>%
  yml_title("Reproducible Research in R") %>% 
  yml_category(c("r", "reprodicibility")) %>% 
  yml_output(
    pdf_document(
      keep_tex = TRUE,
      includes = includes2(after_body = "footer.tex")
    )
  ) %>%
  yml_latex_opts(biblio_style = "apalike")
```

You can also use `yml_toplevel()` to append any YAML fields not covered in **ymlthis**.

## Parameterized reports

[Parameterized reports](https://yihui.org/rmarkdown/parameterized-reports.html) are a powerful feature of **R Markdown** that lets you specify variables in the YAML metadata used in your report, letting you re-use reports for a variety of settings. To set parameters, you use the `params` YAML field and access the parameter in your report by calling `params$variable_name`. Basic YAML for parameters looks like this

```yaml
params:
  country: "Turkey"
```

Calling `params$country` in the **R Markdown** document will thus return `"Turkey"`. `yml_params()` will write this for you:

```{r}
yml() %>% 
  yml_params(country = "Turkey")
```

You can also fill in parameters using a **Shiny** app with the "Knit with Parameters" button in the RStudio IDE or by passing `"ask"` to the `params` argument in `rmarkdown::render()`. While **R Markdown** will try to guess the Shiny widget type by the value of the parameter, you can specify them yourself with **ymlthis** functions that start with `shiny_*()`.

```{r}
yml() %>%
  yml_params(
    data = shiny_file("Upload Data (.csv)"),
    n = shiny_numeric("n to sample", 10),
    date = shiny_date("Date"),
    show_plot = shiny_checkbox("Plot the data?", TRUE)
  )
```

## References and citations

[**R Markdown** has excellent support for citations](https://yihui.org/rmarkdown/markdown-syntax.html). The simplest way to use references in an **R Markdown** file is to add a bibliography file using the `bibliography` field.

```{r}
yml() %>% 
  yml_citations(bibliography = "refs.bib")
```

However, if you only have a few references and want to keep your file self-contained, you can also specify references directly in your YAML using `yml_reference()` and `reference()`.

```{r}
ref <- reference(
  id = "fenner2012a",
  title = "One-click science marketing",
  author = list(
    family = "Fenner",
    given = "Martin"
  ),
  `container-title` = "Nature Materials",
  volume = 11L,
  URL = "https://doi.org/10.1038/nmat3283",
  DOI = "10.1038/nmat3283",
  issue = 4L,
  publisher = "Nature Publishing Group",
  page = "261-263",
  type = "article-journal",
  issued = list(
    year = 2012,
    month = 3
  )
)

yml() %>%
  yml_reference(ref)
```

`yml_reference()` also supports package citation using the `.bibentry` argument and `citation()`.

```{r}
yml() %>%
  yml_reference(.bibentry = citation("purrr"))
```

If you have an existing `.bib` file, but you want to specify it in the YAML, instead, you can convert it with `bib2yml()`. For instance, if you wrote a `.bib` file for the packages used in your document with `knitr::write_bib()`, `bib2yml()` will translate the file to YAML you can include directly in the metadata.

# R Markdown extensions

Packages that extend **R Markdown**, such as **bookdown** and **blogdown**, also extend the YAML used to make documents. One of the main ways that other packages introduce YAML is through new output functions. [**xaringan**](https://yihui.org/rmarkdown/xaringan.html), for instance, doesn't use custom YAML outside of its output function, so **ymlthis** supports it out-of-box. Passing `xaringan::moon_reader()` to `yml_output()` will write the YAML for you.

```{r}
yml() %>% 
  yml_title("Presentation Ninja") %>% 
  yml_subtitle("with xaringan") %>% 
  yml_output(
    xaringan::moon_reader(
      lib_dir = "libs",
      nature = list(
        highlightStyle = "github",
        highlightLines = TRUE,
        countIncrementalSlides = FALSE
      )
    )
  )
```


**ymlthis** can process any output function. Other packages also add additional YAML; **ymlthis** supports six **R Markdown** packages: **bookdown**, **blogdown**, **pkgdown**, **pagedown**, **rticles**, and **distill**. **ymlthis** also supports YAML for writing scheduled emails with RStudio Connect. You can find functions supporting these packages with the patterns `yml_packagename_*()` and `packagename_*()` (`rsconnect`, in the case of RStudio Connect functions). Functions that start with `yml_packagename_*()` document YAML fields and return `yml` objects, while functions that start with `packagename_*()` are helper functions. There are also a few template functions. `pkgdown_template()`, for instance, will assemble a full template for `_pkgdown.yml` and return it as a `yml` object, and `blogdown_template()` will return YAML templates matching your Hugo theme.

|  package|  output function | top-level YAML |
|--:|--:|--:|
| bookdown |  `r check()` |  `r check()` |
| blogdown |  `r check()` |  `r check()` |
| pkgdown |  `r check()` |  `r check()` |
| pagedown |  `r check()` | `r check()` |
| rticles |  `r check()` |  `r check()` |
| distill |  `r check()` |  `r check()` |
| learnr |  `r check()` |  `r cross()`|
| xaringan |  `r check()` |  `r cross()`|
| revealjs |  `r check()` |  `r cross()`|
| flexdashboard |  `r check()` |  `r cross()`|

Table: Sources of YAML in R Markdown Extension

# R Markdown workflows

**ymlthis** prints YAML cleanly to the console such that you could copy and paste it into an **R Markdown** document. However, **ymlthis** also provides a number of other workflows. 

### YAML add-in

The easiest way is to use the Shiny add-in included with **ymlthis**; the add-in supports the most commonly used R Markdown options, citations, LaTeX options, and parameterized reports. You can then export the YAML to an R Markdown file, YAML file, or have it placed on your clipboard.

For more flexibility or to use R Markdown extension packages, you'll have to write code, as we've been doing in this vignette. Your main options are to write the YAML to a file or to place it on your clipboard.

### Writing to files

`use_rmarkdown()`, `use_yml_file()`, and friends will take a `yml` object and write to a file for you. Passing `yml` objects to `use_rmarkdown()` is often the simplest approach: it will translate the `yml` object into YAML and open a new R Markdown file for you with the metadata already written.

**ymlthis** also supports YAML files. For instance, using `pkgdown_template() %>% use_pkgdown_yml()` will write the YAML for your **pkgdown** site to `_pkgdown.yml` based on your package directory. **ymlthis** also has some helper functions for working with Pandoc templates and highlighting themes.

As an example, let's set up the navbar YAML for an **R Markdown** website and then pass it to `use_navbar_yml()`.

```{r}
navbar_yaml <- yml_empty() %>%
  yml_site_opts(
    name = "my-website",
    output_dir =  "_site",
    include = "demo.R",
    exclude = c("docs.txt", "*.csv")
  ) %>%
  yml_navbar(
    title = "My Website",
    left = list(
      navbar_page("Home", href = "index.html"),
      navbar_page(navbar_separator(), href = "about.html")
    )
  ) %>%
  yml_output(html_document(toc = TRUE, highlight = "textmate"))

# save to temporary directory since this is not interactive
path <- tempfile()
fs::dir_create(path)

use_navbar_yml(navbar_yaml, path = path)
```

In addition to writing to files, you can save YAML to your `.Rprofile` using `options(ymlthis.defaults = "{YAML}")`. `yml()` will return the stored YAML by default. If you pass a `yml` object to `use_yml_defaults()`, the code to do this will be placed on your clipboard, which you should paste into your `.Rprofile`. Open that file with `usethis::edit_r_profile()`. You can also set a default for body text for `use_rmarkdown()` by setting the `ymlthis.rmd_body()` option, e.g. `options(ymlthis.rmd_body = "{your text}")` (or take advantage of `use_rmd_defaults()`). Together with specifying default YAML, `use_rmarkdown()` also serves as an ad-hoc way to make R Markdown templates. 

```{r}
old <- options(
  ymlthis.default_yml = "author: Malcolm Barrett
date: '`r format(Sys.Date())`'
output: bookdown::pdf_document2",
  ymlthis.rmd_body = c(
    "",
    ymlthis::setup_chunk(),
    "",
    ymlthis::code_chunk(
      library(ymlthis)
    )
  )
)

#  use temporary path set above
use_rmarkdown(path = file.path(path, "analysis.Rmd"))

# reset previous option defaults
options(old)
```


|  function | action |
|--:|--:|
|  `use_yml_file()` |  Write `yml` to a file |
|  `use_bookdown_yml()`|  Write `yml` to `_bookdown.yml` |
|  `use_navbar_yml()` | Write `yml` to `_navbar.yml` |
|  `use_output_yml()` | Write `yml` to `_output.yml` |
|  `use_pkgdown_yml()` | Write `yml` to `_pkgdown.yml`  |
|  `use_site_yml()` | Write `yml` to `_site.yml` |

Table: ymlthis `use_*()` functions to write to `.yml` files

|  function | action |
|--:|--:|
|  `use_rmarkdown()` | Write `yml` to a `.Rmd` file  |
|  `use_index_rmd()` | Write `yml` to `Index.Rmd`  |

Table: ymlthis `use_*()` to write to `.Rmd` files

### Placing YAML on your clipboard

A final way to use **ymlthis** is to put YAML on your clipboard to paste into a file or other setting. To place rendered YAML on your clipboard, simply pass a `yml` object to `use_yml()`.

|  function | action |
|--:|--:|
|  `use_yml()` | Place `yml` on your clipboard  |
|  `use_yml_defaults()` | Place code on your clipboard to save `yml` to your default options |
|  `use_pandoc_highlight_style()` |  Write pandoc theme templates to a `.theme` file |
|  `use_pandoc_template()` | Write pandoc templates to a file  |

Table: Additional **ymlthis** `use_*()` functions

# Working with yml objects 

Under the hood, `yml` objects are lists of types that match the corresponding YAML and are only converted to YAML when printing or writing to files. Because `yml` objects are just lists, you can work with them as such. **ymlthis** also includes several **purrr**-like functions for working with `yml` objects. Let's define a `yml` object that has a fairly comprehensive set of options:

```{r}
x <- 
  yml() %>%
  yml_author(
    c("Yihui Xie", "Hadley Wickham"),
    affiliation = "RStudio"
  ) %>%
  yml_date("07/04/2019") %>%
  yml_title("Reproducible Research in R") %>% 
  yml_category(c("r", "reprodicibility")) %>% 
  yml_output(
    pdf_document(
      keep_tex = TRUE,
      includes = includes2(after_body = "footer.tex")
    ),
    html_document()
  ) %>%
  yml_latex_opts(biblio_style = "apalike")
```

The resulting YAML of `x` is:

```{r echo=FALSE}
x %>% ymlthis::asis_yaml_output()
```

We can use `yml_discard()` to remove the `category` option:

```{r}
x %>% 
  yml_discard("category")
```

We can use **purrr**-style lambdas to express what to discard. How about any YAML fields with a length greater than one?

```{r}
x %>% 
  yml_discard(~ length(.x) > 1)
```

The `yml_pluck()` function is useful for selectively acquiring a nested portion of the YAML:

```{r}
x %>% 
  yml_pluck("output", "pdf_document")
```

```{r, include=FALSE}
options(oldoption)
```

