Skip to content

WeBWorK 2.21 Release Candidate#2940

Open
drgrice1 wants to merge 446 commits into
mainfrom
WeBWorK-2.21
Open

WeBWorK 2.21 Release Candidate#2940
drgrice1 wants to merge 446 commits into
mainfrom
WeBWorK-2.21

Conversation

@drgrice1

Copy link
Copy Markdown
Member

This is the release candidate for WeBWorK 2.21. Please re-target any pull requests that you want to get into the release for this branch.

drgrice1 and others added 30 commits February 1, 2026 05:56
The settings `att_to_open_children` and `counts_parent_grade` were not
being transferred from the set definition file due to incorrect casing
used.  Thanks to @hal4stvf for pointing this out.

Part of the problem here is the mix of snake case and cammel case.  The
set definition file, the problem table in the database, and the default
value from `defaults.config` use `att_to_open_children`.  However, the
`addProblemToSet` method expects the argument of `attToOpenChildren`.
We need to eliminate snake case usage altogether.  It is the most
annoying case to type (`shift _ t` takes three keystrokes but `shift t`
only takes two).  But even worse is mixing these different casing
schemes, particularly as is done in this case.

This fixes issue #2897.
The issue occurs when the `$LTIGradeMode` is "course",
`$LTIGradeOnSubmit` is 1, `$LTISendScoresAfterDate` is
"reduced_scoring_datae', and `$LTISendGradesEarlyThreshold` is
"attempted".

In this case if a user grades a test and receives a score of 0 (and all
versions of this test have a score of 0), then the `grade_gateway`
method returns the default `$bestSetData` array defined at the beginning
of the method with only two elements.  It does not have the array of
problem records.  So when the `getSetPassbackScore` method gets the
return value and assigns it to `($totalRight, $total, $problemRecords, $setVersions)`
the set versions that are returned end up assigned to the
`$problemRecords` variable.  That causes an exception when the
`setAttempted` method tries to call the `attempted` method on a set
version which does not have that method.

So just add an empty array as the third value in the default
`$bsetSetData` array.  This works in all calling scenarios.
When problem randomization is enabled and a new problem version is
opened, don't use the problem data from the previous version.

When show me another is enabled don't use the problem data from the
assigned problem.

To fix these issues force an empty problem data hash by passing `'{}'`
as the `problemData` translation option and forces the usage of the
hidden problem_data input for show me another problems.

The following example can be used to test this:

```perl
DOCUMENT();

loadMacros('PGstandard.pl', 'PGML.pl', 'scaffold.pl');

$a = random(1,  10);
$b = random(11, 20);

Scaffold::Begin(
    is_open                  => 'correct_or_first_incorrect',
    preview_can_change_state => 0
);

Section::Begin('Part 1');
BEGIN_PGML
Enter [`[$a]`]: [_]{$a}{5}
END_PGML
Section::End();

Section::Begin('Part 2');
BEGIN_PGML
Enter [`[$b]`] [_]{$b}{5}
END_PGML
Section::End();

Scaffold::End();

ENDDOCUMENT();
```

Add that problem to a set and enable both problem randomization and show
me another.  Then test the following with the develop branch.

Now login as a student user, open the problem in the set, and submit the
correct answer for the first part in the problem.  Then submit answers
enough times to need to request a new version, and then request a new
version.  Now in the new version, enter an answer and click "Preview My
Answers", and the second part will open. Since the scaffold has the
`preview_can_change_state => 0` option set, even if the "correct" answer
is entered the second part should not open when "Preview My Answers" is
clicked, but it does (and does so even an incorrect answer is entered).

Now try the "Show Me Another" button after submitting the correct answer
to the first part in the assigned problem in the set.  In the show me
another problem, enter an answer to the first part, and click "Preview
My Answers".  Again, the second part opens regardless of if the first
part is correct or not, and again it shouldn't open even if the first
part is correct.

Now test with this pull request, and of course the correct behaviour
happens.  That is the second part only opens when the first part is
submitted (either with "Submit Answers" in the actual set or with "Check
Answers" in the show me another problem) and the first part is correct.
Previously if a new problem version is being opened, then the answers
from a previous version were deleted from the form fields of the last
form submission.

Now, the form fields form any previous form submission are simply not
even sent to PG.  If this is a new problem version, there is absolutely
nothing in the form fields that PG needs. This is a much more efficient
and thorough approach.  It ensures that if a problem uses some other
inputs that are not part of the answer, those inputs are cleared as
well.  GeoGebra problems do this for instance to save their state.
The problem grader is now always visible for users that have the
permission to use it and in the case that they are acting for another
user.  This does mean that there is no way to open the problem grader
when viewing your own problem.  However, the problem grader is in a
collapse.  The state of the collapse is stored in local storage, and
whenever you open another problem or change effective users, the
collapse goes back to the state that it was in the last time that you
had a page open that showed the problem grader.

Correct answers in feedback are now always shown with the reveal button,
even when the problem grader is on the page.  However, the reveal button
is removed by JavaScript behind the scenes while the problem grader is
expanded, and put back if the feedback button is not opened while the
problem grader is open.  So if you open a feedback button while the
problem grader is open, the reveal button is not shown, and the correct
answer is immediately visible.  To summarize the reveal button
visibility, the reveal button will not be shown anytime that a feedback
button is opened while the problem grader is open, and in that case will
never return until the page reloads, but any feedback button that is not
opened while the problem grader is open will still show the reveal
button, and as usual once the reveal button is used, it will never come
back until the page is reloaded.

The problem grader is now below the problem in homework sets as it is in
tests. With the collapse and the grader always in the page, I really do
not want it above the problem as it currently is.

The original reason for the problem grader being on top was so that it
would be close to the old results table with the answers.  With that
gone, that reason no longer applies.

Also remove the code for the `output_hidden_info` method in the
`Problem.html.ep` template. This is because the answer to the question
`$c->can('output_hidden_info')` is `$c` can't.  There is no such method
anywhere in the code anymore.
The default option should be disabled.
…abled

Minor tweak to the mass date edit on the set list page.
…ed issue.

Currently when the sets manager page loads the "Import how many sets?"
select has "a single set" initially selected and the "Import from
where?" select has "Select filenames below" selected.  But then if you
change the first select to "multiple sets" the "Import from where?"
select still has "Select filenames below" selected.  Furthermore, if you
then click on that select and use shift-down arrow to select multiple
sets, that first disabled option stays selected.  Then form validation
fails for that option since it has no value if you click the "Import"
button.

This just makes it so that when you switch from the "Import how many
sets?" select from "a single set" to "multiple sets", that first option
in the "Import from where?" select is immediately unselected.

There is also a little clean up of this section of JavaScript code.  The
elements with id `import_source_select` and name `action.import.number`
are actually the same element, so no need to find them in the DOM twice.
Also ensure the elements exist and are found before trying to work with
them. More of this is needed in this file, but this is probably good
enough for now.
between selecting single or multiple sets in the import sets form.
This uses translations for the text from data attributes.

The `(taken from filenames)` text that is put into the value for the
"Import sets with names" input is also translated using a data
attribute.
Fix problem_data with problem randomization and show me another.
Fix sets manager import form selection multiple default option selected issue.
The instructor links help is updated to order the links in the help in
the same order that they are in the site navigation.  Also add help for
the "Job Manager" which was missing.

Also fix the links the PG problem editor help.  The links above the
CodeMirror editor window in the PG problem editor have changed in two
ways that the links in the help were not updated to match.

First, the "Problem Techniques" button was replaced with the "Sample
Problems" button.  So that Wiki link is now also removed from the help,
and it is now the local server sample problems link.

The PGML lab was updated so that it does not need the PGML-lab.pg file
in the templates directory of the course.  It now directly uses that
problem from the assets/pg directory.  The link in the help file now
does the same thing.

I removed the `reference-link` class from the links above the CodeMirror
window because that class does not do anything.  I also removed the
old webwork.maa.org links in the comments because those don't need to be
there even if they are updated to the new locations.
Rework the single problem grader interface.
This is achieved by displaying the student nav on the problem set page
for users that have the permission to act as a user as well as always
showing the student nav in problems and in tests.

If you are acting as a user, then the student nav looks the same as
before with the next and previous buttons and the name of the user that
is currently being acted as shown on the button.  However, if you are
not currently acting as another user, then the next and previous buttons
are not shown and the button says "Select Student to Act As" (or in a
test it says "Select a Test to Review").

Also fix the breadcrumb in a test when the set is not valid, but the
setID does have the `setID,v?` format.  Currently if you are acting as a
student user and reviewing a test version, say "test,v1", but you have
not worked the test, and you click the "Stop Acting" button, then the
message stating that the selected test is not valid for the user is
shown (it would be nice to not show this even) and the breadcrumb ends
with the inactive link "test,v1", and you can only go back to the
assignments page. Now, the "setID" link is shown and works, and the
inactive "v1" link is at the end.

This is built on top of #2875 since it would conflict rather heavily
with that pull request if it were not.
Make it much easier to act as a student.
Add an "accommodation time factor" to provide for extra time on timed tests.
In most cases the `webwork.maa.org` links have been updated to their new
locations.  However, there are some exceptions and other things noted
below.

In addition to updating links in the `README.md` file, the file was
generally cleaned up and issues reported by markdown lint fixed.

For example, a markdown file must have a single top level header and it
must be the first line of the file.  So the `Welcome to WeBWorK` header
was moved before the license.  I would actually like to remove the
license from the file as well.  It is not standard practice to include
that here.  It is in the `LICENSE` file.  That should be enough. Perhaps
a link to the license could be here instead?

Also, the bare links were replaced with markdown links with link text
instead of directly showing the URL.

The `webwork.maa.org` links in the files in the
`courses.dist/modelCourse/templates/setDemo` directory were not updated.
I have another plan for the `Demo` set that will be in a future pull
request.

The `$webworkURLs{docs}` configuration variable (in `defaults.config`)
was not updated, but was deleted. The only place that was used was to
pass that to PG in `lib/WeBWorK/Utils/Rendering.pm`.  However, PG
doesn't use that.  So that usage was removed as well.
The CAPA problems have now been removed from the Contrib section of the
OPL (see openwebwork/webwork-open-problem-library#1277).
So this is not needed anymore.

Note that the `courses.dist/modelCourse/templates/setDemo/prob0837.pg`
problem is already unused (it is not in the `setDemo.def` file).
The color scheme (dark or light) that is used is automatically detected
from the browser's settings initially, but can be set via a color scheme
chooser in the page header.

PG problems are still rendered in light mode regardless of the color
mode for the rest of the page.  Converting PG to honor dark mode will
take some work. Note that there are some small changes needed for the
image view dialog and knowls of PG to make sure that those dialogs
render in light mode. There is also a minor change to make the scaffold
buttons stay in light mode as well.

Note that there were some issues with light mode (i.e., the existing
themes).  The contrast of the links in the site nav were not good when
they were focused or hovered over with the mouse. This was due to an
override of the link focus styles that made the colors lighter in those
cases. That was needed for links in the masthead (the page header), but
generally was bad elsewhere. So instead this uses the Bootstrap defaults
for the hover/active colors which darkens the colors instead of
lightening them.  So now there is just a special case for links in the
masthead, and the other links use bootstraps default colors which gives
higher contrast in the site nav.

One side advantage of the above approach since it darkens links on hover
and focus instead of lightening them is that I can finally switch to a
link color for the math4-yellow theme that is not off theme.  Previously
it was a reddish color that I never really like in the scope of the
theme, but was needed for contrast.  Now it uses a rather dark yellow
and gives a more consistent feel for the theme.

The MathJax `no-dark-mode` extension has been converted into a
`bs-color-scheme` extension which rewrites the MathJax styles to honor
the `data-bs-theme` value instead of using media queries for the browser
mode.  This means that MathJax will display in the correct mode wherever
the element is in the page.  For example, on a problem page the math in
the problem will always be in light mode.  On the problem grader page
the math in the problem there will also be in light mode, but the
formula student answers will be in dark mode if the page is set to that.
Note that the MathJax dialogs will always be in dark mode if the page is
set to that since those are injected outside of the problem content div.
The menu will also always be dark mode in a problem if the page is set
to that since there isn't an override for the menu in the
`data-bs-theme` extension.  Its styles work differently.

Note that there was a small change needed for the PG CodeMirror editor
to give its default light theme a white background.  This was done in
the `pg-codemirror-editor` repository, and the new npm package published
and included in this pull request.

I am sure that I missed some colors that need to be adjusted in dark
mode and perhaps issues with forcing PG into light mode, but I can't
find anything right now.  So please check this carefully.

The `README` files in the theme directories have been deleted, and
replaced with a single `README.md` file in the parent `htdocs/themes`
directory.  It has instructions on how to create a custom theme, and
documents the Sass and CSS variables that can be set. There is a small
change in `ConfigValues.pm` to only list directories when listing theme
directories, and to skip this `README.md` file.
drgrice1 and others added 30 commits June 24, 2026 15:46
Update to node 24 in the build instead of node 20.

Update the Perl::Tidy version to the version currently used in
development.

Don't install the `Statistics::R::IO` module.  That is not used anymore.

Update to the mariadb 10.11 docker image for the database volume. That
should have been done before when I updated the docker build to Ubuntu
24.  That matches the version of mariadb in Ubuntu 24.

Remove the `--db-layout` option that was passed to the `addcourse`
script.  That is not valid for the script anymore.

Note that this depends on #2957, since the docker build will fail
without the bug in the `addcourse` script fixed.
The `DBD::MariaDB` package is provided by the Ubuntu
`libdb-mariadb-perl` package again. So that does not need to be
installed from cpan anymore.

Also change the mariadb docker image to version 11.8 to match the
version used by Ubuntu 26.

The `libio-compress-perl` Ubuntu package is a dependency of the
`Archive::Zip::SimpleZip` Perl package that is needed since the Perl
packages it provides fail to build when installed from cpan. It may be
that they just need some other build dependency, but it is better to
install the Ubuntu packages anyway.

Several dependencies of the Perl `Net::SAML2` package were added to
speed up the build some and avoid these being installed from cpan.

Remove `install` from the `cpanm` command.  That isn't a command or
option for the `cpanm` command and results in the `install` perl package
being installed which isn't needed.

The `pgfsys-dvisvgm-bbox-fix.patch` file is not needed for Ubuntu 26.
Its changes are included in upstream file installed on the system.

Fix the comments about executing `docker compose`.  That is no longer
executed as `docker-compose`.

Update the `docker-entrypoint.sh` to use `libpapers2`.  The `libpapers1`
package no longer exists.

The `newgrp` command used in the `docker-entrypoint.sh` script is no
longer is installed by default.  The `util-linux-extra` package is
needed for that.
Signed-off-by: John E <jeis4wpi@outlook.com>
More typo fixes (#3027 for the release candidate)
login stage to trigger the authentication stage on the LMS.

The parameter was is not part of the LTI standard, and is used by Moodle
to prevent the authentication stage from entering a self-reposting loop,
as a self-reposting mechanism is used to pull in the Moodle session
cookie which is no longer provided by browsers when SameSite=Lax is set
on the LMS side and the sites are considered cross-site.

Having this unneeded parameter set breaks the Moodle to WeBWorK
login/launch and content selection mechanism after Moodle changed
to defaulting to SameSite=Lax.

Additional details are in:
    #2982
The "Save" tab will always shown for all file types, but will be
disabled for any file not in the course's templates directory (symlinks
do not count here, i.e., this tab will not be disabled for a file that
is linked to from the course's templates directory assuming the server
has write permission to the file), or the server does not have write
permission to the file.

The "Append" tabe will be shown for all PG file types (problems and set
headers).  However, it will be disabled for any file not in the course's
templates directory (again symlinks do not count here, i.e., this tab
will not be disabled for a file that is linked to from the course's
templates directory, even if the server does not have write permissions
to the file).

Also the help has been updated. help for this. The help for each action
tab now states when the tab is available and when it is active.
Newer Archive::Tar refuses, under its secure extract mode, to extract
symbolic and hard links whose targets fall outside the extraction
directory (the CVE-2026-42496 / CVE-2026-42497 hardening in Archive::Tar
3.08, backported into distribution perl packages), and aborts the whole
extraction when an archive contains one.

Every course archive contains the standard template links (Library,
Contrib, capaLibrary, Student_Orientation), whose relative targets point
outside the course directory, so no course could be unarchived once the
system's Archive::Tar carried the fix.

Remove the link entries and extract the remaining files with secure
extract mode still enabled -- so regular files cannot escape the course
directory via absolute or ../ paths -- then recreate the symbolic links
directly. Access through a recreated link remains governed by the
valid_symlinks course environment option, so this grants no new read
access.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
When extraction fails partway through, it leaves the partially extracted
course directory behind. unarchiveCourse only moved a displaced course
back into place, so the incomplete directory remained.

For a fresh restore this left an orphaned, database-less course stub that
blocked a same-name retry with a misleading "Cannot overwrite existing
course" error. When unarchiving over an existing course it was worse:
_unarchiveCourse_move_away has already renamed the existing course to
<id>_tmp, and _unarchiveCourse_move_back then fails because renameCourse
refuses to move it back onto the name still occupied by the partial
extraction, leaving the original course stranded under _tmp.

Remove the partially extracted directory in the failure branch before
moving any displaced course back. _unarchiveCourse_move_away has already
moved a pre-existing course of this name aside, so the directory can only
be the incomplete extraction.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
The File Manager's tar extraction hits the same problem as course
unarchiving: newer Archive::Tar refuses, under secure extract mode, to
extract symbolic links whose targets leave the extraction directory (the
CVE-2026-42496 hardening), so an instructor extracting a tarball that
contains such links would have those links skipped with an error.

The extraction already validates each member's location with
path_is_subdir, so recreate symbolic-link members directly with symlink()
instead of extracting them. Access through the link remains governed by
the valid_symlinks course environment option.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This reworks what was done in #3008 and #3016. Rather than trying to
force the PG critic and hardcopy xml into light mode, remove the
`bg-white` class from the render panel and use the page colors. This
means that these things are in a proper dark mode for those that use it.

Problems do not need the white background since by default iframes are
given a white background.  Also the iframe elements do not need to have
the `color-scheme` style set to `light`.  That has no effect inside the
iframe anyway.
This has been deprecated since the release of webwork 2.18. It is time
for it to go.  I believe that everyone that used to use this endpoint
have now updated to use the `render_rpc` endpoint. If not, then we can
wait another release for this.
A better approach for dark mode for some rendering in the editor.
Any time that a package has certain scripts defined (such as `install`
or `postinstall`), npm now warns about them and tells you to "Run `npm
approve-scripts --allow-scripts-pending` to review, or `npm
approve-scripts <pkg>` to allow."  Note that doing so just adds the
section to the `package.json` file that you see in this pull request.

The package `@parcel/watcher` has an `install` script that rebuilds its
distribution code if an environment variable is set. This script is
harmless, but does not need to be run.

The package `iframe-resizer` has a `postinstall` script that gives a
message about the newer versions of the iframe resizer begin split into
parts. This script also does not need to be run.
… grades page.

If the "Additional Grade Information" is shown then the lack of a margin
is not good.  If that is not shown the margin doesn't do anything
particularly harmful to the layout.
Deny scripts for two npm packages.
This version fixes the issue with certain expressions causing the
browser to run out of memory and crash. See
mathjax/MathJax#3578,
https://forums.openwebwork.org/mod/forum/discuss.php?d=8819, and
openwebwork/pg#1451.

Also remove the workaround for the `--mjx-bg-alpha` variable. That is
not needed anymore.
Add a margin to the bottom of the "Future Assignments" on the student grades page.
…al-symlinks

Bugfix/unarchive course external symlinks
typos identified by github.com/crate-ci/typos
icon alert if a date has been overrided for a user on the Assignments…
configure mathjax to line break long display math
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.

8 participants