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/PlotCatUse Quarto Live’s HTML format and enable PlotCat:
format: live-html
filters:
- plotcatR 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:
- matplotlibExercise 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 nativewebrorpyodidecell. - Assign custom exercise IDs on the container div:
::: {.plotcat #scatter-exercise}. Auto-generated IDs areexercise-1,exercise-2, etc. - Extra classes on the
.plotcatDiv 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: 6Heading
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;
}Scoped Container Styling
Custom card
.plotcat.custom-card {
--plotcat-bg: #fffbeb;
--plotcat-border: #f59e0b;
--plotcat-accent: #d97706;
--plotcat-accent-rgb: 217, 119, 6;
}