8  Setting options with YAML

8.1 Overview

There’s a lot going on when you set a Quarto option. You need to:

  • know the name of the option and the values it can take,
  • figure out where to set the option, and
  • get the YAML syntax right for setting the option to its value.

In this chapter, you’ll learn more about setting options in Quarto so you can nail each of those steps.

You’ll start by learning more about YAML syntax. Then, you’ll see some ways things can go wrong. Finally, you’ll learn more about how to find out what options are available, and where to put them.

8.2 General YAML syntax

In this section you’ll learn the necessary YAML fundamentals to avoid syntax errors when setting options. Although the syntax applies generally to any YAML, all the examples you’ll see are valid Quarto options and values.

8.2.1 YAML Mappings

A YAML mapping is the specification of a key-value pair using the syntax key: value. Values can be simple, like a string, boolean, or number:

document.qmd
---
1title: My Document
2toc: true
3toc-depth: 2
---
1
A string
2
A boolean, true/false
3
A number

Or, values can be more complicated like another mapping. When the value of a key is another mapping, indentation is used to keep track of scope. For example, here the value of the author key is another mapping, setting name to the value Soraya Drake:

document.qmd
---
title: My document
author:
  name: Soraya Drake
---

It doesn’t matter how many spaces you indent as long as you use spaces (as opposed to tabs), and use the same number consistently. A common style convention, and the one we follow in this book and in Quarto documentation, is to use two spaces for each level of indentation. For example, the name key nested under author is indented two spaces, whereas the name key nested under affiliation, which itself is nested under author, is indented four spaces:

document.qmd
---
title: My document
author:
  name: Soraya Drake
  affiliation: 
    name: Everpine University    
    url: http://everpine.edu
---

The names you can use in Quarto, along with the types of values they take, are not specified by the YAML language, but by Quarto’s own schema.

8.2.2 YAML Sequences

A YAML sequence is a way to provide a key a set of ordered values. There are two syntaxes to specify a YAML sequence. When the values in the sequence are simple, separate them with commas inside square brackets:

document.qmd
---
theme: [cosmo, styles.scss]
---

The alternate syntax puts each value on its own line, and adds a dash prefix followed by a space:

document.qmd
---
theme: 
  - cosmo
  - styles.scss
---

This alternate syntax can also handle situations where the values are further mappings. For example, here the value of author is a sequence of length two, where each element is a mapping of name and affiliation:

document.qmd
---
title: My document
author:
  - name: Soraya Drake
    affiliation: Everpine University    
  - name: Zahir Kamarov
    affiliation: Peregrine Heights Institute
---

8.2.3 YAML Scalars

YAML uses the term scalar to talk about the simplest types of value: strings, numbers, and booleans. You saw an example of each earlier:

document.qmd
---
title: My Document  # A string
toc: true           # A boolean, `true`/`false`
toc-depth: 2        # A number
---

The only values recognized as boolean are true and false; numbers can be single integers (2), decimals (2.1), or scientific (2.1e+2), and anything else is treated as a string.

YAML comments

The hash symbol (#) indicates the start of a comment, which is ended by the end of the line.

8.2.4 Quotes

Strings don’t require quotes, but you may need them if your string contains characters that have special meaning in YAML (e.g. #, :, etc.), or is something that would otherwise be interpreted as a number or boolean:

document.qmd
---
title: "Quotes: and things that need them"  
author: "#quarto"
subtitle: "100"
---

In YAML, double-quoted strings (") allow escape characters in them, whereas single-quoted strings (') are interpreted literally:

document.qmd
---
title: "Quotes: \U0001F4E8"
subtitle: 'Quotes: \U0001F4E8'
---

Q: where does the \U go in subtitle go? YAML might be interpreting literally but Quarto/Pandoc might escape somewhere?

8.2.5 Long strings

For strings that are longer than you’d comfortably put on a single line, or need explicit line breaks, you can use what YAML calls block scalars .

There are two styles: literal and folded.

Literal block scalars are indicated by a pipe (|), and line breaks are considered significant, whereas folded block scalars are indicated by a greater than symbol (>), and line breaks are collapsed to spaces.

In both cases, start your string on a new line indented under the key:

literal.qmd
---
title: |
  A title

  spanning two lines
---
folded.qmd
---
title: >
  A title

  collapsed into one line
---
A screenshot of a title that reads 'A title' then a line break followed by 'spanning two lines'.
(a) Rendered title using literal (|) block scalar
A screenshot of a title that reads 'A title collapsed into one line' all on a single line.
(b) Rendered title using folded (>) block scalar
Figure 8.1

Depending on where the string value is used, line breaks may or may not mean anything to Quarto. For instance, when interpreted as markdown, a single line break doesn’t result in anything in the output. However, a double line break will be interpreted as a new paragraph.

8.2.6 Using default

You’ll come across examples where the value of a Quarto option is default, like when you are specifying multiple formats:

document.qmd
---
format:
  html: default
  pdf: default
---

The value default doesn’t have a special YAML meaning— it’s something Quarto adds for certain options where the value is usually another mapping, but you just want the default values for all properties.

8.3 What happens when you get it wrong?

When you render a project or document, one of the first things that happens is the options are parsed and validated. When you make a mistake in setting an option there are a few possible outcomes:

  1. You get an error message, and the error message clearly points out your mistake.

  2. You get an error message, but it’s not clear from that message what or where your mistake is.

  3. You don’t get an error message at all.

It’s hard to enumerate all the ways you can make a mistake, but we’ll give a couple of examples for each of these outcomes in the hope it helps you track down yours.

Some examples in this chapter will result in an error from quarto render—we’ve highlighted these examples with a red border (TODO: add an icon for PDF version), like this:

render_error.qmd
---
title: Bad YAML : (
---

The error messages shown in the text are current as of Quarto 1.6.

We’ve split the examples by the kind of mistake you make:

  • Using the wrong YAML syntax
  • Using the wrong name for an option
  • Using the wrong type of value for an option

8.3.1 Using the wrong YAML syntax

When your YAML can’t be parsed by Quarto you’ll get a YAMLException error. These are actually surprisingly rare, not because everyone is great at YAML, but because most YAML syntax mistakes don’t result in invalid YAML. The YAML remains valid, it just won’t be interpreted in the way you intended.

For example, if you forget the space after a colon when setting an option like code-fold:

document.qmd
---
title: "Untitled"
format:
  html:
    code-fold:true
---

Then you don’t get a YAMLException but instead a validation error:

Validation of YAML front matter failed.
(line 5, columns 5--18) Field "html" has value code-fold:true, which must instead be an object

✖ The value code-fold:true is a string.
ℹ The error happened in location format:html.
ℹ In YAML, key-value pairs in objects must be separated by a space.
ℹ Did you mean code-fold: true instead?

The YAML has been parsed, but with the missing space code-fold:true was interpreted as a string not a mapping. Quarto does a good job here suggesting what your mistake might have been and a solution.

Generally, if you get a validation error, first check your syntax carefully.

8.3.2 Specifying the wrong key

There are some instances where when you use the wrong name for an option you’ll get an error. For example, if you pluralize the lightbox option loop:

document.qmd
title: "Presentation"
format: html
lightbox: 
  loops: true 

You’ll get a YAML validation error that catches and reports the problem:

ERROR: Validation of YAML front matter failed.
ERROR: In file long-string.qmd
(line 5, columns 3--8) property name loops is invalid
4: lightbox: 
5:   loops: true 
    ~~~~~~
ℹ The error happened in location lightbox:loops.
ℹ Did you mean loop?

Options where Quarto only allows a certain set of property names are known as closed schemas, e.g., the lightbox option has a closed schema. However, not all Quarto options have closed schemas.

When the schema is open, Quarto simply accepts an unknown option name and you get no error. For example, you might use an underscore instead of a hyphen in code-fold:

document.qmd
---
title: My document
format: 
  html:
    code_fold: true
---

Even though code_fold isn’t a recognized option for html, you’ll get no error. But, you also won’t get any code folding. Why does Quarto have open schemas? There are lots of places it makes sense to let users define their own keys, for example, when you want to use the meta shortcode and define some custom keys in your metadata.

A similar problem occurs when you nest options incorrectly. For example, you might get code-fold right, but forget to nest html under format:

document.qmd
---
title: My document
html:
  code-fold: true
---

As a top-level option html isn’t something Quarto knows about, but it passes validation. The result is no error, and no folded code.

Code completion can be a useful indicator for these problems. If you aren’t getting the completion you expect, perhaps you’ve got the wrong name, or you’ve nested it under the wrong option.

8.3.3 Specifying the wrong type of value

Checking the type of value you’ve passed is something Quarto is good at, assuming your syntax is correct and you’ve got the right option name.

For example, consider trying to add a table of contents like this:

document.qmd
---
title: My document
toc: yes
---

Upon render, Quarto returns the error:

ERROR: Validation of YAML front matter failed.
ERROR: (line 3, columns 6--8) Field "toc" has value yes, which must instead be `true` or `false`

✖ The value yes is a string.
ℹ The error happened in location toc.
ℹ Quarto uses YAML 1.2, which interprets booleans strictly.
ℹ Try using true instead.

ERROR: Render failed due to invalid YAML

This is a really useful message—it tells you the YAML front matter validation failed; it tells you where the problem is, (line 3, columns 6--8) Field "toc"; and it tells you what the problem was, Quarto expected a boolean, but got a string. It even suggests a solution try using true instead.

Not all validation error messages are as illuminating. For example, consider trying to add an “Other Link” like this:

document.qmd
---
title: "Untitled"
format:
  html:
    other-links: http://quarto.org
---

The validation error returned is:

ERROR: Validation of YAML front matter failed.
ERROR: In file type-errors.qmd
(line 5, columns 18--34) Field "other-links" has value http://quarto.org, which must instead be 'false'
4:   html:
5:     other-links: http://quarto.org
                   ~~~~~~~~~~~~~~~~~
6: ---

It’s clear where the error is ((line 5, columns 18--34) Field "other-links"), and that the wrong type of value has been encountered. But it’s unclear what Quarto actually wants. It says it was expecting false, but that doesn’t help us figure out how to actually specify a link.

Obtuse messages

Quarto tries not to overwhelm you with output in an error message, but sometimes the process of shortening an error message leads to a message that isn’t very helpful.

This particular form of message that ends with which must instead be x, is a common culprit of being too brief to be helpful. Quarto will often report one value, x, often the first alphabetically, but in reality there are many values that the option could take.

For validation errors like this you should look for an example in the Guide section of Quarto. In the section “Code and Other Links” you can see an example showing Quarto was expecting an array of objects:

document.qmd
---
title: "Untitled"
format:
  html:
    other-links: 
      - text: Quarto
        href: http://quarto.org
---

8.3.4 Ways Quarto tries to help

Quarto ships with YAML intelligence which encompasses two tools you can use to help you get your YAML right: YAML completion and YAML validation.

These tools are available in RStudio, and the Quarto extension for VS Code and Positron. The code to implement them comes with the Quarto CLI, which means they’ll always represent your current version of Quarto.

8.3.4.1 YAML completion

YAML completion suggests code completions when you are editing YAML in your Quarto documents and projects. You can hit a shortcut to see suggested completions of option names, and values.

Use completion:

  • At the top-level without typing anything to remind yourself of available options.
  • When you have started typing an option name to avoid mis-spelling it. If the option doesn’t appear as a completion, check you have it nested correctly.
  • After completing the option name to get suggested values. This is particularly useful for options that take one of a few special strings.

8.3.4.2 YAML validation

YAML validation performs the same validation that occurs when you render, but provides feedback and help where and when you are editing. It is activated when you save your file.

It will warn you when:

  • a value has the incorrect type
  • a value isn’t one of the enumerated allowable values
  • the name of an option isn’t valid (but only in situations where free-form options aren’t allowed)
  • indention is inconsistent

8.4 What are the possible options?

The best place to find out what options are available is the Reference section of the Quarto documentation. These pages are automatically generated from the YAML schema defined in the source code of the Quarto CLI.

The options available depend on where the option will be applied. From smallest to largest scope these are: to a code cell, to a document format, or to a project.

Those scopes also map to where you put the option: inside the code cell, in the document header, or in _quarto.yml. However, you can generally apply options to a larger scope, by placing them in the corresponding location. For example, echo is a code cell option, but you can use it in the document header to apply to formats, or you can use it in _quarto.yml to apply to all documents in a project.

Table 8.1 matches the sections of the Reference Guide, to the other names for the same options, and where the options might be found. In the following sections, you’ll work through these scopes from largest to smallest and learn some general principles to help you put your options in the right place.

Table 8.1: The three kinds of options you can set in Quarto
Reference Guide Section Other names Where they might occur
Projects

Project options

Project metadata

_quarto.yml
Formats

Document options

Document metadata

Document header

_quarto.yml

Code Cells Execution options

Code cells, i.e. after #|

Document header

_quarto.yml

8.5 Project options

Project options are literally those listed under project in _quarto.yml, or under a project type (e.g., website, book, or manuscript) in _quarto.yml. You cannot modify them on a document or code-cell level, nor does it generally make sense to. For example, options under the website key set up global navigation, and website level metadata.

Project options aren’t the only thing you might find in _quarto.yml. You can also set document options that should apply to all documents in _quarto.yml, you’ll learn more about this next.

8.6 Document options

Document options can be tricky because they can appear in lots of different ways. For example, the toc option might appear:

  • at the top-level of a document header:

    document.qmd
    ---
    title: My document
    format: html
    toc: true
    ---
  • nested under a format in the document header:

    document.qmd
    ---
    title: My document
    format: 
      html:
        toc: true
    ---
  • or in _quarto.yml:

    _quarto.yml
    toc: true

To understand what these variations mean, and when to use them, you’ll dive into the following principles:

  • Everything is a format option
  • Top-level options are applied to all formats
  • Options in _quarto.yml apply to all documents

8.6.1 Everything is a format option

Consider the following document header:

---
title: My document
toc: true
format: html
---

From Quarto’s perspective, this is equivalent to the header:

---
format:
  html:
    title: My document
    toc: true
---

That is, the options title and toc are HTML format options. It’s convenient to be able to put things at the top-level, but internally, Quarto will move those options under each format. This is why Quarto’s reference pages are laid out by format—options are supported, or not, depending on the output format.

OK, not quite everything…

engine is an option that isn’t applied at a format level—you cannot specify different engines for different formats.

8.6.2 Top-level options are applied to all formats

Quarto assumes any options you specify at the top-level should be applied to all formats. For example, if we extend our document header to add the pdf format:

---
title: My document
toc: true
format: 
  html: default
  pdf: default
---

Quarto interprets this as:

format:
  html:
    title: My document
    toc: true
  pdf: 
    title: My document
    toc: true

This is a good example of why this behavior exists—you’ll want many options to be the same across formats, and being able to specify them at the top-level saves a lot of typing.

Option values nested under a format will override any specified at the top level. For example, you might want toc: true for most formats, but override it for revealjs:

---
title: My document
toc: true
format: 
  html: default
  pdf: default
  revealjs:
    toc: false
---

There are a couple of consequences of this behavior to be aware of:

  • Options are silently ignored by formats that don’t support them. While this is true regardless of where you set the option, it can be harder to remember when you set options at the top-level. For example, you can set cold-fold: true at the top-level, and it will work great for format: html, but it isn’t supported by format: pdf.

  • YAML completion will suggest options at the top-level that are supported by at least one format, but that might not be the format you targeting. For example, the completion fig-pos is suggested at the top-level, but it only applies to format: pdf.

Both are reminders that understanding whether an option is supported by a format is up to you, and the best way to check is on the Quarto reference pages for the formats you are targeting.

8.6.3 Options in _quarto.yml apply to all documents

You can move any options you’ve set in the document header to _quarto.yml and they’ll apply to all documents in your project.

For example, if you want all documents in the project to have a table of contents you could include toc: true in your _quarto.yml file:

_quarto.yml
toc: true
engine is the exception again

You can’t set engine at the project level by putting it in _quarto.yml.

Options specified in _quarto.yml follow the same principles as those in the document header. By specifying toc: true at the top-level it will apply to all formats. Alternatively, you could specify it for a specific format, e.g. pdf, by nesting it under the format:

_quarto.yml
format: 
  pdf:
    toc: true

As discussed in Section 5.4.2 you can override any options in _quarto.yml at a document-level by setting them in the document header. However, if you specify any formats via format in a document header, only those specified will be rendered, regardless of which formats are specified in _quarto.yml. This gets a little tricky, so let’s look at a couple of examples. Consider Snippet 8.1: a _quarto.yml that sets one top-level option, toc, for all formats, an html option code-fold, and specifies default options for the pdf format.

Snippet 8.1: An example of project level options
_quarto.yml
toc: true
format: 
  html:
    code-fold: true
  pdf: default

For any document in the project, that would be equivalent to setting the following in the document header:

---
format:
  html:
    toc: true
    code-fold: true
  pdf:
    toc: true
---

The result of quarto render would be an HTML document (with a table of contents and using code fold), and a PDF document (with a table of contents).

When a document sets a format via format either with no options (Snippet 8.2 (a)) or as the result of setting an option nested under the format (Snippet 8.2 (b)), only the options for that format are merged from _quarto.yml (Snippet 8.3 (a) and Snippet 8.3 (b) respectively). The result of quarto render on Snippet 8.2 (a) and Snippet 8.2 (b) is only an HTML document.

Snippet 8.2: A document that sets a format in the document header
(a) format: html set with no other options.
---
format: html
---
(b) format: html set with additional options.
---
format: 
  html:
    toc: false
---
Snippet 8.3: The equivalent header for the files in Snippet 8.2 when merged with the settings in _quarto.yml.
(a)
---
format: 
  html:
    toc: true
    code-fold: true
---
(b)
---
format: 
  html:
    toc: false
    code-fold: true
---

If you want to specify some format specific options in a document, but maintain the full list of target formats from _quarto.yml, specify all formats in the document header. For example, to override some HTML options, but use the PDF options from _quarto.yml, add pdf: default to the list of formats:

---
format: 
  html:
    toc: false
  pdf: default
---

8.6.4 _metadata.yml

There is one additional place you can put document options: in a _metadata.yml file. Options placed in _metadata.yml will apply to all documents in the same directory as the _metadata.yml.

Only for document options (and execution options if they have a document equivalent), not project options.

8.6.5 Command line metadata

Command line metadata overrides metadata set in files:

Terminal
quarto render document.qmd -M toc:false

8.7 Execution options

We use the term execution options to describe options you can set in code cells. The set of options available depends on your execution engine: knitr, jupyter or ojs.

You can generally split execution options into two types:

  • information that is unique to a code cell like identifiers (label, lst-label), captions (fig-cap, tbl-cap, lst-cap, fig-subcap, tbl-subcap, fig-scap) or other annotation (fig-alt, fig-link).

  • settings that could conceivably apply to many code cells that control things like: if the code is executed (eval), or how code and results appear in the output(echo, output, warning, error), where output appears (column, panel, output-location), or how code is presented (code-fold, code-overflow, code-line-numbers).

For options in the later category, just like document options, you can increase their scope by moving them: to the document header to apply to all code cells in the document; or to _quarto.yml to apply to all code cells in the project.

8.7.1 Execution options set in code cells

Execution options are set in code cells using YAML syntax after a special comment:

```{r}
#| echo: false

```

Execution options need to be specified before any code, and are prefaced by the native comment character for the code cell language (# for r, python and julia), followed by a pipe (|), and a space.

You can use the same YAML syntax as in the document header, but for multiline statements, remember to preface each line with the cell option comment. For example, to use a literal block string:

```{r}
#| fig-cap: |
#|   Here's a long caption
#|   spread over two lines

plot(1:10)
```

8.7.2 Execution options set in the document header

As reasonable working model, assume you can move an execution option from a code cell to the document header and it will apply to all code cells in the document. For example, you could move echo: false out of a code cell and into the document header:

document.qmd
---
title: My document
echo: false
---

You can override the document level setting by setting the option in a code cell:

```{r}
#| echo: true

```

When you move an option in this way it behaves just like a document option:

  1. To figure out if an option is supported at the document level look in the reference guide for your target formats.

  2. If you nest an execution option under a format, it will only apply to that format.

So, while assuming you can move an execution option to the document header is a good working model, the definitive way to check is to see if it is a document option for your target formats.

There are a couple of special cases it is worth pointing out.

8.7.3 fig-width and fig-height

For the jupyter engine, fig-width and fig-height are document options only—you cannot set them at the cell level. If you need cell level control of the size of a figure, you’ll need to set it in the code that creates the figure.

8.7.4 Knitr specific options

There are a number of execution options that are specific to the knitr engine, that don’t have document option equivalents. Some common ones include message, collapse and prompt.

You can set these for all code cells using the knitr: chunk_opts option. For example, to suppress all messages:

---
title: "Untitled"
format: html
knitr:
  opts_chunk:
    message: false
---

8.7.5 Execution options set in _quarto.yml

When an execution option is also a document option, you can move it to _quarto.yml to apply to all code cells in a project.

For example, to omit the code “echo” all code cells, and all formats, in a project you could set echo at the top-level of _quarto.yml:

_quarto.yml
echo: false

You can then override this at the document or cell level as usual.