๐ฅ Improved Legends Support โ Now with better handling of Legended
, PlotLegends
. Easily integrate custom legends into your plots.
๐ฆ Export Enhancements โ Cleaner wljs-html-export
, better organized formats, and improved Mathematica & HTML notebooks!
๐ฅ๏ธ Dynamic HTML Upgrades โ Smarter virtual machines for tracking symbol mutations, leading to more efficient interactivity.
๐ณ Docker Support โ Deploy effortlessly with a single command, including all the latest libraries and Wolfram Engine support!
๐ Autotests โ Now using playwright
to catch bugs early with screenshot-based integration testing.
๐ Windows Compatibility โ Full support for ESM & Shell cells on Windows machines!
Try out the latest improvements and experience a smoother workflow! ๐
const balloonContainer = document.getElementById("balloon-container"); function random(num) { return Math.floor(Math.random() * num); } function getRandomStyles() { var r = random(255); var g = random(255); var b = random(255); var mt = random(200); var ml = random(50); var dur = random(5) + 5; return ` background-color: rgba(${r},${g},${b},0.7); color: rgba(${r},${g},${b},0.7); box-shadow: inset -7px -3px 10px rgba(${r - 10},${g - 10},${b - 10},0.7); margin: ${mt}px 0 0 ${ml}px; animation: float ${dur}s ease-in infinite `; } function createBalloons(num) { for (var i = num; i > 0; i--) { var balloon = document.createElement("div"); balloon.className = "balloon"; balloon.style.cssText = getRandomStyles(); balloonContainer.append(balloon); } } function removeBalloons() { balloonContainer.style.opacity = 0; setTimeout(() => { balloonContainer.remove() }, 500) } createBalloons(10); setTimeout(removeBalloons, 15000); return '';
Better support for Legendsโ
We have implemented all types of Legeds objects
Plot[{Sin[x], Cos[x]}, {x, 0, 5}, PlotLegends -> SwatchLegend["Expressions"]]
(*VB[*)(Legended[ToExpression[FrontEndRef["e61eab2f-97bc-4480-bdf3-06e0d3ebe318"], InputForm], SwatchLegend[{Directive[Opacity[1.], RGBColor[0.24, 0.6, 0.8], AbsoluteThickness[2]], Directive[Opacity[1.], RGBColor[0.95, 0.627, 0.1425], AbsoluteThickness[2]]}, {HoldForm[Sin[HoldForm[x]]], HoldForm[Cos[HoldForm[x]]]}, LegendMarkers -> Automatic, LabelStyle -> {}, LegendLayout -> "Column"]])(*,*)(*"1:eJylUk1Kw0AUTv23VFAPIAhuA60ptS5KqP3RRUqxKe5nJi92aJqRycQ2B/AQunXnCbr2AC7ceADdiCB6A2cmKEZRF77Fx/C97/3O28Ss588ahhGtSDiiMG4CYRwJxt0FyThwDKHnzyhFXkLLo9KldH5OcesS2pyFohV6rQmQWCAcgLslaaiUAOFt39zdwcQsl6tFE3u+ZRYrUPQswGCVqmniOQm9WIYtqQcgrxsGiWb7PAZ/XmkKEtwxEmTwuSWlcWgk0hGWJTQpByLoKaT9LUroniBCRcINbS92Kta19vcaLGCcTzfOng6nNza3tN3b/OJc2aOdplmTUMcRC2IB/QElwxCiiKoW/lvZ1/Zs86vX2w5efbB5LX93eVK7/rtydgO599QHLPDajI9SRlV0afjdHSlm8ltYg0U/hmX+Td9O+i0dxIfAI72QeizYCAlKvqjVHTkIQ+CKJADfyIyRlRY+EjsoYbHQNykXF4/CNx9Orz8="*)(*]VB*)
This expression can still be copied and reevaluated. Here are some other examples
legend = PointLegend[{Red, Green, Blue}, {"red", "green", "blue"}]
(*VB[*)(PointLegend[{RGBColor[1, 0, 0], RGBColor[0, 1, 0], RGBColor[0, 0, 1]}, {"red", "green", "blue"}])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KWlMIB43kAjIz8wr8UlNT81LSWOGKfHJLC6B8DiARJC7k3N+Tn5RJsiITAYYgUUBWI6RkAK4KlQLg0G8otSUYFYgnV6UmpoXDJJKyilNBQBj0SLI"*)(*]VB*)
Plot[{x, (*SpB[*)Power[x(*|*),(*|*)2](*]SpB*), (*SpB[*)Power[x(*|*),(*|*)3](*]SpB*)}, {x,0,3}, PlotStyle->{(*VB[*)(RGBColor[1, 0, 0])(*,*)(*"1:eJxTTMoPSmNiYGAo5gUSYZmp5S6pyflFiSX5RcEsQBHn4PCQNGaQPAeQCHJ3cs7PyS8qYgCDD/ZQBgMDnAEA4iUPRg=="*)(*]VB*), (*VB[*)(RGBColor[0, 1, 0])(*,*)(*"1:eJxTTMoPSmNiYGAo5gUSYZmp5S6pyflFiSX5RcEsQBHn4PCQNGaQPAeQCHJ3cs7PyS8qYoACKOODPVwEANd+D0Y="*)(*]VB*), (*VB[*)(RGBColor[0, 0, 1])(*,*)(*"1:eJxTTMoPSmNiYGAo5gUSYZmp5S6pyflFiSX5RcEsQBHn4PCQNGaQPAeQCHJ3cs7PyS8qYoACdMYHewDM1w9G"*)(*]VB*)}, PlotLegends->legend]
(*VB[*)(Legended[ToExpression[FrontEndRef["8a98ade3-2d63-4f26-a8ae-7dc244b66356"], InputForm], PointLegend[{RGBColor[1, 0, 0], RGBColor[0, 1, 0], RGBColor[0, 0, 1]}, {"red", "green", "blue"}, LabelStyle -> {}, LegendLayout -> "Column"]])(*,*)(*"1:eJyFUcFOAyEQpVaNqXrxD0y87mV3pdtrdfWySU0xvcMyNCQUEhai+/cO1DbZxMTLY+bNm+ExPAq3VXNCyHCPsNPw9Qq98zw4z66R6WAPVqqLpFggtFJjKenULHEPCG/e2dBa2X5DHwMXBtgT0g1fNVxCVZSSVkWtSlrwhkOxlH1Z14LS6pkeB18ibCO23aQAuNxYM2b200dQKRhuET6ctuHX0fzU2OkhHLPc/b5+ccZ5ndxpcoI/BLk2+09wVk0vZCnzINkVnnsPYFkqCYN2J0/KS+u4AMPCaECRie2p9O68746PLob8AeglHuwPAvJcDg=="*)(*]VB*)
Line legends
Plot[{Sin[x], Cos[x]}, {x, 0, 5}, PlotLegends -> LineLegend["Expressions"]]
(*VB[*)(Legended[ToExpression[FrontEndRef["27faadb4-b494-4f2d-8307-cf1e6bbbeb90"], InputForm], LineLegend[{Directive[Opacity[1.], RGBColor[0.24, 0.6, 0.8], AbsoluteThickness[2]], Directive[Opacity[1.], RGBColor[0.95, 0.627, 0.1425], AbsoluteThickness[2]]}, {HoldForm[Sin[HoldForm[x]]], HoldForm[Cos[HoldForm[x]]]}, LegendMarkers -> None, LabelStyle -> {}, LegendLayout -> "Column"]])(*,*)(*"1:eJylUjtOAzEQ3UD4RSABB0BCoo0UkhUhRbSCfKBIiMhG9PbuGKxs7Mj2QvYAHAJaOk6QmgNQ0HAAaBASghvg9SqIBQEFUzxZb97MG3u8jnmXTFuWJZc0HFE4q4PHBVJcuLOaacExMJ9MxYqchoZPdSrWkUzMrWpoCs5Ug/mNEXihQjgAd0PTxTJByMd2HtsVO2+Top/fLhXKeY9swhbGGHClkDTOauiGumw+PgDyOyyIDNsTIZCZiXmLMvg8UNZwUiUXWNBQpwI8RU8hmW5OQ2eIPKoiYZl4dRKxcdrbrfGACzFeO38+HN86omTiwRGXF3E8OUmbFQ07WPIgVNA7oV6fgZQ0HuG/zsTEiyOu3+7aePnREdXc/dWwevO3c/oFMpPW+zzwm1wMEiZ2dCn7npYxM/qtrMblj2WprZmfk6yljUQfhDSpA87gi9DsEGEIXBUFQKzUDdLSxY+eLRTxUJnPqN8sHLB3riSscA=="*)(*]VB*)
LaTeX can also be used via inset cells
Plot[{Sin[x], Cos[x]}, {x, 0, 5}, PlotLegends -> LineLegend[Automatic, { CellView["$\\sin(x)$", "Display"->"markdown"], CellView["$\\cos(x)$", "Display"->"markdown"] }]]
(*VB[*)(Legended[ToExpression[FrontEndRef["15c987a5-5b18-4040-98d8-b639fdbcef18"], InputForm], LineLegend[{Directive[Opacity[1.], RGBColor[0.24, 0.6, 0.8], AbsoluteThickness[2]], Directive[Opacity[1.], RGBColor[0.95, 0.627, 0.1425], AbsoluteThickness[2]]}, {CellView["$\\sin(x)$", "Display" -> "markdown"], CellView["$\\cos(x)$", "Display" -> "markdown"]}, LegendMarkers -> None, LabelStyle -> {}, LegendLayout -> "Column"]])(*,*)(*"1:eJylUkFOwkAUrYqiRBP1ACYmLHTRBAJoWZBGAd2ARCCu2EzbX50wzJCZqdADeAjduvMErD2ACzceQDfGxOgNnE4DUYwxxr94ad68vv/n/dl0WNOfMwxDrCg4wTCogMs4koy3FhRTg1Ognj8bKVIKqh5WR5HOn4m4dQUHnFFZpV51CG4gkUOglVZ0tuAWrV1UMAtO1jLzmXzGLFqeZTo7uaLvOS74WSs2TihoBuq3xegDkNegJNRsmwfgz4+b1zCFzwMlNCdkfIElBRXMwZX4HOLpkgoafeRiGXJD15sdi3Wnw/0yI4zz0cbFy/HozuY5XY82v7qM6tmObdYU7DmCkUBC+wy7XQpC4GiE/3b2db3a/Ob9vu6sPtm8lHq47pduf+/8NYHZsXUZCInW04oCS3c6AtOt4XZ6Kuiknlj0CQp16D3Eux4b0J99XCb+7DOW6bcVL66uBMCFPjpiFKaEesvIAdKSIQHf+H7HiXR54llDIQukfq4q1aBHPwDgj7dk"*)(*]VB*)
Put anything into Legended!โ
We managed to get a decent coverage of the default Mathematica's Legended
features
PieChart[{1, Legended[2, "Bob"], 3, Legended[4, "John"]}]
(*VB[*)(Legended[ToExpression[FrontEndRef["1101bbb8-6474-4e18-97a7-132f94392b5b"], InputForm], SwatchLegend[{Directive[EdgeForm[Directive[GrayLevel[0], Opacity[0.5]]], RGBColor[0.928, 0.5210666666666667, 0.2]], Directive[EdgeForm[Directive[GrayLevel[0], Opacity[0.5]]], RGBColor[0.49920000000000003, 0.5552, 0.8309304]]}, {"Bob", "John"}, LegendMarkers -> {{Graphics[{GrayLevel[0.9], Directive[EdgeForm[Directive[GrayLevel[0], Opacity[0.5]]], RGBColor[0.928, 0.5210666666666667, 0.2]], Rectangle[{0, 0}, {1, 1}]}, {DisplayFunction -> Identity, ImageSize -> 10}], Graphics[{GrayLevel[0.9], Directive[EdgeForm[Directive[GrayLevel[0], Opacity[0.5]]], RGBColor[0.49920000000000003, 0.5552, 0.8309304]], Rectangle[{0, 0}, {1, 1}]}, {DisplayFunction -> Identity, ImageSize -> 10}]}, {None, None, None, None}}, LabelStyle -> {}, LegendLayout -> "Column"]])(*,*)(*"1:eJzVVEFrFDEUHuuqa6kKvXkUeh1wtqvbPQ3U7paW0cKOVDwmM292g7PJ+ibTOv4BQcGTCO0f0IMnf4MXRfEntIIn0YtXL74ksHSqrd6qOXwkX17e+96XzFzhapCd9jyvuECwKWB7BRKFTCuMzxITwRBkms2YiFmCXipoy8Rlpww3T9BHJXVPpr0HkJSa8RziBaKD4GrAOV/yr7c7bb8NwZLf7bCOHyy2sm57sdvi17hL3CAYlHSsaSbA0g2ZV5a9jSVkZ0zMHEG8zXQyOijJxESi0G51nmBFICRabIHT17Sah9BXOD4yyFCryKoItiAXtPAcf45gY8ISoSv07NgPnVlW6OryDZUrxMuNzYv+628hwscn3rNX+yHu7pjxNjxRWXv3Hz/9/H0vxEcv7rxrvfkU4sz8y7s/nn8J697F5uiy4rEh1tVI1i/FPgzn+U2G9wCL31lfXzWd8slIJIVTNt3/tTP88N6Mryfr1t9c4oDqMTnMod6zLeYq1nlT38JRjll/L9leiknOqn4pqSMlrbS1FKQm1YfCjZC1MRtCLB6CmJ1m/w89/9ML/Zc9bxzMbie3lIRjJodSmiQR45DHuqLmvGPEzk0/wIhVqtT2x0wOlmP5E/5XaXY="*)(*]VB*)
Highlight prime numbers
Legended[ Grid[Partition[ Table[If[PrimeQ[n], Item[n, Background -> LightBlue], n], {n, 100}], 10], Frame -> All], SwatchLegend[{LightBlue}, {"prime numbers"}]]
(*VB[*)(Legended[ToExpression[FrontEndRef["16d53b61-0d6d-44a3-9318-25b4a87a5c88"], InputForm], SwatchLegend[{RGBColor[0.87, 0.94, 1]}, {"prime numbers"}]])(*,*)(*"1:eJxTTMoPSmNmYGAo5gUSYZmp5S6pyflFiSX5RcFsQBGf1PTUvJQ0JpAKLiDhmpIJlAKpS2MEiQkBCbei/LwS17wU14rU5NKSxKSc1GAVoLChWYqpcZKZoa5BilmKrolJorGupbGhha6RaZJJooV5ommyhQXEYBYgEVQK1MYBYqQmpvjn5VSCRUOKSlMhaniARHB5YklyBtRJjDCdPpnFJRAvgLW7Oznn5+QXFV1fXGDLdf21fZHIOveHVSLv7DNBOlC1BYM8XVCUmZuqkFeam5RaVAwAF9RFfA=="*)(*]VB*)
Autohide strings double-quotesโ
We added some optimizations on fractions, grids and subscripts. If it sees a raw string, the rendering will be done in a simplified way
RandomWord[5] // TableForm
(*GB[*){{"localize"}(*||*),(*||*){"pugilistic"}(*||*),(*||*){"publicizing"}(*||*),(*||*){"goulash"}(*||*),(*||*){"premiere"}}(*]GB*)
One this one can be used for labeling
Labeled[Red, (*FB[*)(("\[Alpha]")(*,*)/(*,*)("\[Beta]"))(*]FB*), Left]
(*GB[*){{(*FB[*)(("\[Alpha]")(*,*)/(*,*)("\[Beta]"))(*]FB*)(*VB[*)(**)(*,*)(*"1:eJxTTMoPSmNiYGAo5gUSYZmp5S6pyflFiSX5RcEsQBHPktRciDyIF1Sak1osAGS4pKYlluaUOCUWpwaXVOakBvMABX0Sk1JzUlPAFADFtBeE"*)(*]VB*)(*|*),(*|*)(*BB[*)((*VB[*)(RGBColor[1, 0, 0])(*,*)(*"1:eJxTTMoPSmNiYGAo5gUSYZmp5S6pyflFiSX5RcEsQBHn4PCQNGaQPAeQCHJ3cs7PyS8qYgCDD/ZQBgMDnAEA4iUPRg=="*)(*]VB*))(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KWnMIB4vkAjLTC13SU3OL0osyS8KBskHJOalpjHBVAeV5qQWcwIZjjmZ6Xm5qXklCDmfzOKSYjYgwxkonFpUzAFkOiUWp+ZkYpgggCQVkF+cWZKZn4eiHgAIiyhB"*)(*]BB*)(*VB[*)(**)(*,*)(*"1:eJxTTMoPSmNiYGAo5gUSYZmp5S6pyflFiSX5RcEsQBHPktRciDyIF1Sak1osAGS4pKYlluaUOCUWpwaXVOakBrMDBX0Sk1JzUlMAU+0Vnw=="*)(*]VB*)}}(*]GB*)
Note, that those symbols were entered as string. But double quotes are hidden upon rendering.
Exporting formats improvementsโ
Better organized and refactoredโ
We got rid of a mess in the codebase of wljs-html-export
, which takes care about various exporting/importing formats. Mathematica notebooks got better support, but still far from perfect. A massive improvement was made in HTML notebooks.
Improvements in Dynamic HTML exportโ
We no longer use JS frontend for inspecting bindings and sampling the data from your sliders. Instead we do everyhting from Wolfram Kernel by injecting a sniffer and listern to symbols mutations and FrontSubmit
calls.
There are 3 kinds of virtual machines we use (picked automatically based on the results on analysis) with funny names
- State Machine - has a state, which is determined by the combination of all input elements. When state changes it dispatches a coresponding symbol mutation.
- Pavlov Machine - (aka Pavlov Dog) does not have a state. It basically records pairs of event - FrontSubmit calls
- Animation Machine - detects a series of symbols mutations caused by the same event and records the whole series (typically an animation made using
AnimationFrameListener
). It does not have a real state, only an abstract frame number
We plan to introduce basic a few kB CNN networks as an option to compress the mutations more efficiently in the future.
Applicationsโ
Symbols mutationsโ
Try to records these Manipulate
and ManipulatePlot
Manipulate[Series[Sin[x], {x,0,n}], {n,1,10,1}]
(*GB[*){{(*VB[*)(EventObject[<|"Id" -> "3acbfd8a-0401-4258-83ad-e87bf7879953", "Initial" -> {6}, "View" -> "d9ea10fb-01d8-46d3-bf5b-e10babd2ee53"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKp1imJhoapCXpGhimWOiamKUY6yalmSbpphoaJCUmpRilppoaAwCS5xZ/"*)(*]VB*)}(*||*),(*||*){(*VB[*)(FrontEndRef["2fbe8bf7-0c1e-4ba1-acf1-88f511a751fe"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKG6UlpVokpZnrGiQbpuqaJCUa6iYmpxnqWlikmRoaJpqbGqalAgCWzhZb"*)(*]VB*)}}(*]GB*)
ManipulatePlot[f[w x], {x,-10,10}, {w,0,10,1.0}, {f, {Sinc, Sin}}]
(*GB[*){{(*VB[*)(Graphics[{AbsoluteThickness[2], RGBColor[0.368417, 0.506779, 0.709798], Line[Offload[pts$140885]]}, ImageSize -> {400, 300}, PlotRange -> Automatic, Axes -> True, TransitionType -> "Linear", TransitionDuration -> 50, Epilog -> {}, Prolog -> {}, AxesLabel -> {}, "TrackedExpression" -> Null, PlotRange -> {{-11., 11.}, {-0.2780903607885227, 1.0608614457518346}}])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KWncIB4HkHAvSizIyEwuTmOGyftkFpdAVAsCCcek4vyc0pLUEKCi7LzU4uJMJqAoRDVIf5C7k3N+Tn5RUcG0SU9Vply3LzKc9nJ6h/kD+6LjLTO8V217Zo+w2iczLxXCYwcS/mlpOfmJKcVcQHZBSbGKoYmBhYVpGhNMdVBpTmoxJ5DhmZuYnhqcWZWKkAM5MnMC0KhMHSCBRU9ATn5JUGJeOoTnWFqSn5tYkpmMphLEcKwA+grECCkqTUWT5wMLJ+YVZ5Zk5ueFVBakBrNB/ZFYhKZWCEWtS2lRIojONGLAcB/ICNeCzJz89DQGlFDHVBZQlE9IGSfUDz6JSak5+FQGC0JcmJydmuJaUVAEisz8PLC0X2lODr5ARA14VF4RAxioHYAxHNDkr920arY+c3F/UUbZx5uePz/YAwAqMZ+h"*)(*]VB*)(*|*),(*|*)(*VB[*)(EventObject[<|"Id" -> "12c9ebfb-489e-419e-8d32-61e984dd9a74", "Initial" -> {5., Sinc}, "View" -> "c8966543-e647-49f5-91d5-35e82af21e90"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKJ1tYmpmZmhjrppqZmOuaWKaZ6loappjqGpumWhglphkZploaAAB1lxT/"*)(*]VB*)}}(*]GB*)
Or custom dynamics
radius = 1.0; Graphics[{Hue[radius // Offload], Disk[{0,0}, radius // Offload]}, ImageSize->Small] EventHandler[InputRange[0,1,0.1], (radius = #)&]
(*VB[*)(Graphics[{Hue[Offload[radius]], Disk[{0, 0}, Offload[radius]]}, ImageSize -> Small])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KWlMIB4HkHAvSizIyEwuhoiA5H0yi0sgqplBqktTIRx2IOGflpaTn5hSzAZkFyWmZJYiaXPJLM5GNSQTSDOACeJMCCrNSS3mBDI8cxPTU4Mzq1KLWYG84NzEnBwAm6MoCw=="*)(*]VB*)
(*VB[*)(EventObject[<|"Id" -> "14f363aa-79a2-415e-a632-320d3cf23de7", "Initial" -> 0.5, "View" -> "35294751-5497-49ac-9c79-51727b990b44"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKG5saWZqYmxrqmppYmuuaWCYm61omm1vqmhqaG5knWVoaJJmYAABp1BRx"*)(*]VB*)
FrontSubmit callsโ
Here this is done indirectly by EmitSound
EventHandler[InputButton[], (Sound[SoundNote["C5"]] // EmitSound)&]
(*VB[*)(EventObject[<|"Id" -> "72504de6-472e-4867-8ee7-a0093bc4f680", "Initial" -> False, "View" -> "5f9aa11d-3952-4376-8bc5-3c11b423434c"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKm6ZZJiYaGqboGluaGumaGJub6VokJZvqGicbGiaZGBmbGJskAwB88RUJ"*)(*]VB*)
Another example now with Plotly
p = Plotly[{<| "values" -> {19, 26, 10}, "labels" -> {"Residential", "Non-Residential", "Utility"}, "type" -> "pie" |>}]
(*VB[*)(FrontEndRef["4a687ce6-33bb-471d-8db5-e8ce9393f151"])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKmySaWZgnp5rpGhsnJemamBum6FqkJJnqplokp1oaWxqnGZoaAgCHcxWy"*)(*]VB*)
EventHandler[InputRange[0,100,10], PlotlyAnimate[p, <|"data" -> {<|"values" -> {19, 26, #}|>}, "traces" -> {0} |>, <||>]& ]
(*VB[*)(EventObject[<|"Id" -> "ee2d0524-c254-4dde-93f2-8b37fb4e045a", "Initial" -> 50, "View" -> "baba10ff-5481-427f-9ce6-1ba59e280380"|>])(*,*)(*"1:eJxTTMoPSmNkYGAoZgESHvk5KRCeEJBwK8rPK3HNS3GtSE0uLUlMykkNVgEKJyUmJRoapKXpmppYGOqaGJmn6Vomp5rpGiYlmlqmGlkYGFsYAACN1hWe"*)(*]VB*)
The same works for slides, i.e. SlideEventListener
will also be captured by Pavlov Machine if you have one automatically
Docker Imageโ
We refined our docker image with a help of Yan Loose and testing done by @RomchikL. Deploy it in a single line
docker run -it
-v ~/wljs:"/home/wljs/WLJS Notebooks"
-v ~/wljs/Licensing:/home/wljs/.WolframEngine/Licensing
-e PUID=$(id -u)
-e PGID=$(id -g)
-p 8000:3000
--name wljs
ghcr.io/jerryi/wolfram-js-frontend:main
It will prompt you a login and password from Wolfram account and then start a server at
http://127.0.0.1:8000
This docker image includes
- all latest libraries of WLJS
- WLJS Notebook
- Wolfram Engine >=14.2
- Nginx proxy
See more options here.
Autotestsโ
We integrated playwright
into our workflow to capture any bugs before the release. For now we stick to integration tests using screenshots of DOM elements.
Feel free to contribute. All tests are in the main repo.
ESM and Shell cellsโ
Both of them finally got a full support on Windows Machines!
.sh dir
Ballon animation by Jemima (codepen)