Math in lwarp (via controlled expansion?)

Here is the issue I am thinking about, and some possible approaches. When writing a latex/html document using lwarp, the math code is left embedded directly into the resulting HTML file and left up to mathjax to interpret.

If there are non-standard macros in there, they will not be expanded by latex, and mathjax will not know what to do with them -- (1) below. The standard approach is to just give mathjax the macro definitions (\CustomizeMathJax below). Mathjax has macros for this purpose and I don't disagree.

However, sometimes a macro is more complex than this; for instance, in a recent application I needed a macro which added an argument to a fixed offset. This was simple in tex; in mathjax I needed to reimplement the macro in JS (and now I will need to reimplement it when I switch the MathJax 3.)

This feels like a perfect place for some kind of controlled expansion. For instance, consider the example below.

\documentclass{article}

\usepackage[mathjax]{lwarp}

\newcommand\xyz{x}
\newcommand\bfxyz{\mathbf{x}}

% Standard' solution:
%\CustomizeMathJax{\newcommand\xyz{x}}
%\CustomizeMathJax{\newcommand\bfxyz{\mathbf{x}}}

\begin{document}

$(1) \quad a + b = \xyz,\bfxyz .$

\edef\mymath{%
\noexpand$(2) \noexpand\quad a + b = \xyz. \noexpand$
}
\mymath

\edef\mymath{%
\noexpand$(3) \noexpand\quad a + b = \expandonce\bfxyz. \noexpand$
}
\mymath

\end{document}


Using edefs and expanding only certain macros, I can get tex to do the expansion and not have to worry about what mathjax sees.

However, this is obviously not really a solution: I had to add \noexpand in front of a lot things related to math mode. I also had to be pretty careful about how many times things were expanded, either adding \expandonce as in (3) or rewriting the macro definition as \newcommand\bfxyz{\noexpand\mathbf{x}}, say.

It feels like what I really want to do is to expand only the macros in some list (e.g., \xyz,\bfxyz), and do that until nothing in the list remains. But maybe there is another approach that I don't know about -- possibly something using \protected@edef?

So, is there a better solution to this problem?

I think \protected@edef does what you need here:

\documentclass{article}

\usepackage[mathjax]{lwarp}

\newcommand\xyz{x}
\newcommand\bfxyz{\mathbf{x}}

% Standard' solution:
%\CustomizeMathJax{\newcommand\xyz{x}}
%\CustomizeMathJax{\newcommand\bfxyz{\mathbf{x}}}
\makeatletter
\begin{document}

$(1) \quad a + b = \xyz,\bfxyz .$

\protected@edef\mymath{%
$(2) \quad a + b = \xyz.$
}
\show\mymath
\mymath

\protected@edef\mymath{%
$(3) \quad a + b = \bfxyz.$
}
\show\mymath
\mymath

\end{document}


Produces this log

> \mymath=macro:
->\protect $(2) \hskip 1em\relax a + b = x.\protect$ .
l.19 \show\mymath

?
> \mymath=macro:
->\protect $(3) \hskip 1em\relax a + b = \protect \mathbf {x}. \protect$ .
l.25 \show\mymath


If there are any standard commands that do expand in the protected@edef you could redeclare then as robust using \MakeRobust\zzz so thre expansion is stopped.

For examle I assumed above it is OK for \quad to expand but if you want to hold it as \quad add

\MakeRobust\quad


to the preamble then the log shows

> \mymath=macro:
->\protect $(2) \protect \quad a + b = x.\protect$ .
l.21 \show\mymath

?
> \mymath=macro:
->\protect $(3) \protect \quad a + b = \protect \mathbf {x}. \protect$ .
l.27 \show\mymath

• I think you're right. Actually, your version does not compile under lwarp, but replacing $...$ with $... \noexpand$ does work. (For some reason, \] is undefined when lwarp does the html run.) Do you think that this approach is robust, in the sense that there aren't many/any fragile commands that would wreak havoc if this was applied generally? This is the purpose of the fragile/robust distinction, right? – Alex Watson Oct 2 '19 at 13:01
• @AlexWatson there are not that many fragile commands (and the next version of latex that you can already test as pdflatex-dev in texlive at least) will have far fewer fragile commands. In any case any command that dies in protected@edef will definitely die in \edef so it is certainly a step in the right direction compared to the version in the question... you might want to take up the \[ behaviour with the lwarp maintainer, it ought not to break, I think. – David Carlisle Oct 2 '19 at 13:06
• Thank you. I do think this is a good working solution, and I'll write to the maintainer (if he isn't watching the tag.) – Alex Watson Oct 2 '19 at 13:17