Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
51 changes: 45 additions & 6 deletions quarto/quarto-authoring/SKILL.md
Original file line number Diff line number Diff line change
@@ -1,12 +1,11 @@
---
name: quarto-authoring
description: >
Writing and authoring Quarto documents (.qmd), including code cell options,
figure and table captions, cross-references, callout blocks (notes, warnings,
tips), citations and bibliography, page layout and columns, Mermaid diagrams,
YAML metadata configuration, and Quarto extensions. Also covers converting and
migrating R Markdown (.Rmd), bookdown, blogdown, xaringan, and distill projects
to Quarto, and creating Quarto websites, books, presentations, and reports.
Writing and authoring Quarto documents (.qmd) with R (knitr) and Python (Jupyter)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Two issues with the description rewrite.

First, "R (knitr) and Python (Jupyter) engines" is not quite accurate. Knitr runs any language registered as a knitr language engine (Python, Julia, Bash, SQL, Stan, and more), and jupyter runs any registered kernel (R via IRkernel, Julia via IJulia, Bash, and more). Pinning the description to two language/engine pairs paints Quarto as narrower than it is. There are three native engines (knitr, jupyter, julia), and in 1.9 the julia engine was refactored to sit on top of the new engine-extension mechanism, so it is both a native engine and the reference implementation for third-party engine extensions. The skill is pinned to 1.9.36 (line 17), so leaving julia and engine extensions out is a dated inaccuracy. Quarto is language-agnostic anyway, so any enumeration of languages will bit-rot the next time a new kernel or engine ships. And since Quarto 1.9 ships engine extensions, the set of computing engines behind a code cell is no longer closed: in principle anything can end up there, so engines are the stable abstraction to describe in the skill.

Second, the trigger wording. "Migrating R Markdown, bookdown, ..." narrows a key trigger, because users are far more likely to say "convert my old .Rmd" than "migrate my .Rmd", and the description is the main signal the LLM uses to pick this skill. Please keep "converting and migrating".

One more thing: the rewrite shortens the keyword surface ("code cell options, figure and table captions, cross-references, callout blocks (notes, warnings, tips), citations and bibliography" becomes "code cells, figures, tables, cross-references, callouts, citations"). Shorter descriptions match less reliably on keyword-rich queries, so the longer form was closer to what I would want.

Suggested rewording that keeps the enumerative surface, restores "converting", adds the missing .ipynb trigger, and refers to engines rather than languages:

description: >
  Writing and authoring Quarto documents (.qmd) with the knitr, jupyter, and
  julia engines (and any Quarto 1.9+ engine extensions). Covers code cell
  options, figure and table captions, cross-references, callout blocks
  (notes, warnings, tips), citations and bibliography, page layout and
  columns, Mermaid diagrams, YAML metadata configuration, and Quarto
  extensions. Also covers converting and migrating R Markdown (.Rmd),
  bookdown, blogdown, xaringan, distill projects, and Jupyter notebooks
  (.ipynb) to Quarto, and creating Quarto websites, books, presentations,
  and reports.

engines. Covers code cells, figures, tables, cross-references, callouts, citations,
layout, Mermaid diagrams, YAML metadata, and extensions. Also covers migrating
R Markdown, bookdown, blogdown, xaringan, distill, and Jupyter notebooks to Quarto,
and creating websites, books, presentations, and reports.
metadata:
author: Mickaël Canouil (@mcanouil)
version: "1.2"
Expand Down Expand Up @@ -74,6 +73,7 @@ Only read the one matching the source format when the user explicitly asks to co
- xaringan slides: [references/conversion-xaringan.md](references/conversion-xaringan.md)
- distill article: [references/conversion-distill.md](references/conversion-distill.md)
- blogdown site: [references/conversion-blogdown.md](references/conversion-blogdown.md)
- Jupyter notebook (.ipynb) to Quarto: [references/conversion-jupyter.md](references/conversion-jupyter.md)

## QMD Essentials

Expand Down Expand Up @@ -124,6 +124,8 @@ Quarto uses the language's comment symbol + `|` for cell options. Options use **
- Mermaid: `%%|`
- Graphviz/DOT: `//|`

R example (knitr engine):

````markdown
```{r}
#| label: fig-example
Expand All @@ -134,6 +136,27 @@ plot(x, y)
```
````

Python example (Jupyter engine):

````markdown
```{python}
#| label: fig-example
#| echo: false
#| fig-cap: "A scatter plot example."

import matplotlib.pyplot as plt
plt.scatter(x, y)
plt.show()
```
````

Quarto auto-detects the engine from the first executable cell. To force an engine, set in YAML:

```yaml
engine: knitr # for R
engine: jupyter # for Python
```

Common execution options:

| Option | Description | Values |
Expand Down Expand Up @@ -164,6 +187,8 @@ Labels must start with a type prefix. Reference with `@`:
- Section: `sec-` prefix, e.g., `{#sec-intro}` → `@sec-intro`
- Equation: `eq-` prefix, e.g., `{#eq-model}` → `@eq-model`

R:

````markdown
```{r}
#| label: fig-plot
Expand All @@ -174,6 +199,20 @@ plot(1)
See @fig-plot for the results.
````

Python:

````markdown
```{python}
#| label: fig-plot
#| fig-cap: "A caption for the plot."
import matplotlib.pyplot as plt
plt.plot([1])
plt.show()
```

See @fig-plot for the results.
````

Details: [references/cross-references.md](references/cross-references.md)

### Callout Blocks
Expand Down
106 changes: 106 additions & 0 deletions quarto/quarto-authoring/references/code-cells.md
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,16 @@ library(ggplot2)
```
````

````markdown
```{python}
#| echo: false

# This code runs but is not shown
import pandas as pd
import matplotlib.pyplot as plt
```
````

Show fenced code block with attributes:

````markdown
Expand Down Expand Up @@ -96,6 +106,8 @@ Options for controlling figure output:

### Figure Example

R:

Comment on lines +109 to +110
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Rather than showing two examples of the same thing, I'd rather we diversify the examples to use languages in addition to R.

In other words, in this case, we're trying to show the model the set of cell options that are relevant for figures. LLMs can generalize from one example showing the code cell options; we don't need two examples that contain identical options.

That said, I do think it's helpful for there to be diversity in the examples, which also helps the model generalize. So I'd prefer if, in cases like this example, rather than adding a new identical example we were to simply rewrite some examples in other languages. We should prefer R and Python, but it'd be nice to have Julia or another language often used by Quarto authors in the examples.

````markdown
```{r}
#| label: fig-analysis
Expand All @@ -111,8 +123,26 @@ ggplot(data, aes(x, y)) +
```
````

Python:

````markdown
```{python}
#| label: fig-analysis
#| fig-cap: "Analysis results showing the relationship between variables."
#| fig-alt: "Scatter plot with trend line showing positive correlation."
#| fig-width: 10
#| fig-height: 6
#| fig-align: center

import seaborn as sns
sns.regplot(x=data["x"], y=data["y"])
```
````

### Multiple Figures

R:

````markdown
```{r}
#| label: fig-panels
Expand All @@ -127,6 +157,25 @@ hist(y)
```
````

Python:

````markdown
```{python}
#| label: fig-panels
#| fig-cap: "Multiple panel figure."
#| fig-subcap:
#| - "Distribution of X"
#| - "Distribution of Y"
#| layout-ncol: 2

import matplotlib.pyplot as plt
plt.hist(x)
plt.show()
plt.hist(y)
plt.show()
```
````

## Table Options

Options for controlling table output:
Expand All @@ -140,6 +189,8 @@ Options for controlling table output:

### Table Example

R:

````markdown
```{r}
#| label: tbl-summary
Expand All @@ -149,6 +200,29 @@ knitr::kable(summary_data)
```
````

Python (pandas — `output: asis` renders markdown table in all formats):

````markdown
```{python}
#| label: tbl-summary
#| tbl-cap: "Summary statistics by group."
#| output: asis
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

output: asis shows up seven times across this PR (here, in tables.md, and in layout.md) without a single line explaining what it does. The skill will end up learning "add output: asis when doing Python tables" as a ritual rather than understanding the underlying model.

Briefly, asis tells Quarto to pass the cell output through as raw markdown that should not be processed further. That matters because:

  • The content must already be valid markdown (pipe table, headings, prose).
  • Non-markdown content needs a raw block: ```{=html}, ```{=latex}, and so on.
  • It interacts with tbl-cap in format-specific ways. Captions on output: asis markdown tables do not behave identically to knitr's table path.

Could we add one explainer subsection in this file, under "Execution Options", that defines asis and its requirements, then reference it from the table and layout examples instead of repeating the option verbatim in every Python snippet?


print(summary_df.to_markdown(index=False))
```
````
Comment on lines +203 to +213
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This is a good example of a case where it is quite helpful to have an extra example in Python, because the additional example shows something new.


Python (pandas — plain `df` auto-displays as HTML table in HTML output):

````markdown
```{python}
#| label: tbl-summary
#| tbl-cap: "Summary statistics by group."

summary_df
```
````
Comment on lines +215 to +224
Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend removing this example, but keeping the comment about pandas data frames auto-displaying as HTML in HTML output (either above or below the asis-output example)


## Caching and Freeze

Control caching of code cell results:
Expand All @@ -161,6 +235,8 @@ Control caching of code cell results:

### Caching Example

R:

````markdown
```{r}
#| label: slow-computation
Expand All @@ -171,6 +247,18 @@ result <- slow_function(data)
```
````

Python:

````markdown
```{python}
#| label: slow-computation
#| cache: true
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Cell-level #| cache: true is a knitr feature. With the jupyter engine, caching is handled by jupyter-cache and is enabled at document level via execute: cache: true in YAML (or freeze: auto in _quarto.yml for project-level freezing). Individual Python cells can only opt out with #| cache: false. They cannot opt in.

As written this example is silently inert: it will not cache, and it will teach the skill a pattern that does nothing, which is worse than omitting Python caching entirely.

Suggest dropping the code example and replacing it with a short prose note pointing at https://quarto.org/docs/projects/code-execution.html#cache (use the .llms.md URL instead or .html).


# This expensive computation is cached
result = slow_function(data)
```
````

### Project-Level Freeze

In `_quarto.yml`:
Expand Down Expand Up @@ -240,6 +328,8 @@ plot(1:10)

Add annotations to explain code:

R:

````markdown
```{r}
#| code-annotations: hover
Expand All @@ -255,6 +345,22 @@ mtcars |> # <1>
2. Filter to cars with MPG over 20
3. Select only the columns we need

Python:

````markdown
```{python}
#| code-annotations: hover

import pandas as pd # <1>
df = pd.read_csv("data.csv") # <2>
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Minor, but the example is self-inconsistent: it reads data.csv and then uses mtcars column names (mpg, cyl). Either load the dataset under a filename that matches (mtcars.csv) or switch to a source that actually has those columns, like seaborn.load_dataset("mpg"). As-is, the annotation "Load the dataset from a CSV file" leaves the skill guessing at what is in data.csv.

result = df[df["mpg"] > 20][["mpg", "cyl"]] # <3>
```
````

1. Import pandas for data manipulation
2. Load the dataset from a CSV file
3. Filter rows and select columns of interest

Annotation styles: `hover`, `select`, `below`, `beside`.

## Filename Display
Expand Down
Loading