Back to Releases

Release Notes *3.2.1*

October 31, 2026
docker run -it \
  -v ~/wljs:"/home/wljs/WLJS Notebooks" \
  -v ~/wljs/Licensing:/home/wljs/.WolframEngine/Licensing \
  -v ~/wljs/tmp:/tmp \
  -p 8000:3000 \
  --name wljs \
  ghcr.io/wljsteam/wljs-notebook:3.2.1
brew install --cask wljs-notebook

Critical patch

We fixed caching error related to the stored frontend objects when saving. At certain conditions when the kernel link suddenly goes down an attempt to save notebook could corrupt graphs, images and other frontend objects.

However, we could just ship this path alone, so here are some extras for the desert

Improved Rasterize

We implemented the missing features of Rasterize expression such as "Graphics", RasterSize options. 2nd argument specifies in which form the output should be returned. By the default

Rasterize[60]
Rasterize[60, "Image"]

are the same, now can also pack raster data into Graphics, which is used internally by some Plot* functions

Rasterize[60, "Graphics", RasterSize->20]
% // Head 
(*VB[*)(FrontEndRef["F47b0f25c-02d8-4418-92b0-b5604cac0eac"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgUJm5gnGaQZmSbrGhilWOiamBha6FoaJRnoJpmaGZgkJyYbpCYmAwCQ1hXU"*)(*]VB*)
Graphics

Providing a list will also work:

Rasterize[60, {"Image", "Graphics"}, RasterSize->20];
Head /@ %
{Image,Graphics}

This allows LineIntegralConvolutionPlot and others to accept images for stream convolution plots

house = ExampleData[{"TestImage", "House"}];

LineIntegralConvolutionPlot[
    {{-1 - (*SpB[*)Power[x(*|*),(*|*)2](*]SpB*) + y, 1 + x - (*SpB[*)Power[y(*|*),(*|*)2](*]SpB*)}, house}
    ,
    {x, -3, 3}
    ,
    {y, -3, 3}
    ,
    VectorPoints -> 10
    ,
    VectorColorFunction -> None
    ,
    VectorStyle -> White
]
(*VB[*)(FrontEndRef["Fdf17ab9d-509f-4563-830f-6fbb4bfe1f42"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgUJp6QZmicmWabomhpYpumamJoZ61oYG6TpmqUlJZkkpaUappkYAQCh3hZR"*)(*]VB*)

Locator support in Manipulate

We improved Manipulate compatibility with Mathematica. Use Locator control option for manipulated expression to add interactive positioning element aka "crosshair"

Locators in the context of Manipulate can only work if the output expression is Graphics

Manipulate[
  ParametricPlot[Exp[-x/s]({Cos[x], Sin[x]} + loc), {x,0,5Pi}], 
  {s, 1.0, 15.0}, {{loc, {0.,0.}}, Locator}, ContinuousAction->True]

A locator control positioned on a parametric plot

If JIT optimization fails (it may happen especially on ContourPlots), Locator may not be as useful as a 1-2 basic sliders.

Prefer DensityPlot over ContourPlot in the case of locators

Draw the potential of two charges:

Manipulate[
 DensityPlot[
  q1/Norm[{x, y} - p[[1]]] + q2/Norm[{x, y} - p[[2]]], {x, -2, 
   2}, {y, -2, 2}], {{q1, -1}, -3, 3}, {{q2, 1}, -3, 
  3}, {{p, {{-1, 0}, {1, 0}}}, Locator}]

Two locator controls positioning charges on a density plot

Here is more complicated example, where raster graphics is combined with vector

Show the local direction of the gradient of a function along with its level curves investigating different unconstrained optimization methods

Module%5B%7Bf%2C%20L%2C%20fplot%7D%2C%0A%20f%5Bx_%2C%20y_%5D%20%3A%3D%20%28%2ASpB%5B%2A%29Power%5B%281-x%29%28%2A%7C%2A%29%2C%28%2A%7C%2A%292%5D%28%2A%5DSpB%2A%29%20%2B%20100%20%28%28%2ASpB%5B%2A%29Power%5B%28y-Sin%5B%5C%5BPi%5D%20x%5D%29%28%2A%7C%2A%29%2C%28%2A%7C%2A%292%5D%28%2A%5DSpB%2A%29%29%3B%0A%20L%20%3D%201.5%60%3B%0A%0A%20fplot%20%3D%20Show%5B%0A%20%20%20%20LineIntegralConvolutionPlot%5BEvaluate%5BD%5Bf%5Bx%2C%20y%5D%2C%20%7B%7Bx%2C%20y%7D%7D%5D%5D%2C%20%7Bx%2C%20-L%2C%20L%7D%2C%20%7By%2C%20-L%2C%20L%7D%2C%20ColorFunction-%3E%22Rainbow%22%5D%2C%0A%20%20%20%20ContourPlot%5Bf%5Bx%2C%20y%5D%2C%20%7Bx%2C%20-L%2C%20L%7D%2C%20%7By%2C%20-L%2C%20L%7D%2C%20ContourShading%20-%3E%20None%2C%20ContourStyle%20-%3E%20Pink%5D%0A%20%5D%3B%0A%0A%20Manipulate%5B%0A%20%20Module%5B%7Bsteps%7D%2C%0A%20%20%20%20%20%20%20%20steps%20%3D%20Reap%5BQuiet%5BFindMinimum%5Bf%5Bx%2C%20y%5D%2C%20Evaluate%5B%28%2ABB%5B%2A%29%28Transpose%5B%7B%7Bx%2Cy%7D%2Cp0%7D%5D%29%28%2A%2C%2A%29%28%2A%221%3AeJxTTMoPSmNmYGAo5gcSAUX5ZZkpqSn%2BBSWZ%2BXnFaYwgCRYg4ZGfk5LGBOLxAomwzNRyl9Tk%2FKLEkvyiYE6gSEhRYl5xQX5xajBISwhEKUhjUGlOajDYhNTEFFSlaIpYgQzXstS8ErCQX2lODgB64iTl%22%2A%29%28%2A%5DBB%2A%29%5D%2C%20Method%20-%3E%20method%2C%20StepMonitor%20%3A%3E%20Sow%5B%7Bx%2C%20y%7D%5D%5D%5D%5D%5B%5B2%2C%201%5D%5D%3B%20%0A%20%20%20%20%20%20%20%20steps%20%3D%20Prepend%5Bsteps%2C%20p0%5D%3B%20%0A%20%20%20%20%20%20%20%20Show%5Bfplot%2C%20Graphics%5B%7BGreen%2C%20Line%5Bsteps%5D%2C%20%7BPointSize%5B0.025%60%5D%2C%20Point%5BLast%5Bsteps%5D%5D%7D%7D%5D%2C%20PlotRange%20-%3E%20%7B%7B-L%2C%20L%7D%2C%20%7B-L%2C%20L%7D%7D%5D%0A%20%20%5D%2C%20%0A%20%20%20%20%7B%7Bp0%2C%20%7B-1%2C%20-1%7D%7D%2C%20Locator%7D%2C%0A%20%20%20%20%7Bmethod%2C%20%7BAutomatic%2C%20%22Newton%22%2C%20%22GaussNewton%22%2C%20%22QuasiNewton%22%2C%20%22PrincipalAxis%22%7D%7D%0A%20%5D%0A%5D

A locator control selecting the starting point for an optimization method

New event listeners for Graphics

We added new events to track:

  • "metaclick" - fired when you click with %3Ckbd%20%3ECtrl%2FCmd%3C%2Fkbd%3E pressed
  • "shiftclick" - fired when you click with %3Ckbd%20%3EShift%3C%2Fkbd%3E pressed
  • "capturekeyevents" - fires for both: pressed and released keys
EventHandler%5BPlot%5Bx%2C%20%7Bx%2C0%2C1%7D%5D%2C%20%7B%0A%20%20%22metaclick%22%20-%3E%20%28Print%5BStringTemplate%5B%22Meta%20as%20%60%60%22%5D%5B%23%5D%5D%26%29%2C%0A%20%20%22shiftclick%22%20-%3E%20%28Print%5BStringTemplate%5B%22Shift%20as%20%60%60%22%5D%5B%23%5D%5D%26%29%0A%7D%5D

and here is an example for key capture

EventHandler%5BGraphics%5B%7B%0A%20%20Disk%5B%5D%2C%20StandardRed%2C%20Text%5B%22Focus%20on%20me%22%2C%20%7B0%2C0%7D%2C%20%7B0%2C0%7D%5D%0A%7D%2C%20ImageSize-%3E200%5D%2C%20%7B%0A%20%20%22capturekeyevents%22%20-%3E%20%28Print%5BStringTemplate%5B%22%60%60%22%5D%5B%23%5D%5D%26%29%0A%7D%5D

New event lsiteners for Graphics3D

We added missing click event and mousemove for 3D. This was rather tricky, since one needs to cast rays in 3D space and check for intersection. Here is a good example for that:

Module[{pos = {0,0,0}},
 EventHandler[Plot3D[x y, {x,-1,1}, {y,-1,1}, 
  BoxRatios->{1,1,1}, Epilog->{
  Red, Sphere[pos//Offload, 0.1]
 }], {"click" -> ((pos = #) &)}]
]

try to click on the plotted surface

Dynamic color and opacity for 3D

We had this feature for ages in Graphics. RGBColor, Hue and Opacity now can be dynamic too in Graphics3D context.

color = List @@ Pink;
Graphics3D[{RGBColor[color//Offload], Cuboid[]}]
(*VB[*)(Graphics3D[{RGBColor[Offload[color]], Cuboid[{0, 0, 0}]}])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRAeF5BwL0osyMhMLjZ2SWOCqfDJLC6BqOAAEkHuTs75OflFEBF2IOGflpaTn5hSrAlkO+enpaWm+mQWlqaWFiW4VpSk5hVn5ucVJyAMTkhGaGcDaSlNys9MSWNGti4TSDMgCAB5bSnY"*)(*]VB*)
color = List@@RGBColor@RandomColor[];

Or use a picker

EventHandler[InputColor[color], (color=#)&]
(*VB[*)(EventObject[<|"Id" -> "3092d982-5108-4841-9e03-569e17bfc529", "Initial" -> {1, 0.5, 0.5}, "View" -> "F3cd52012-73aa-40ee-9949-440597e6e2eb"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgUJGyenmBoZGBrpmhsnJuqaGKSm6lpamljqmpgYmFqap5qlGqUmAQCQuhWN"*)(*]VB*)

Improved NumberForm support on the frontend

Sometimes you need trailing zeros for numbers. On Wolfram Kernel this is easy:

NumberForm[2, {2,0}, NumberPadding->"0"]
NumberForm[2, {2,0}, NumberPadding->"0"] // ToString
(*VB[*)(2)(*,*)(*"1:eJxdT81Kw0AYDP6A+Bb2lGw9VDEeBA+7oStU0sr+xSge0u1XWbLpJk1jUp/Ax3bj0cswMwzMzNXase1pEATtpYf5xhzcXhno+Y+XISLkHUXhbHYbhejaMzS5eYDFIETqXni1LPMn7OLPlPc8U6ui7Bq9i1le2qlUtUjIQA1matGIzPSJrBP2OsRa1vzNTu91qYys6JFnlulv3Eg9/0qf5R3FOK+oco+Tse+DEBRtT8aBZx5YZ4FfjASKzWpnj3+u2HfwLzO+4WBBH4q1hfbcS1rYFn4BxP5CVA=="*)(*]VB*)
"002"

Now this is also supported on the frontend (if expression is executed inside Offload)

val = 2;
TextView[NumberForm[val, {3, 0}, NumberPadding->"0"]//ToString//Offload]
(*VB[*)(FrontEndRef["Ff84631b4-ad4b-4ccd-8165-c6135fd47d43"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgUJp1mYmBkbJpnoJqaYJOmaJCen6FoYmpnqJpsZGpumpZiYp5gYAwCdCRXr"*)(*]VB*)