Skip to content

PG 2.21 Release Candidate - #1393

Merged
drgrice1 merged 431 commits into
mainfrom
PG-2.21
Aug 4, 2026
Merged

PG 2.21 Release Candidate#1393
drgrice1 merged 431 commits into
mainfrom
PG-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.

dlglin and others added 30 commits April 28, 2026 14:27
Update the version to 2.21 and the copyright years to include 2026.
This is a result of a workaround for a bug in the JSXGraph library and
failure to properly convert all of the code in the `keyDownListener`
function to work outside of the library.  The `Const` object is not
defined.  To access those constants instead the `JXG` global object must
be used.
When collecting a matrix array answer use `student_array`
instead of `student_formula` as `student_formula` should
always be a formula, and this could fail to convert to a
formula if an answer blank is left empty, causing a future
`typeMatch` error.

Fixes #1406.
When checking if `$other` is an object, check that it is
actually a `Value` object instead just that it is a reference
in the various `typeMatch` methods. This is done by using
`Value::isValue($other)` instead of `ref($other)`.

In addition add a test for `Value::isValue($other)` in
the `Value::Formula::typeMatch` method to be consistent
with the other methods.

This was suggested by @dpvc.
Don't use student_formula to collect matrix array and update typeMatch methods.
This fixes issue #1349 and is the result of the discussion in that
issue.  See the issue for details and example problems.
This color has a contrast ratio of 6.68 against the white background.
The red color has a contrast ration of 4.00 which is not sufficient for
accessibility purposes.
The method returns an array containing references to arrays that form a
partition the vertex indices into the connected components of the graph.
For example, for the graph with vertices E, F, G, H, I, J, K, and L, and
edge set {{{E, L}, {F, G}, {F, L}, {G, J}, {H, I}, {J, K}, {J, L}}}, the
method will return ([E, F, G, J, K, L], [H, I]).
Instead of trying to place the labels using the coordinates, use the
`anchor` and padding options to get better positioning.  The primary
advantage is now the labels don't float away when the image is enlarged.
This was not done originally because at the time this macro was
implemented the `anchor` and `padding` options didn't exist.

The weights for the default layout and the wheel layout are still
positioned along the perpendicular vector for now.  The problem is that
those labels are rotated, and that does not work well with the anchor.
This is a TikZ issue (I implemented the anchor for JSXGraph to work the
same as the TikZ anchor option).  The problem is that the rotation is
around the position of the anchor, and not around the center of the
text. The usual solution for this in TikZ is to use a `\rotatebox` on
the node contents. Perhaps another rotation option could be addded to
the plots macro that would rotate the text instead of rotating around
the anchor position.
an invalid edge set for a graph with a single edge.
First, the method is now quite a bit more efficient.  Rather than
finding and sorting only the weights of the edges in the graph, and then
searching through the graph to find those edges at each step in the
algorithm, the edges with the weights are all listed and sorted by
weight (more like the actual sorted edges algorithm works).  So there is
no need to find the edge later, you just follow the algorithm and
process the edges in order.

Second, the return value of the method is reordered and more data
returned.  See the updated POD for good documentation on what is
returned.

This makes the method return a lot more useful information that can be
used for constructing a solution to problems using the sorted edges
algorithm.
First, the method is now quite a bit more efficient.  Rather than
finding and sorting only the weights of the edges in the graph, and then
searching through the graph to find those edges at each step in the
algorithm, the edges with the weights are all listed and sorted by
weight (more like the actual sorted edges algorithm works).  So there is
no need to find the edge later, you just follow the algorithm and
process the edges in order.

Also make the algorithm terminate once the minimal spanning tree is
complete as it should.

Second, the return value of the method returns more data. See the
updated POD for good documentation on what is returned.

This makes the method return more useful information that can be used
for constructing a solution to problems using the sorted edges
algorithm.

These is the basically the same changes that were made for the
`sortedEdgesPath` method.
This returns a translated string description of the graph.  The string
that is returned is suitable for use as the "alt" text for the image
returned by one of the image methods.
This is giving warnings when the unit tests are run.
Make list answers work in MultiAnswer and RadioMultiAnswer part answers.
Fix a typo in the `ProhibitBeginproblem.pm` PG critic policy.
Fix an ambibous `abs` call in `AnswerChecker.pm`.
Using `//=` in signatures is a feature that is not available until
version 5.28 of perl.

I am not entirely certain of why the added `to_string` is needed or why
it works with newer versions of perl, but it causes an issue with older
perl versions as well.

This fixes issue openwebwork/webwork2#2978.
This addes a comment to the POD about the `scores` array that is set
internally, and that can be used in a custom checker.
Add a note in the `parserMultiAnswer.pl` macro about the `scores` array.
Some improvements and additions to the `SimpleGraph.pl` macro.
This adds two options to plots, `texPackages` and `tikzLibraries`
to Plots, that can be used to add additional packages and libraries
fro generating TikZ output. This also adds "amsmath" in the list
of default packages that are loaded.
This is for problmes that use the `dragndrop.js` JavaScript and the
`DragNDrop.pm` module via the `draggableProof.pl` and
`draggableSubsets.pl` macros.

The elements in a drag and drop list can now be focused using tab and
shift-tab.  Once focused the arrow keys move the elements around.  If an
element is moved with the keyboard controls the changes are announced in
a visually hidden span.  Note that drag and drop actions via the mouse
cursor are not aria announced for now.  I am assuming that a screen
reader user would not be using the mouse for drag and drop.

There is now also a "Drag and Drop Help" button that is shown below the
drag and drop lists.  If pressed, help is shown describing the keyboard
controls.  This help can be customized by the problem.

There are new options for the macros that allow for customizing the help
and associated texts.  See the updated POD in the module and macros for
details.  Also, I don't like that there are some options that are for
the `DragNDrop.pm` package that are passed in from the macros, but are
different in the macros than in the module.  Basically the first letter
is upper case in the macros, but lower case in the module.  So the upper
case first letter variants is deprecated (but will still work with a
compatibility layer).  I don't like that the macros use Pascal case to
begin with for options.  Options should be camel case.

Note that I also made all of the texts for the drag and drop object
translatable via `maketext`.  The texts can be customized per problem as
mentioned above, but if only a translation is needed there is no need
for such customization.
This sets the `aria` option from the JSXGraph library for all graphed
objects. Thus objects are described as they are graphed.

I am sure this will still need some work, but this makes the graphtool
at least basically accessible.

There is also a need to specifically set the tabindex for objects
(usually to the empty string which is the closest thing to unsetting it
that the JSXGraph library allows).  Otherwise JSXGraph now sets that to
-1 for everything and tries to focus those things with javascript and
that is interfering with the graphtools own focus behavior. This is more
of what was done in #1357.

Note that the aria labels are not translated.  Although nothing for the
graphtool is.  The usual data attribute approach really would be a mess
for this.  There are a lot of strings.  Translating the graphtool would
take a lot of effort with the current methods for javascript
translation.
pstaabp and others added 27 commits July 27, 2026 22:01
Add better documentation of the convert-to-pgml script.

Separate the loadMacros to a separate subroutine and perform error handling in the subroutine to better capture possible syntax errors.

Also, add a better way to parse the answer blanks in PGML form.
And rewrite the list of macros to be removed from the list.
The loadMacros parsing is now much more versatile.  In addition to basic
single and double quoting, and `qw` quotes, it can handle any quotelike
quotes. There is a minimal attempt to keep comments inside of a
`loadMacros` call. Basically, if a macro is removed from the list, then
a comment after it is also removed.  If a macro is kept, then so is the
comment that was after it. If there is a line that only has a comment on
it, then if the preceding line had a comment it is assumed that the
comment continues that one, and if that is kept so is the next line.
Otherwise the comment line is dropped.

Previously the `MathObjects.pl` macro was removed if loaded, since it is
loaded by `PGML.pl`.  Now `niceTables.pl` is also removed, since
`PGML.pl` also loads that.

The naive approach of replacing `ans_rule` calls with PGML has been
removed.  Instead any `ans_rule` call is just wrapped in `[@ ... @]*`,
and the corresponding `ANS` calls are left alone.  One advantage of this
approach is that after the conversion is completed, the problem actually
works.  In addition, the previous approach was clobbering the `ans_rule`
calls in many cases that give information about what needs to be done to
properly convert the answers into the PGML answer syntax. The con is
that the conversion into PGML syntax must be done manually.  However,
since that really was the case before other than basically just putting
a non-functional PGML answer template into place, that is not really a
tradeoff.

Instead of handling only two very specific forms of heredoc/nowdoc
syntax `SOLUTION(EV3(<<'END_SOLUTION'));` and `TEXT(EV2(<<EOT))` where
the heredoc/nowdoc terminator was fixed and must be exactly what is
shown above, any such form is handled.  The heredoc/nowdoc terminator
can be anything the author specified and an unquoted, singled quoted, or
double quoted terminator can be used. In addition both `EV2` and `EV3`
are covered, and the `HINT` form is also handled. In addition spaces can
be in those constructs as allowed by Perl. Note that there are OPL
problems that do all of those things, so it was really quite naive to
only literally cover those two cases.

Variable interpolation now actually works much better, including for
hash and array access, and hash reference and array reference access.

Note that a file that already uses PGML and does not have any of the old
style PG constructs is actually completely left alone.  @pstaapb's #1425
still modifies those files in some cases.

The `bin/convert-to-pgml.pl` script no longer accepts `-s|--suffix`
argument.  Instead it accepts a `-e|--extension-prefix` argument.  That
is much the same except that its value is prepended to `.pg` instead of
used as the extension itself. It defaults to `pgml` as the `suffix`
option did before. So if `problem.pg` is converted, then the
result will be written to `problem.pgml.pg`. Thus the resulting file has
the correct pg problem file extension.

A new option for the `bin/convert-to-pgml.pl`, `-p|--output-path` was
added. When given, the converted file is written into that directory
with the same name as the original file. The `-b|--backup` and
`-e|--extension-prefix` options are ignored, unless the output path
resolves to the directory containing the original file, in which case
those options will still apply.

TRhere were some other minor things fixed along the way as well that I
did not list here, such as an issue with the conversion of the `$HR`
variable into a PGML `---` in which the `---` was added, but the `$HR`
variable left and changed into `[$HR]` resulting in

```
---

[$HR]
```

in the converted file.

This was done in collaboration with Claude.
This is something that has been missed with MathQuill inputs for a
while.  The original text input has an `aria-label`, but when it is
hidden that becomes meaningless.  So transfer that label to the
MathQuill input.  The input also needs the `role` to be set to `textbox`
for this to work.
1. The DIV containing the standard answer boxes are set to use dir='ltr'
so that then result/feedback icon appears to their right even when a
answer box is used directly in the text in a problem which is
being rendered in an RTL setting. This will match the behavior
which occurs when answers are inside an LTR span in order to handle
interleaved math and answers in RTL language problems. It should have no
visible effect on problems in English or other LTR languages, but makes
things consistent for problems in RTL languages. This change was suggested
to me by @drgrice1.

2. Set the CSS for the feedback message box to have a default setting
of dir='ltr'. This will be changed automatically to dir='rtl' when
the course language is either set to Hebrew or Arabic (as those
languages are set to use HTML with dir='rtl' set, so will use the
RTL version of the CSS.) That will make feedback messages in such
courses (which are expected to mostly be in the RTL language)
render in the appropriate RTL manner. There should be no effect on
courses in LTR languages.
…lnerabilities.

Actually only `postcss` needed to be updated, but I updated all of the
development dependencies to their latest versions (only `sass` and
`yargs` were not at their newest versions).  The development
dependencies are easy to test.  If the `generate-assets.js` script still
works as it should then all is good.  Note that you can test by
executing `npm ci` since that runs the script.

I left production dependencies as they are.  I didn't actually even
check if there are any upgrades, but those can take more time to
properly test since we actually use those.
Update the npm development dependencies once again to fix security vulnerabilities.
2 small changes to improve behavior in RTL problems/courses
Transfer aria labels of text inputs to MathQuill inputs.
Move unionTables.pl to deprecated folder
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
When creating a copy of a context, only keys on the new
context were copied, instead all keys from the old context
should be copied. This is fixed by looping over `$self`
instead of `$context`. This fix was suggested by @dpvc.
tex, string, and separator options for units
change Round function to use sprintf and combat machine rounding error
@drgrice1
drgrice1 merged commit 726ff42 into main Aug 4, 2026
6 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.

7 participants