DRY Slides with ---
Never repeat yourself, let Quarto do it

Quarto Extension

The Problem

Too much content, not enough slides

When a topic spans multiple slides, you end up writing the same heading over and over:

## My Long Topic

First part of the content...

## My Long Topic

Second part of the content...

## My Long Topic

Third part of the content...

This violates the DRY principle and makes refactoring painful.

The Solution

The cascade extension

A filter that repeats the heading chain automatically when you use --- to create a new slide.

## My Long Topic

First part of the content...

---

Second part, heading repeated for you!
  • Works only for revealjs output.
  • Repeats the full heading hierarchy, not just the immediate title.

The cascade extension

This very slide was created with ---.

No heading was written in the source; it was repeated from the previous slide.

Nested headings work too

Deep dive

Content under a nested heading structure.

Nested headings work too

Still diving

Both ## Nested headings work too and ### Still diving on the slide. Only parent headings above this ### level are repeated from the previous slide.

Fine Tuning

Opting out with {.no-cascade}

A pinned subheading

A heading marked {.no-cascade} stays here but is never repeated.

Opting out with {.no-cascade}

Only ## Opting out with {.no-cascade} is repeated. The ### A pinned subheading is not, because of the {.no-cascade} class.

Limiting the depth

Level three heading

This presentation sets depth: 2, so only the top two heading levels cascade.

Level four heading

This level-four heading is below the depth limit.

Limiting the depth

Level three heading

Both ## Limiting the depth and ### Level three heading are repeated. The #### Level four heading is dropped because it sits beyond depth: 2.

Per-heading depth override

Sub-heading kept off the chain

The heading attribute cascade-depth="1" overrides the document-level depth: 2 here.

Per-heading depth override

Only ## Per-heading depth override is repeated; the ### Sub-heading kept off the chain is dropped because of the per-heading override.

Inside Blocks

Callouts split too

::: {.callout-tip title="A multi-part tip"}

First half of the tip.

---

Second half: the heading **and** the callout were repeated automatically.

:::

Callouts split too

A multi-part tip

First half of the tip.

Callouts split too

A multi-part tip

Second half: the heading and the callout were repeated automatically.

Regular divs split too

::: {.column-margin}

A side note, first part.

---

Second part, still in the margin, on a new slide.

:::

Regular divs split too

A side note, first part.

Regular divs split too

Second part, still in the margin, on a new slide.

Cross-reference does not break

(i.e., ^%a+%- ID)

::: {#tip-one .callout-tip title="A multi-part tip"}

First half of the tip.

---

Second half: the heading **and** the callout were repeated automatically.

:::

Tip 1: A multi-part tip

First half of the tip.


Second half: the heading and the callout were repeated automatically.

Before and After

Before: repetitive markdown

## Results

### Experiment A

Observations for experiment A...

## Results

### Experiment A

More observations for experiment A...

## Results

### Experiment B

Observations for experiment B...

After: DRY markdown

## Results

### Experiment A

Observations for experiment A...

---

More observations for experiment A...

---

### Experiment B

Observations for experiment B...

Fewer lines, single source of truth for headings, and zero risk of typos.