strawman attempt at a static-first runestone multiplechoice interactive - #3163
Draft
StevenClontz wants to merge 2 commits into
Draft
strawman attempt at a static-first runestone multiplechoice interactive#3163StevenClontz wants to merge 2 commits into
StevenClontz wants to merge 2 commits into
Conversation
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
WIP draft PR based upon discussions with @oscarlevin in mathtech discord.
Following is the LLM summary of this proposal. I will review and update before marking as ready to review by others. A known deficiency as of this edit: this only touches exercises with choices, but there are several other semantically-described
<exercise/>s that should have improved print-ready HTML for use in worksheet/handout print previews.Static-first, JS-hydrated multiple-choice exercises
Summary
A
<worksheet>is meant to be printed, but a multiple-choice<exercise>(one with a
<choices>block) was rendered straight to a Runestone-JS-onlyskeleton — a bare
<ul data-component="multiplechoice">of answer/feedback<li>s that only became a real question once Runestone's JS enhanced it atruntime. Printing a worksheet goes through a client-side-only "print
preview" pass that swaps stylesheets and reflows content, but never touches
the DOM inside an exercise, and there's no XSLT-time "print mode" to branch
on, since screen and print share one DOM. The result: a printed worksheet
either showed nothing where the question belonged, or leaked the raw,
unstyled skeleton.
This PR reworks multiple-choice rendering, site-wide, into a static-first,
progressively-enhanced pattern:
list of choices — annotated with just enough data (
data-correct, a.choice-feedbackblock) to rebuild the interactive widget later.data-componentskeleton Runestone expects, and explicitly hands it toRunestone via
window.runestoneComponents.renderOneComponent()— the sameentry point
knowl.jsalready uses for interactives injected after pageload, since Runestone's own automatic scan only ever sees markup that
existed when it ran.
never runs, so the plain static HTML is simply what's shown.
Worksheets get a working printed/no-JS fallback as the direct result of a
general fix, rather than a worksheet-specific special case — and every
multiple-choice exercise anywhere in a book now degrades gracefully without
JS, for free.
Before / after
Regular (interactive) view — unchanged from a reader's perspective:
Runestone's full widget, radio buttons, and "Check Me" button.
Print preview view — previously a dead or broken skeleton; now a clean,
readable, lettered list:
How it works
<ul data-component="multiplechoice">skeleton, unusable without JS<statement>+ lettered<ol>of choices, readable as-isrenderOneComponent()Files changed
xsl/pretext-runestone.xsl— the multiple-choice templates nowhand-author static HTML (statement, lettered
<ol>of choices,data-correct, a.choice-feedbackblock gated by the same$b-has-solutionswitch used everywhere else) instead of theJS-dependent skeleton.
xsl/pretext-html.xsl— forwards the already-computed$b-has-solutionflag into the template above.js/pretext_add_on.js(+ regeneratedjs/dist/pretext-core.js) —new
hydrateMultipleChoice(), called from the existingDOMContentLoadedhandler whenever the page isn't a print preview; rebuilds the interactive
skeleton in place and hands it to Runestone via
renderOneComponent().Testing
Verified end-to-end against a real build (Saxon + the modified core, served
locally) with a headless-browser check:
widget (
class="... runestone-component-ready"), radio buttons render,MathJax typesets, and clicking an answer + "Check Me" correctly reveals
the matching feedback ("✔️ Correct, 7 is prime.").
?printpreview=<id>): hydration is skipped, nodata-componentanywhere, no radio buttons — just the plain letteredlist.
broken output.
common/exercise-worksheet,exercise-divisional, etc.) correctly gate whether.choice-feedbackstarts hidden, reusing the existing mechanism rather than inventing a new
one.
Scope
Multiple-choice (
choices) only, matching the original ask. OtherRunestone interactivity types (
truefalse,parson,matching, etc.) areunchanged and out of scope for this PR.