2 Writing in Quarto
Markdown, Citations, and Manuscript Formatting
2.1 Purpose
This chapter covers writing in Quarto independently of any data or analysis. This is relevant if you want to write any part of your manuscript (e,g., the introduction, methods, or results section) directly in Quarto, rather than drafting in Word or Overleaf and manually inserting statistics afterwards.
Quarto is an implementation of literate programming (Knuth, 1984), whereby code and prose are written together in a single document. The document is then rendered to a readable output format, in this case HTML, Word, or PDF. This approach has been popularised in the R community through R Markdown (Xie et al., 2018, 2020), of which Quarto (Allaire et al., 2024) is the next-generation successor, with broader language support and improved output options.
Writing in Quarto means that your prose and your analysis live in the same document. Values reported in the text can be pulled directly from your data and models using inline R code, so they update automatically when analyses change. This eliminates a common source of error in academic writing: the manual transcription of numbers from statistical software into a word processor. For example, Nuijten et al. (2016) found that around 50% of psychology papers contained at least one statistical reporting error, many attributable to exactly this kind of manual transcription.
This chapter focuses on the writing side: Markdown syntax, document structure, citations, and cross-references. Connecting prose to data and models is covered in later chapters.
I recommend writing in the source editor (the default plain text view) rather than the visual editor. The source editor keeps the Markdown syntax visible, which helps you understand what Quarto is doing and makes it easier to debug rendering issues.
That said, the visual editor (enabled via the toolbar or editor: visual in the YAML) has its advantages:
- Formatting is applied visually, similar to Word
- Citations can be inserted via a built-in Zotero integration
- Tables can be edited with a point-and-click interface
The trade-off is that the visual editor can silently reformat your Markdown in unexpected ways, and it is easier to lose track of the underlying syntax. For beginners, the source editor builds better habits.
To set the source editor as default, add to your YAML:
editor: sourceOr toggle the button just above the top left corner of your script (Script/Visual).
2.2 Text formatting
Quarto uses Markdown for text formatting. Markdown is a lightweight plain-text syntax that is readable in its raw form and renders to formatted output. Unlike Word or Overleaf, formatting in Quarto is entirely handled by the source document: there are no toolbar buttons or style menus, only text.
The most common formatting options are:
| Markdown | Output |
|---|---|
**bold** |
bold |
*italic* |
italic |
***bold italic*** |
bold italic |
`code` |
code |
~~strikethrough~~ |
|
H~2~O |
H2O |
R^2^ |
R2 |
Markdown formatting is intentionally minimal. For most academic writing purposes (prose, headings, lists, tables, and equations) it covers everything needed without requiring knowledge of LaTeX or HTML. That being said, I still highly recommend having some LaTeX familiarity, as it’s commonly used by linguists and might be helpful with future collaborations.
2.2.1 APA 7 statistical symbols
APA 7 requires statistical symbols to be italicised in text. In Markdown, wrapping text in *...* produces italics, which renders correctly in HTML, Word, and PDF output:
| Statistic | Markdown | Output |
|---|---|---|
| Mean | *M* = 310.8 |
M = 310.8 |
| SD | *SD* = 155.9 |
SD = 155.9 |
| t-test | *t*(48) = 2.31 |
t(48) = 2.31 |
| p-value | *p* < .001 |
p < .001 |
APA 7 omits the zero before the decimal point for values that cannot exceed 1 (e.g. p = 0.031 is incorrect; p = .031 is correct). This applies to correlation coefficients, proportions, and p-values. Inline R code can be written to apply this formatting automatically — see Section 5.5 for an example.
2.3 Headers
Use ## for first-level sections within a chapter, ### for subsections. The chapter title is set in the YAML title: field:
## Methods
### Participants
#### Inclusion criteriaIn a Quarto book, avoid using # (H1) inside chapter files — it is reserved for the chapter title set in the YAML.
2.4 Lists and callouts
- unordered item
- nested item
1. ordered item
1. nested itemCallout boxes draw attention to key points, and can include a title if you specify one:
::: callout-note
## This tip has a title
A tip.
:::A tip.
::: callout-note
A note.
:::A note.
::: callout-warning
A warning.
:::A warning.
::: {.callout-important collapse="true"}
## Important: collapsing a callout
An important point. You can also collapse a callout box. This only works in HTML output.
:::An important point. You can also collapse a callout box. This only works in HTML output.
2.5 Equations
Write LaTeX math inline with $...$ or in a display block with $$...$$:
The model was specified as:
$$
y_i = \beta_0 + \beta_1 \text{Tense}_i + \beta_2 \text{Lifetime}_i + \varepsilon_i
$$ {#eq-model}This is then rendered as:
\[ y_i = \beta_0 + \beta_1 \text{Tense}_i + \beta_2 \text{Lifetime}_i + \varepsilon_i \tag{2.1}\]
Reference in prose with @eq-model → “Equation 2.1”
If you need the LaTeX code for a mathematical symbol or expression, hover over any rendered equation in an HTML document and right-click. Select Math Settings → TeX Commands to display the underlying LaTeX source. This is useful for replicating equation formatting or looking up the correct LaTeX syntax for a symbol.
2.6 Cross-references
Cross-references allow you to refer to figures, tables, sections, and equations by label rather than by number. Quarto resolves the labels to the correct numbers at render time, so adding or reordering elements never requires manually updating references in the text.
Every cross-reference label must begin with a type-specific prefix. The prefix tells Quarto what kind of element is being referenced and how to format the reference in the output:
| Type | Prefix | Reference syntax | Example output |
|---|---|---|---|
| Figure | fig- |
@fig-rt |
Figure 1 |
| Table | tbl- |
@tbl-desc |
Table 1 |
| Section | sec- |
@sec-results |
Section 3 |
| Equation | eq- |
@eq-model |
Equation 1 |
Labels are set in the chunk options for figures and tables, and in the heading syntax for sections. A label without the correct prefix will not be recognised as a cross-reference and will render as plain text.
We’ll cover tables later today, and figures in the next session.
2.6.1 Sections
Add a label to any heading using the {#sec-} syntax:
## Results {#sec-results}
## Discussion {#sec-discussion}Reference in prose:
The implications of these findings are discussed in @sec-discussion.Cross-references are one of the most practical advantages of writing in Quarto (or LaTeX) over Word. In Word, renumbering figures after adding one to the middle of a document requires updating every reference manually. In Quarto, the numbers are always correct automatically.
2.7 Numbered example sentences
Pandoc’s (@) syntax auto-numbers linguistic examples continuously across the document. Labels are optional but allow cross-referencing in prose:
(@cond-a) Example sentence 1.
(@cond-b) Example sentence 2.
Sentences (@cond-a) and (@cond-b) differed in lifetime status.- Example sentence 1.
- Example sentence 2.
Sentences (1) and (2) differed in lifetime status.
This syntax works across all output formats — HTML, Word, and PDF — making it the most portable option for linguistic examples.
2.7.1 gb4e for PDF output
For more control (sub-examples (1a, 1b), interlinear glosses, or aligned formatting) the gb4e LaTeX package is the standard choice in linguistics. Add it to your PDF YAML header:
format:
pdf:
include-in-header:
text: |
\usepackage{gb4e}
\noautomathThen use raw LaTeX blocks in your .qmd.
\begin{exe}
\ex \label{ex-good} The manager hired the assistant.
\ex \label{ex-bad} *The assistant was hired the manager.
\end{exe}- The manager hired the assistant.
- *The assistant was hired the manager.
Cross-reference in prose using standard LaTeX \ref{} inside a raw inline span:
As shown in example (\ref{ex-good}), the active form is grammatical.gb4e cross-references only resolve in PDF output and have no effect in HTML or Word. Use (@) syntax if you need cross-references to work across all formats.
2.8 Citations
Quarto handles citations through Pandoc’s citation processing system. References are stored in a BibTeX file (.bib) and formatted according to a Citation Style Language (.csl) file. This means citation formatting is automatic and consistent, and switching between citation styles (e.g. APA to Chicago) requires only changing the .csl file.
Add the following to your document YAML:
bibliography: references.bib
csl: apa.cslThe .bib file contains structured reference entries in BibTeX format. The .csl file controls how those references are formatted in the output. Both files should be placed in your project root, or referenced with a relative path.
Download apa.csl from the Zotero style repository:
download.file(
"https://www.zotero.org/styles/apa",
here::here("apa.csl")
)2.8.1 Citation syntax
Citations are inserted using @key syntax, where key is the identifier from your .bib entry:
| Syntax | Output |
|---|---|
@Bates2015 |
Bates et al. (2015) |
[@Bates2015] |
(Bates et al., 2015) |
[-@Bates2015] |
(2015) |
[@Bates2015, p. 12] |
(Bates et al., 2015, p. 12) |
[@Bates2015; @R2024] |
(Bates et al., 2015; R Core Team, 2024) |
These can be added in-text, so As described in @Bates2015... would be rendered as: As described in Bates et al. (2015)….
2.8.2 Getting BibTeX entries
BibTeX entries can be obtained from several sources:
- Zotero — export individual items or your full library as BibTeX. This is the recommended workflow for managing references across a project.
- Google Scholar — click Cite below a result, then select BibTeX to copy the entry.
- DOI — paste a DOI at
doi2bib.orgto generate a BibTeX entry automatically. - R packages —
toBibtex(citation("lme4"))generates a citable BibTeX entry for any R package. Always cite the packages you use.
2.8.3 References section
Add a references section at the end of your document. Quarto will populate it automatically with all cited works:
## References {.unnumbered}
::: {#refs}
:::The .unnumbered class prevents the References heading from receiving a section number, which is standard in APA manuscripts.
2.9 Inline reporting
Inline R code allows values computed in R to be embedded directly in prose. Rather than typing a number manually, you write a small R expression that is evaluated at render time and replaced with its result. This means reported values are always consistent with the underlying analysis, and update automatically if the data or model changes.
The syntax for inline R code is a backtick followed by r, a space, the R expression, and a closing backtick. For example:
The data were collected from ` r n_distinct(df$px)` participants. The mean total reading time was ` r round(mean(df$tt, na.rm = TRUE), 1)` ms (*SD* = ` r round(sd(df$tt, na.rm = TRUE), 1)`).This is particularly useful for results sections, where small changes to preprocessing or exclusion criteria can affect many reported values. With inline reporting, re-running the analysis and re-rendering the document is sufficient to update all reported statistics.
2.9.1 Rounding and formatting
Use round() to control decimal places. For p-values, a small helper avoids reporting exact values below a threshold:
fmt_p <- function(p) {
ifelse(p < .001,
"< .001",
paste0("= ", round(p, 3)))
}This function (fmt_p()) will print p-values smaller than .001 as p < .001, printing all other p-values to three decimal points. You can also create a function to print < .01 and < .05 when applicable (I would do this using the case_when() function). This can then be used inline (but note that you should also report the estimate, standard error, and t- or z-values):
The effect was significant (*p* ` r fmt_p(p_value)`).2.9.2 Connecting to models
You can also extract estimates directly from fitted model objects and report them inline, rather than typing them out manually. This makes your results robust to upstream changes: if you refit a model, the reported values update automatically. This is covered in depth in the model reporting chapter.
Any number that appears in your manuscript should be computed, not typed. This is the single most effective way to eliminate reporting errors in academic writing.