Static checks on a tutorial's .qmd source for the mistakes that look
fine in the file and only show up later – in the rendered page, in a
reader's browser, or when a reader's saved progress silently resets.
Each one is a rule from this package's authoring guide; this function
encodes them so a content package can enforce them in its tests, the way
tutorial.helpers::check_tutorial_defaults() did for 'learnr' tutorials.
Pair it with render_tutorials(): rendering proves the document builds,
these checks catch what a successful render does not.
Arguments
- paths
Character vector of tutorials to check: paths to
.qmdfiles, or to directories containing them, as forrender_tutorials().- skip
Character vector of check names (see "Checks") to leave out, e.g.
"minutes"for a tutorial that deliberately has no "how many minutes" question.- error
If
TRUE(the default), stop with an error listing every problem found. IfFALSE, just return them.
Value
A data frame of problems with columns path, check, and
message, invisibly. It has zero rows when every check passed.
Checks
Each check has a name, used in skip:
format– the YAML header hasformat: live-html.engine– the YAML header hasengine: knitr.ordering– if the YAML header setslearnr2: ordering:, it is a single number (see "Ordering" inavailable_tutorials()).include– the document includes the 'quarto-live' runtime partial,{{< include _extensions/r-wasm/live/_knitr.qmd >}}. Without it no{webr}cell works.gradethis– if any{webr}cell hascheck: true, the document also includes_extensions/r-wasm/live/_gradethis.qmd.student_info– an{r}chunk callslearnr2::student_info().minutes– an{r}chunk has the "how many minutes" question, i.e. alearnr2::question()withvalidate = "integer".download– an{r}chunk callslearnr2::download_answers_button().labels– every{r}and{webr}chunk has its own#| label:line, and no two chunks share a label. A question's chunk label is the key its saved answer is stored under, so a missing or duplicated label loses or merges readers' progress.echo– every{r}chunk that renders a learnr2 widget (question(),quiz(),student_info(),download_answers_button(),tutorial_options()) has#| echo: false, so the reader sees the widget, not the R code that produced it.persist– every{webr}exercise cell (one with#| exercise:that is not asetup,check,solution, orhintcell) has#| persist: true, without which the reader's code is never saved and never appears in a download.solution– every exercise that has acheck: truecell also has asolution: truecell. A.solutiondiv is not enough: the grader fails with "No solution code was found".packages– every non-base package a{webr}cell uses (vialibrary(),require(), orpkg::) is listed underwebr: packages:in the YAML header, the only place WebR learns what to install.gradethisis exempt, since the_gradethis.qmdinclude provides it.
Examples
qmd <- create_tutorial("checked", dir = tempfile(), open = FALSE)
#> Created tutorial: /tmp/RtmpGP7ebo/file1a102090f034/checked/checked.qmd
check_tutorial(qmd)
# Break the template, then see the problems instead of an error.
lines <- readLines(qmd)
writeLines(lines[!grepl("^#\\| echo: false", lines)], qmd)
problems <- check_tutorial(qmd, error = FALSE)
problems[, c("check", "message")]
#> check message
#> 1 echo line 15 (student-information-1): widget chunk needs `#| echo: false`.
#> 2 echo line 54 (a-quiz-question-1): widget chunk needs `#| echo: false`.
#> 3 echo line 67 (your-answers-1): widget chunk needs `#| echo: false`.
#> 4 echo line 77 (your-answers-2): widget chunk needs `#| echo: false`.
unlink(dirname(dirname(qmd)), recursive = TRUE)