Reference

Configuration options, chunk markup syntax, and CSS theme variables for the plotcat extension.

Document Setup

Install Quarto Live and PlotCat in the project:

quarto add r-wasm/quarto-live
quarto add VisruthSK/PlotCat

Use Quarto Live’s HTML format and enable PlotCat:

format: live-html

filters:
  - plotcat

R pages must declare the svglite package under format.live-html.webr.packages. List every non-base R or Python package used by target or starter code. PlotCat does not infer or install runtime packages; configure them through Quarto Live.

format:
  live-html:
    webr:
      packages:
        - svglite
        - ggplot2
    pyodide:
      packages:
        - matplotlib

Exercise Markup

Write the target plot as the first chunk inside a .plotcat Div. Set #| eval: false so Quarto leaves it for the browser runtime.

::: {.plotcat}
```{r}
#| eval: false
tinyplot::tinyplot(
  dist ~ speed,
  data = cars,
  main = "Stopping distance by speed",
  xlab = "Speed",
  ylab = "Stopping distance"
)
```
:::

Add a second chunk for starter code. Set #| eval: false on the starter chunk.

::: {.plotcat}
```{r}
#| eval: false
tinyplot::tinyplot(
  dist ~ speed,
  data = cars,
  main = "Stopping distance by speed",
  xlab = "Speed",
  ylab = "Stopping distance"
)
```

```{r}
#| eval: false
tinyplot::tinyplot(
  dist ~ speed,
  data = cars
)
```
:::

Markup Rules

  • Both chunks need #| eval: false. PlotCat executes code in the browser, not during document rendering.
  • The first chunk becomes the browser-rendered target. Its source is obfuscated in the HTML. The obfuscation discourages casual inspection but is not a security boundary.
  • The second chunk populates the student code editor. Omit it for a blank editor.
  • Both chunks in an exercise must use the same language. Use {r} or {webr} for R, and {python} or {pyodide} for Python. PlotCat normalizes the student editor to Quarto Live’s native webr or pyodide cell.
  • Assign custom exercise IDs on the container div: ::: {.plotcat #scatter-exercise}. Auto-generated IDs are exercise-1, exercise-2, etc.
  • Extra classes on the .plotcat Div are forwarded to the widget container for scoped styling.

Comparison Modes

SVG plots support three comparison modes. Plotly charts use side-by-side comparison; overlay and wipe are unavailable.

Mode Behavior
Side by side (default) Target and student plots rendered in a two-column grid. Stacks to single column below 48rem.
Overlay Student plot rendered on top of the target at 50% opacity.
Wipe A draggable vertical slider reveals the target on the left and the student plot on the right. Keyboard: Arrow keys, Home, End.

Scoring & Comparison

PlotCat compares SVG plots using feature weights and Plotly figures using four weighted categories.

SVG Weights

Set per-exercise weight overrides as Div attributes:

::: {.plotcat id="scatter"
    svg-geometry="0.4"
    svg-text="0.4"}

Set document-wide defaults under plotcat.weights.svg in YAML frontmatter:

plotcat:
  weights:
    svg:
      geometry: 0.5
      text: 0.25
Attribute Default Controls
svg-geometry 0.6 Element positions (bag overlap of coarse geometry, coordinates rounded to ~0.1% relative precision)
svg-text 0.15 Text content match (bag overlap of visible <text> strings)
svg-style 0.1 Fill, stroke, opacity attributes on geometry elements
svg-frame 0.15 Aspect ratio from viewBox or explicit dimensions (pass/fail, not proportional)

Plotly figures

PlotCat compares the target and student figure JSON, rather than the rendered pixels or source code. It reads four top-level fields:

Field What PlotCat can compare
data Trace type and order, coordinates, customdata, hover text, marker and line properties, and other serialized trace settings
layout Titles, axes, ranges, legends, annotations, shapes, margins, and other serialized layout settings
frames Names, data, and layout stored in animation frames
config Configuration values included by the browser runtime

PlotCat grades each property present in the target. Set a title, color, range, hover template, or similar property in the target code when it should affect the score. Plotly defaults that do not appear in the target JSON are not graded.

Weight Default Covers
plotly-trace 0.3 Trace count and type
plotly-data 0.4 All non-style trace data, including coordinates, names, hover text, and customdata
plotly-style 0.2 Trace styling, including marker, line, fill, and opacity settings
plotly-layout 0.1 Layout, animation frames, and Plotly configuration

Arrays are positional. Missing, reordered, or extra traces, points, annotations, and shapes reduce the score. Extra properties inside a student object are ignored, so students may add settings that the target does not require.

PlotCat ignores generated uid values and keys that begin with _. It allows small floating-point differences. In text properties, <b> and <strong> are equivalent, as are <i> and <em> and common forms of <br>.

Functions, callbacks, and settings omitted from the serialized figure cannot be compared. Plotly exercises use side-by-side mode because overlay and wipe are unavailable for Plotly charts.

Dimensions

Override plot dimensions per exercise. Default is 7 inches wide by 5 inches tall for both R and Python.

::: {.plotcat id="tall-plot" plotcat-width="4" plotcat-height="6"}

Set document-wide defaults under plotcat.dimensions in YAML frontmatter.

plotcat:
  dimensions:
    width: 8
    height: 6

Heading

Override the heading text per exercise. Defaults to “Recreate this plot”.

::: {.plotcat id="labeled" plotcat-heading="Reproduce the graphic"}

Set the heading in YAML frontmatter for a document-wide default.

plotcat:
  heading: "Reproduce the graphic"

CSS Variables

PlotCat exposes CSS custom properties on .plotcat containers. Override these variables globally in your stylesheet or locally on specific containers.

Variable Default Description
--plotcat-border color-mix(in srgb, var(--bs-body-color, #212529) 20%, var(--bs-body-bg, #ffffff)) Border color for the exercise card and internal dividers
--plotcat-accent var(--bs-primary, #0d6efd) Brand color for buttons, focus highlights, score badges, active mode toggles, and the wipe handle
--plotcat-accent-rgb var(--bs-primary-rgb, 13, 110, 253) Space-separated RGB values used for focus ring and badge background opacity channels
--plotcat-bg var(--bs-body-bg, #ffffff) Card and plot container background
--plotcat-nested-bg color-mix(in srgb, var(--bs-body-color, #212529) 6%, var(--bs-body-bg, #ffffff)) Surface color for the code editor and comparison control bar
--plotcat-shadow-color rgb(var(--bs-emphasis-color-rgb, 0, 0, 0)) Tint for card drop shadows and handle depth

Bootstrap Variable Integration

PlotCat inherits global colors from Quarto Bootstrap themes.

  • --bs-body-color: Primary text color for labels, status messages, and editor code.
  • --bs-body-bg: Baseline for card and plot surfaces.
  • --bs-primary: Mapped to --plotcat-accent.
  • --bs-primary-rgb: Mapped to --plotcat-accent-rgb.
  • --bs-font-monospace: Font stack for the code editor.
  • --bs-body-font-family: Font stack for headers, labels, and buttons.
  • --bs-secondary-color: Color for muted comparison labels and idle status text.
  • --bs-danger: Color for execution error messages.

Custom Styling Examples

Theme Accent Override

.plotcat.accent-green {
  --plotcat-accent: #059669;
  --plotcat-accent-rgb: 5, 150, 105;
}
Recreate this plot
Loading plot…
Compare

Scoped Container Styling

Custom card

.plotcat.custom-card {
  --plotcat-bg: #fffbeb;
  --plotcat-border: #f59e0b;
  --plotcat-accent: #d97706;
  --plotcat-accent-rgb: 217, 119, 6;
}
Recreate this plot
Loading plot…
Compare