4

I now use the breqn package in LuaTeX mode only. Not in TeX4ht mode since it does not work there and is not needed. So I load breqn only when not in TeX4ht mode and use \ifdefined\HCode to make sure it is used only when compiling to PDF and not HTML.

I found some issue where TeX4ht still sees {dmath*} and dgroup which are commands from breqn, even though I made sure by using \ifdefined\HCode these only can be seen when compiling to PDF.

Compiling to PDF doesn't show any error at all. But compiling to HTML gives an error.

Here is an MWE:

\documentclass[12pt]{book}
\usepackage{amsmath}
\ifdefined\HCode %only load breaqn when not in TeX4ht mode
\else
\usepackage{breqn}
\fi

\begin{document}
\ifdefined\HCode
\begin{align*}
\else
\begin{dgroup*}
\fi

\ifdefined\HCode
   A &= B
\else
\begin{dmath*}
   A = B
\end{dmath*}     %error is around here
\fi

\ifdefined\HCode
\end{align*}
\else
\end{dgroup*}
\fi
\end{document}

Compiling using lualatex foo2.tex doesn't give any error and correct output.

But

make4ht -ulm default -a debug foo2.tex "mathjax,htm"

gives

(/usr/local/texlive/2021/texmf-dist/tex/generic/tex4ht/html5.4ht)) (./foo2.aux)
(/usr/local/texlive/2021/texmf-dist/tex/latex/base/ts1cmr.fd)

! LaTeX Error: Environment dgroup* undefined.

See the LaTeX manual or LaTeX Companion for explanation.
Type  H <return>  for immediate help.
 ...

l.31 \end{dmath*}

I had to do it this way. It is a long story, but my question is: Why does the above work correctly with LuaTeX, but not with TeX4ht? Am I doing something wrong? If yes, then how come LuaTeX is happy with it, but not TeX4ht? Is there a way to make tex4ht compile the above?

I am using TeX Live (TL) 2021, and it was updated about two weeks ago. On Linux.

Update oct 25, 2021

I found an issue with proposed solution. It does not work with multiple dmath* inside dgroup*. It only works with one dmath* inside dgroup*. But if I have one dmath*, I really do not need dgroup*.

Since hard to show all this in a comment to the answer, I show it here.

Here is MWE

\documentclass[12pt]{book}    
\usepackage{amsmath} 
\usepackage{breqn}
\begin{document}    

\begin{dgroup*}
\begin{dmath*}
   A = B
\end{dmath*}      
\begin{dmath*}
   C = D
\end{dmath*}    
\end{dgroup*}
\end{document}

Using same .cfg file shown in the answer, and compiled using

make4ht -ulm default -a debug -c ./new.cfg test_breqn.tex "mathjax,htm"

gives this HTML

enter image description here

The second dmath* needs to be on new line. The HTML is

<!DOCTYPE html> 
<html lang='en-US' xml:lang='en-US'> 
<head> <title></title> 
<meta charset='utf-8' /> 
<meta content='TeX4ht (https://tug.org/tex4ht/)' name='generator' /> 
<meta content='width=device-width,initial-scale=1' name='viewport' /> 
<link href='test_breqn.css' rel='stylesheet' type='text/css' /> 
<meta content='test_breqn.tex' name='src' /> 
<script>window.MathJax = { tex: { tags: "ams", environments: { "dgroup*": ["", ""], "dmath*": ["", ""], }  } }</script> 
 <script async='async' id='MathJax-script' src='https://cdn.jsdelivr.net/npm/mathjax@3/es5/tex-chtml-full.js' type='text/javascript'></script>  
</head><body>
<!-- l. 13 --><p class='noindent'>\begin {dgroup*} \begin {dmath*} A = B \end {dmath*} \begin {dmath*} C = D \end {dmath*} \end {dgroup*}
</p>   
 
</body> 
</html>

This is the PDF version:

enter image description here

I hope there is a way around this.

1
  • \ifdefined\HCode \begin{align*} \else \begin{dgroup*} \fi can't really work, you need the condition around the entire environment Oct 24 at 22:01
8

Edit:

You can also use make4ht filters to edit the math content in the HTML file to get something that MathJax supports. For example, the following build file converts dgroup* environment to align*, and it also changes the math content to suitable form:

local filter = require "make4ht-filter"

local function process_options(options)
  -- convert [number={foo}] to \tag{foo}
  local number = options:match("number%s*=%s*{?(%w+)")
  if number then
    return "\\tag{" .. number .. "}"
  end
  return ""
end


local function escape_equal(str)
  -- there can be multiple equal characters in the string. we should put the & character
  -- just before the one which is not inside any group
  -- escape nested equal signs
  str = str:gsub("({[^{^}]+)=([^{^}]+})", "%1:EQUAL:%2")
  -- replace remaining =
  str = str:gsub("=", "&=")
  -- return escaped =
  str = str:gsub(":EQUAL:", "=")
  return str
end

local function make_align(dgroup)
  -- change breqn environment contents to align*
  -- change = to &=
  local dgroup = escape_equal(dgroup)
  -- return the fixed text in align* environment
  return "\\begin{align*}" ..  dgroup .. "\\end{align*}"
end

local function process_dgroup(s, env_name)
  return s:gsub("\\begin%s*{" .. env_name .. "}(.-)\\end%s*{" .. env_name .. "}",
  function(dgroup)
    -- remove environemnts
    -- change dmath[...,number={label}] to \tag{label}
    dgroup = dgroup:gsub("\\begin%s*{dmath}%s*(%b[])", process_options)
    -- remove all other environemnts
    dgroup = dgroup:gsub("\\begin%s*{.-}","")
    dgroup = dgroup:gsub("\\end%s*{.-}", "\\\\")
    return make_align(dgroup)
  end)
end

-- process remaining dmath environments
local function process_dmath(s, env_name)
  return s:gsub("\\begin%s*{" .. env_name .. "}(.-)\\end%s*{" .. env_name .. "}",
  function(dmath)
    -- options can be still here
    local dmath = dmath:gsub("^%s*(%b[])", process_options)
    return make_align(dmath)
  end)
end

local process = filter {
  -- find all dgroup* environments and convert them to align*
  function(s)
    local s = process_dgroup(s,"dgroup%*")
    s = process_dgroup(s, "dgroup")
    -- process remaining dmath environments in the document
    s = process_dmath(s, "dmath%*")
    s = process_dmath(s, "dmath")
    return s
  end
}


-- install filter to match HTML files
Make:match("html?$", process)

It produces a following HTML code:

<p class='noindent'>test 1, OK
</p><!-- l. 15 --><p class='indent'>   \begin{align*}  A &amp;= B \\  C &amp;= D \\ \end{align*}
</p><!-- l. 17 --><p class='indent'>   test 2 FAIL
</p><!-- l. 26 --><p class='indent'>   \begin{align*}  A &amp;= B \\ \tag{1} C &amp;= D \\ \end{align*}
</p><!-- l. 29 --><p class='indent'>   test 3 OK
</p><!-- l. 33 --><p class='indent'>   \begin{align*} A &amp;= B \end{align*}
</p><!-- l. 35 --><p class='indent'>   test 4 FAIL
</p><!-- l. 39 --><p class='indent'>   \begin{align*}\tag{1} A &amp;= B \end{align*}
</p><!-- l. 41 --><p class='indent'>   test 5 OK
</p><!-- l. 45 --><p class='indent'>   \begin{align*} A &amp;= B \end{align*}
</p>

Which is displayed by MathJax like this:

enter image description here

Original answer:

Alternatively, you can add support for your math environments to MathJax, using this config file:

\Preamble{xhtml} 
\Configure{MathJaxConfig}{{ 
    tex: { 
      tags: "ams", 
      \detokenize{% 
      environments: {
        "dgroup*": ["", ""],
        "dmath*": ["", ""],
      } 
  } 
} 
}} 
\VerbMath{dgroup*}
\begin{document} 
\EndPreamble

The \VerbMath{dgroup*} command ensures that TeX4ht passes the whole content of the dgroup* environment to the HTML file. You then need to configure MathJax to support both dgroup* and dmath* environments. This is thanks to:

  environments: {
    "dgroup*": ["", ""],
    "dmath*": ["", ""],
  } 

I've found that you don't need to provide any other code, MathJax just switches to the display math mode and prints the content.

Your TeX file can be then simplified:

\documentclass[12pt]{book}    
\usepackage{amsmath} 
\usepackage{breqn}

\begin{document}    
\begin{dgroup*}
\begin{dmath*}
   A = B
\end{dmath*}     %error is around here           
\end{dgroup*}
\end{document}

And this is the result:

enter image description here

7
  • 1
    @Nasser should give you the tick:-) Oct 25 at 10:06
  • Thanks! This is much easier so I do not have to duplicate code. I will test it more on my main file.
    – Nasser
    Oct 25 at 11:43
  • @Nasser yes, it is easier. you should try to avoid the \ifdefined\HCode in your documents, try to add support for unsupported commands instead :)
    – michal.h21
    Oct 25 at 12:06
  • hi Michal. I found a problem. Please see updated answer. I hope there is a magic code you have that can fix this, otherwise, it will not really work. I still need to test dmath and dgroup with [number=label] which give labels to equations in breqn. But one thing at a time :)
    – Nasser
    Oct 25 at 13:05
  • 1
    @Nasser you can post-process the HTML file using make4ht filters and fix some things here. I've updated my answer to show this.
    – michal.h21
    Oct 25 at 20:35
5

If \Hcode is defined then \begin{align*} will be executed and as a first action this will grab all the code up to \end{align*}. This body is executed multiple times, once with a measuring pass and then a main typesetting pass. The body collected will be

\else
\begin{dgroup*}
\fi

\ifdefined\HCode
   A &= B
\else
\begin{dmath*}
   A = B
\end{dmath*}     %error is around here           
\fi

\ifdefined\HCode

and the if conditionals will be unmatched. You need the conditional to be around the entire environment.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.