michal-h21 / make4ht

Build system for tex4ht
131 stars 15 forks source link

'mathml'-option not compatible with cases environment #135

Closed yalguzaq closed 10 months ago

yalguzaq commented 10 months ago

LaTeX

\documentclass[10pt]{article}
\usepackage{mathtools}

\begin{document}
\begin{equation*}
  \begin{dcases*}
    1 & if $a < \alpha < b$,\\
    2 & if $\alpha = b$,\\
    3 & if $b < \alpha < \infty$.
  \end{dcases*}
\end{equation*}
\end{document}

make4ht

make4ht file.tex 'mathjax'

Desired output

via make4ht file.tex 'mathjax' image

Erroneous output

Elements like \alpha get messed up. image

michal-h21 commented 10 months ago

Try this configuration file:

\Preamble{xhtml}
\catcode`\:=11
\Configure{dcases*}
   {\HCode{<\a:mathml mtable\Hnewline \mml:class="dcases-star">}}
   {\HCode{</\a:mathml mtable>}}
   {\HCode{<\a:mathml mtr>}}    {\HCode{</\a:mathml mtr>}}
   {\HCode{\Hnewline<\a:mathml mtd columnalign="left">}%
    \ifnum\HCol=2
       \PauseMathClass
       \HCode{<\a:mathml mtext>}%
       \Configure{$}{\EndPauseMathClass\HCode{</\a:mathml mtext>}}{\PauseMathClass\HCode{<\a:mathml mtext>}}{}
       \Configure{()}{\HCode{</\a:mathml mtext>}\EndPauseMathClass}{\PauseMathClass\HCode{<\a:mathml mtext>}}{}
    \fi
   }
   {\ifnum\HCol=2
       \EndPauseMathClass
       \HCode{</\a:mathml mtext>}%
    \fi
    \HCode{</\a:mathml mtd>}}
\catcode`\:=12
\begin{document}
\EndPreamble

It leads to a wrong spacing, so you will also need this build file to add explicit spaces around inline math:

local domfilter = require "make4ht-domfilter"

local function get_third_parent(el)
  local first = el:get_parent()
  if not first then return nil end
  local second = first:get_parent()
  if not second then return nil end
  return second:get_parent()
end

local function add_space(el, pos)
  local parent = el:get_parent()
  local space = parent:create_element("mspace")
  space:set_attribute("width", "0.3em")
  parent:add_child_node(space, pos)
end

local process = domfilter {
  function(dom)
    dom:traverse_elements(function(el)
      -- we need to fix spacing in dcases* environments
      -- when you use something like:
      -- \begin{dcases*}
      -- 1 & if $a=b$ then
      -- \end{dcases*}
      -- the spaces around $a=b$ will be missing
      -- we detect if the <mtext> elements contains spaces that are collapsed by the browser, and add explicit <mspace>
      -- elements when necessary
      if el:get_element_name() == "mtext" then
        local parent = get_third_parent(el)
        if parent and parent:get_element_name() == "mtable" and parent:get_attribute("class") == "dcases-star" then
          local text = el:get_text()
          local pos = el:find_element_pos()
          if pos == 1 and text:match("%s$") then 
            add_space(el, 2)
          elseif text:match("^%s") and not el._used then
            add_space(el, pos)
            -- this is necessary to avoid infinite loop, we mark this element as processed
            el._used = true
          end
        end
      end
    end)
    return dom
  end
}

Make:match("html$", process)
yalguzaq commented 10 months ago

Thanks a lot! Will this be included in the next update?

michal-h21 commented 10 months ago

Yes, but it will also need make4ht update, which usually takes longer.