- Renamed the
exercise_submission
event toexercise_result
and added the following fields:id
- a randomly generated identifier that can be used to align with the associatedexercise_result
event.time_elapsed
- the time required to run the exercise (in seconds)timeout_exceeded
- indicates whether the exercise was interrupted due to an exceeded timeout. May beNA
for some platforms/evaluators if that information is not known or reported. (#337)
- If a
-code-check
chunk returns feedback for an exercise submission, the result of the exercise is no longer displayed for a correct answer (only the feedback is displayed). If both the result and feedback should be displayed, all checking should be performed in a-check
chunk (i.e., don't provide a-code-check
chunk). (#403) random_praise()
no longer includes the phrase Correct!. Instead, it returns a random praising statement. (#463, #453)
- Introduced "setup chunk chaining", which allows a setup chunk to depend on another setup chunk and so on, forming a chain of setup code that can be used for exercises via
exercise.setup
. Runrun_tutorial("setup-chunks", "learnr")
for a demo. (#390) - Introduced an experimental function
external_evaluator()
which can be used to define an exercise evaluator that runs on a remote server and is invoked via HTTP. This allows all exercise execution to be performed outside of the Shiny process hosting the learnr document. (#345, #354) - For the "forked" evaluator (the default used on Linux), add a limit to the number of forked exercises that learnr will execute in parallel. Previously, this was uncapped, which could cause a learnr process to run out of memory when an influx of traffic arrived. The default limit is 3, but it can be configured using the
tutorial.max.forked.procs
option or theTUTORIAL_MAX_FORKED_PROCS
environment variable. (#353) - Added a new
tutorial_options()
, namelyexercise.error.checker
, for customizing feedback when exercise submission code produces an evaluation error. This option accepts a function with the same arguments asexercise.checker
. Usegradethis::grade_learnr_error()
for a sensible default for this option. (#403) - Added an event handler system, with the functions
event_register_handler()
andone_time()
. There is also a new event"section_viewed"
, which is triggered when a new section becomes visible. (#398) - Previously, when a question submission was reset, it would be recorded as a
"question_submission"
event with the valuereset=TRUE
. Now it a separate event,"reset_question_submission"
. (#398) - Added a new
polyglot
tutorial to learnr. This tutorial displays mixing R, python, and sql exercises. Seerun_tutorial("polyglot", "learnr")
for a an example. (#397) - Text throughout the learnr interface can be customized or localized using the new
language
argument oftutorial()
. Translations for English and French are provided and contributes will be welcomed. Read more about these features invignette("multilang", package = "learnr")
. (#456, #479) - When a "data/" directory is found in the same directory as the tutorial R Markdown document, it is now automatically made available within exercises. An alternative directory can be specified using the
tutorial.data_dir
global option. (#539) - Messages generated by R during exercises are now translated to match the tutorial language, if translations are available. (#558)
- Tutorial authors can now access the current state of the user's progress in a tutorial with
get_tutorial_state()
or get information about the current tutorial withget_tutorial_info()
. (#562) - Tutorial state is now returned by
get_tutorial_state()
in order of appearance in the tutorial. The full list of exercises and questions is included asitems
in the list returned byget_tutorial_info()
. (#570, #571) - Users are now warned if their submission contains blanks they are expected to fill in. The default blank pattern is three or more underscores, e.g.
____
. The pattern for blanks can be set with theexercise.blanks
chunk or tutorial option. (#547)
- Added an
exercise_submitted
event which is fired before evaluating an exercise. This event can be associated with anexercise_result
event using the randomly generatedid
included in the data of both events. (#337) - Added a
restore
flag onexercise_submitted
events which isTRUE
if the exercise is being restored from a previous execution, orFALSE
if the exercise is being run interactively. - Add
label
field to theexercise_hint
event to identify for which exercise the user requested a hint. (#377) - Added
include=FALSE
to setup chunks to prevent exercises from printing out messages or potential code output for those setup chunks. (#390) - Added error handling when user specifies a non-existent label for
exercise.setup
option with an error message. (#390) - We no longer forward the checker code to browser (in html), but instead cache it. (#390)
- We no longer display an invisible exercise result warning automatically. Instead, authors must set the exercise chunk option
exercise.warn_invisible = TRUE
to display an invisible result warning message. (#373) exercise.cap
now accepts HTML input. If noexercise.cap
is provided, an icon of the exercise engine will be displayed. If no icon is known, theexercise.cap
will default to the combination of the exercise engine and" code"
. (#397, #429)engine
is now passed to theexercise.checker
to help distinguish what language is being checked in the exercise. (#397)- Hitting the
TAB
key in an exercise has always opened the auto-completion drop down. Now, hitting theTAB
key will also complete the currently selected code completion. (#428) question_text()
gainsrows
andcols
parameters. If either is provided, a multi-linetextAreaInput()
is used for the text input. (#460, #455)- Feedback messages can now be an htmltools tag or tagList, or a character message (#458)
- Added an option to reveal [default] (or hide) the solution to an exercise. Set
exercise.reveal_solution
in the chunk options of a*-solution
chunk to choose whether or not the solution is revealed to the user. The option can also be set globally withtutorial_options()
. In a future version of learnr, the default will be changed to hide solutions. (#402) - Added shortcuts for pipe (
Command/Control+Shift+M
) and assignment (Alt+-
) operators in exercise code boxes. (#472) - Added Spanish language support (@yabellini #483, #546)
- Added Portuguese language support (@beatrizmilz #488, #551)
- Added Basque language support (@mikelmadina #489)
- Added Turkish language support (@hyigit2, @coatless #493, #554)
- Added option for quickly restoring a tutorial without re-evaluating the last stored exercise submission. This feature is enabled by setting the global option
tutorial.quick_restore = TRUE
or the environment variableTUTORIAL_QUICK_RESTORE=1
(thanks @mstackhouse, #509). - Clicking "Run Code" or using the keyboard shortcut (Cmd/Ctrl + Enter) now runs the selected code only, if any code is selected (#512).
exercise_result()
no longer combines the code output and feedback; this now happens just before presenting the exercise result to the user (#522).- Correct/incorrect question markers are now configurable via CSS. You can change or style these markers using the
.tutorial-question .question-final .correct::before
and.tutorial-qusetion .question-final .incorrect::before
selectors. A new helper function,finalize_question()
, can be used to apply the.question-final
class to custom learnr questions. (#531) options()
and environment variables are now reset after rendering exercises so changes made by user input or checking code cannot affect other exercises. (#542)- Exercise checking is now conducted in the same temporary directory where exercises are evaluated. (#544)
- User submissions for R code exercises are now checked for parsing errors prior to any other checks. If the submitted code is unparsable, a friendly error feedback message is returned and no further evaluation or checking is performed. (#547)
- Support the updated Bootstrap 4+ popover
dispose
method name, previouslydestroy
. (#560) - Properly enforce time limits and measure exercise execution times that exceed 60 seconds (#366, #368)
- Fixed unexpected behavior for
question_is_correct.learnr_text()
wheretrim = FALSE
. Comparisons will now happen with the original input value, not theHTML()
formatted answer value. (#376) - Fixed exercise progress spinner being prematurely cleared. (#384)
- Updated
run_tutorial()
to render tutorials in a temp directory if the R user does not have write permissions. (#347) - An informative error is now thrown when an exercise chunk's body contains nothing, which lets the tutorial author know that something (e.g., empty line(s)) must be present in the chunk body for it to be rendered as an exercise. (#410) (#172)
- When
exercise.completion=TRUE
, completion is no longer performed inside of quotes. This (intentionally) prevents the student from being able to list files on the R server (#401). - Fail gracefully when unable to open an indexedDB store (e.g. in cross-origin iframes in Safari). (#417).
- When a quiz's question or answer text are not characters, e.g. HTML,
htmltools
tags, numeric, etc., they are now cast to characters for the displayed answer text and the quiz's default loading text (#450). - The
envir_prep
environment used in exercise checking now captures the result of both global and exercise-specific setup code, representing the environment in which the user code will be evaluated as described in the documentation. We also ensure thatenvir_result
(the environment containing the result of evaluating global, setup and user code) is a sibling ofenvir_prep
. (#480) - HTML dependencies of exercises run by users now excludes dependencies created with
htmltools::tags$head()
. (thanks @andysouth, #484) - Avoid selecting the answer labeled
"FALSE"
by default inquestion_radio()
(#515). - Custom CSS files are now loaded last, after all of learnr's other web dependencies. (#574)
-
learnr
gained the functionlearnr::tutorial_package_dependencies()
, used to enumerate a tutorial's R package dependencies. Front-ends can use this to ensure a tutorial's dependencies are satisfied before attempting to run that tutorial.learnr::available_tutorials()
gained the columnpackage_dependencies
containing the required packages to run the document. (#329) -
Include vignette about publishing learnr tutorials on shinyapps.io. (#322)
-
learnr
's built-in tutorials now come with a description as part of the YAML header, with the intention of this being used in front-end software that catalogues availablelearnr
tutorials on the system. (#312) -
Add
session_start
andsession_stop
events. (#311)
-
Fixed a bug where broken exercise code created non-"length-one character vector". (#311)
-
Fixed extra parameter documentation bug for CRAN. (#323)
-
Fixed video initialization error caused by a jQuery version increase in Shiny. (#326)
-
Fixed progressive reveal bug where the next section would not be displayed unless refreshed. (#330)
-
Fixed a bug where topics would not be loaded if they contained non-ascii characters. (#330)
-
Quiz questions are implemented using shiny modules (instead of htmlwidgets). (#194)
-
Aggressively rerender prerendered tutorials in favor of a cohesive exercise environment (#169, #179, and rstudio/rmarkdown#1420)
-
Added a new function,
safe
, which evaluates code in a new, safe R environment. (#174)
-
Added the last evaluated exercise submission value,
last_value
, as an exercise checker function argument. (#228) -
Question width will expand to the container width. (#222)
-
Available tutorial names will be displayed when no
name
parameter or an incorrectname
is provided torun_tutorial()
. (#234) -
The
options
parameter was added toquestion
to allow custom questions to pass along custom information. Seesortable::sortable_question
for an example. (#243) -
Missing package dependencies will ask to be installed at tutorial run time. (@isteves, #253)
-
When questions are tried again, the existing answer will remain, not forcing the user to restart from scratch. (#270)
-
A version number has been added to
question_submission
events. This will help when using custom storage methods. (#291) -
Tutorial storage on the browser is now executed directly on
indexedDB
usingidb-keyval
(droppinglocalforage
). This change prevents browser tabs from blocking each other when trying to accessindexedDB
data. (#305)
-
Fixed a spurious console warning when running exercises using Pandoc 2.0. (#154)
-
Added a fail-safe to try-catch bad student code that would crash the tutorial. (@adamblake, #229)
-
Replaced references to
checkthat
andgrader
in docs with gradethis (#269) -
Removed a warning created by pandoc when evaluating exercises where pandoc was wanting a title or pagetitle. #303
-
Fixed #136 by displaying full HTML messages (rather than just the text) if provided by the
incorrect
or thecorrect
args toquestion()
. (#146) -
Improved documentation for deploying
learnr
tutorials in Shiny Server. (#142) -
Fixed a highlight.js issue from rmarkdown 1.8. (#133)
-
Fixed an false positive in the diagnostics system. (#141)
- Fixed a compatibility issue, so that existing tutorials don't break when using Pandoc 2.0. (#130)
@ commit #14413cc
@ commit #eeae534
@ commit #b71c637
@ commit #55c33cf
@ commit #a853163
@ commit #3339f8a
@ commit #9cd0082
@ commit #a81a694
init commit! #e2dbb20