Reveal.js Code Annotation Fragments

Quarto Extension

Introduction

What is Codefrag?

This extension enables fragment-based navigation through code annotations in Reveal.js presentations.

  • Navigate annotations using arrow keys.
  • Annotations are treated as fragments.
  • Synchronises with line highlighting when present.

Installation

Install the extension using:

quarto add mcanouil/quarto-revealjs-codefrag@1.0.1

Basic Setup

Add to your document YAML:

format:
  revealjs:
    code-annotations: select
revealjs-plugins:
  - codefrag

Sequential Annotations

Code Annotations

Use arrow keys to step through each annotation.

library(dplyr)

mtcars |>
  filter(mpg > 20) |>
  select(mpg, cyl, hp) |>
  arrange(desc(mpg))
1
Load the dplyr package for data manipulation.
2
Start with the mtcars dataset.
3
Filter rows where mpg is greater than 20.
4
Select only the columns we need.
5
Sort by mpg in descending order.

Python Example

Annotations work with any language.

import polars as pl

df = pl.read_csv("data.csv")
df = df.filter(
    pl.col("value") > 0
)
result = df.group_by("category").agg(
    pl.col("value").mean()
)
1
Import Polars for data manipulation.
2
Read a CSV file into a DataFrame.
3
Filter rows where value is positive.
4
Group by category and compute the mean.

Line Highlighting Sync

Synced Annotations (Matching Lines)

Every highlight clone matches an annotation on the same lines, so they share a navigation step.

library(ggplot2)

ggplot(mtcars) +
  aes(x = mpg, y = wt) +
  geom_point() +
  theme_minimal()
1
Load the ggplot2 package.
2
Build a scatter plot of mpg vs wt.
3
Apply a minimal theme.

Partial Match (Unmatched Annotation)

Without a leading |, the first highlight step is the initial state. Unmatched annotations appear at the end; matched pairs still sync.

library(ggplot2)

ggplot(mtcars) +
  aes(x = mpg, y = wt) +
  geom_point() +
  theme_minimal()
1
Load the ggplot2 package.
2
Build a scatter plot of mpg vs wt.
3
Apply a minimal theme.

Subset Match (Annotation Inside Highlight Range)

An annotation whose lines are a subset of a highlight’s lines syncs with that step. Here, <2> marks only line 3 yet syncs with the highlight spanning lines 2-3.

library(dplyr)
mtcars |>
  filter(cyl == 6) |>
  summarise(mean_mpg = mean(mpg))
1
Load the dplyr package.
2
Keep only six-cylinder cars.
3
Compute the mean mileage.

Mixed Fragments

Annotations with Other Fragments

Text fragments appear first, then code annotations follow.

This paragraph fades in as the first fragment.

This paragraph fades in as the second fragment.

model <- lm(mpg ~ wt, data = mtcars)
summary(model)
plot(model, which = 1)
1
Fit a linear model predicting mpg from weight.
2
Print the model summary.
3
Plot residuals versus fitted values.

This paragraph fades in after all annotations.

Custom Fragment Indices

Use code-annotation-fragment-indices to interleave annotations with other fragments.

We need a data manipulation library before writing any pipeline code.

With the data piped in, we can start applying transformations.

The result keeps only cars that achieve more than 20 miles per gallon.

library(dplyr)
mtcars |>
  filter(mpg > 20)
1
Load dplyr for data wrangling.
2
Pipe the mtcars dataset into the next step.
3
Keep only rows where mpg exceeds 20.

Incremental List then Annotations

  • Import a data processing library.
  • Scan the file lazily for efficiency.
  • Collect the results into memory.
import polars as pl
df = pl.scan_csv("train.csv")
df.collect()
1
Import the Polars library.
2
Create a lazy frame from CSV.
3
Materialise the lazy frame into memory.

Line Highlighting

Line Highlights Only (No Annotations)

Line highlighting without annotations steps through highlights as normal fragments.

library(dplyr)

mtcars |>
  filter(mpg > 20) |>

  summarise(mean_mpg = mean(mpg))

Line Highlights with Annotations

All highlight clones match annotations on the same lines, so they sync.

library(dplyr)

mtcars |>
  filter(mpg > 20) |>

  summarise(mean_mpg = mean(mpg))
1
Load the dplyr package.
2
Build the filtering pipeline.
3
Compute the summary statistic.

Line Highlights with Custom Indices

Use code-line-fragment-indices to control which fragment index each highlight step receives.

A two-panel layout is set up to compare plots side by side.

The first panel draws a basic scatter plot of speed vs distance.

The second panel repeats the plot in red for comparison.

par(mfrow = c(1, 2))
plot(cars)
plot(cars, col = "red")
par(mfrow = c(1, 1))

Line Highlights with Custom Indices and Annotations

Combines code-line-fragment-indices with annotations.

Define the input as a numeric sequence.

Square each value to build a parabola.

x <- 1:10

y <- x^2

plot(x, y)
1
Create a sequence from 1 to 10.
2
Plot the result.

Line Highlights with Fragments Before

This script generates a simple parabola. Step through each highlighted line below.

x <- 1:10

y <- x^2

plot(x, y)
1
Create a sequence from 1 to 10.
2
Plot the result.

Plain Fragments

Fragments Without Annotations

Slides with plain fragments (no code annotations or line highlights) should print as a single page.

First point appears.

Second point appears.

Third point appears.

Configuration

Disabling the Plugin

Disable fragment navigation while keeping tooltips:

extensions:
  codefrag:
    enabled: false

Features

  1. Sequential Fragments: Annotations become navigable fragments.
  2. Line Highlight Sync: Matching annotations and highlights share a step.
  3. Partial Match: Matched pairs sync; unmatched items get their own steps.
  4. Custom Indices: Control fragment order with custom index attributes.
  5. Tooltip Patching: Tooltips reposition to avoid clipping.
  6. Bidirectional Navigation: Navigate forwards and backwards.

Thank You

Questions?

Feel free to ask any questions about the Reveal.js Code Annotation Fragments extension.