Skip to content

Quarto export fixes, success criteria in feedback, widget display polish; v0.2.0 - #240

Merged
mcmullarkey merged 28 commits into
mainfrom
fix/export-quarto-book-ready
Sep 13, 2026
Merged

mcmullarkey merged 28 commits into
mainfrom
fix/export-quarto-book-ready

Conversation

@mcmullarkey

Copy link
Copy Markdown
Owner

Summary

Makes blendtutor export-quarto output render and grade correctly in real Quarto projects, fixes the widget display in books, and bumps the workspace and Quarto extension to 0.2.0.

Export (ADR-0019)

  • gotchas export as a ::: {.gotchas} div and packages as a packages="a,b" attribute (the filter already parsed both). Package names with quotes, commas, or whitespace are rejected at Lesson::parse.
  • --document prints a standalone page (title, blendtutor filter, coi: true for R); --key-page prints an API key page. clap enforces exactly one of <lesson> / --key-page.
  • A lesson with no checks, solution, or hints warns on stderr; stdout is unchanged.
  • blendtutor new lesson templates show the optional fields commented out.

Success criteria reach the grader (ADR-0020)

  • exercise.success_criteria was read by nothing. build_prompt (Rust) and both browser buildPrompt copies now add a neutralized Success criteria: section between the task and the fenced submission when present; the prompt is byte-identical otherwise.
  • SiteLesson and the Quarto filter payload carry success_criteria (10 keys), authored as ::: {.success-criteria}.

Quarto widget display (ADR-0021)

  • The prompt survives the runtime replacing the static fallback.
  • The status badge and output box stay hidden until a run.
  • The inline key form labels its input ("Fireworks API key", fw_... placeholder) and says the key is stored only in the browser.
  • New quarto-theme.css sets the color tokens from body.quarto-light / body.quarto-dark, so a light book stays light on a dark-mode OS.
  • A throwing run shows its error instead of sticking on "running".

Docs

  • README and book: run quarto add from the folder with _quarto.yml, the new export shapes, learner-aid blocks.
  • Corrected the claim that R does not run in type: book projects: the deployed demo book runs R with crossOriginIsolated false (webR's slower fallback channel). test_demo_docs.sh c5 now pins the true statement.

Widget after the display fix

Test plan

  • cargo test --workspace, clippy -D warnings, fmt, RUSTDOCFLAGS="-D warnings" cargo doc
  • New scripts/tests/test_quarto_display.py (render + headless Chrome): red before, 14/14 after
  • Quarto scripts in a clean worktree: filter, bootstrap, distribution, asset deployment, UX, key page, feedback, demo docs, model alignment, asset sync
  • Exported a real LLM-graded R lesson with --document, rendered it, confirmed the 10-key payload carries its rubric
  • Checked the deployed demo book in headless Chrome: R executes without COI
  • Live Fireworks feedback call (not exercised)

The Quarto filter already parses ::: {.gotchas} divs and a packages="a,b" div attribute, but export-quarto dropped both, so exported lessons lost their pitfalls panel and failed to preload dependencies in webR/Pyodide.
Gotchas become a nested ::: {.gotchas} div and packages a comma-separated packages="..." attribute on the opening div, matching what blendtutor.lua already parses. Absent fields still emit nothing.
A packages entry containing a quote, comma, or whitespace (or an empty one) would corrupt the exported packages="a,b" div attribute and the uv run --with list. Lesson::parse now refuses it with InvalidPackageName; version specifiers like numpy>=2 stay valid. Also asserts no gotchas div is emitted when gotchas are absent.
… pages

An R lesson exported with --document opens with title, blendtutor filter and coi front matter (plus a book-mode COI warning); Python omits coi; titles are YAML-escaped. --key-page prints a full page with the .blendtutor-key mount div that matches demo-book/api-key.qmd. --key-page and a lesson path are mutually exclusive.
core::quarto_export gains ExportShape { Snippet, Document } and key_page_qmd(). --document prefixes title, blendtutor filter and (R only) coi: true plus a book-mode COI note; titles are YAML-escaped. --key-page prints a complete page with the .blendtutor-key mount div. clap enforces exactly one of <lesson> or --key-page, and --document conflicts with --key-page.
… or hints

Such an exercise renders with only Run and LLM feedback, which authors mistake for a broken widget. The warning goes to stderr so piping stdout into a .qmd stays clean; lessons with any learner aid and --key-page stay silent.
core::quarto_export::thin_lesson_warning returns a message when a lesson has no checks, solution, or hints; the CLI prints it to stderr before writing the unchanged .qmd to stdout.
solution, hints, gotchas, checks and packages were invisible to authors because the scaffold never mentioned them. Both language templates should show each one commented out, and the lesson must still validate unchanged.
Both the R and Python templates now list solution, hints and gotchas inside exercise, and checks and packages at lesson level, all commented out with working examples. A unit test uncomments them and parses the result, so the examples stay valid.
…payload

build_prompt must place a neutralized "Success criteria:" section between the task and the code fence when the lesson has criteria, and stay unchanged without them. The Quarto filter must parse a ::: {.success-criteria} div into a 10th payload key, and the browser buildPrompt must mirror the Rust layout.
The intra-doc link to the private front_matter fn broke RUSTDOCFLAGS="-D warnings" cargo doc (rustdoc::private_intra_doc_links), which scripts/check-docs.sh and the docs workflow enforce.
…d Quarto

build_prompt and both browser buildPrompt copies add a neutralized "Success criteria:" section between the task and the fenced submission when a lesson has non-blank criteria, leaving the prompt unchanged otherwise. SiteLesson and the Quarto filter payload carry success_criteria (10 keys); the filter reads it from a ::: {.success-criteria} div, which export-quarto now emits. Vendored demo-book extension copies are synced.
README and the book now say to run quarto add from the folder holding _quarto.yml, document export-quarto --document/--key-page and the thin-lesson warning, list the .solution/.hints/.gotchas/.success-criteria blocks and packages attribute, and note that COI (and so runnable R) does not work in type: book projects.
The deployed demo book executes R exercises with crossOriginIsolated false (webR falls back to its slower non-isolated channel), so clause c5 pinned a false "R does not run in book mode" claim. c5 now requires the true statement. c12 is also red: the previous docs commit pushed README past its 150-line ceiling.
The deployed demo book runs R exercises with crossOriginIsolated false: the COI service worker registers with an assets/ scope that cannot control book pages, and webR falls back to its slower non-isolated channel. README, the book guide, ADR-0019 and the --document front-matter comment claimed R does not run in type: book projects; they now say R runs there without isolation and that coi: true speeds up standalone pages. Also trims README back under its 150-line ceiling, which the previous docs commit exceeded.
…the key form, follows the page theme

Renders an R exercise without checks, serves it, and drives headless Chrome: the prompt must survive the runtime mount, the status badge and output box must not render before a run, the inline key form must label its input with an fw_ placeholder and a storage note, and a quarto-theme.css keyed on body.quarto-light/quarto-dark must mirror the shared token palettes.
…ors its CSS lookups

Token values are lowercased before comparison, body.quarto-light/quarto-dark selectors are anchored so a future -dim variant cannot match, and the :root and @media (prefers-color-scheme: dark) openers are anchored to line starts: the stylesheet header comment mentions both, so an unanchored search read the wrong block and saw an empty dark palette.
…ey form, follows the page theme

The runtime moves the prompt out of the static fallback before removing it, and creates the status badge and output box hidden until a run reveals them. The inline key form explains itself and labels its input with an fw_ placeholder. A new quarto-theme.css re-declares the color tokens on body.quarto-light/quarto-dark so a light book stays light on a dark-mode OS; shared styles.css gains [hidden]/:empty display rules, resynced to the extension. Demo-book copies synced.
… run

The prompt moved out of the static fallback had no CSS once re-classed .bt-prompt; it now gets the fallback prompt rhythm in primary color, and the display test asserts the rule applies. A runtime.run() that throws no longer leaves the badge on running with the output hidden: the error is written to the output, shown, and the run marked failed.
Workspace crates and the Quarto extension move to 0.2.0 together (the extension had stayed at 0.1.0 through the 0.1.1 CLI release). BT_DEP_VERSION and the blendtutor-<version> libs paths pinned by the Quarto script tests follow.
Headless Chrome screenshot of an exported R pseudocode lesson rendered with the branch extension: prompt visible, no idle badge or empty output, light widget on a light page. Evidence for the PR; remove before release housekeeping if not wanted on main.
The version bump replaced literal 0.1.0 strings but missed two regex-escaped blendtutor-0\.1\.0 patterns (asset href file check, COI shim src check), so the rendered demo book appeared to have no blendtutor asset hrefs.
The PR body links the screenshot at commit fdfd117, so the image stays viewable; the file does not belong on main.
@mcmullarkey
mcmullarkey merged commit 1669680 into main Sep 13, 2026
5 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant