From 6367aa11ef0b99d86693b685ab67096514792a0f Mon Sep 17 00:00:00 2001
From: Norbert Preining <norbert@preining.info>
Date: Thu, 10 Mar 2022 03:04:28 +0000
Subject: CTAN sync 202203100304

---
 macros/latex/contrib/lwarp/lwarp.dtx | 2325 +++++++++++++++++++++++++++-------
 1 file changed, 1894 insertions(+), 431 deletions(-)

(limited to 'macros/latex/contrib/lwarp/lwarp.dtx')

diff --git a/macros/latex/contrib/lwarp/lwarp.dtx b/macros/latex/contrib/lwarp/lwarp.dtx
index 9800198020..38e6532986 100644
--- a/macros/latex/contrib/lwarp/lwarp.dtx
+++ b/macros/latex/contrib/lwarp/lwarp.dtx
@@ -16,7 +16,7 @@
 % \iffalse
 %<package>\NeedsTeXFormat{LaTeX2e}[1999/12/01]
 %<package>\ProvidesPackage{lwarp}
-%<package>    [2022/02/01 v0.903  Allows LaTeX to directly produce HTML5 output.]
+%<package>    [2022/03/09 v0.904  Allows LaTeX to directly produce HTML5 output.]
 %
 %<*driver>
 \documentclass{ltxdoc}
@@ -1272,6 +1272,25 @@ seamlessly integrating with the rest of the \HTML\ output, including any math
 appearing in non-\MathJax\ \SVG\ output.
 \end{enumerate}
 
+\subsubsection{\MathJax\ rendering options}
+
+\trouble[fonts]{mathjax=\MathJax>font}
+\trouble{mathjax=\MathJax>rendering}
+\trouble{font>mathjax=\MathJax}
+\gindex{mathjax=\MathJax>rendering}
+\gindex{mathjax=\MathJax>font}
+\gindex{font>mathjax=\MathJax}
+
+\MathJax\ v3 may render using \acro{chtml} or \SVG.
+\SVG\ display renders italic characters correctly.
+To select \SVG\ rendering, right-click on some math,
+and select
+\begin{UIdisplay}
+Math Settings $\to$ Math Renderer $\to$ SVG
+\end{UIdisplay}
+
+Wait a moment for the math to rerender.
+
 \subsubsection{Customizing \MathJax}
 \label{sec:limitscustomizemathjax}
 \gindex{mathjax=\MathJax>custom functions}
@@ -2887,37 +2906,47 @@ For wrapped figures, overhang and number of lines are ignored.
 }
 
 \newcommand{\limitssiunitx}{%
-\pkg{sunitx} v3 is not yet supported.  For now, specify version 2:
-\trouble[v3 not yet!]{siunitx=\pkg{siunitx}>v3}
-\begin{sourcedisplay}
-\cs{usepackage}\{siunitx\}\textred{[=v2]}
-\end{sourcedisplay}
-This may be also be necessary before loading other packages which also use \pkg{siunitx},
-such as \pkg{chemmacros}.
+\pkg{siunitx} is well supported by \pkg{lwarp}.
+
+\paragraph{Limitations} Some general limitations:
 
 Due to \prog{pdftotext} limitations, fraction output is replaced by symbol
 \margintag{fractions}
 output for \optn{per-mode} and \optn{quotient-mode}.
 
-Some units will require that the expression be placed inside math mode.
-\trouble[math mode required]{siunitx=\pkg{siunitx}}
+\cs{cancel} is not currently supported for \pkg{siunitx} v3.
+
+Negative values are not automatically colored.
+
+% Some units will require that the expression be placed inside math mode.
+% \trouble[math mode required]{siunitx=\pkg{siunitx}}
 
-Tabular \texttt{S} and {s} columns are rendered as simple \texttt{c} columns.
+Tabular \texttt{S} and {s} columns are rendered as simple \texttt{c} columns,
+although key settings will be set.
 \trouble[\env{tabular}]{siunitx=\pkg{siunitx}>tabular S and s columns}
-These may be replaced by \texttt{c} columns with each cell contained in
-\cs{num} or \cs{si}.
-
-For math mode with \SVG\ display, the original \pkg{siunitx} code is used while
-generating the \SVG\ image.
-For text mode, \pkg{lwarp} uses an emulation which provides a very effective
-\HTML\ interpretation of \pkg{siunitx}.
-For math expressions while using \MathJax,
-\trouble{siunitx=\pkg{siunitx}>mathjax=\MathJax}
-\trouble[MathJax]{mathjax=\MathJax>siunitx=\pkg{siunitx}}
-a limited emulation is used.
-Most functions work reasonably well, but many options cannot be emulated.
-Complicated parsing such as for \cs{ang} is not supported.
-The result usually looks fine, and otherwise is enough to get the meaning across.
+If using scientific notation, \optn{table-format},
+\optn{table-align-uncertainty}, \optn{drop-exponent}, etc..
+use \cs{tablenum} for each cell.
+This is especially required for \optn{drop-exponent},
+\trouble[\optn{drop-exponent}]{siunitx=\pkg{siunitx}>drop-exponent=\optn{drop-exponent}}
+without which the value will be shown incorrectly.
+
+\optn{table-auto-round} is ignored.
+\trouble[\optn{table-auto-round}]{siunitx=\pkg{siunitx}>table-auto-round=\optn{table-auto-roound}}
+
+\paragraph{Math rendering} Math may be rendered in several ways in the same document:
+
+\begin{description}
+\item [For math mode with \SVG\ display:] The original \pkg{siunitx} code is used while
+    generating the \SVG\ image.
+
+\item [For \HTML\ text mode:] \pkg{lwarp} uses \pkg{siunitx} code patched for \HTML,
+    and simplified units.
+
+\item [For math expressions while using \MathJax:] A limited emulation is used.
+    Most functions work reasonably well, but many options cannot be emulated.
+    The result usually looks fine, and otherwise is enough to get the meaning across.
+\end{description}
 
 % \pkg{lwarp}'s \MathJax\ emulation for \pkg{siunitx} is meant to be a
 % stop-gap measure until an extension is included in \MathJax.
@@ -2928,15 +2957,58 @@ The result usually looks fine, and otherwise is enough to get the meaning across
 % See \cs{MathJaxFilename} to select a custom \MathJax\ script, but \pkg{lwarp}'s
 % emulation would have to be diabled as well.
 
-Document modifications required for \MathJax:
+\paragraph{Custom units} \pkg{siunitx} allows customized units:
+
+\DescribeMacro{\DeclareSIUnit} \marg{name} \marg{definition}
+
+    \cs{DeclareSIUnit} declares a version of the unit for the print version.
+    This is also used when the unit is printed in \SVG\ math
+    or a \env{lateximage}.
+    It is also used for \HTML\ if an \HTML-specific version is not defined
+    with \cs{HTMLDeclareSIUnit}.
+\begin{sourcedisplay}
+\cs{DeclareSIUnit}\cs{myunit}\{\cs{ensuremath}\{\cs{text}\{m\}\_{}y\}\}
+\end{sourcedisplay}
+
+\DescribeMacro{\HTMLDeclareSIUnit} \marg{name} \marg{definition}
+
+    Use this after the print unit has been defined.
+\trouble[v3 only!]{siunitx=\pkg{siunitx}>\cs{HTMLDeclareSIUnit}}
+    For \pkg{siunitx} v3,
+    \cs{HTMLDeclareSIUnit} declares a simplified version of the unit for \HTML,
+    for example if the print-mode unit uses \TeX\ boxes or \cs{ensuremath}:
+\begin{sourcedisplay}
+\cs{HTMLDeclareSIUnit}\cs{myunit}\{\cs{text}\{m\}\cs{textsubscript}\{\cs{textit}\{y\}\}\}
+\end{sourcedisplay}
+
+It is also possible to provide a custom unit for \MathJax:
+\begin{sourcedisplay}
+\cs{CustomizeMathJax}\{\cs{newcommand}\{\cs{myunit}\}\{\cs{text}\{m\}\_{}y\}\}
+\end{sourcedisplay}
+
+\paragraph{Predefined units} Most units work as-is with \HTML.
+For the following units, \pkg{lwarp} has already set \cs{HTMLDeclareSIUnit}:
+\cs{celsius}, \cs{arcminute}, \cs{arcsecond}, \cs{elementarycharge}, 
+\cs{clight}, \cs{bohr}, \cs{electronmass}, \cs{hartree}, \cs{planckbar}.
+
+\paragraph{Document modifications required for \MathJax}
+\trouble{siunitx=\pkg{siunitx}>mathjax=\MathJax}
+\trouble[MathJax]{mathjax=\MathJax>siunitx=\pkg{siunitx}}
 \begin{itemize}
 \item Place \cs{sisetup} in the preamble before \texttt{\cs{begin}\{document\}}.
     \watchout[\cs{sisetup}]
     Changes made later may be ignored, especially with \MathJax.
     The \MathJax\ emulation also ignores most macro options.
+\item Complex numbers are displayed as entered,
+    \watchout[complex numbers]
+    ignoring \optn{output-complex-root}.
 \item Custom units may be added with \cs{CustomizeMathJax}.
     \margintag{custom units}
-    See the \pkg{lwarp-siunitx} code for examples.
+    For example, from \pkg{lwarp-common-mathjax-siunitx}:
+    \begin{sourcedisplay}
+    \cs{CustomizeMathJax}\{\cs{newcommand}\{\cs{hartree}\}\{\cs{mathit}\{E\}\_{}\{\cs{mathrm}\{h\}\}\}\} \\
+    \cs{CustomizeMathJax}\{\cs{newcommand}\{\cs{angstrom}\}\{\cs{mathrm}\{\cs{unicode}\{x212B\}\}\}\}
+    \end{sourcedisplay}
 \item Units work better using \texttt{\textasciitilde} between units
     \watchout[unit spacing]
     instead of using periods.
@@ -2949,6 +3021,8 @@ Document modifications required for \MathJax:
     Single units do not require braces.
 \item For \cs{numlist}, the argument is printed as text as-is,
     so use space between semicolons for improved readability.
+\item If using \optn{parse-numbers = false}, also use \cs{num} or \cs{qty}.
+    \watchout[\texttt{Missing \$\ inserted}]{siunitx=\pkg{siunitx}>Missing \$\ inserted.}
 \end{itemize}
 
 Also see \nameref{sec:limitsmathjax}, \cref{sec:limitsmathjax}.
@@ -3172,7 +3246,7 @@ This boolean may be tested by the user for later use.
 %<*package>
 % \fi
 %
-% \CheckSum{54471}
+% \CheckSum{55400}
 %
 % \CharacterTable
 % {Upper-case     \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
@@ -3318,6 +3392,7 @@ This boolean may be tested by the user for later use.
 % \changes{v0.902}{2021/10/01}{\ 2021/10/01}
 % \changes{v0.903}{2021/12/23}{Now uses \cs{IfPackageLoadedTF}, etc.}
 % \changes{v0.903}{2022/02/01}{\ 2022/02/01}
+% \changes{v0.904}{2022/03/09}{\ 2022/03/09}
 
 
 
@@ -3552,6 +3627,16 @@ This boolean may be tested by the user for later use.
 %
 % \begin{description}
 % \needspace{2\baselineskip}
+% \item[v0.904:] Added \pkg{siunitx} v3.
+%   \begin{itemize}
+%       \item Fixed \HTML\ tags inside non-Latin text.
+%       \item \MathJax\ now defaults to \SVG\ rendering.
+%       \item Added \pkg{siunitx} v3.  Updated \pkg{siunitx-v2}.
+%           See \cref{sec:limitssiunitx} for limitations.
+%       \item Updated \pkg{caption}, \pkg{chemmacros}, \pkg{fbox}, \pkg{hyperref},
+%               \pkg{multicol}, \pkg{wrapfig2}.
+%   \end{itemize}
+% \needspace{2\baselineskip}
 % \item[v0.903:] Various updates and improvements.
 %   \begin{itemize}
 %       \item Error if \prog{pdftotext} not available.
@@ -12050,21 +12135,46 @@ This boolean may be tested by the user for later use.
 %
 % \changes{v0.25}{2017/03/22}{Docs: Testing \pkg{lwarp}.}
 %
+% Compiling \filenm{lwarp.ins} generates all the \filenm{*.sty} files for \pkg{lwarp}.
+% It can be useful to create additional \filenm{*.ins} files to be able to
+% recompile only the pieces which have changed.
+%
+% For example,
+% \margintag{compiling individual packages}
+% to be able to recompile the \pkg{lwarp} core alone,
+% \DescribeFile{core.ins}
+% copy \filenm{lwarp.ins} to \filenm{core.ins},
+% then modify \filenm{core.ins} to only compile:
+% \begin{sourceverb}
+% \generate{
+% \file{lwarp.sty}{\from{lwarp.dtx}{package}}
+% }
+% \end{sourceverb}
+%
+% For individual packages, create \filenm{packagename.ins}, set to compile only:
+% \begin{sourceverb}
+% \generate{
+% \file{lwarp-packagename.sty}{\from{lwarp.dtx}{packagename}}
+% }
+% \end{sourceverb}
+%
 % When changes have been made, test the print output before testing the
 % \HTML.  The print output compiles faster, and any errors in the printed
 % version will be easier to figure out than the \HTML\ version.
 %
-% Remember that the configuration files are only rewritten when compiling the
+% Remember that the configuration files
+% \margintag{compiling \CSS\ and other generated files}
+% are only rewritten when compiling the
 % printed version of the document.
 %
 % \changes{v0.57}{2018/05/28}{Docs: Recompiling \prog{lwarpmk} or \CSS\ files.}
 % When changing the source to \prog{lwarpmk} or a \CSS\ file in \filenm{lwarp.dtx}:
 % \begin{enumerate}
 % \item Change the source in \filenm{lwarp.dtx}.
-% \item |pdflatex lwarp.ins|
+% \item |pdflatex lwarp.ins| -or- |pdflatex core.ins|
 % \item |pdflatex lwarp.dtx|
 % \item If modifying \prog{lwarpmk} the new version should now be active.
-% \item If modifying \CSS\ files:
+% \item If modifying \CSS\ files or other files generated by \pkg{lwarp}:
 %   \begin{enumerate}
 %   \item For the document, |lwarpmk print| to update the \CSS\ files
 %       in the project.
@@ -13650,6 +13760,7 @@ This boolean may be tested by the user for later use.
 \LWR@loadafter{lips}
 \LWR@loadafter{listings}
 \LWR@loadafter{listliketab}
+\LWR@loadafter{lltjp-siunitx}
 \LWR@loadafter{lltjp-tascmac}
 \LWR@loadafter{longtable}
 \LWR@loadafter{lpic}
@@ -18114,7 +18225,7 @@ span.textnormal, div.textnormal {
     font-variant: normal;
     font-variant-numeric: normal ;
     font-family: "DejaVu Serif", "Bitstream Vera Serif",
-    "Lucida Bright", Georgia, serif;
+        "Lucida Bright", Georgia, serif;
 }
 
 span.textmd, div.textmd { font-weight: normal; }
@@ -20541,6 +20652,8 @@ page_compositor "."
 % \changes{v0.891}{2020/09/07}{File: \filenm{lwarp_mathjax.txt}: Renamed \filenm{tagformat} extension.}
 % \changes{v0.892}{2020/09/26}{File: \filenm{lwarp_mathjax.txt}: Added \cs{left} \Slash \cs{right} delimiters.}
 % \changes{v0.895}{2021/01/13}{File: \filenm{lwarp_mathjax.txt}: Added \cs{ifblank}, \cs{ifstrequal} macros.}
+% \changes{v0.904}{2022/02/21}{File: \filenm{lwarp_mathjax.txt}: Added \cs{gsub} macro.}
+% \changes{v0.904}{2022/02/25}{File: \filenm{lwarp_mathjax.txt}: Defaults to \SVG\ instead of \acro{chtml}.}
 % ^^A *lwarp_mathjax.txt
 %
 % \codeconfig
@@ -20593,12 +20706,13 @@ MathJax = {
       }
 
       //  Create the command map for:
-      //    \ifstar, \ifnextchar, \ifblank, \ifstrequal, \seteqnumber
+      //    \ifstar, \ifnextchar, \ifblank, \ifstrequal, \gsub, \seteqnumber
       new CommandMap('Lwarp-macros', {
         ifstar: 'IfstarFunction',
         ifnextchar: 'IfnextcharFunction',
         ifblank: 'IfblankFunction',
         ifstrequal: 'IfstrequalFunction',
+        gsubstitute: 'GsubstituteFunction',
         seteqnumber: 'SeteqnumberFunction'
       }, {
         //  This function implements an ifstar macro.
@@ -20641,6 +20755,15 @@ MathJax = {
           useArgument(parser, isequal ? resultequal : resultnotequal);
         },
 
+        // This function implements a gsub macro.
+        GsubstituteFunction(parser, name) {
+          const gsubfirst = parser.GetArgument(name);
+          const gsubsecond = parser.GetArgument(name);
+          const gsubthird = parser.GetArgument(name);
+          let gsubresult=gsubfirst.replace(gsubsecond, gsubthird);
+          useArgument(parser, gsubresult);
+        },
+
         //  This function modifies the equation numbers.
         SeteqnumberFunction(parser, name) {
             //  Get the macro parameters
@@ -20741,7 +20864,7 @@ MathJax = {
 
 <script
     id="MathJax-script"
-    src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml.js"
+    src="https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-svg.js"
 ></script>
 \end{filecontents*}
 % \end{Verbatim}% for syntax highlighting
@@ -20878,7 +21001,7 @@ MathJax = {
 -- Copyright 2016-2022 Brian Dunn
 
 
-printversion = "v0.903"
+printversion = "v0.904"
 requiredconfversion = "2" -- also at *lwarpmk.conf
 
 function printhelp ()
@@ -22233,7 +22356,6 @@ end -- not --version
 %    \end{macrocode}
 % \end{macro}
 
-
 % \DescribeBoolean{LWR@mathmacro} True if currently defining math macros.
 %   Used to disable \SVG\ math hashing and \MathJax\ math contents while
 %   defining a macro using inline math.
@@ -22269,6 +22391,30 @@ end -- not --version
 %    \end{macrocode}
 
 
+% \codehtml
+%    \begin{macrocode}
+\begin{warpHTML}
+%    \end{macrocode}
+
+% A definition for |&| in case it is referred to after
+% \cs{StartDefiningTabulars} but outside a \env{tabular}.
+% \changes{v0.904}{2022/03/03}{Warn if \& outside \env{tabular}.}
+%    \begin{macrocode}
+\StartDefiningTabulars
+\protected\gdef&{%
+    \PackageWarning{lwarp}{%
+        An ampersand is being used inside a tabular\MessageBreak
+    }%
+}%
+\StopDefiningTabulars
+%    \end{macrocode}
+
+%    \begin{macrocode}
+\end{warpHTML}
+%    \end{macrocode}
+
+
+
 % \section{Localizing dynamic math}
 % \label{sec:localizingdynamicmath}
 % \trouble{SVG image>math incorrect>dymamic}
@@ -22353,21 +22499,69 @@ end -- not --version
 %    \end{macrocode}
 
 % \HTML\ Unicode entities:
+
 %    \begin{macrocode}
 \let\LWR@origampersand\&
 %    \end{macrocode}
+
+
+% \begin{macro}{\LWR@fontfortags} \marg{macro name}
+%
+% Forces roman TT font for \HTML\ tags.
+% \changes{v0.904}{2022/03/02}{Improved font control.}
+%    \begin{macrocode}
+\newrobustcmd*{\LWR@fontfortags}[1]{%
+    \ifmmode%
+        \PackageError{lwarp}%
+            {%
+                An HTML tag was generated inside math.\MessageBreak
+                This should never occur.\MessageBreak
+                Something is broken in Lwarp%
+            }%
+            {(Using #1.)}%
+    \else%
+%    \end{macrocode}
+%
+% Used by \pkg{ltjtbook}, \pkg{platex}, and related.
+%    \begin{macrocode}
+        \ifdef{\romanencoding}%
+            {%
+                \romanencoding{\encodingdefault}%
+            }%
+            {%
+%    \end{macrocode}
+%
+% Used by \pkg{babel}:
+%    \begin{macrocode}
+                \ifdef{\latintext}
+                    {\latintext}
+                    {\fontencoding\encodingdefault}%
+            }%
+        \LWR@print@normalfont%
+        \LWR@origttfamily%
+    \fi%
+}
+%    \end{macrocode}
+% \end{macro}
+
 % \begin{macro}{\HTMLentity} \marg{entitytag}
+%
+% \cs{protect} is in case the tag appears in \TOC, \LOF, \LOT.
+%
+% \changes{v0.904}{2022/02/19}{Improved font control.}
 %    \begin{macrocode}
 \newcommand*{\HTMLentity}[1]{%
 % \LWR@traceinfo{HTMLentity \detokenize{#1}}%
-\begingroup%
-\LWR@hook@processingtags%
-\LWR@origampersand#1;%
-\endgroup%
+    \begingroup%
+    \LWR@hook@processingtags%
+    \LWR@fontfortags{HTMLentity}%
+    \protect\LWR@origampersand\LWR@isolate{#1};%
+    \endgroup%
 % \LWR@traceinfo{HTMLentity done}%
 }
 %    \end{macrocode}
 % \end{macro}
+
 % \begin{macro}{\HTMLunicode} \marg{hex\_unicode}
 %    \begin{macrocode}
 \newcommand*{\HTMLunicode}[1]{\HTMLentity{\LWR@origpound{}x#1}}
@@ -23221,13 +23415,15 @@ end -- not --version
 % Break ligatures and use upright apostrophes in \HTML\ tags.
 %
 % \cs{protect} is in case the tag appears in \TOC, \LOF, \LOT.
+%
 % \changes{v0.85}{2020/04/30}{Fix: Added print macros for \pkg{fontspec}.}
+% \changes{v0.904}{2022/02/19}{Improved font control.}
 %    \begin{macrocode}
 \newcommand*{\LWR@htmltagc}[1]{%
     \LWR@traceinfo{LWR@htmltagc !\detokenize{#1}!}%
     \begingroup%
     \LWR@hook@processingtags%
-    \ifmmode\else\protect\LWR@print@normalfont\protect\LWR@origttfamily\fi%
+    \LWR@fontfortags{LWR@htmltagc}%
     \protect\LWR@origtextless%
     \LWR@isolate{#1}%
     \protect\LWR@origtextgreater%
@@ -23411,7 +23607,7 @@ end -- not --version
 % \LWR@traceinfo{LWR@htmlopencomment}%
     \begingroup%
     \LWR@hook@processingtags%
-    \ifmmode\else\protect\LWR@print@normalfont\protect\LWR@origttfamily\fi%
+    \LWR@fontfortags{LWR@htmlopencomment}%
     \LWR@print@mbox{\LWR@origtextless{}!-\/-}%
     \endgroup%
 }
@@ -23420,7 +23616,7 @@ end -- not --version
 % \LWR@traceinfo{LWR@htmlclosecomment}%
     \begingroup%
     \LWR@hook@processingtags%
-    \ifmmode\else\protect\LWR@print@normalfont\protect\LWR@origttfamily\fi%
+    \LWR@fontfortags{LWr@htmlclosecomment}%
     \LWR@print@mbox{-\/-\LWR@origtextgreater}%
     \endgroup%
 }
@@ -30949,22 +31145,7 @@ end -- not --version
 
 % \subsection{Parsing `w' columns}
 %
-% \begin{macro}{\LWR@parsewcolumn} \marg{this column type}
-% The width will be ignored.
-%
-% The arguments to the column type are absorbed by \cs{LWR@columntype@<char>},
-% defined by \cs{LWR@modifycolumntype}.
-%
-% The argument is ignored,
-% but provided for compatibility with \cs{LWR@parsenormalcolumn}.
-%
-%    \begin{macrocode}
-\newcommand*{\LWR@parsewcolumn}[1]{%
-    \LWR@columnspeclookahead{1}%
-    \expandafter\LWR@parsenormalcolumn\expandafter{\LWR@strresulttwo}%
-}
-%    \end{macrocode}
-% \end{macro}
+% |W| and |w| columns are handled via \pkg{array} with \cs{HTMLnewcolumntype}.
 
 
 % \subsection{Parsing '*' columns}
@@ -31204,14 +31385,6 @@ end -- not --version
 \LWR@modifycolumntype{b}{1}{LWR@parsenormalcolumn}
     {LWR@printmccoltype@normal}{LWR@printmccoldata@paragraph}
 %    \end{macrocode}
-% \changes{v0.56}{2018/05/10}{Added \pkg{array} \texttt{W} column.}
-%    \begin{macrocode}
-\LWR@modifycolumntype{w}{2}{LWR@parsewcolumn}
-    {LWR@printmccoltype@normal}{LWR@printmccoldata@normal}
-
-\LWR@modifycolumntype{W}{2}{LWR@parsewcolumn}
-    {LWR@printmccoltype@normal}{LWR@printmccoldata@normal}
-%    \end{macrocode}
 % A star column:
 %    \begin{macrocode}
 \LWR@modifycolumntype{*}{2}{LWR@parsestarcolumn}
@@ -31220,7 +31393,11 @@ end -- not --version
 %
 %
 %
-% \begin{macro}{\HTMLnewcolumntype} \marg{col type} \oarg{num args} \marg{replacement text}
+% \begin{macro}{\HTMLnewcolumntype}
+%   \marg{col type}
+%   \oarg{num args}
+%   \oarg{optional arg}
+%   \marg{replacement text}
 %
 % A user-level macro to creates an \HTML\ version
 % of the replacement text for the column type.
@@ -31233,11 +31410,20 @@ end -- not --version
 % \end{sourceverb}
 %
 % \changes{v0.901}{2021/08/17}{Improved \cs{newcolumntype} emulation.}
+% \changes{v0.904}{2022/03/05}{Added optional arg.}
 %    \begin{macrocode}
-\NewDocumentCommand{\HTMLnewcolumntype}{m O{0} m}{%
-    \expandafter\newcommand\expandafter*%
-        \csname LWR@HTML@NC@rewrite@#1\endcsname[#2]{\NC@find #3}%
-    \LWR@formatted{NC@rewrite@#1}%
+\NewDocumentCommand{\HTMLnewcolumntype}{m O{0} o m}{%
+    \IfValueTF{#3}
+    {
+        \expandafter\newcommand\expandafter*%
+            \csname LWR@HTML@NC@rewrite@#1\endcsname[#2][#3]{\NC@find #4}%
+        \LWR@formatted{NC@rewrite@#1}%
+    }
+    {
+        \expandafter\newcommand\expandafter*%
+            \csname LWR@HTML@NC@rewrite@#1\endcsname[#2]{\NC@find #4}%
+        \LWR@formatted{NC@rewrite@#1}%
+    }
 }
 %    \end{macrocode}
 % \end{macro}
@@ -31252,7 +31438,7 @@ end -- not --version
 %    \end{macrocode}
 %
 %    \begin{macrocode}
-\NewDocumentCommand{\HTMLnewcolumntype}{m O{0} m}{}
+\NewDocumentCommand{\HTMLnewcolumntype}{m O{0} o m}{}
 %    \end{macrocode}
 %
 %    \begin{macrocode}
@@ -37483,8 +37669,8 @@ end -- not --version
 
 \renewcommand*{\$}{%
     \ifnumcomp{\value{LWR@lateximagedepth}}{>}{0}%
-    {\LWR@origtextdollar}%
-    {\HTMLunicode{00024}}%
+        {\LWR@origtextdollar}%
+        {\HTMLunicode{00024}}%
 }
 %    \end{macrocode}
 
@@ -40075,7 +40261,8 @@ end -- not --version
 % \label{sec:siunitx}
 
 % \DescribePackage{siunitx}
-% The \pkg{lwarp} core passes a few options to \pkg{siunitx}.
+
+% A few \HTML\ unit equivalents are defined here.
 
 % \limitssiunitx
 %
@@ -40090,6 +40277,7 @@ end -- not --version
 % Options for siunitx:
 % \changes{v0.50}{2018/02/24}{\pkg{siunitx}: Improved units.}
 % \changes{v0.897}{2021/05/23}{\pkg{siunitx}: Rollback for v2.}
+% \changes{v0.904}{2022/02/19}{\pkg{siunitx}: Added v3.}
 %    \begin{macrocode}
 \newrobustcmd{\LWR@siunitx@textcelsius}{\HTMLentity{deg}C}
 \newrobustcmd{\LWR@siunitx@textdegree}{\HTMLentity{deg}}
@@ -40104,15 +40292,6 @@ end -- not --version
 \renewrobustcmd{\LWR@siunitx@textdblprime}{\text{\ensuremath{^{\prime\prime}}}}%
 \renewrobustcmd{\LWR@siunitx@textplanckbar}{\text{\ensuremath{\hbar}}}%
 }
-
-\PassOptionsToPackage{
-    detect-mode=true,
-    per-mode=symbol,	% fraction is not seen by pdftotext
-    text-celsius = {\LWR@siunitx@textcelsius},
-    text-degree = {\LWR@siunitx@textdegree},
-    text-arcminute = {\LWR@siunitx@textprime} ,
-    text-arcsecond = {\LWR@siunitx@textdblprime} ,
-}{siunitx-v2}
 %    \end{macrocode}
 
 %    \begin{macrocode}
@@ -40120,7 +40299,14 @@ end -- not --version
 %    \end{macrocode}
 
 
-
+% \codeprint
+%
+% The print version of \cs{HTMLDeclareSIUnit}.
+%    \begin{macrocode}
+\begin{warpprint}
+\NewDocumentCommand{\HTMLDeclareSIUnit}{o +m m}{}
+\end{warpprint}
+%    \end{macrocode}
 
 
 % \section{Graphics print-mode modifications}
@@ -41570,14 +41756,19 @@ color:\LWR@origpound\LWR@tempcolor%
 
 % \begin{macro}{\textnormal} \marg{text}
 % \changes{v0.902}{2021/09/28}{Reduce nested spans.}
+% \changes{v0.904}{2022/03/02}{Improved.}
 %    \begin{macrocode}
 \DeclareRobustCommand{\LWR@HTML@textnormal}[1]{%
-%     \textmd{\textrm{\textup{#1}}}%
         \LWR@HTML@mdseries%
         \LWR@HTML@rmfamily%
         \LWR@HTML@upshape%
+        \LWR@HTML@ulcshape%
         \InlineClass(%
-            font-weight:normal; font-family:serif; font-style:normal
+            font-weight: normal;
+            font-family: serif;
+            font-style: normal;
+            font-variant: normal;
+            font-variant-numeric: normal ;
         ){textnormal}{#1}%
 }
 
@@ -41632,6 +41823,7 @@ color:\LWR@origpound\LWR@tempcolor%
 % \changes{v0.48}{2018/02/02}{Added.  Improves font control.}
 % \changes{v0.56}{2018/04/27}{Added \attribute{span.textbf}, etc.}
 % \changes{v0.62}{2018/11/15}{Tracks depth to avoid nesting repeated font changes.}
+% \changes{v0.904}{2022/03/02}{Uses \optn{textnormal} if possible.}
 %    \begin{macrocode}
 \newcounter{LWR@textcurrentfontdepth}
 \setcounter{LWR@textcurrentfontdepth}{0}
@@ -41645,13 +41837,22 @@ color:\LWR@origpound\LWR@tempcolor%
         }%
         {%
             \addtocounter{LWR@textcurrentfontdepth}{1}%
-            \InlineClass{%
-                    text\LWR@f@family\LWR@origtilde{}%
-                    text\LWR@f@series\LWR@origtilde{}%
-                    text\LWR@f@shape\LWR@origtilde{}%
-                    text\LWR@f@shapecaps%
+            \ifboolexpr{%
+                test {\ifdefstring{\LWR@f@family}{rm}} and
+                test {\ifdefstring{\LWR@f@series}{md}} and
+                test {\ifdefstring{\LWR@f@shape}{up}} and
+                test {\ifdefstring{\LWR@f@shapecaps}{ulc}}
+            }%
+                {\InlineClass{textnormal}{#1}}%
+                {%
+                    \InlineClass{%
+                            text\LWR@f@family\LWR@origtilde{}%
+                            text\LWR@f@series\LWR@origtilde{}%
+                            text\LWR@f@shape\LWR@origtilde{}%
+                            text\LWR@f@shapecaps%
+                        }%
+                        {#1}%
                 }%
-                {#1}%
             \addtocounter{LWR@textcurrentfontdepth}{-1}%
         }%
 }
@@ -42000,13 +42201,16 @@ color:\LWR@origpound\LWR@tempcolor%
 %
 % \begin{macro}{\LWR@tempcolor}
 % \begin{macro}{\LWR@tempcolortwo}
+% \begin{macro}{\LWR@tempcolorthree}
 % The color converted to \HTML\ colorspace.
 %    \begin{macrocode}
 \newcommand*{\LWR@tempcolor}{}
 \newcommand*{\LWR@tempcolortwo}{}
+\newcommand*{\LWR@tempcolorthree}{}
 %    \end{macrocode}
 % \end{macro}
 % \end{macro}
+% \end{macro}
 %
 %
 % \begin{macro}{\LWR@findcurrenttextcolor}
@@ -44970,13 +45174,13 @@ color:\LWR@origpound\LWR@tempcolor%
 \LetLtxMacro\LWR@origmake@df@tag@@@\make@df@tag@@@
 
 \renewcommand*{\make@df@tag@@}[1]{%
-\LWR@remembertag{#1}%
-\LWR@origmake@df@tag@@{#1}%
+    \LWR@remembertag{#1}%
+    \LWR@origmake@df@tag@@{#1}%
 }
 
 \renewcommand*{\make@df@tag@@@}[1]{%
-\LWR@remembertag{#1}%
-\LWR@origmake@df@tag@@@{#1}%
+    \LWR@remembertag{#1}%
+    \LWR@origmake@df@tag@@@{#1}%
 }
 
 }% not mathjax
@@ -45881,6 +46085,7 @@ color:\LWR@origpound\LWR@tempcolor%
 %
 % Provide simplified column types for \HTML:
 % \changes{v0.901}{2021/08/12}{\pkg{array}: Improved \cs{newcolumntype} emulation.}
+% \changes{v0.904}{2022/03/05}{\pkg{array}: Improved \texttt{W} and \texttt{w} processing.}
 %    \begin{macrocode}
 \HTMLnewcolumntype{w}[2]{#1}
 \HTMLnewcolumntype{W}[2]{#1}
@@ -48670,6 +48875,7 @@ color:\LWR@origpound\LWR@tempcolor%
 %
 % \changes{v0.44}{2017/11/16}{\pkg{cancel}: Added.}
 % \changes{v0.87}{2020/06/02}{\pkg{cancel}: Now uses \MathJax\ v3 extension.}
+% \changes{v0.904}{2022/03/08}{\pkg{cancel}: Now \cs{LWR@formatted}.}
 %
 % \codehtml
 %
@@ -48681,17 +48887,6 @@ color:\LWR@origpound\LWR@tempcolor%
 %
 %
 % \cs{cancelto} is math-only, so is used as-is.
-%    \begin{macrocode}
-\LetLtxMacro\LWR@origcancel\cancel
-\LetLtxMacro\LWR@origbcancel\bcancel
-\LetLtxMacro\LWR@origxcancel\xcancel
-
-\appto\LWR@restoreorigformatting{%
-\LetLtxMacro\cancel\LWR@origcancel%
-\LetLtxMacro\bcancel\LWR@origbcancel%
-\LetLtxMacro\xcancel\LWR@origxcancel%
-}
-%    \end{macrocode}
 
 
 % \begin{noindmacro}{\LWR@cancelcolor}
@@ -48709,7 +48904,7 @@ color:\LWR@origpound\LWR@tempcolor%
 
 % \begin{noindmacro}{\cancel} \marg{text}
 %    \begin{macrocode}
-\DeclareRobustCommand{\cancel}[1]{%
+\DeclareRobustCommand{\LWR@HTML@cancel}[1]{%
 \begingroup%
 \CancelColor%
 \LWR@findcurrenttextcolor%
@@ -48718,6 +48913,7 @@ color:\LWR@origpound\LWR@tempcolor%
     {text-decoration:line-through}%
 \endgroup%
 }
+\LWR@formatted{cancel}%
 
 \LetLtxMacro\bcancel\cancel
 \LetLtxMacro\xcancel\cancel
@@ -48898,6 +49094,19 @@ s%
 %    \end{macrocode}
 
 
+% \changes{v0.904}{2022/03/04}{\pkg{caption}: Added \cs{captiontext}.}
+%    \begin{macrocode}
+\long\def\caption@@@text#1#2#3[#4]#5{%
+    \begin{BlockClass}{figurecaption}%      lwarp
+  \begingroup
+    #3{\csname c@#1\endcsname #4\relax}%
+    #2{\caption@fnum{#1}}{#5}%
+  \endgroup%
+    \end{BlockClass}%                       lwarp
+}
+%    \end{macrocode}
+
+
 % Updates for late patches for \pkg{scrextend}:
 % \changes{v0.88}{2020/07/15}{\pkg{caption}, \pkg{scrextend}: Fixed \cs{caption*}.}
 %    \begin{macrocode}
@@ -49102,7 +49311,16 @@ s%
 \renewcommand{\caption@@make@}[2]{%
   \caption@stepthecounter%
   \caption@beginhook%
+%   \caption@box\hsize{%
+%     \caption@singlelinecheck{\caption@slc{#1}{#2}\caption@singleline\caption@multiline}{\caption@multiline}%
+%     \caption@calcmargin
+%     \caption@make@leftmargin
+%     \caption@make@parbox{%
+%       \caption@make@indention
       \caption@@@make{#1}{#2}%
+%     }
+%     \caption@make@rightmargin
+%   }%
   \caption@endhook%
 }
 %    \end{macrocode}
@@ -49990,7 +50208,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
 % \codehtml
 %
 %    \begin{macrocode}
-\LWR@ProvidesPackagePass{chemformula}[2019/10/13]
+\LWR@ProvidesPackagePass{chemformula}[2022/01/23]
 %    \end{macrocode}
 
 %    \begin{macrocode}
@@ -50400,7 +50618,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
 % \codehtml
 %
 %    \begin{macrocode}
-\LWR@ProvidesPackagePass{chemmacros}[2017/08/28]
+\LWR@ProvidesPackagePass{chemmacros}[2022/02/13]
 %    \end{macrocode}
 %
 % \SVG\ file hashing assumes that the relevent options are constant for the entire document.
@@ -50437,22 +50655,45 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
 % \subsection{Code}
 %
 %
+%    \begin{macrocode}
+\ExplSyntaxOn
+%    \end{macrocode}
+%
+%
+% \subsection{Loading packages}
+%
+% Also accept the \pkg{lwarp} version:
+% \changes{v0.904}{2022/03/03}{\pkg{chemmacros}: Accept \pkg{lwarp} version of pkgs.}
+%    \begin{macrocode}
+\prg_set_conditional:Npnn \chemmacros_if_package_loaded:n #1 {p,T,F,TF}
+  {
+    \cs_if_exist:cTF {ver@#1.sty}
+      { \prg_return_true: }
+      {
+        \cs_if_exist:cTF {ver@lwarp-#1.sty}
+            { \prg_return_true: }
+            { \prg_return_false: }
+      }
+  }
+%    \end{macrocode}
+%
+% Nullify \pkg{hyperref} detection:
+% \changes{v0.904}{2022/03/03}{\pkg{chemmacros}: Nullify \pkg{hyperref} detection.}
+%    \begin{macrocode}
+\hook_gput_code:nnn {begindocument/end} {chemmacros}
+  {
+      \bool_set_false:N \l__chemmacros_hyperref_bool
+  }
+%    \end{macrocode}
+%
+%
+%
 % \subsection{Loading modules}
 %
 % Patching \pkg{chemmacros} modules must be done \cs{AtBeginDocument},
 % since modules are invoked by the user in the preamble, and each patch is
 % only done if the module is loaded.
 %
-%    \begin{macrocode}
-\ExplSyntaxOn
-
-\newcommand{\@ifchemmacrosmoduleloaded}[1]{%
-\@ifl@aded{\c__chemmacros_module_extension_tl}{\c__chemmacros_module_prefix_tl.#1}%
-}
-
-\ExplSyntaxOff
-%    \end{macrocode}
-%
 %
 % \subsection{New environments}
 % \label{sec:chemmacroshtmlenvs}
@@ -50484,17 +50725,12 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
 % \end{noindenvironment}
 %
 %
-%    \begin{macrocode}
-\ExplSyntaxOn
-%    \end{macrocode}
-%
-%
 % \subsection{Acid-base}
 %
 % \changes{v0.903}{2021/12/18}{\pkg{chemmacros}: Improved alt tag sanitization.}
 %    \begin{macrocode}
 \AtBeginDocument{
-\@ifchemmacrosmoduleloaded{acid-base}{
+\chemmacros_module_if_loaded:nTF{{acid-base}}{
 \PackageInfo{lwarp}{Patching~chemmacros~module~acid-base}
 
 \cs_gset_protected:Npn \chemmacros_p:n #1
@@ -50526,7 +50762,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
     \begingroup
     \boolfalse{mathjax}
     \LWR@subsingledollar*{\textbackslash{}pH}{chemmacros}{
-        \chemmacros_p:n { \chemmacros_chemformula:n {H} }
+        \chemmacros_p:n { \chemmacros_formula:n {H} }
     }
     \endgroup
 }
@@ -50535,7 +50771,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
     \begingroup
     \boolfalse{mathjax}
     \LWR@subsingledollar*{\textbackslash{}pOH}{chemmacros}{
-        \chemmacros_p:n { \chemmacros_chemformula:n {OH} }
+        \chemmacros_p:n { \chemmacros_formula:n {OH} }
     }
     \endgroup
 }
@@ -50598,7 +50834,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
     \endgroup
 }
 
-}{}% \@ifchemmacrosmoduleloaded
+}{}% module loaded
 }% AtBeginDocument
 %    \end{macrocode}
 %
@@ -50607,7 +50843,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
 %
 %    \begin{macrocode}
 \AtBeginDocument{
-\@ifchemmacrosmoduleloaded{charges}{
+\chemmacros_module_if_loaded:nTF{{charges}}{
 \PackageInfo{lwarp}{Patching~chemmacros~module~charges}
 
 \cs_gset_protected:Npn \fplus  {
@@ -50625,7 +50861,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
     \endgroup
 }
 
-}{}% \@ifchemmacrosmoduleloaded
+}{}% Module loaded.
 }% AtBeginDocument
 %    \end{macrocode}
 %
@@ -50634,16 +50870,16 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
 %
 %    \begin{macrocode}
 \AtBeginDocument{
-\@ifchemmacrosmoduleloaded{nomenclature}{
+\chemmacros_module_if_loaded:nTF{{nomenclature}}{
 \PackageInfo{lwarp}{Patching~chemmacros~module~nomenclature}
 
 \cs_gset_protected:Npn \chemmacros_charge:n #1
   {
     \ifnumcomp{\value{LWR@lateximagedepth}}{>}{0}
-    {\chemmacros_chemformula:n { {}^{#1} }}
+    {\chemmacros_formula:n { {}^{#1} }}
     {
         \ifmmode
-            {\chemmacros_chemformula:n { {}^{#1} }}
+            {\chemmacros_formula:n { {}^{#1} }}
         \else
             { \textsuperscript{\ensuremath{#1}} }
         \fi
@@ -50663,7 +50899,6 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
 % ^^A \RenewChemIUPAC \chemprime { \HTMLunicode{2032} }
 %
 %    \begin{macrocode}
-\ChemCompatibilityFrom{5.8}
 \cs_gset_protected:Npn \__chemmacros_cip:n #1
   {
     \tl_set:Nn \l__chemmacros_tmpa_tl {#1}
@@ -50680,7 +50915,6 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
         }}% lwarp
     }
   }
-\EndChemCompatibility
 %    \end{macrocode}
 %
 %    \begin{macrocode}
@@ -50706,9 +50940,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
         \chemmacros_coordination_symbol:nnnn
         { \l__chemmacros_coord_use_hyphen_bool }
         {
-            \chemmacros_if_compatibility:nnTF {>} {5.7}
             { \c_true_bool }
-            { \c_false_bool }
         }
         { \chemeta }
         {#1}
@@ -50724,9 +50956,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
         \chemmacros_coordination_symbol:nnnn
         { \l__chemmacros_coord_use_hyphen_bool }
         {
-            \chemmacros_if_compatibility:nnTF {>} {5.7}
             { \c_true_bool }
-            { \c_false_bool }
         }
         { \chemkappa }
         {#1}
@@ -50747,7 +50977,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
     }
     \endgroup
   }
-}{}% \@ifchemmacrosmoduleloaded
+}{}% Module loaded.
 }% AtBeginDocument
 %    \end{macrocode}
 %
@@ -50756,7 +50986,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
 %
 %    \begin{macrocode}
 \AtBeginDocument{
-\@ifchemmacrosmoduleloaded{particles}{
+\chemmacros_module_if_loaded:nTF{{particles}}{
 \PackageInfo{lwarp}{Patching~chemmacros~module~particles}
 
 \cs_gset_protected:Npn \chemmacros_declare_nucleophile:Nn #1#2
@@ -50766,11 +50996,10 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
         \bool_if:NTF \l__chemmacros_nucleophile_elpair_bool
           {
             \chemmacros_elpair:n { #2 }
-            \chemmacros_if_compatibility:nnT {>=} {5.3}
               { \skip_horizontal:N \l__chemmacros_nucleophile_dim }
-            \chemmacros_chemformula:n { {}^{-} }
+            \chemmacros_formula:n { {}^{-} }
           }
-          { \chemmacros_chemformula:n { #2^{-} } }
+          { \chemmacros_formula:n { #2^{-} } }
       }
     \DeclareDocumentCommand #1 {o}
       {%
@@ -50787,7 +51016,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
 \RenewChemNucleophile \Nuc {Nu}
 \RenewChemNucleophile \ba  {ba}
 
-}{}% \@ifchemmacrosmoduleloaded
+}{}% Module loaded.
 }% AtBeginDocument
 %    \end{macrocode}
 %
@@ -50796,7 +51025,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
 %
 %    \begin{macrocode}
 \AtBeginDocument{
-\@ifchemmacrosmoduleloaded{phases}{
+\chemmacros_module_if_loaded:nTF{{phases}}{
 \PackageInfo{lwarp}{Patching~chemmacros~module~phases}
 
 \cs_undefine:N \chemmacros_phase:n
@@ -50824,7 +51053,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
       }
   }
 
-}{}% \@ifchemmacrosmoduleloaded
+}{}% Module loaded.
 }% AtBeginDocument
 %    \end{macrocode}
 %
@@ -50832,7 +51061,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
 %
 %    \begin{macrocode}
 \AtBeginDocument{
-\@ifchemmacrosmoduleloaded{mechanisms}{
+\chemmacros_module_if_loaded:nTF{{mechanisms}}{
 \PackageInfo{lwarp}{Patching~chemmacros~module~mechanisms}
 
 \chemmacros_define_keys:nn {textmechanisms}
@@ -50944,15 +51173,18 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
   }%
 }
 
-}{}% \@ifchemmacrosmoduleloaded
+}{}% Module loaded.
 }% AtBeginDocument
 %    \end{macrocode}
 %
+%
 % \subsection{Newman}
 %
+% There are so many options that it is hard to hash these images for reuse.
+%
 %    \begin{macrocode}
 \AtBeginDocument{
-\@ifchemmacrosmoduleloaded{newman}{
+\chemmacros_module_if_loaded:nTF{{newman}}{
 \PackageInfo{lwarp}{Patching~chemmacros~module~newman}
 
 \RenewDocumentCommand \newman {od()m}%
@@ -50969,7 +51201,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
     \end{lateximage}
   }%
 
-}{}% \@ifchemmacrosmoduleloaded
+}{}% Module loaded.
 }% AtBeginDocument
 %    \end{macrocode}
 %
@@ -50978,7 +51210,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
 % \changes{v0.903}{2021/12/18}{\pkg{chemmacros}: Improved alt tag sanitization.}
 %    \begin{macrocode}
 \AtBeginDocument{
-\@ifchemmacrosmoduleloaded{orbital}{
+\chemmacros_module_if_loaded:nTF{{orbital}}{
 \PackageInfo{lwarp}{Patching~chemmacros~module~orbital}
 
 \RenewDocumentCommand \orbital {om}
@@ -51006,7 +51238,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
     \end{lateximage}
   }
 
-}{}% \@ifchemmacrosmoduleloaded
+}{}% Module loaded.
 }% AtBeginDocument
 %    \end{macrocode}
 %
@@ -51017,12 +51249,17 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
 %   \fqquad \marg{chem} \marg{math} \marg{args number} \marg{argument list (\{\#2\}\{\#3\}...)}
 %    \begin{macrocode}
 \AtBeginDocument{
-\@ifchemmacrosmoduleloaded{reactions}{
+\chemmacros_module_if_loaded:nTF{{reactions}}{
 \PackageInfo{lwarp}{Patching~chemmacros~module~reactions}
 
-\cs_gset_protected:Npn \chemmacros_declare_reaction_env:nnnn #1#2#3#4
+% #1: chem
+% #2: math
+% #3: args number
+% #4: argument list ({#2}{#3}...)
+\cs_gset_protected:Npn \__chemmacros_declare_reaction_env:nnnn #1#2#3#4
   {
-    \exp_args:Nnx \DeclareDocumentEnvironment {#1} { O{} \prg_replicate:nn {#3+0} {m} }
+    \exp_args:Nnx \DeclareDocumentEnvironment {#1}
+      { \int_compare:nT { #3+0 = 0 } {!} O{} \prg_replicate:nn {#3+0} {m} }
       {
         \boolfalse{mathjax}%                        lwarp
         \ifdefvoid{\LWR@ThisAltText}{%              lwarp
@@ -51030,13 +51267,15 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
         }{}%                                        lwarp
         \chemmacros_add_reaction_description:n {##1}
         \__chemmacros_begin_reaction:
-        \chemmacros_reaction_read:nnw {#2} {#4}
+        \__chemmacros_reaction_read:nnw {#2} {#4}
       }
       {
         \__chemmacros_end_reaction:
         \gdef\LWR@ThisAltText{}%                    lwarp
+        \ignorespacesafterend
       }
   }
+
 \cs_generate_variant:Nn \chemmacros_declare_reaction_env:nnnn {nnnV}
 
 \RenewChemReaction {reaction}   {equation}
@@ -51044,18 +51283,191 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
 \RenewChemReaction {reactions}  {align}
 \RenewChemReaction {reactions*} {align*}
 
-}{}% \@ifchemmacrosmoduleloaded
+}{}% Module loaded.
 }% AtBeginDocument
 %    \end{macrocode}
 % \end{noindmacro}
 %
 %
+% \subsection{Reactants}
+%
+% Recompiled for tabular ampersand processing,
+% with the only change being \cs{StartDefiningTabulars}.
+% \cs{xpatchcmd} does not work here.
+%
+%    \begin{macrocode}
+\StartDefiningTabulars%     lwarp
+
+% #1: star: include ID in table
+\RenewDocumentCommand \printreactants {s}
+  {
+    \group_begin:
+      \chemmacros_set_keys:nn {reactants} { switch = false }
+      \int_step_variable:nNn
+        { \seq_count:N \g_chemnum_initiated_compounds_seq }
+        \l__chemmacros_reactants_tmpa_tl 
+        {
+          \seq_put_right:Nx 
+            \l__chemmacros_reactants_tmpa_seq
+            {
+              \chemnum_cmpd:nnne { \c_false_bool } { \c_true_bool } {}
+                {
+                  \seq_item:NV
+                    \g_chemnum_initiated_compounds_seq
+                    \l__chemmacros_reactants_tmpa_tl
+                }
+              & 
+              \bool_if:nT {#1}
+                {
+                  \seq_item:NV
+                    \g_chemnum_initiated_compounds_seq
+                    \l__chemmacros_reactants_tmpa_tl
+                  &
+                }
+              % TODO: expl3-command ??
+              \solvent
+                {
+                  \seq_item:NV
+                    \g_chemnum_initiated_compounds_seq
+                    \l__chemmacros_reactants_tmpa_tl
+                }
+              \tabularnewline
+            }
+          \tl_set:Nx
+            \l__chemmacros_reactants_tmpb_tl
+            {
+              \seq_item:NV
+                \g_chemnum_initiated_compounds_seq
+                \l__chemmacros_reactants_tmpa_tl
+            }
+          \chemmacros_reactants_list_subreactant:Vn
+            \l__chemmacros_reactants_tmpb_tl
+            {#1}
+        }
+      % TODO: longtable ?
+      %       table customizable?
+      % first draft of two styles
+      \par
+      \noindent
+      \bool_if:NTF \l__chemmacros_reactants_printreactants_style_bool
+        {
+          \str_case:Vn \l__chemmacros_reactants_printreactants_style_str
+            {
+              {xltabular}
+              {
+                \chemmacros_if_package_loaded:nTF {xltabular}
+                  {   
+                    \bool_if:nTF {#1}
+                      {
+                        \begin {xltabular}
+                          { \textwidth }
+                          { @{}ll>{\raggedright\arraybackslash}X@{} }
+                      }
+                      {
+                        \begin {xltabular}
+                          { \textwidth }
+                          { @{}l>{\raggedright\arraybackslash}X@{} }
+                      }
+                    \seq_use:Nn \l__chemmacros_reactants_tmpa_seq { }
+                    \end{xltabular}
+                  }
+                  {
+                    \msg_expandable_error:nnnn
+                      {chemmacros}
+                      {package-not-loaded}
+                      { \printreactants }
+                      {xltabular}
+                  }
+              }
+              {longtable}
+              {
+                \chemmacros_if_package_loaded:nTF {longtable}
+                  {   
+                    \bool_if:nTF {#1}
+                      {
+                        \begin {longtable}[l]
+                          { @{}ll>{\raggedright\arraybackslash}p{0.6\textwidth}@{} }
+                      }
+                      {
+                        \begin {longtable}[l]
+                        { @{}l>{\raggedright\arraybackslash}p{0.9\textwidth}@{} }
+                      }
+                    \seq_use:Nn \l__chemmacros_reactants_tmpa_seq { }
+                    \end{longtable}
+                  }
+                  {
+                    \msg_expandable_error:nnnn
+                      {chemmacros}
+                      {package-not-loaded}
+                      { \printreactants }
+                      {longtable}
+                  }
+              }
+            }
+    }
+        {
+            \msg_warning:nn {chemmacros} {missing-printreactants-style}
+        }
+    \group_end:
+  }
+
+% #1: full ID
+% #2: star, include ID in table
+\cs_gset_protected:Npn \chemmacros_reactants_list_subreactant:nn #1#2
+  {
+    \chemnum_if_subcompounds:nT {#1}
+      {
+        \int_step_variable:nNn
+          { \chemnum_count_subcompounds:n {#1} } 
+          \l__chemmacros_reactants_tmpa_tl 
+          {
+            \seq_put_right:Nx 
+            \l__chemmacros_reactants_tmpa_seq
+              {
+                \chemnum_cmpd:nnne { \c_false_bool } { \c_true_bool } {}
+                  {
+                    \exp_not:n {#1}
+                    \exp_not:V \l_chemnum_compound_separator_tl
+                    \chemnum_get_subcompound:nV
+                      {#1}
+                      \l__chemmacros_reactants_tmpa_tl
+                  }
+                & 
+                \bool_if:nT {#2}
+                  {
+                    #1
+                    \l_chemnum_compound_separator_tl
+                    \chemnum_get_subcompound:nV
+                      {#1}
+                      \l__chemmacros_reactants_tmpa_tl
+                    &
+                  }
+                % TODO: expl3-command ??
+                \solvent
+                  {
+                    #1
+                    \l_chemnum_compound_separator_tl
+                    \chemnum_get_subcompound:nV
+                      {#1}
+                      \l__chemmacros_reactants_tmpa_tl
+                  }
+                \tabularnewline
+              }
+          }
+      }
+  }
+\cs_generate_variant:Nn \chemmacros_reactants_list_subreactant:nn {V}
+
+\StopDefiningTabulars%      lwarp
+%    \end{macrocode}
+%
+%
 % \subsection{Redox}
 %
 % \changes{v0.903}{2021/12/18}{\pkg{chemmacros}: Improved alt tag sanitization.}
 %    \begin{macrocode}
 \AtBeginDocument{
-\@ifchemmacrosmoduleloaded{redox}{
+\chemmacros_module_if_loaded:nTF{{redox}}{
 \PackageInfo{lwarp}{Patching~chemmacros~module~redox}
 
 \NewDocumentCommand \LWR@chemmacros@ox { s m >{\SplitArgument{1}{,}}m }
@@ -51086,7 +51498,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
       {
         \LWR@subsingledollar*{% yes hash
             \textbackslash{}%
-            ox*%
+            ox%
             \{%
                 \LWR@HTMLsanitizedetokenized{\detokenize{#3}}%
             \}% alt
@@ -51099,7 +51511,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
     \endgroup
   }
 
-}{}% \@ifchemmacrosmoduleloaded
+}{}% Module loaded.
 }% AtBeginDocument
 %    \end{macrocode}
 %
@@ -51108,7 +51520,7 @@ test {\ifnumgreater{\csuse{Changes@In########1}}{0}}%
 % Fix for \pkg{chemmacros} as of v5.8b, when using \pkg{newfloat} and \pkg{babel}:
 %    \begin{macrocode}
 \AtBeginDocument{
-\@ifchemmacrosmoduleloaded{scheme}{
+\chemmacros_module_if_loaded:nTF{{scheme}}{
 \PackageInfo{lwarp}{Patching~chemmacros~module~scheme}
 
 \ifdefstring{\schemename}{los}{
@@ -51117,7 +51529,7 @@ name = \chemmacros_translate:n {scheme-name}
 }
 }{}
 
-}{}% \@ifchemmacrosmoduleloaded
+}{}% Module loaded.
 }% AtBeginDocument
 %    \end{macrocode}
 %
@@ -51125,28 +51537,9 @@ name = \chemmacros_translate:n {scheme-name}
 %
 %    \begin{macrocode}
 \AtBeginDocument{
-\@ifchemmacrosmoduleloaded{spectroscopy}{
+\chemmacros_module_if_loaded:nTF{{spectroscopy}}{
 \PackageInfo{lwarp}{Patching~chemmacros~module~spectroscopy}
 
-\ChemCompatibilityTo{5.8}
-\cs_gset_protected:Npn \__chemmacros_nmr_base:nn #1#2
-  {
-    \tl_if_blank:VF \g__chemmacros_nmr_element_coupled_tl
-      {
-        \tl_put_left:Nn \g__chemmacros_nmr_element_coupled_tl { \{ }
-        \tl_put_right:Nn \g__chemmacros_nmr_element_coupled_tl { \} }
-      }
-    \tl_put_left:Nn \g__chemmacros_nmr_element_coupled_tl {#2}
-%     \chemmacros_chemformula:n { ^{#1} }
-    \textsuperscript{#1}
-    \bool_if:NTF \l__chemmacros_nmr_parse_bool
-      { \chemformula_ch:nV {} \g__chemmacros_nmr_element_coupled_tl }
-      { \chemmacros_chemformula:V \g__chemmacros_nmr_element_coupled_tl }
-    \tl_use:N \l__chemmacros_nmr_element_method_connector_tl
-    \tl_use:N \l__chemmacros_nmr_method_tl
-  }
-\EndChemCompatibility
-\ChemCompatibilityFrom{5.8}
 \cs_gset_protected:Npn \__chemmacros_nmr_base:nn #1#2
   {
     \group_begin:
@@ -51157,24 +51550,23 @@ name = \chemmacros_translate:n {scheme-name}
           \tl_put_right:Nn \g__chemmacros_nmr_element_coupled_tl { \} }
         }
       \tl_put_left:Nn \g__chemmacros_nmr_element_coupled_tl {#2}
-%       \chemmacros_chemformula:n { ^{#1} }
+%       \chemmacros_formula:n { ^{#1} }
       \textsuperscript{#1}
       \tl_if_blank:VF \g__chemmacros_nmr_element_coupled_tl
         {
           \bool_if:NTF \l__chemmacros_nmr_parse_bool
             { \chemformula_ch:nV {} \g__chemmacros_nmr_element_coupled_tl }
-            { \chemmacros_chemformula:V \g__chemmacros_nmr_element_coupled_tl }
+            { \chemmacros_formula:V \g__chemmacros_nmr_element_coupled_tl }
         }
       \tl_use:N \l__chemmacros_nmr_element_method_connector_tl
       \tl_use:N \l__chemmacros_nmr_method_tl
     \group_end:
   }
-\EndChemCompatibility
 
 
 \cs_gset_protected:Npn \chemmacros_nmr_position:n #1
   {
-    \chemmacros_chemformula:x
+    \chemmacros_formula:x
       {
         \exp_not:V \g__chemmacros_nmr_element_tl
         \bool_if:NF \l__chemmacros_nmr_position_side_bool
@@ -51209,7 +51601,7 @@ name = \chemmacros_translate:n {scheme-name}
             \textsubscript% lwarp
               {
                 \l__chemmacros_nmr_coupling_nuclei_pre_tl
-                \chemmacros_chemformula:n {#2}
+                \chemmacros_formula:n {#2}
                 \l__chemmacros_nmr_coupling_nuclei_post_tl
               }
           }
@@ -51218,7 +51610,7 @@ name = \chemmacros_translate:n {scheme-name}
         \tl_set:Nn \l__chemmacros_nmr_coupling_nuclei_tl
           {
             \l__chemmacros_nmr_coupling_nuclei_pre_tl
-            \chemmacros_chemformula:n {#2}
+            \chemmacros_formula:n {#2}
             \l__chemmacros_nmr_coupling_nuclei_post_tl
           }
       }
@@ -51281,7 +51673,7 @@ name = \chemmacros_translate:n {scheme-name}
                 \bool_if:NT \l__chemmacros_nmr_comma_bool
                     { , ~ }
                 \bool_if:NT \l__chemmacros_nmr_solvent_bool
-                    { \chemmacros_chemformula:n {#4} }
+                    { \chemmacros_formula:n {#4} }
                 \bool_if:NT \l__chemmacros_nmr_delimiters_bool
                     { ) }
                 \tl_if_blank:nT {#1} {:~}
@@ -51353,26 +51745,33 @@ name = \chemmacros_translate:n {scheme-name}
     \IfBooleanF {#1} { \bool_if:NT \l__chemmacros_nmr_use_equal_bool { ~ = } }
   }
 
-}{}% \@ifchemmacrosmoduleloaded
+}{}% Module loaded.
 }% AtBeginDocument
 %    \end{macrocode}
 %
+%
 % \subsection{Thermodynamics}
 %
 % \changes{v0.903}{2021/12/18}{\pkg{chemmacros}: Improved alt tag sanitization.}
 %    \begin{macrocode}
 \AtBeginDocument{
-\@ifchemmacrosmoduleloaded{thermodynamics}{
+\chemmacros_module_if_loaded:nTF{{thermodynamics}}{
 \PackageInfo{lwarp}{Patching~chemmacros~module~thermodynamics}
 
-\cs_gset_protected:Npn \chemmacros_state:nn #1#2
+\cs_gset_protected:Npn \chemmacros_state:nnnnnn #1#2#3#4#5#6
   {
     \group_begin:
-      \boolfalse{mathjax}
-      \chemmacros_set_keys:nn {thermodynamics} {#1}
+      \chemmacros_set_keys:ne {thermodynamics}
+        {
+          \exp_not:n {#1} ,
+          \tl_if_novalue:nF {#2} { subscript-left = \exp_not:n {#2} , }
+          \tl_if_novalue:nF {#3} { superscript-left = \exp_not:n {#3} , }
+          \tl_if_novalue:nF {#5} { subscript-right = \exp_not:n {#5} , }
+          \tl_if_novalue:nF {#6} { superscript-right = \exp_not:n {#6} }
+        }
         \LWR@subsingledollar*{% yes hashing
             \textbackslash{}state%
-            \{\LWR@HTMLsanitizedetokenized{\detokenize{#2}}\}% alt
+            \{\LWR@HTMLsanitizedetokenized{\detokenize{#4}}\}% alt
         }{%
             chemmacros_state% add'l hashing
             #1% options
@@ -51382,36 +51781,37 @@ name = \chemmacros_translate:n {scheme-name}
             RSB \tl_use:N \l__chemmacros_state_sb_right_tl
         }
         {
-         \LWR@origensuredmath{
-          \chemmacros_text:V \l__chemmacros_state_pre_tl
-          \c_math_superscript_token
-            { \chemmacros_text:V \l__chemmacros_state_sp_left_tl }
+            \LWR@origensuredmath
+                {
+                \chemmacros_text:V \l__chemmacros_state_pre_tl
+                \c_math_superscript_token
+                    { \chemmacros_text:V \l__chemmacros_state_sp_left_tl }
 %    \end{macrocode}
 % Only add the subscripts if they are being used.
 % This avoids causing an incorrect depth, as the empty subscript will be
 % measured by \TeX\ but cropped out by \prog{pdfcrop}.
 %    \begin{macrocode}
-          \tl_if_empty:NTF \l__chemmacros_state_sb_left_tl
-          {}
-          {
-            \c_math_subscript_token
-            { \chemmacros_text:V \l__chemmacros_state_sb_left_tl }
-          }
-          #2
-          \c_math_superscript_token
-            { \chemmacros_text:V \l__chemmacros_state_sp_right_tl }
-          \tl_if_empty:NTF \l__chemmacros_state_sb_right_tl
-          {}
-          {
-            \c_math_subscript_token
-            { \chemmacros_text:V \l__chemmacros_state_sb_right_tl }
-          }
-          \chemmacros_text:V \l__chemmacros_state_post_tl
-         }
+                \tl_if_empty:NTF \l__chemmacros_state_sb_left_tl
+                {}
+                {
+                    \c_math_subscript_token
+                        { \chemmacros_text:V \l__chemmacros_state_sb_left_tl }
+                }
+                #4
+                \c_math_superscript_token
+                    { \chemmacros_text:V \l__chemmacros_state_sp_right_tl }
+                \tl_if_empty:NTF \l__chemmacros_state_sb_right_tl
+                {}
+                {
+                    \c_math_subscript_token
+                    { \chemmacros_text:V \l__chemmacros_state_sb_right_tl }
+                }
+                \chemmacros_text:V \l__chemmacros_state_post_tl
+                }
         }
     \group_end:
   }
-\cs_generate_variant:Nn \chemmacros_state:nn { nV }
+\cs_generate_variant:Nn \chemmacros_state:nnnnnn { nVVVVV }
 
 \cs_gset_protected:Npn \chemmacros_declare_state:Nn #1#2
   {
@@ -51435,17 +51835,26 @@ name = \chemmacros_translate:n {scheme-name}
     \DeclareDocumentCommand #1 { sO{}D(){}m }
       {
         \group_begin:
-          \chemmacros_set_keys:xn
+          \chemmacros_set_keys:en
             {thermodynamics/\chemmacros_remove_backslash:N #1}
             {#2}
           \tl_if_blank:nF {##3}
             {
-              \chemmacros_set_keys:nx {thermodynamics}
+              \chemmacros_set_keys:ne {thermodynamics}
                 { subscript-\l__chemmacros_state_sb_pos_tl = \exp_not:n {##3} }
             }
-              \chemmacros_state:nV {##2} \l__chemmacros_state_symbol_tl
+%           \LWR@origensuredmath
+%             {
+              \chemmacros_state:nVVVVV
+                {##2}
+                \c_novalue_tl
+                \c_novalue_tl
+                \l__chemmacros_state_symbol_tl
+                \c_novalue_tl
+                \c_novalue_tl
               \chemmacros_set_keys_groups:nnn {thermodynamics} {variables} {##2}
-              \IfBooleanF {##1} {  = ~ \SI {##4} { \l__chemmacros_state_unit_tl } }
+              \IfBooleanF {##1} { = \qty {##4} { \l__chemmacros_state_unit_tl } }
+%             }
         \group_end:
       }
   }
@@ -51457,7 +51866,7 @@ name = \chemmacros_translate:n {scheme-name}
 \RenewChemState \entropy  { symbol = S , unit = \joule\per\kelvin\per\mole , pre = }
 \RenewChemState \gibbs    { symbol = G , unit = \kilo\joule\per\mole }
 
-}{}% \@ifchemmacrosmoduleloaded
+}{}% Module loaded.
 }% AtBeginDocument
 %    \end{macrocode}
 %
@@ -56593,7 +57002,7 @@ solid {\FancyVerbRuleColor{\LWR@origpound\LWR@tempcolor}} ; % space
 % \codehtml
 %
 %    \begin{macrocode}
-\LWR@ProvidesPackagePass{fbox}[2020/06/22]
+\LWR@ProvidesPackagePass{fbox}[2022/02/20]
 %    \end{macrocode}
 %
 % This will be \cs{LWR@formatted} when  \cs{AtBeginDocument}:
@@ -56607,19 +57016,26 @@ solid {\FancyVerbRuleColor{\LWR@origpound\LWR@tempcolor}} ; % space
 %    \end{macrocode}
 %
 % \begin{noindmacro}{LWR@fboxpkg@border}
-% \marg{1: top \Slash bottom \Slash left \Slash right} \marg{2: padding, or empty}
+%   \marg{1: top \Slash bottom \Slash left \Slash right}
+%   \marg{2: t \Slash b \Slash l \Slash r}
+%   \marg{3: padding, or empty}
 %
 % Accumulates \HTML\ styles for border, and padding if given:
+% \changes{v0.904}{2022/03/05}{\pkg{fbox}: Added border colors.}
 %    \begin{macrocode}
-\newcommand*{\LWR@fboxpkg@border}[2]{%
+\newcommand*{\LWR@fboxpkg@border}[3]{%
+    \colorlet{LWR@border@color}{\csuse{fbox@#2color}}%
+    \protect\convertcolorspec{named}{LWR@border@color}{HTML}\LWR@tempbordercolor\relax%
     \appto\LWR@tempone{%
         border-#1: % space
         \LWR@printlength{\LWR@atleastonept} % space
-        solid \LWR@origpound\LWR@tempcolor ;\LWR@indentHTML
+        solid \LWR@origpound%
     }%
-    \ifblank{#2}{}{%
+    \expandafter\appto\expandafter\LWR@tempone\expandafter{\LWR@tempbordercolor}%
+    \appto\LWR@tempone{ ;\LWR@indentHTML}%
+    \ifblank{#3}{}{%
         \appto\LWR@tempone{%
-            padding-#1: \LWR@printlength{#2} ;\LWR@indentHTML
+            padding-#1: \LWR@printlength{#3} ;\LWR@indentHTML
         }%
     }%
 }
@@ -56671,20 +57087,21 @@ solid {\FancyVerbRuleColor{\LWR@origpound\LWR@tempcolor}} ; % space
 %    \end{macrocode}
 %
 % Per the original to decode the borders, in a new way:
+% \changes{v0.904}{2022/03/05}{\pkg{fbox}: Added border colors.}
 %    \begin{macrocode}
     \ifnum\the\@tempcntb>8\relax
-        \advance\@tempcntb by -8
-        \LWR@fboxpkg@border{top}{\fbox@@sep}%
+        \advance\@tempcntb by -8\relax
+        \LWR@fboxpkg@border{top}{t}{\fbox@@sep}%
     \fi
     \ifnum\@tempcntb>3
-        \advance\@tempcntb by -4
-        \LWR@fboxpkg@border{left}{}%
+        \advance\@tempcntb by -4\relax
+        \LWR@fboxpkg@border{left}{l}{}%
     \fi
-    \ifnum\@tempcntb>1
-        \LWR@fboxpkg@border{right}{}%
+    \ifnum\@tempcntb>1\relax
+        \LWR@fboxpkg@border{right}{r}{}%
     \fi
     \ifodd\@tempcntb
-        \LWR@fboxpkg@border{bottom}{\fbox@@sep}%
+        \LWR@fboxpkg@border{bottom}{b}{\fbox@@sep}%
     \fi
 %    \end{macrocode}
 %
@@ -61736,6 +62153,21 @@ do not attempt to patch lwarp's version of `hyperref'.)\MessageBreak}
 %    \end{macrocode}
 
 
+% No application for \pkg{lwarp}:
+% \changes{v0.904}{2022/03/04}{\pkg{hyperref}: Added \cs{HyperDest*}.}
+%    \begin{macrocode}
+\newcommand*{\HyperDestNameFilter}[1]{#1}
+\newcommand*{\HyperDestLabelReplace}[1]{#1}
+\newcommand*{\HyperDestRename}[2]{}
+%    \end{macrocode}
+
+% No application for \pkg{lwarp}:
+% \changes{v0.904}{2022/03/04}{\pkg{hyperref}: Added \cs{hyperget}.}
+%    \begin{macrocode}
+\newcommand*{\hyperget}[2]{}
+%    \end{macrocode}
+
+
 
 % \begin{noindmacro}{\hyperimage} \marg{URL} \marg{alt text}
 %
@@ -65566,6 +65998,70 @@ do not attempt to patch lwarp's version of `hyperref'.)\MessageBreak}
 %
 %
 % \iffalse
+%<*lltjp-siunitx>
+% \fi
+%
+% \part{lwarp-lltjp-siunitx.sty}
+%
+% \section{lltjp-siunitx}
+%
+% \credits{The Lua\TeX-ja project team}
+%
+% \DescribePackage{lltjp-siunitx}
+% \pkg{lltjp-siunitx} is patched for use by \pkg{lwarp}.
+%
+% \changes{v0.904}{2022/03/08}{\pkg{lltjp-siunitx}: Added.}
+%
+% \codehtml
+%
+%    \begin{macrocode}
+\LWR@ProvidesPackagePass{lltjp-siunitx}% 2021-10-31, no date assigned in file
+%    \end{macrocode}
+%
+% This is the \pkg{siunitx} v3 file, as patched by \pkg{lltjp-siunitx}.
+%
+%    \begin{macrocode}
+\ExplSyntaxOn
+
+\cs_set_protected:Npn \siunitx_print_text:n #1
+  {
+    \text
+      {
+        \ltj@allalchar % <--- LuaTeX-ja
+        \bool_if:NT \l__siunitx_print_text_family_bool
+          { \fontfamily { \familydefault } }
+        \bool_if:NT \l__siunitx_print_text_series_bool
+          { \fontseries { \seriesdefault } }
+        \bool_if:NT \l__siunitx_print_text_shape_bool
+          { \fontshape { \shapedefault } }
+        \bool_lazy_any:nT
+          {
+            { \l__siunitx_print_text_family_bool }
+            { \l__siunitx_print_text_series_bool }
+            { \l__siunitx_print_text_shape_bool }
+          }
+          { \selectfont }
+        \tl_use:N \l__siunitx_print_text_font_tl
+        \exp_args:NnV \tl_if_head_eq_meaning:nNTF {#1} \l_siunitx_unit_fraction_tl
+          {
+            \__siunitx_print_text_fraction:Nnn #1
+          }
+          {
+            \__siunitx_print_text_replace:n {#1}
+          }
+      }
+  }
+
+\ExplSyntaxOff
+%    \end{macrocode}
+%
+% \iffalse
+%</lltjp-siunitx>
+% \fi
+%
+%
+%
+% \iffalse
 %<*lltjp-tascmac>
 % \fi
 %
@@ -70079,7 +70575,7 @@ background:
 
 % \codehtml
 %    \begin{macrocode}
-\LWR@ProvidesPackageDrop{multicol}[2018/12/27]
+\LWR@ProvidesPackageDrop{multicol}[2021/10/28]
 %    \end{macrocode}
 
 % Multicols are converted into a 1--3 column display, browser-supported.
@@ -70120,8 +70616,10 @@ background:
 % \end{noindenvironment}
 
 % Emulated null functions which are not used in \HTML:
+% \changes{v0.904}{2022/02/07}{\pkg{multicol}: Added \cs{newcolumn}.}
 %    \begin{macrocode}
 \newcommand*{\columnbreak}{}
+\newcommand*{\newcolumn}{}
 \newcommand*{\RLmulticolcolumns}{}
 \newcommand*{\LRmulticolcolumns}{}
 
@@ -79352,20 +79850,13 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 % \credits{Joseph Wright}
 %
 % \DescribePackage{siunitx}
-% \pkg{siunitx-v2} is patched for use by \pkg{lwarp},
+% \pkg{siunitx} is patched for use by \pkg{lwarp},
 % and is emulated for \MathJax.
 %
-% Use as:
-% \begin{sourceverb}
-% \usepackage{siunitx}[=v2]
-% \end{sourceverb}
-%
-% \pkg{siunitx} v3 is not yet supported.
-% \watchout
-%
 % ^^A \limitssiunitx
 %
 % \changes{v0.897}{2021/05/23}{\pkg{siunitx}: Rollback for v2.}
+% \changes{v0.904}{2022/02/19}{\pkg{siunitx}: Added v3.}
 %
 % \codehtml
 %
@@ -79377,19 +79868,542 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 \DeclareRelease{v2}{2010-05-23}{lwarp-siunitx-v2.sty}
 \DeclareCurrentRelease{}{2021-05-17}
 
-\PackageWarningNoLine{lwarp}
+\RequirePackage{xcolor}% for \convertcolorspec
+
+\LWR@ProvidesPackagePass{siunitx}[2022-02-15]
+
+\ExplSyntaxOn
+%    \end{macrocode}
+
+% ^^A May be of use to try to create color for negative values:
+% ^^A 
+% ^^A % \cs_set_protected:Npn \__siunitx_number_parse_sign_aux:Nw #1#2 \q_stop
+% ^^A %   {
+% ^^A %     \tl_if_in:NnTF \l_siunitx_number_input_sign_tl {#1}
+% ^^A %       {
+% ^^A %         \tl_set:Nn \l__siunitx_number_arg_tl {#2}
+% ^^A %         \bool_lazy_and:nnTF
+% ^^A %           { \token_if_eq_charcode_p:NN #1 + }
+% ^^A %           { ! \l__siunitx_number_explicit_plus_bool }
+% ^^A %           { \tl_set:Nn \l__siunitx_number_parsed_tl { { } } }
+% ^^A %           { \tl_set:Nn \l__siunitx_number_parsed_tl { {#1} } }
+% ^^A %
+% ^^A %           % If #! is { - } then is a negative number
+% ^^A %
+% ^^A %       }
+% ^^A %       { \tl_set:Nn \l__siunitx_number_parsed_tl { { } } }
+% ^^A %     \tl_if_empty:NTF \l__siunitx_number_arg_tl
+% ^^A %       { \tl_clear:N \l__siunitx_number_parsed_tl }
+% ^^A %       { \__siunitx_number_parse_exponent: }
+% ^^A %   }
+% ^^A %
+% ^^A %
+% ^^A % \cs_set_protected:Npn \siunitx_print_number:n #1
+% ^^A %   {
+% ^^A %     \__siunitx_print_aux:nn { number } {#1}
+% ^^A %   }
+
+
+
+
+%    \begin{macrocode}
+\cs_set_protected:Npn \siunitx_number_format:nN #1#2
+  {
+    \group_begin:
+      \bool_if:NTF \l_siunitx_number_parse_bool
+        {
+          \siunitx_number_parse:nN {#1} \l__siunitx_number_parsed_tl
+          \siunitx_number_process:NN \l__siunitx_number_parsed_tl \l__siunitx_number_parsed_tl
+          \tl_set:Nx \l__siunitx_number_outputted_tl
+            { \siunitx_number_output:N \l__siunitx_number_parsed_tl }
+        }
+        {
+            \tl_set:Nn \l__siunitx_number_outputted_tl
+            {
+                \LWR@subsingledollar{%                  lwarp
+                    \textbackslash( % space
+                    \LWR@HTMLsanitizedetokenized{%
+                        \detokenize{#1}%
+                    } \textbackslash)%                  lwarp
+                }%
+                {siunitx unparsed}%
+                {\ensuremath{#1}}%                      lwarp
+            }
+        }
+    \exp_args:NNNV \group_end:
+    \tl_set:Nn #2 \l__siunitx_number_outputted_tl
+  }
+%    \end{macrocode}
+%
+%
+%    \begin{macrocode}
+\cs_set_protected:Npn \__siunitx_compound_unparsed:n #1
+  {
+    \tl_if_blank:nF {#1}
+      { \seq_put_right:Nn \l__siunitx_compound_tmp_seq
+        {
+            \LWR@subsingledollar{%                  lwarp
+                \textbackslash( % space
+                \LWR@HTMLsanitizedetokenized{%
+                    \detokenize{#1}%
+                } \textbackslash)%                  lwarp
+            }%
+            {siunitx unparsed}%
+            {\ensuremath{#1}}%                      lwarp
+        }
+      }
+  }
+%    \end{macrocode}
+%
+%
+% If not in a \env{lateximage}, always use text mode.
+% Ignore current text font if resetting text family, series, and shape.
+%    \begin{macrocode}
+\cs_set_protected:Npn \__siunitx_print_aux:nn #1#2
+  {
+    \tl_if_empty:cTF { l__siunitx_print_ #1 _color_tl }
+      { \use:n }
+      { \exp_args:Nv \textcolor { l__siunitx_print_ #1 _color_tl } }
+        {
+            \ifnumcomp{\value{LWR@lateximagedepth}}{>}{0}%      lwarp
+            {
+                \use:c
+                    {
+                    siunitx_print_
+                    \tl_use:c { l__siunitx_print_ #1 _mode_tl } :n
+                    }
+                    {#2}
+            }
+            {
+                \bool_lazy_all:nTF%     lwarp
+                    {
+                        {\l__siunitx_print_text_family_bool}
+                        {\l__siunitx_print_text_series_bool}
+                        {\l__siunitx_print_text_shape_bool}
+                    }
+                    {% No font control if reset-text-family/series/shape
+                        \use:c
+                            {
+                            siunitx_print_%                         lwarp
+                                text%                               lwarp
+                                :n%                                 lwarp
+                            }%                                      lwarp
+                            {#2}%                                   lwarp
+                    }
+                    {
+                        \LWR@textcurrentfont{%                      lwarp
+                            \use:c
+                                {
+                                siunitx_print_%                     lwarp
+                                    text%                           lwarp
+                                    :n%                             lwarp
+                                }%                                  lwarp
+                                {#2}%                               lwarp
+                        }
+                    }
+            }
+        }
+  }
+%    \end{macrocode}
+%
+%
+% To determine whether to make a complex root be italic or upright,
+% \cs{l\_\_siunitx\_complex\_output\_root\_tl} is compared to
+% \cs{LWR@siunitx@complexrm<i/j>}, and the \CSS\ style is set appropriately.
+%    \begin{macrocode}
+\newcommand*{\LWR@siunitx@complexrootstyle}{textrm}
+
+\newcommand*{\LWR@siunitx@complexrmi}{\mathrm{i}}
+\newcommand*{\LWR@siunitx@complexrmj}{\mathrm{j}}
+
+\newcommand*{\LWR@siunitx@setcomplexroot}{%
+    \renewcommand*{\LWR@siunitx@complexrootstyle}{textit}%
+    \ifdefequal{\l__siunitx_complex_output_root_tl}{\LWR@siunitx@complexrmi}%
+        {\renewcommand*{\LWR@siunitx@complexrootstyle}{textrm}}%
+        {}%
+    \ifdefequal{\l__siunitx_complex_output_root_tl}{\LWR@siunitx@complexrmj}%
+        {\renewcommand*{\LWR@siunitx@complexrootstyle}{textrm}}%
+        {}%
+}
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\cs_set_protected:Npn \__siunitx_complex_format_auxii:n #1
+  {
+    \LWR@siunitx@setcomplexroot%                        lwarp
+    \__siunitx_complex_format_units:n {#1}
+    \tl_if_empty:NF \l__siunitx_complex_real_tl
+      { \exp_after:wN \__siunitx_complex_drop_exponent:nnnnnnn \l__siunitx_complex_real_tl }
+    \exp_after:wN \__siunitx_complex_format_sign:nnnnnnn \l__siunitx_complex_img_tl
+    \tl_set:Nx \l__siunitx_complex_tmp_tl
+      { \siunitx_number_output:NN \l__siunitx_complex_img_tl \q_nil }
+    \exp_after:wN \__siunitx_complex_extract_exponent:w \l__siunitx_complex_tmp_tl \q_stop
+    \tl_set:Nx \l__siunitx_complex_tmp_tl
+      {
+        \bool_lazy_or:nnTF
+          {
+            \bool_lazy_and_p:nn
+              { \l_siunitx_number_bracket_ambiguous_bool }
+              { ! \tl_if_empty_p:N \l__siunitx_complex_exp_tl }
+          }
+          {
+            ! \bool_lazy_any_p:n
+              {
+                { \tl_if_blank_p:n {#1} }
+                { \tl_if_empty_p:N \l__siunitx_complex_real_tl }
+                { \tl_if_empty_p:N \l__siunitx_complex_img_tl }
+              }
+          }
+          { \__siunitx_complex_format_bracket:n }
+          { \use:n }
+          {
+            \siunitx_number_output:N \l__siunitx_complex_real_tl
+            \exp_not:V \l__siunitx_complex_sign_tl
+            \bool_if:NF \l__siunitx_complex_root_after_bool
+              {
+                \InlineClass{\LWR@siunitx@complexrootstyle}%    lwarp
+                    {
+                        \exp_not:V \l__siunitx_complex_output_root_tl
+                    }
+              }
+             \exp_not:V \l__siunitx_complex_tmp_tl
+            \bool_if:NT \l__siunitx_complex_root_after_bool
+              {
+                \InlineClass{\LWR@siunitx@complexrootstyle}%    lwarp
+                    {
+                        \exp_not:V \l__siunitx_complex_output_root_tl
+                    }
+              }
+           }
+         \exp_not:V \l__siunitx_complex_exp_tl
+      }
+  }
+%    \end{macrocode}
+%
+%
+% \marg{1: deg/min/sec character}
+% \marg{2: ?}
+% \marg{3: ?}
+% \marg{4: integer part of angle}
+% \marg{5: decimal point character}
+% \marg{6: decimal part of angle}
+% \marg{7: ?}
+% \marg{8: ?}
+%
+% If not in a \env{lateximage}, print a simplified verison
+% without the box measurement things which conflict with \pkg{lwarp}:
+%    \begin{macrocode}
+\cs_set_protected:Npn \__siunitx_angle_arc_print_auxii:nw
+  #1#2 \q_nil #3 \q_nil #4 \q_nil #5 \q_nil #6 \q_nil #7 \q_nil #8 \q_stop
+  {
+    \mode_if_math:TF
+      { \bool_set_true:N \l__siunitx_angle_tmp_bool }
+      { \bool_set_false:N \l__siunitx_angle_tmp_bool }
+    \siunitx_print_number:n {#2#3#4}
+    \ifnumcomp{\value{LWR@lateximagedepth}}{>}{0}%      lwarp
+    {%                                                  lwarp
+        \tl_if_blank:nTF {#6}
+        { \__siunitx_angle_arc_print_auxvi:n {#1} }
+        {
+            \hbox_set:Nn \l__siunitx_angle_marker_box
+            {
+                \__siunitx_angle_arc_print_auxiii:n
+                { \siunitx_print_number:n {#5} }
+            }
+            \hbox_set:Nn \l__siunitx_angle_unit_box
+            {
+                \__siunitx_angle_arc_print_auxiii:n
+                {
+                    \siunitx_unit_format:nN {#1} \l__siunitx_angle_tmp_tl
+                    \siunitx_print_unit:V \l__siunitx_angle_tmp_tl
+                    \skip_horizontal:n { -\scriptspace }
+                }
+            }
+            \dim_compare:nNnTF { \box_wd:N \l__siunitx_angle_marker_box } >
+            { \box_wd:N \l__siunitx_angle_unit_box }
+            {
+                \__siunitx_angle_arc_print_auxiv:NN
+                \l__siunitx_angle_marker_box
+                \l__siunitx_angle_unit_box
+            }
+            {
+                \__siunitx_angle_arc_print_auxiv:NN
+                \l__siunitx_angle_unit_box
+                \l__siunitx_angle_marker_box
+            }
+            \hbox_set_to_wd:Nnn \l__siunitx_angle_marker_box
+            \l__siunitx_angle_tmp_dim
+            {
+                \hbox_overlap_right:n
+                { \box_use_drop:N \l__siunitx_angle_marker_box }
+                \hbox_overlap_right:n
+                { \box_use_drop:N \l__siunitx_angle_unit_box }
+                \tex_hfil:D
+            }
+            \box_use:N \l__siunitx_angle_marker_box
+            \skip_horizontal:N \scriptspace
+            \siunitx_print_number:n {#6}
+        }
+    }%
+%    \end{macrocode}
+%
+% \marg{1: deg/min/sec character}
+% \marg{2: ?}
+% \marg{3: ?}
+% \marg{4: integer part of angle}
+% \marg{5: decimal point character}
+% \marg{6: decimal part of angle}
+% \marg{7: ?}
+% \marg{8: ?}
+%    \begin{macrocode}
+    {%          lwarp: not in a lateximage, simplify for HTML
+        \tl_if_blank:nTF {#6}
+        { \__siunitx_angle_arc_print_auxvi:n {#1} }
+        {
+            \__siunitx_angle_arc_print_auxiii:n
+            {
+                \siunitx_print_number:n {#5}
+            }
+            \__siunitx_angle_arc_print_auxiii:n
+            {
+                \siunitx_unit_format:nN {#1} \l__siunitx_angle_tmp_tl
+                \siunitx_print_unit:V \l__siunitx_angle_tmp_tl
+            }
+            \siunitx_print_number:n {#6}
+        }
+    }%          lwarp
+  }
+%    \end{macrocode}
+%
+% If not in a \env{lateximage}, print a simple inline fraction,
+% avoiding the use of \SVG\ math:
+%    \begin{macrocode}
+\cs_set_protected:Npn \__siunitx_print_text_fraction:Nnn #1#2#3
+  {
+    \ifnumcomp{\value{LWR@lateximagedepth}}{>}{0}% lwarp
+    {%
+      \ensuremath
+      {
+        #1
+          { \mbox { \__siunitx_print_text_replace:n {#2} } }
+          { \mbox { \__siunitx_print_text_replace:n {#3} } }
+      }
+    }%
+    {%                                                          lwarp
+          { \mbox { \__siunitx_print_text_replace:n {#2} } }%   lwarp
+            /%                                                  lwarp
+          { \mbox { \__siunitx_print_text_replace:n {#3} } }%   lwarp
+    }%      lwarp
+  }
+%    \end{macrocode}
+%
+% If not in a \env{lateximage}, print a \cs{textsubscript}:
+%    \begin{macrocode}
+\cs_set_protected:Npn \__siunitx_unit_format_qualifier_subscript:
+  {
+    \ifnumcomp{\value{LWR@lateximagedepth}}{>}{0}%      lwarp
     {%
-        **************\MessageBreak
-        Siunitx version 3 is not yet supported by Lwarp.\MessageBreak
-        V2 emulation is used here.\MessageBreak
-        **************
+        \__siunitx_unit_format_font:
+        \tl_set:Nx \l__siunitx_unit_part_tl
+        {
+            \c__siunitx_unit_math_subscript_tl
+            {
+                \exp_not:V \l_siunitx_unit_font_tl
+                { \exp_not:V \l__siunitx_unit_part_tl }
+            }
+        }
     }
+    {%      lwarp simplified for HTML:
+        \__siunitx_unit_format_font:
+        \tl_set:Nx \l__siunitx_unit_part_tl
+        {
+            \textsubscript
+            {
+                \exp_not:V \l_siunitx_unit_font_tl
+                { \exp_not:V \l__siunitx_unit_part_tl }
+            }
+        }
+    }
+  }
+%    \end{macrocode}
+%
+%    \begin{macrocode}
+\cs_set_protected:Npn \siunitx_quantity:nn #1#2
+  {
+    \group_begin:
+      \siunitx_unit_options_apply:n {#2}
+      \tl_if_blank:nTF {#1}
+        {
+          \siunitx_unit_format:nN {#2} \l__siunitx_quantity_unit_tl
+          \siunitx_print_unit:V \l__siunitx_quantity_unit_tl
+        }
+        {
+          \bool_if:NTF \l_siunitx_number_parse_bool
+            { \__siunitx_quantity_parsed:nn {#1} {#2} }
+            {
+              \tl_set:Nn \l__siunitx_quantity_number_tl {
+                \LWR@subsingledollar{%                  lwarp
+                    \textbackslash( % space
+                    \LWR@HTMLsanitizedetokenized{%
+                        \detokenize{#1}%
+                    } \textbackslash)%                  lwarp
+                }%
+                {siunitx unparsed}%
+                {\ensuremath{#1}}%                      lwarp
+              }
+              \siunitx_unit_format:nN {#2} \l__siunitx_quantity_unit_tl
+              \siunitx_quantity_print:VV
+                \l__siunitx_quantity_number_tl \l__siunitx_quantity_unit_tl
+            }
+        }
+    \group_end:
+  }
+%    \end{macrocode}
+%
+
+% ^^A *88* \cancel
+%
+% \cs{cancel} for \HTML\ does not work yet.
+%    \begin{macrocode}
+\newcommand*{\LWR@siunitx@nocancel}[1]{%
+    \ifnumcomp{\value{LWR@lateximagedepth}}{>}{0}%
+        {\cancel{#1}}%  SVG
+        {#1}%           HTML
+}
+
+\AtBeginDocument{
+\__siunitx_unit_set_symbolic:Npnn \cancel
+  { }
+%   { \__siunitx_unit_parse_special:n { \cancel } }
+  { \__siunitx_unit_parse_special:n { \LWR@siunitx@nocancel } }%    lwarp
+}
+%    \end{macrocode}
+%
+%
+% For \HTML, use a simple unaligned \cs{num}:
+%    \begin{macrocode}
+\newcommand{\LWR@HTML@tablenum}[2][]{\num[#1]{#2}}
+\LWR@formatted{tablenum}
+%    \end{macrocode}
+%
+%
+% For \HTML, the |S| column is simplified to a |c| column.
+% Keys are set locally, allowing \optn{drop-exponent}, etc.
+%    \begin{macrocode}
+\AtBeginDocument{
+\HTMLnewcolumntype{S}[1][]{>{\begingroup\sisetup{#1}}c<{\endgroup}}
+}
+%    \end{macrocode}
+%
+%
+% To define simplified units for \HTML:
+%
+% \begin{macro}{\HTMLDeclareSIUnit} \oarg{options} \marg{name} \marg{definition}
+%    \begin{macrocode}
+\NewDocumentCommand{\HTMLDeclareSIUnit}{o +m m}
+{
+    \ifcsdef{ __siunitx_unit_ \token_to_str:N #2 :w }
+        {}
+        {
+            \PackageError{lwarp}
+                {%
+                    First~use\MessageBreak
+                        \space\space\protect\DeclareSIUnit{
+                          \token_to_str:N#2}{...}\MessageBreak
+                    before~using\MessageBreak
+                        \space\space\protect\HTMLDeclareSIUnit{
+                          \token_to_str:N#2}{...}%
+                }
+                {%
+                    See~the~Lwarp~manual~section~about~special~cases,~
+                    regarding~siunitx.%
+                }
+        }
+    \csNewCommandCopycs
+        { __orig_siunitx_unit_ \token_to_str:N #2 :w }
+        { __siunitx_unit_ \token_to_str:N #2 :w }
+    \DeclareSIUnit[#1]{#2}
+        {
+            \ifnumcomp{\value{LWR@lateximagedepth}}{>}{0}
+                {\csuse{ __orig_siunitx_unit_ \token_to_str:N #2 :w }}
+                {#3}
+        }
+}
+%    \end{macrocode}
+% \end{macro}
+
+%    \begin{macrocode}
+\ExplSyntaxOff
+%    \end{macrocode}
+
+% \HTML\ versions for existing units:
+%    \begin{macrocode}
+\AtBeginDocument{
+\HTMLDeclareSIUnit\celsius{\LWR@siunitx@textcelsius}
+\HTMLDeclareSIUnit\arcminute{\LWR@siunitx@textprime}
+\HTMLDeclareSIUnit\arcsecond{\LWR@siunitx@textdblprime}
+\HTMLDeclareSIUnit\elementarycharge{\textit{e}}
+%
+\HTMLDeclareSIUnit\clight{\text{\textit{c}\textsubscript{0}}}
+\HTMLDeclareSIUnit\bohr{\text{\textit{a}\textsubscript{0}}}
+\HTMLDeclareSIUnit\electronmass{\text{\textit{m}\textsubscript{e}}}
+\HTMLDeclareSIUnit\hartree{\text{\textit{E}\textsubscript{h}}}
+\HTMLDeclareSIUnit\planckbar{\LWR@siunitx@textplanckbar}
+}% \AtBeginDocument
+%    \end{macrocode}
+%
 
-\RequirePackage{xcolor}% for \convertcolorspec
 
-% \LWR@ProvidesPackagePass{siunitx}[2021-05-21]
 
-\RequirePackage{siunitx-v2}
+% Initial options:
+%    \begin{macrocode}
+\AtBeginDocument{
+\sisetup{
+    per-mode=symbol,    % fraction is not seen by pdftotext
+    angle-symbol-degree = {\LWR@siunitx@textdegree},
+    angle-symbol-minute = {\LWR@siunitx@textprime} ,
+    angle-symbol-second = {\LWR@siunitx@textdblprime} ,
+}
+}
+%    \end{macrocode}
+%
+%
+% Load late paches for \pkg{lltjp-siunitx}:
+%    \begin{macrocode}
+\AtBeginDocument{
+\ifdef{\ltj@allalchar}
+    {\LWR@origRequirePackage{lwarp-lltjp-siunitx}}
+    {}
+}
+%    \end{macrocode}
+%
+%
+% For \MathJax:
+%    \begin{macrocode}
+\LWR@origRequirePackage{lwarp-common-mathjax-siunitx}
+
+\CustomizeMathJax{\let\unit\si}
+\CustomizeMathJax{\let\qty\SI}
+\CustomizeMathJax{\let\qtylist\SIlist}
+\CustomizeMathJax{\let\qtyrange\SIrange}
+\CustomizeMathJax{\let\numproduct\num}
+\CustomizeMathJax{\let\qtyproduct\SI}
+\CustomizeMathJax{\let\complexnum\num}
+\CustomizeMathJax{\newcommand{\complexqty}[3][]{(\complexnum{#2})\si{#3}}}
+%    \end{macrocode}
+%
+% Pass \optn{range-phrase} to \pkg{common-mathjax-siunitx}:
+% \changes{v0.904}{2022/02/28}{\pkg{siunitx}, \MathJax: Use \optn{range-phrase}.}
+%    \begin{macrocode}
+\ExplSyntaxOn
+\AtBeginDocument{
+\edef\LWR@siunitx@rangephrase{\l_siunitx_range_phrase_tl}
+\expandafter\CustomizeMathJax\expandafter{%
+    \expandafter\def\expandafter\LWRsiunitxrangephrase%
+    \expandafter{\LWR@siunitx@rangephrase}%
+}
+}
+\ExplSyntaxOff
 %    \end{macrocode}
 
 % \iffalse
@@ -79421,16 +80435,17 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 % \changes{v0.38}{2017/08/26}{\pkg{siunitx}: Removed from \pkg{lwarp} core.}
 % \changes{v0.50}{2018/10/23}{\pkg{siunitx}: Fix: Loads \pkg{xcolor}.}
 % \changes{v0.897}{2021/05/23}{\pkg{siunitx-v2}: Rollback for v2.}
+% \changes{v0.904}{2022/02/26}{\pkg{siunitx-v2}: Updated to v2.8e.}
 %
 % \codehtml
 %
 %    \begin{macrocode}
 \RequirePackage{xcolor}% for \convertcolorspec
 
-\LWR@ProvidesPackagePass{siunitx-v2}[2021-04-17]
+\LWR@ProvidesPackagePass{siunitx}[=v2]% 2021-04-17
 %    \end{macrocode}
 
-% \changes{v0.50}{2018/02/24}{\pkg{siunitx}: Improved units.}
+% \changes{v0.50}{2018/02/24}{\pkg{siunitx-v2}: Improved units.}
 %    \begin{macrocode}
 \AtBeginDocument{% in case textcomp was not loaded
     \DeclareSIUnit\bohr{\textit{a}\textsubscript{0}}
@@ -79443,11 +80458,11 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 %    \end{macrocode}
 
 % Support the |S| and |s| column types:
-% \changes{v0.901}{2021/08/18}{\pkg{siunitx}: Improved \cs{newcolumntype} emulation.}
+% \changes{v0.901}{2021/08/18}{\pkg{siunitx-v2}: Improved \cs{newcolumntype} emulation.}
 %    \begin{macrocode}
 \AtBeginDocument{
-\HTMLnewcolumntype{S}{c}
-\HTMLnewcolumntype{s}{c}
+\HTMLnewcolumntype{S}[1][]{>{\begingroup\sisetup{#1}}c<{\endgroup}}
+\HTMLnewcolumntype{s}[1][]{>{\begingroup\sisetup{#1}}c<{\endgroup}}
 }
 %    \end{macrocode}
 
@@ -79457,17 +80472,45 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 % Similar for \cs{mbox}.
 % \SVG\ math is created explicitly when necessary, using \cs{LWR@subsingledollar}.
 %
-% \changes{v0.42}{2017/10/16}{\pkg{siunitx}: Improved \cs{ensuremath}.}
-% \changes{v0.48}{2018/02/13}{\pkg{siunitx}: Improved \SVG\ math.}
+% \changes{v0.42}{2017/10/16}{\pkg{siunitx-v2}: Improved \cs{ensuremath}.}
+% \changes{v0.48}{2018/02/13}{\pkg{siunitx-v2}: Improved \SVG\ math.}
 %    \begin{macrocode}
 
 \ExplSyntaxOn
 %
 %    \end{macrocode}
+%
+% Modified to use the print version of \cs{@ensuredmath} to avoid
+% having a \env{lateximage} each time.
+%    \begin{macrocode}
+\AtBeginDocument{
+\cs_set_protected:Npn \__siunitx_print_text:
+  {
+    \LetLtxMacro\@ensuredmath\LWR@origensuredmath%          lwarp
+    \tl_replace_all:Nnn \l__siunitx_print_arg_tl { - }
+      { \textminus }
+    \__siunitx_print_text_aux:
+    \tl_replace_all:Nnn \l__siunitx_print_arg_tl { \mp }
+      { \ensuremath { \mp } }
+    \tl_remove_all:Nn \l__siunitx_print_arg_tl { \mathord }
+    \cs_set_eq:NN \PrintSubscript   \__siunitx_print_text_sub:n
+    \cs_set_eq:NN \PrintSuperscript \__siunitx_print_text_super:n
+    \__siunitx_print_text_aux:NnN
+      _ { math_subscript }   \__siunitx_print_text_sub:n
+      _ { active }           \__siunitx_print_text_sub:n
+      ^ { math_superscript } \__siunitx_print_text_super:n
+      ^ { active }           \__siunitx_print_text_super:n
+      \q_recursion_tail ?  ?
+      \q_recursion_stop
+    \l__siunitx_print_arg_tl
+  }
+}
+%    \end{macrocode}
+%
 % Modified to set set \HTML\ \cs{textcolor} if not black:
-% \changes{v0.48}{2018/02/14}{\pkg{siunitx}: Improved color output.}
+% \changes{v0.48}{2018/02/14}{\pkg{siunitx-v2}: Improved color output.}
 %    \begin{macrocode}
-\cs_set_protected:Npn \__siunitx_print_aux:
+\cs_new_protected:Npn \LWR@HTML@__siunitx_print_aux:
   {
     \text
       {
@@ -79505,13 +80548,14 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
           }
       }
   }
+\LWR@formatted{__siunitx_print_aux:}
 
-\cs_set_protected:Npn \__siunitx_set_math_fam:n #1 {
+\cs_new_protected:Npn \LWR@HTML@__siunitx_set_math_fam:n #1 {
   \group_begin:
-    \LetLtxMacro\@ensuredmath\LWR@origensuredmath% lwarp
-    \LetLtxMacro\mbox\LWR@print@mbox% lwarp
-    \hbox_set:Nn \l__siunitx_tmp_box
-      {
+%     \LetLtxMacro\@ensuredmath\LWR@origensuredmath% lwarp
+%     \LetLtxMacro\mbox\LWR@print@mbox% lwarp
+%     \hbox_set:Nn \l__siunitx_tmp_box
+%       {
         \ensuremath
           {
             \use:c { math #1 }
@@ -79519,15 +80563,14 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
                 \int_const:cn { c__siunitx_math #1 _int } { \fam }
               }
           }
-      }
+%       }
   \group_end:
 }
+\LWR@formatted{__siunitx_set_math_fam:n}
 
-\cs_set_protected:Npn \__siunitx_combined_output:n #1 {
+\cs_new_protected:Npn \LWR@HTML@__siunitx_combined_output:n #1 {
 %
     \group_begin:% lwarp
-    \LetLtxMacro\@ensuredmath\LWR@origensuredmath% lwarp
-    \LetLtxMacro\mbox\LWR@print@mbox% lwarp
   \bool_if:NTF \l__siunitx_number_parse_bool
     {
       \tl_clear:N \l__siunitx_number_out_tl
@@ -79537,39 +80580,43 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
     {
 %    \end{macrocode}
 % For |parse-numbers=false|:
-% \changes{v0.48}{2018/02/14}{\pkg{siunitx}: Improved \SVG\ math.}
-% \changes{v0.50}{2018/02/24}{\pkg{siunitx}: Improved \SVG\ math \attribute{alt} tags.}
-% \changes{v0.79}{2020/01/21}{\pkg{siunitx}: Improved \MathJax.}
-% \changes{v0.903}{2021/12/18}{\pkg{siunitx}: Improved alt tag sanitization.}
+% \changes{v0.48}{2018/02/14}{\pkg{siunitx-v2}: Improved \SVG\ math.}
+% \changes{v0.50}{2018/02/24}{\pkg{siunitx-v2}: Improved \SVG\ math \attribute{alt} tags.}
+% \changes{v0.79}{2020/01/21}{\pkg{siunitx-v2}: Improved \MathJax.}
+% \changes{v0.903}{2021/12/18}{\pkg{siunitx-v2}: Improved alt tag sanitization.}
 %    \begin{macrocode}
         \__siunitx_unit_output_pre_print:
         \begingroup%                            lwarp
             \boolfalse{mathjax}%                lwarp
 %       \__siunitx_print:nn { number } { \ensuremath {#1} }
-            \LWR@subsingledollar{%              lwarp
+            \LWR@subsingledollar%       lwarp
+                {%  alt text
                     \textbackslash( % space
                     \LWR@HTMLsanitizedetokenized{%
                         \detokenize{#1}%
                     } \textbackslash)%          lwarp
-            }{siunitx}{%
-                \__siunitx_print:nn { number } {%
-                    \LWR@origensuredmath{#1}%
-                }%
-            }%                                  lwarp
+                }
+                {siunitx}%  addl hashing
+                {%
+                    \__siunitx_print:nn { number } {%
+                        \LWR@origensuredmath{#1}%
+                    }%
+                }%                              lwarp
         \endgroup%                              lwarp
         \__siunitx_unit_output_print:
     }
    \group_end:% lwarp
 %
 }
+\LWR@formatted{__siunitx_combined_output:n}
 %    \end{macrocode}
 %
 %
 % For |parse-numbers=false|:
-% \changes{v0.79}{2020/01/21}{\pkg{siunitx}: Improved \MathJax.}
-% \changes{v0.903}{2021/12/18}{\pkg{siunitx}: Improved alt tag sanitization.}
+% \changes{v0.79}{2020/01/21}{\pkg{siunitx-v2}: Improved \MathJax.}
+% \changes{v0.903}{2021/12/18}{\pkg{siunitx-v2}: Improved alt tag sanitization.}
 %    \begin{macrocode}
-\cs_set_protected:Npn \__siunitx_range_numbers_aux:n #1
+\cs_new_protected:Npn \LWR@HTML@__siunitx_range_numbers_aux:n #1
   {
     \bool_if:NTF \l__siunitx_number_parse_bool
       {
@@ -79583,29 +80630,33 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
       {
         \__siunitx_unit_output_pre_print:
         \begingroup%    lwarp
-            \boolfalse{mathjax}%                    lwarp
+            \boolfalse{mathjax}%                        lwarp
 %           \__siunitx_print:nn { number } {#1}
-                \LWR@subsingledollar{%              lwarp
-                    \textbackslash( % space
-                    \LWR@HTMLsanitizedetokenized{%
-                        \detokenize{#1}%
-                    } \textbackslash)%              lwarp
-                }{siunitx}{%
-                    \__siunitx_print:nn { number } {%
-                        \LWR@origensuredmath{#1}%
-                    } %                             lwarp
-                }%                                  lwarp
-        \endgroup%                                  lwarp
+                \LWR@subsingledollar%                   lwarp
+                    {%  alt text
+                        \textbackslash( % space
+                        \LWR@HTMLsanitizedetokenized{%
+                            \detokenize{#1}%
+                        } \textbackslash)%              lwarp
+                    }%
+                    {siunitx}%  addl hashing
+                    {%
+                        \__siunitx_print:nn { number } {%
+                            \LWR@origensuredmath{#1}%
+                        } %                             lwarp
+                    }%                                  lwarp
+        \endgroup%                                      lwarp
         \__siunitx_unit_output_print:
       }
   }
+\LWR@formatted{__siunitx_range_numbers_aux:n}
 %    \end{macrocode}
 %
 % For |parse-numbers=false|:
-% \changes{v0.79}{2020/01/21}{\pkg{siunitx}: Improved \MathJax.}
-% \changes{v0.903}{2021/12/18}{\pkg{siunitx}: Improved alt tag sanitization.}
+% \changes{v0.79}{2020/01/21}{\pkg{siunitx-v2}: Improved \MathJax.}
+% \changes{v0.903}{2021/12/18}{\pkg{siunitx-v2}: Improved alt tag sanitization.}
 %    \begin{macrocode}
-\cs_set_protected:Npn \__siunitx_angle_print_direct_aux:nn #1#2 {
+\cs_new_protected:Npn \LWR@HTML@__siunitx_angle_print_direct_aux:nn #1#2 {
   \tl_if_empty:nF {#1}
     {
       \tl_set:Nn \l__siunitx_unit_tl {#2}
@@ -79617,7 +80668,9 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
                     \LWR@HTMLsanitizedetokenized{%
                         \detokenize{#1}%
                     } \textbackslash)%                  lwarp
-                }{siunitx}{%
+                }%
+                {siunitx}%
+                {%
                     \__siunitx_print:nn { number } {
                         \LWR@origensuredmath{#1}%
                     }%                                  lwarp
@@ -79626,13 +80679,14 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
       \__siunitx_unit_output_print:
     }
 }
+\LWR@formatted{__siunitx_angle_print_direct_aux:nn}
 %
 %    \end{macrocode}
 %
 % For quotients, the fraction code is replaced by the symbol code:
-% \changes{v0.48}{2018/02/14}{\pkg{siunitx}: Changes fraction to symbol.}
+% \changes{v0.48}{2018/02/14}{\pkg{siunitx-v2}: Changes fraction to symbol.}
 %    \begin{macrocode}
-\cs_set_protected:Npn \__siunitx_number_output_quotient_fraction: {
+\cs_new_protected:Npn \LWR@HTML@__siunitx_number_output_quotient_fraction: {
   \bool_set_true:N \l__siunitx_number_compound_bool
   \__siunitx_number_output_quotient_aux_i:
   \tl_set_eq:NN \l__siunitx_number_out_tl
@@ -79642,12 +80696,13 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
     \l__siunitx_number_denominator_tl
   \__siunitx_number_output_single_aux:
 }
+\LWR@formatted{__siunitx_number_output_quotient_fraction:}
 %    \end{macrocode}
 %
 % For units, the fraction code is replaced by the symbol code:
-% \changes{v0.48}{2018/02/14}{\pkg{siunitx}: Changes fraction to symbol.}
+% \changes{v0.48}{2018/02/14}{\pkg{siunitx-v2}: Changes fraction to symbol.}
 %    \begin{macrocode}
-\cs_set_protected:Npn \__siunitx_unit_format_fraction_fraction: {
+\cs_new_protected:Npn \LWR@HTML@__siunitx_unit_format_fraction_fraction: {
   \__siunitx_unit_format_fraction_symbol_aux:
   \int_compare:nNnT { \l__siunitx_unit_denominator_int } > { 1 }
     {
@@ -79661,11 +80716,12 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
   \tl_put_right:NV \l__siunitx_unit_tl \l__siunitx_per_symbol_tl
   \tl_put_right:NV \l__siunitx_unit_tl \l__siunitx_unit_denominator_tl
 }
+\LWR@formatted{__siunitx_unit_format_fraction_fraction:}
 %    \end{macrocode}
 %
-% \changes{v0.50}{2018/02/24}{\pkg{siunitx}: Improved units.}
+% \changes{v0.50}{2018/02/24}{\pkg{siunitx-v2}: Improved units.}
 %    \begin{macrocode}
-\cs_set_protected:Npn \__siunitx_angle_print_astronomy_aux: {
+\cs_new_protected:Npn \LWR@HTML@__siunitx_angle_print_astronomy_aux: {
   \prop_get:NnNT \l__siunitx_number_out_prop { mantissa-integer }
     \l__siunitx_tmpa_tl
     { \__siunitx_print:nV { number } \l__siunitx_tmpa_tl }
@@ -79693,111 +80749,350 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
     { \__siunitx_angle_print_astronomy_unit: }
  }% lateximage
  {% not a lateximage
-      \__siunitx_print:nV { unit } \l__siunitx_unit_tl
       \__siunitx_print:nn { number } { { \l__siunitx_output_decimal_tl } }
+      \__siunitx_print:nV { unit } \l__siunitx_unit_tl
  }% not a lateximage
   \prop_get:NnNT \l__siunitx_number_out_prop { mantissa-decimal }
     \l__siunitx_tmpa_tl
     { \__siunitx_print:nV { number } \l__siunitx_tmpa_tl }
 }
+\LWR@formatted{__siunitx_angle_print_astronomy_aux:}
 %    \end{macrocode}
 %
-% \changes{v0.79}{2020/01/20}{\pkg{siunitx}: Fix: \cs{square}, \cs{cubed}.}
+% \changes{v0.79}{2020/01/20}{\pkg{siunitx-v2}: Fix: \cs{square}, \cs{cubed}.}
 %    \begin{macrocode}
-\cs_set_protected:Npn \__siunitx_textsuperscript:n #1 {\textsuperscript{#1}}
+\cs_new_protected:Npn \LWR@HTML@__siunitx_textsuperscript:n #1 {\textsuperscript{#1}}
+\LWR@formatted{__siunitx_textsuperscript:n}
+
+\cs_new_eq:NN \LWR@HTML@__siunitx_print_text_super:n \textsuperscript
+\LWR@formatted{__siunitx_print_text_super:n}
+
+\cs_new_eq:NN \LWR@HTML@__siunitx_print_text_sub:n \textsubscript
+\LWR@formatted{__siunitx_print_text_sub:n}
 %    \end{macrocode}
-%
-% \begin{noindmacro}{\num} \oarg{options} \marg{value}
+
+
+% \cs{LWR@origenduresmath} is added here in case the user asks for \cs{mathrm}, etc.
+% for \optn{output-exponent-marker}.
 %    \begin{macrocode}
-\RenewDocumentCommand \num { o m } {
-  \leavevmode
-  \group_begin:% lwarp
-    \LetLtxMacro\@ensuredmath\LWR@origensuredmath% lwarp
-    \LetLtxMacro\mbox\LWR@print@mbox% lwarp
-    \bool_set_false:N \l__siunitx_font_set_bool
-    \IfNoValueF {#1}
-      { \keys_set:nn { siunitx } {#1} }
-    \__siunitx_number_output:n {#2}
-  \group_end:% lwarp
+\cs_new_protected:Npn \LWR@HTML@__siunitx_number_format_final_exponent: {
+  \prop_get:NnN \l__siunitx_number_out_prop { exponent }
+    \l__siunitx_tmpa_tl
+  \tl_if_empty:NTF \l__siunitx_output_exponent_tl
+    {
+      \tl_set:Nx \l__siunitx_tmpa_tl
+       { ^ { \exp_not:V \l__siunitx_tmpa_tl } }
+      \tl_put_left:NV \l__siunitx_tmpa_tl \l__siunitx_exponent_base_tl
+    }
+    {
+      \tl_set:Nx  \l__siunitx_tmpa_tl
+        {
+          \LWR@origensuredmath{%    lwarp
+            \exp_not:V \l__siunitx_output_exponent_tl
+          }%                        lwarp
+          \exp_not:N \mathord
+          \exp_not:V  \l__siunitx_tmpa_tl
+        }
+    }
+  \prop_put:NnV \l__siunitx_number_out_prop { exponent-result }
+    \l__siunitx_tmpa_tl
 }
+\LWR@formatted{__siunitx_number_format_final_exponent:}
 %    \end{macrocode}
-% \end{noindmacro}
-%
-% \begin{noindmacro}{\numrange} \oarg{options} \marg{value1} \marg{value2}
+
+
+% \cs{LWR@origensuredmath} is added here to avoid using an image for the exponent product.
 %    \begin{macrocode}
-\RenewDocumentCommand \numrange { o m m } {
-  \leavevmode
-  \group_begin:% lwarp
-    \LetLtxMacro\@ensuredmath\LWR@origensuredmath% lwarp
-    \LetLtxMacro\mbox\LWR@print@mbox% lwarp
-    \bool_set_false:N \l__siunitx_font_set_bool
-    \IfNoValueF {#1}
-      { \keys_set:nn { siunitx } {#1} }
-    \__siunitx_range_numbers:nn {#2} {#3}
-  \group_end:% lwarp
+\cs_new_protected:Npn \LWR@HTML@__siunitx_number_format_final_combined: {
+  \__siunitx_number_format_brackets:n { mantissa }
+  \prop_get:NnN \l__siunitx_number_out_prop { mantissa-result }
+    \l__siunitx_tmpa_tl
+  \tl_if_empty:NT \l__siunitx_output_exponent_tl
+    {
+      \tl_put_right:Nx \l__siunitx_tmpa_tl
+        {
+          \exp_not:N \LWR@origensuredmath%       lwarp
+            {
+              \bool_if:NTF \l__siunitx_tight_bool
+                { {  \exp_not:V \l__siunitx_exponent_product_tl } }
+                { { } \exp_not:V \l__siunitx_exponent_product_tl { } }
+            }
+        }
+    }
+  \prop_get:NnN \l__siunitx_number_out_prop { exponent-result }
+    \l__siunitx_tmpb_tl
+  \tl_put_right:NV \l__siunitx_tmpa_tl \l__siunitx_tmpb_tl
+  \prop_put:NnV \l__siunitx_number_out_prop { result }
+    \l__siunitx_tmpa_tl
+  \prop_put:Nnn \l__siunitx_number_out_prop
+    { result-bracket-exponent } { true }
 }
+\LWR@formatted{__siunitx_number_format_final_combined:}
 %    \end{macrocode}
-% \end{noindmacro}
-%
-% \begin{noindmacro}{\ang} \marg{options} \marg{angle}
+
+
+% \cs{LWR@origensuredmath} is added here to avoid using an image for the exponent product.
 %    \begin{macrocode}
-\RenewDocumentCommand \ang { o > { \SplitArgument { 2 } { ; } } m } {
-  \group_begin:% lwarp
-    \LetLtxMacro\@ensuredmath\LWR@origensuredmath% lwarp
-    \LetLtxMacro\mbox\LWR@print@mbox% lwarp
-    \IfNoValueF {#1}
-      { \keys_set:nn { siunitx } {#1} }
-    \__siunitx_angle_output:nnn #2
-  \group_end:% lwarp
+\cs_new_protected:Npn \LWR@HTML@__siunitx_number_output_parts_aux: {
+  \bool_if:NTF \l__siunitx_multi_repeat_bool
+    {
+      \prop_if_in:NnT \l__siunitx_number_out_prop { mantissa-result }
+        {
+          \__siunitx_number_output_parts_aux:n { mantissa }
+          \__siunitx_number_output_parts_aux:n { complex }
+        }
+      \prop_get:NnNT \l__siunitx_number_out_prop { exponent-result }
+        \l__siunitx_tmpa_tl
+        {
+          \prop_if_in:NnT \l__siunitx_number_out_prop { mantissa-result }
+            {
+              \tl_put_left:Nx \l__siunitx_tmpa_tl
+                {
+                  \exp_not:N \LWR@origensuredmath
+                    {
+                      \bool_if:NTF \l__siunitx_tight_bool
+                        { {  \exp_not:V \l__siunitx_exponent_product_tl } }
+                        { { } \exp_not:V \l__siunitx_exponent_product_tl { } }
+                    }
+                }
+              \prop_put:NnV \l__siunitx_number_out_prop { exponent }
+                \l__siunitx_tmpa_tl
+            }
+          \__siunitx_number_output_parts_print:n { exponent }
+        }
+    }
+    { \__siunitx_number_output_single: }
 }
+\LWR@formatted{__siunitx_number_output_parts_aux:}
 %    \end{macrocode}
-% \end{noindmacro}
-%
-% \begin{noindmacro}{\si} \marg{options} \marg{unit}
+
+
+% \cs{LWR@origensuredmath} is added here to avoid using an image for the exponent product.
 %    \begin{macrocode}
-\RenewDocumentCommand \si { o m } {
-  \leavevmode
-  \group_begin:% lwarp
-    \LetLtxMacro\@ensuredmath\LWR@origensuredmath% lwarp
-    \LetLtxMacro\mbox\LWR@print@mbox% lwarp
-    \bool_set_false:N \l__siunitx_font_set_bool
-    \IfNoValueTF {#1}
-      { \__siunitx_unit_output:nn {#2} { } }
+\cs_new_protected:Npn \LWR@HTML@__siunitx_unit_output_print: {
+  \int_compare:nNnF { \l__siunitx_unit_prefix_int } = { 0 }
+    {
+      \tl_set:Nx \l__siunitx_tmpa_tl
+        {
+          \bool_if:NTF \l__siunitx_tight_bool
+            {
+              \exp_not:N \LWR@origensuredmath%      lwarp
+                { { \exp_not:V \l__siunitx_exponent_product_tl } }
+            }
+            {
+              \exp_not:N \LWR@origensuredmath%      lwarp
+                { { } \exp_not:V \l__siunitx_exponent_product_tl { } }
+            }
+          \int_use:N \l__siunitx_unit_prefix_base_int
+          ^ { \int_use:N \l__siunitx_unit_prefix_int }
+        }
+      \__siunitx_print:nV { number } \l__siunitx_tmpa_tl
+    }
+  \tl_if_empty:NF \l__siunitx_unit_tl
+    {
+      \__siunitx_unit_output_number_sep:
+      \__siunitx_print:nV { unit } \l__siunitx_unit_tl
+    }
+}
+\LWR@formatted{__siunitx_unit_output_print:}
+%    \end{macrocode}
+
+
+% \cs{LWR@origensuredmath} is added here to avoid using an image for the exponent product.
+%    \begin{macrocode}
+\cs_new_protected:Npn \LWR@HTML@__siunitx_range_exponent:
+  {
+    \bool_if:NT \l__siunitx_process_fixed_bool
+      {
+        \tl_set_eq:NN \l__siunitx_tmpa_tl \l__siunitx_exponent_product_tl
+        \bool_if:NT \l__siunitx_tight_bool
+          {
+            \tl_set:Nx \l__siunitx_tmpa_tl
+              { \exp_not:N \mathord \exp_not:o \l__siunitx_tmpa_tl }
+          }
+        \tl_set:Nx \l__siunitx_tmpa_tl
+          {
+            \exp_not:N \LWR@origensuredmath {%      lwarp
+                { } \exp_not:o \l__siunitx_tmpa_tl  { }
+            }
+            10 \exp_not:N \PrintSuperscript
+              { \int_use:N \l__siunitx_process_fixed_int }
+          }
+        \__siunitx_print:nV { number } \l__siunitx_tmpa_tl
+      }
+  }
+\LWR@formatted{__siunitx_range_exponent:}
+%    \end{macrocode}
+
+
+% \cs{LWR@origensuredmath} is added here to avoid using an image for the exponent product.
+%    \begin{macrocode}
+\cs_new_protected:Npn \LWR@HTML@__siunitx_table_print_S_reserved_exponent_product:
+  {
+    \tl_set_eq:NN \l__siunitx_tmpb_tl \l__siunitx_exponent_product_tl
+    \bool_if:NT \l__siunitx_tight_bool
+      {
+        \tl_set:Nx \l__siunitx_tmpb_tl
+          { \exp_not:N \mathord \exp_not:o \l__siunitx_tmpb_tl }
+      }
+    \tl_set:Nx \l__siunitx_tmpa_tl
       {
-        \keys_set:nn { siunitx } {#1}
-        \__siunitx_unit_output:nn {#2} {#1}
+        \exp_not:N \LWR@origensuredmath { { } \exp_not:o \l__siunitx_tmpb_tl  { } }
+        \exp_not:o \l__siunitx_tmpa_tl
       }
-  \group_end:% lwarp
+  }
+\LWR@formatted{__siunitx_table_print_S_reserved_exponent_product:}
+%    \end{macrocode}
+
+
+% \cs{LWR@origensuredmath} is added here to avoid using an image for the output product.
+%    \begin{macrocode}
+\cs_new_protected:Npn \LWR@HTML@__siunitx_number_output_product_aux: {
+  \bool_set_true:N \l__siunitx_number_compound_bool
+  \__siunitx_number_preprocess:V \l__siunitx_number_arg_tl
+  \bool_if:NF \l__siunitx_error_bool
+    {
+      \tl_if_empty:NTF \l__siunitx_number_multi_tl
+        { \__siunitx_number_output_parse_aux: }
+        { \__siunitx_number_output_quotient: }
+      \tl_if_empty:NF \l__siunitx_number_next_tl
+        {
+          \bool_if:NTF \l__siunitx_tight_bool
+            {
+              \__siunitx_print:nn { number }
+                { \LWR@origensuredmath { \l__siunitx_output_product_tl } }
+            }
+            {
+              \__siunitx_print:nn  { number }
+                { \LWR@origensuredmath { { } \l__siunitx_output_product_tl { } } }
+            }
+          \__siunitx_number_output_parse:V \l__siunitx_number_next_tl
+        }
+    }
 }
+\LWR@formatted{__siunitx_number_output_product_aux:}
 %    \end{macrocode}
-% \end{noindmacro}
-%
-%
-% \begin{noindmacro}{\SIrange} \oarg{options} \marg{value1} \marg{value2} \marg{unit}
+
+
+% Used to detect the math font.
 %    \begin{macrocode}
-\RenewDocumentCommand{\SIrange}{o m m m}
-{%
-  \leavevmode
-  \group_begin:% lwarp
-    \LetLtxMacro\@ensuredmath\LWR@origensuredmath% lwarp
-    \LetLtxMacro\mbox\LWR@print@mbox% lwarp
-    \bool_set_false:N \l__siunitx_font_set_bool
-    \IfNoValueTF {#1}
-      { \__siunitx_range_unit:nnnn {#4} { } {#2} {#3} }
+\cs_set_protected:Npn \__siunitx_set_math_fam:n #1 {
+  \group_begin:
+    \hbox_set:Nn \l__siunitx_tmp_box
       {
-        \keys_set:nn { siunitx } {#1}
-        \__siunitx_range_unit:nnnn {#4} {#1} {#2} {#3}
+        \LWR@origensuredmath%       lwarp
+          {
+            \use:c { math #1 }
+              {
+                \int_const:cn { c__siunitx_math #1 _int } { \fam }
+              }
+          }
       }
-  \group_end:% lwarp
+  \group_end:
 }
 %    \end{macrocode}
-% \end{noindmacro}
-%
+
+% Force \cs{text}:
+% \changes{v0.904}{2022/02/26}{\pkg{siunitx-v2}: Improved range phrase.}
+%    \begin{macrocode}
+\cs_set_protected:Npn \__siunitx_range_numbers:nn #1#2
+  {
+    \__siunitx_range_numbers_aux:n {#1}
+    \text{\l__siunitx_range_phrase_tl}%     lwarp
+    \__siunitx_range_numbers_aux:n {#2}
+  }
+%    \end{macrocode}
+
+
+% Force \cs{text}:
+% \changes{v0.904}{2022/02/26}{\pkg{siunitx-v2}: Improved range phrase.}
+%    \begin{macrocode}
+\cs_set_protected:Npn \__siunitx_range_unit:nnnn #1#2#3#4 {
+  \__siunitx_unit_parse_options:nn {#1} {#2}
+  \bool_if:NTF \l__siunitx_range_repeat_bool
+    {
+      \__siunitx_unit_in:nn {#1} {#2}
+      \__siunitx_range_numbers_aux:n {#3}
+      \text{\l__siunitx_range_phrase_tl}%       lwarp
+      \__siunitx_range_numbers_aux:n {#4}
+    }
+    {
+      \bool_if:NT \l__siunitx_process_fixed_bool
+        { \bool_set_true:N \l__siunitx_process_drop_exponent_bool }
+      \bool_if:NT \l__siunitx_range_brackets_bool
+        { \__siunitx_print:nV { number } \l__siunitx_bracket_open_tl }
+      \__siunitx_range_numbers:nn {#3} {#4}
+      \bool_if:NT \l__siunitx_range_brackets_bool
+        { \__siunitx_print:nV { number } \l__siunitx_bracket_close_tl }
+      \__siunitx_range_exponent:
+      \__siunitx_unit_output_number_sep:
+      \__siunitx_unit_output:nn {#1} {#2}
+    }
+}
+%    \end{macrocode}
+
+
 %    \begin{macrocode}
 \ExplSyntaxOff
 %    \end{macrocode}
 
 
+%    \begin{macrocode}
+\AtBeginDocument{
+\sisetup{
+    detect-mode=true,
+    per-mode=symbol,    % fraction is not seen by pdftotext
+    text-celsius = {\LWR@siunitx@textcelsius},
+    text-degree = {\LWR@siunitx@textdegree},
+    text-arcminute = {\LWR@siunitx@textprime} ,
+    text-arcsecond = {\LWR@siunitx@textdblprime} ,
+}
+}
+%    \end{macrocode}
+
+
+%    \begin{macrocode}
+\LWR@origRequirePackage{lwarp-common-mathjax-siunitx}
+%    \end{macrocode}
+
+
+% Passing \optn{range-phrase} to \pkg{common-mathjax-siunitx} does not
+% seem to work with v2 using \pkg{translator} as it does with v3 using \pkg{translations}.
+% The \optn{range-phrase} therefore is set to an en-dash.
+% \changes{v0.904}{2022/02/28}{\pkg{siunitx-v2}, \MathJax: Use \optn{range-phrase}.}
+%    \begin{macrocode}
+\AtBeginDocument{
+\CustomizeMathJax{\def\LWRsiunitxrangephrase{\unicode{x2013}}}
+}
+%    \end{macrocode}
+
+
+% \iffalse
+%</siunitx-v2>
+% \fi
+
+
+
+
+%
+% \iffalse
+%<*common-mathjax-siunitx>
+% \fi
+%
+% \part{lwarp-common-mathjax-siunitx.sty}
+
+% \section{common-mathjax-siunitx}
+%
+% \credits{Joseph Wright}
+%
+% \DescribePackage{common-mathjax-siunitx}
+% \pkg{common-mathjax-siunitx} adds \MathJax\ for \pkg{siunitx} and \pkg{siunitx-v2}.
+%
+% \changes{v0.904}{2022/02/21}{\pkg{common-mathjax-siunitx}: Factored from \pkg{siunitx-v2}.}
+%
+% \codehtml
+%
+%
 % For \MathJax.
 % \margintag{\MathJax}
 %
@@ -79841,9 +81136,11 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 % of the arguments of each macro when used, and
 % the final argument of each collects any extra unused delimiters.
 %
-% The number is split by powers (|E|, |e|, |D|, |d|), then by dimensions (|x|),
-% then by plus and minus (|+|, |-|, |+-|), then into pieces before and after the decimal
-% point.
+% The number is split by dimensions (|x|),
+% then by powers (|E|, |e|, |D|, |d|),
+% then by plus \Slash minus (|+-|, \cs{pm}),
+% then by plus and minus (|+|, |-|),
+% then into pieces before and after the decimal point or decimal comma.
 %
 % \changes{v0.895}{2021/01/14}{\pkg{siunitx}, \MathJax:
 %       \cs{num} sci notation, multiples, +-, decimals, comma.}
@@ -79861,6 +81158,12 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 \ExplSyntaxOff
 %    \end{macrocode}
 %
+% Any units which must be distributed across multiple dimensions:
+%    \begin{macrocode}
+\CustomizeMathJax{\def\LWRsiunitxdistribunit{}}
+%    \end{macrocode}
+%
+%
 % \pkg{siunitx} accepts either commas or periods as decimal points.
 % \cs{LWRsiunitxprintdecimal} splits its input by periods then commas,
 % parsing out before and after sections to print on either side of the decimal point.
@@ -79882,7 +81185,7 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
     \ifblank{#1}{0}{\mathrm{#1}}%
 %    \end{macrocode}
 %
-% If something is after the decimal comma, print the decimal comma and the fraction:
+% If something is after the decimal comma, print the decimal and the fraction:
 %    \begin{macrocode}
     \ifblank{#2}%
         {}%
@@ -79901,7 +81204,6 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
     \ifblank{#2}%
         {}%
         {%
-%             {.}%
             {\LWRsiunitxdecimal}%
             \LWRsiunitxprintdecimalsubtwo#2,,\LWRsiunitxENDTWO%
         }%
@@ -79916,7 +81218,9 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 %    \begin{macrocode}
 \CustomizeMathJax{\def\LWRsiunitxnumplus#1+#2+#3\LWRsiunitxEND{%
     \ifblank{#2}%
-        {\LWRsiunitxprintdecimal{#1}}% no plus
+        {%
+            \LWRsiunitxprintdecimal{#1}%
+        }% no plus
         {%
             \ifblank{#1}%
                 {\LWRsiunitxprintdecimal{#2}}% leading plus, ignore
@@ -79926,6 +81230,7 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
                     \LWRsiunitxprintdecimal{#2}%
                 }%
         }%
+    \LWRsiunitxdistribunit%
 }}
 %    \end{macrocode}
 %
@@ -79938,42 +81243,36 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
             \ifblank{#1}{}{\LWRsiunitxprintdecimal{#1}}%
             \unicode{x02212}% mathematical minus sign
             \LWRsiunitxprintdecimal{#2}%
+            \LWRsiunitxdistribunit%
         }%
 }}
 %    \end{macrocode}
 %
-% The following splits by |+-|
+% The following splits by |\pm|
+% \changes{v0.904}{2022/02/28}{\pkg{siunitx}, \MathJax: Fixed \cs{pm}.}
 %    \begin{macrocode}
-\CustomizeMathJax{\def\LWRsiunitxnumpm#1+-#2+-#3\LWRsiunitxEND{%
+\CustomizeMathJax{\def\LWRsiunitxnumpmmacro#1\pm#2\pm#3\LWRsiunitxEND{%
     \ifblank{#2}%
         {\LWRsiunitxnumminus#1---\LWRsiunitxEND}%
         {%
             \LWRsiunitxprintdecimal{#1}%
             \unicode{x0B1}% \pm
             \LWRsiunitxprintdecimal{#2}%
+            \LWRsiunitxdistribunit%
         }%
 }}
 %    \end{macrocode}
 %
-% The following splits by |x|
+% The following splits by |+-|
 %    \begin{macrocode}
-\CustomizeMathJax{\def\LWRsiunitxnumx#1x#2x#3x#4\LWRsiunitxEND{%
+\CustomizeMathJax{\def\LWRsiunitxnumpm#1+-#2+-#3\LWRsiunitxEND{%
     \ifblank{#2}%
-        {\LWRsiunitxnumpm#1+-+-\LWRsiunitxEND}%
+        {\LWRsiunitxnumpmmacro#1\pm\pm\pm\LWRsiunitxEND}%
         {%
-            \ifblank{#3}%
-                {%
-                    \LWRsiunitxprintdecimal{#1}%
-                    \times%
-                    \LWRsiunitxprintdecimal{#2}%
-                }%
-                {%
-                    \LWRsiunitxprintdecimal{#1}%
-                    \times%
-                    \LWRsiunitxprintdecimal{#2}%
-                    \times%
-                    \LWRsiunitxprintdecimal{#3}%
-                }%
+            \LWRsiunitxprintdecimal{#1}%
+            \unicode{x0B1}% \pm
+            \LWRsiunitxprintdecimal{#2}%
+            \LWRsiunitxdistribunit%
         }%
 }}
 %    \end{macrocode}
@@ -79991,7 +81290,8 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
                 {-}%
                 {\LWRsiunitxprintdecimal{#1}\times}%
         }%
-    10^{\LWRsiunitxprintdecimal{#2}}
+    10^{\LWRsiunitxprintdecimal{#2}}%
+    \LWRsiunitxdistribunit%
 }}
 %    \end{macrocode}
 %
@@ -80000,7 +81300,7 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 %    \begin{macrocode}
 \CustomizeMathJax{\def\LWRsiunitxnumD#1D#2D#3\LWRsiunitxEND{%
     \ifblank{#2}%
-        {\LWRsiunitxnumx#1xxxxx\LWRsiunitxEND}%
+        {\LWRsiunitxnumpm#1+-+-\LWRsiunitxEND}%
         {\mathrm{\LWRsiunitxnumscientific{#1}{#2}}}%
 }}
 %    \end{macrocode}
@@ -80032,16 +81332,50 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 }}
 %    \end{macrocode}
 %
+%
+% The following splits by |x|
+% \changes{v0.904}{2022/02/28}{\pkg{siunitx}, \MathJax: Split by \texttt{x} before \texttt{e}.}
+%    \begin{macrocode}
+\CustomizeMathJax{\def\LWRsiunitxnumx#1x#2x#3x#4\LWRsiunitxEND{%
+    \ifblank{#2}%
+        {\LWRsiunitxnume#1eee\LWRsiunitxEND}%
+        {%
+            \ifblank{#3}%
+                {%
+                    \LWRsiunitxnume#1eee\LWRsiunitxEND%
+                    \times%
+                    \LWRsiunitxnume#2eee\LWRsiunitxEND%
+                }%
+                {%
+                    \LWRsiunitxnume#1eee\LWRsiunitxEND%
+                    \times%
+                    \LWRsiunitxnume#2eee\LWRsiunitxEND%
+                    \times%
+                    \LWRsiunitxnume#3eee\LWRsiunitxEND%
+                }%
+        }%
+}}
+%    \end{macrocode}
+%
+%
 % \changes{v0.903}{2021/12/10}{\pkg{siunitx}, \MathJax: Improved decimal commas.}
 %    \begin{macrocode}
-\CustomizeMathJax{\newcommand{\num}[2][]{\LWRsiunitxnume#2eee\LWRsiunitxEND}}
+\CustomizeMathJax{\newcommand{\num}[2][]{%
+    \LWRsiunitxnumx#2xxxxx\LWRsiunitxEND%
+}}
 %    \end{macrocode}
 % \end{noindmacro}
 %
 %
 % \begin{noindmacro}{\si} \oarg{options} \marg{unit}
+%
+% |~| is converted to a thin space.
+% Not able to convert period to thin space because the period might be in
+% \cs{raiseto}, for example.
 %    \begin{macrocode}
-\CustomizeMathJax{\newcommand{\si}[2][]{\mathrm{#2}}}
+\CustomizeMathJax{\newcommand{\si}[2][]{%
+    \mathrm{\gsubstitute{#2}{~}{\,}}%
+}}
 %    \end{macrocode}
 % \end{noindmacro}
 %
@@ -80051,11 +81385,15 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 % \changes{v0.895}{2021/01/14}{\pkg{siunitx}: \MathJax: \cs{SI} prefix parsing.}
 %    \begin{macrocode}
 \CustomizeMathJax{\def\LWRsiunitxSIopt#1[#2]#3{%
-    {#2}\num{#1}{#3}%
+    \def\LWRsiunitxdistribunit{\,\si{#3}}%
+    {#2}\num{#1}%
+    \def\LWRsiunitxdistribunit{}%
 }}
 
 \CustomizeMathJax{\newcommand{\LWRsiunitxSI}[2]{%
-    \num{#1}\,{#2}%
+    \def\LWRsiunitxdistribunit{\,\si{#2}}%
+    \num{#1}%
+    \def\LWRsiunitxdistribunit{}%
 }}
 %    \end{macrocode}
 %
@@ -80083,8 +81421,11 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 % \cs{numrange} should only be used in text mode.
 % If used in \MathJax\ math, an en-dash is used instead of the \optn{range-phrase}.
 % \changes{v0.89}{2020/08/02}{\pkg{siunitx}: Unicode for endash.}
+% \changes{v0.904}{2022/02/28}{\pkg{siunitx}, \MathJax: Use \optn{range-phrase}.}
 %    \begin{macrocode}
-\CustomizeMathJax{\newcommand{\numrange}[3][]{\num{#2}\,\unicode{x2013}\,\num{#3}}}
+\CustomizeMathJax{\newcommand{\numrange}[3][]{%
+    \num{#2}\ \LWRsiunitxrangephrase\ \num{#3}%
+}}
 %    \end{macrocode}
 % \end{noindmacro}
 %
@@ -80094,13 +81435,16 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 % If used in \MathJax, a simple emulation is provided.
 % \changes{v0.903}{2021/12/10}{\pkg{siunitx}: \MathJax: Improved \cs{SIlist}.}
 %    \begin{macrocode}
-\CustomizeMathJax{\newcommand{\SIlist}[3][]{\text{#2}\,#3}}
+\CustomizeMathJax{\newcommand{\SIlist}[3][]{\text{#2}\,\si{#3}}}
 %    \end{macrocode}
 % \end{noindmacro}
 %
 % \begin{noindmacro}{\SIrange} \oarg{options} \marg{value1} \marg{value2} \marg{unit}
+% \changes{v0.904}{2022/02/28}{\pkg{siunitx}, \MathJax: Use \optn{range-phrase}.}
 %    \begin{macrocode}
-\CustomizeMathJax{\newcommand{\SIrange}[4][]{\num{#2}\,#4\,\unicode{x2013}\,\num{#3}\,#4}}
+\CustomizeMathJax{\newcommand{\SIrange}[4][]{%
+    \num{#2}\,#4\ \LWRsiunitxrangephrase\ \num{#3}\,#4%
+}}
 %    \end{macrocode}
 % \end{noindmacro}
 %
@@ -80331,14 +81675,13 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 \CustomizeMathJax{\newcommand{\yobi}{\mathrm{Yi}}}
 \end{warpMathJax}
 %    \end{macrocode}
-
+%
 % \iffalse
-%</siunitx-v2>
+%</common-mathjax-siunitx>
 % \fi
 %
 %
 %
-%
 % \iffalse
 %<*skmath>
 % \fi
@@ -89412,7 +90755,27 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 
 % \codehtml
 %    \begin{macrocode}
-\LWR@ProvidesPackageDrop{wrapfig2}[2021-12-21]
+\@ifpackageloaded{color}{}{%
+   \@ifpackageloaded{xcolor}{}{\LWR@origRequirePackage{xcolor}}%
+ }
+
+\RequirePackage{float}
+
+\IfPackageLoadedWithOptionsTF{wrapfig2}{WFold}
+{}% v4.0
+{% v5+
+  \floatstyle{plain}
+  \ifcsname chapter\endcsname
+    \newfloat{text}{tbp}{lotx}[chapter]
+  \else
+    \newfloat{text}{tbp}{lotx}
+  \fi
+  \floatname{text}{Text}
+%   \let\WF@text@caption\float@caption
+}
+
+
+\LWR@ProvidesPackageDrop{wrapfig2}[2022-02-16]
 
 \LWR@origRequirePackage{lwarp-wrapfig}
 %    \end{macrocode}
@@ -89436,17 +90799,113 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
     \endLWR@BlockClassWP%
     \end{LWR@setvirtualpage}%
 }
+%    \end{macrocode}
+%
+% \changes{v0.904}{2022/02/09}{\pkg{wrapfig2}: Update to v5.0.}
+%    \begin{macrocode}
+\IfPackageLoadedWithOptionsTF{wrapfig2}{WFold}
+{% v4.0:
+    \NewDocumentEnvironment{wraptext}%
+        {O{l}    D||{0.5\columnwidth} D<>{0}   D(){figure}}%
+    {%
+        \wrapfloat{#4}[]{#1}[]{#2}%
+        \tcolorbox%
+    }
+    {%
+        \endtcolorbox%
+        \endwrapfloat%
+        \ignorespaces%
+    }
+}{}
 
-\NewDocumentEnvironment{wraptext}%
-      {O{l}    D||{0.5\columnwidth} D<>{0}   D(){figure}}%
-{%
-    \wrapfloat{#4}[]{#1}[]{#2}%
-    \tcolorbox%
-}
-{%
-    \endtcolorbox%
-    \endwrapfloat%
-    \ignorespaces%
+\IfPackageLoadedWithOptionsTF{wrapfig2}{WFfive}
+{% v5
+    \definecolor{WFbackground}{rgb}{0.95,0.95,0.95}
+    \definecolor{WFframe}{rgb}{0.1,0.1,0.1}
+    \colorlet{WFtext}{black}
+    \def\SetWFbgd#1{\colorlet{WFbackground}{#1}}
+    \def\SetWFfrm#1{\colorlet{WFframe}{#1}}
+    \def\SetWFtxt#1{\colorlet{WFtext}{#1}}
+    \def\WFsplitdimens#1,#2!{\fboxrule=#1\relax\fboxsep=#2\relax}
+
+    \NewDocumentEnvironment{wraptext}{O{0} m O{0pt} G{0.5\columnwidth}}
+    {%
+        \wrapfloat{text}[]{#2}[]{#4}%
+    }
+    {%
+        \endwrapfloat%
+        \ignorespaces%
+    }
+
+    \NewDocumentCommand\includeframedtext{O{\insertwidth} m O{1pt,1ex} o}%
+    {%
+        \WFsplitdimens #3!
+        \convertcolorspec{named}{WFtext}{HTML}\LWR@tempcolor%
+        \LWR@HTML@fcolorboxBlock%
+            [named]{WFframe}[named]{WFbackground}{#2}%
+            (%
+                color:\ \LWR@origpound\LWR@tempcolor ; %
+                border-radius:\ 1ex%
+            )%
+    }
+}{% v6+
+    \RequirePackage{xkeyval}
+
+    \definecolor{WFbackground}{rgb}{0.95,0.95,0.95}
+    \definecolor{WFframe}{rgb}{0.1,0.1,0.1}
+    \colorlet{WFtext}{black}
+    \def\SetWFbgd#1{\colorlet{WFbackground}{#1}}
+    \def\SetWFfrm#1{\colorlet{WFframe}{#1}}
+    \def\SetWFtxt#1{\colorlet{WFtext}{#1}}
+    \def\WFsplitdimens#1,#2!{\fboxrule=#1\relax\fboxsep=#2\relax}
+
+    \newlength{\LWR@wrapfigtwo@radius}
+    \setlength{\LWR@wrapfigtwo@radius}{1ex}
+
+    \DeclareOptionX<wraptext>{scalefactor}[0.8]{%
+%         \def\WFscalefactor{#1}%
+    }
+    \DeclareOptionX<wraptext>{fboxrule}[1pt]{\fboxrule=#1}
+    \DeclareOptionX<wraptext>{fboxsep}[1ex]{\fboxsep=#1}
+    \DeclareOptionX<wraptext>{framecolor}[WFframe]{\SetWFfrm{#1}}
+    \DeclareOptionX<wraptext>{backgroundcolor}[WFbackground]{\SetWFbgd{#1}}
+    \DeclareOptionX<wraptext>{textcolor}[WFtext]{\SetWFtxt{#1}}
+    \DeclareOptionX<wraptext>{fontstyle}[\normalfont]{#1}
+    \DeclareOptionX<wraptext>{radius}[\fboxsep]{%
+        \setlength{\LWR@wrapfigtwo@radius}{#1}%
+    }
+    \DeclareOptionX<wraptext>{insertionwidth}[0.5\columnwidth]{%
+%         \insertwidth=#1%
+    }
+
+    \DeclareOptionX*{\PackageWarning{wrapfig2}{`\CurrentOption' ignored}}
+
+    \ExecuteOptionsX<wraptext>{scalefactor, fboxrule, fboxsep, framecolor,
+    backgroundcolor, textcolor, fontstyle, radius, insertionwidth}
+
+    \ProcessOptionsX*
+
+    \NewDocumentEnvironment{wraptext}{O{0} m O{0pt} G{0.5\columnwidth}}
+    {%
+        \wrapfloat{text}[]{#2}[]{#4}%
+    }
+    {%
+        \endwrapfloat%
+        \ignorespaces%
+    }
+
+    \NewDocumentCommand\includeframedtext{O{\insertwidth} m O{} o}
+    {%
+        \ExecuteOptionsX<wraptext>{#3}%     executes possible key=value options
+        \convertcolorspec{named}{WFtext}{HTML}\LWR@tempcolor%
+        \LWR@HTML@fcolorboxBlock%
+            [named]{WFframe}[named]{WFbackground}%
+            {\LWR@textcurrentfont{#2}}%
+            (%
+                color:\ \LWR@origpound\LWR@tempcolor ; %
+                border-radius:\ \LWR@printlength{\LWR@wrapfigtwo@radius}%
+            )%
+    }
 }
 %    \end{macrocode}
 
@@ -89695,7 +91154,7 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
     \LWR@traceinfo{LWR@findcurrenttextcolor}%
     \protect\colorlet{LWR@current@color}{.}%
     \LWR@traceinfo{LWR@findcurrenttextcolor B}%
-    \protect\convertcolorspec{named}{LWR@current@color}{HTML}\LWR@tempcolor%
+    \protect\convertcolorspec{named}{LWR@current@color}{HTML}\LWR@tempcolor\relax%
     \LWR@traceinfo{LWR@findcurrenttextcolor: done}%
 }
 %    \end{macrocode}
@@ -89781,7 +91240,7 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 % \subsection{\HTML\ border}
 %
 % \begin{noindmacro}{\LWR@borderpadding} \marg{colorstyle} \marg{color}
-% Prints the \HTML\ attributes for a black border and padding.
+% Prints the \HTML\ attributes for a color border and padding.
 %
 % \cs{LWR@forceminwidth} must be used first in order to set the border width.
 %
@@ -89958,14 +91417,16 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
 % \label{sec:fcolorboxBlock}
 % \begin{macro}{\fcolorboxBlock}
 %	\oarg{framemodel} \marg{framecolor} \oarg{boxmodel} \marg{boxcolor} \marg{text}
+%   \parg{add'l \HTML\ style}
 %
 % Converted into a framed \HTML\ hex background color span.
 %
 % A background color of |none| creates a colored frame without a background color.
 %
 % \changes{v0.892}{2020/10/05}{\pkg{xcolor}: Fixed second optional arg.}
+% \changes{v0.904}{2022/02/09}{\pkg{xcolor}: Added optional \HTML\ style.}
 %    \begin{macrocode}
-\NewDocumentCommand{\LWR@HTML@fcolorboxBlock}{O{named} m O{#1} m +m}{%
+\NewDocumentCommand{\LWR@HTML@fcolorboxBlock}{O{named} m O{#1} m +m d()}{%
     \LWR@traceinfo{HTML fcolorboxBlock #2 #4}%
     \begingroup%
     \LWR@hook@processingtags%
@@ -89980,6 +91441,7 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
         {% no background color
             \begin{BlockClass}[%
                 \LWR@borderpadding{#1}{#2}%
+                \IfValueT{#6}{ ; #6}%
             ]{fcolorboxBlock}
             #5
             \end{BlockClass}%
@@ -89989,6 +91451,7 @@ remember to convert PDF images to SVG using 'lwarpmk pdftosvg *-fig.pdf',
             \begin{BlockClass}[%
                 background:\LWR@origpound\LWR@tempcolortwo\ ; %
                 \LWR@borderpadding{#1}{#2}%
+                \IfValueT{#6}{ ; #6}%
             ]{fcolorboxBlock}
             #5
             \end{BlockClass}%
-- 
cgit v1.2.3

