make4ht 和 mathml 中的 mhchem 和分数问题

make4ht 和 mathml 中的 mhchem 和分数问题

我正在编写一篇化学含量较高的文本,我注意到 Overleaf 上的 mhchem 在使用 make4ht 编译时不会创建上标和下标。下载最新版本后,重新支持 make4ht,除了使用分数线时,编译效果非常好。

这是我的 MWE:

\documentclass{book} 
\usepackage[english]{babel}
\usepackage{amsmath}
\usepackage{wasysym}
\usepackage[version=4]{mhchem}

\begin{document}

Text with formula \ce{CuCl2} and \ce{Cu^{2+}}.

\begin{equation}
\frac{\ce{mass CuCl2}}{1}\times\frac{\ce{1 mol CuCl2}}{\ce{MM of CuCl2}}= \mathord{?}\mathord{?}~\ce{ mol CuCl2}
\end{equation}

Text before a reaction.

\begin{equation}
\ce{Al^0 (s) -> Al^3+ (aq) + 3e-}\\
\ce{Cu^2+ (aq) + 2e- -> Cu^0 (s)}
\end{equation}


\end{document}

我使用以下命令进行编译:

make4ht -f html5 -e mybuild.mk4 -um draft -c mwe.cfg main "early^,early_"

使用此 mwe.cfg 文件:

\Preamble{xhtml,mathml}

\Configure{@HEAD}{\HCode{%
     <script type="text/x-mathjax-config">
       MathJax.Hub.Config({
         extensions: ["tex2jax.js"],
         jax: ["input/TeX", "output/HTML-CSS"],
         tex2jax: {
           \unexpanded{inlineMath: [ ['$','$'], ["\\(","\\)"] ],}
           \unexpanded{displayMath: [ ['$$','$$'], ["\\[","\\]"] ],}
           processEscapes: true
         },
         "HTML-CSS": { availableFonts: ["TeX"] }
       });
     </script>
  }}

\Configure{@HEAD}{\HCode{<script type="text/javascript"\Hnewline
src="http://cdn.mathjax.org/mathjax/latest/MathJax.js?config=TeX-AMS-MML_HTMLorMML"\Hnewline
></script>\Hnewline}}

\Css{.MathJax_MathML {text-indent: 0;}}

\begin{document}
\EndPreamble

PDF 渲染得很好,但第一个等式以内嵌方式渲染,没有分数。

答案1

问题是 Mhchem 目前不支持 MathML,因此您得到的结果是错误的渲染。我会尝试修复它,但在修复之前,您可以尝试以下配置文件。它使用 TeX4ht 中的内置 MathJax 支持,并将命令配置\ce为保留在生成的 HTML 中,因此它也可以由 MathJax 渲染:

\Preamble{xhtml,mathjax}
\def\ce#1{\texttt{\detokenize{\(\ce{#1}\)}}}
\begin{document}
\EndPreamble

结果如下:

在此处输入图片描述

mhchem.4ht另外,这里有一个具有基本 MathML 支持的版本:

%% mhchem.4ht
%% 2021-12-31
%% Copyright 2015-2021 Martin Hensel
%
%% This file is part of the mhchem bundle for LaTeX
%
% This work may be distributed and/or modified under the
% conditions of the LaTeX Project Public License version 1.3c
% which is included as lppl-1-3c.txt.
%
% This work has the LPPL maintenance status "maintained".
% The Current Maintainer of this work is Martin Hensel.
%
% ( In order to fight spam, the maintainer's contact      )
% ( information is "encrypted" with ROT13.                )
% ( If you do not know ROT13 yet and have no tool for     )
% ( decryption, simply do an Internet search for "ROT13". )
%
% ,---[ ROT 13 ]---
% | Gur Pheerag Znvagnvare bs guvf jbex vf Znegva Urafry
% |   jub pna or pbagnpgrq ivn
% |     [email protected]
% |   be ivn znvy
% |     Znegva Urafry
% |     Cbfgfge. 20
% |     09232 Unegznaafqbes
% |     Treznal
% `----------
%
% This work consists of all files listed in manifest.txt.
%
%
\ExplSyntaxOn

\Css
  { 
    .mhchem ~ .mhchem-cf { white-space: nowrap; }
    .mhchem ~ .mhchem-isotope { font-size: 0.65em; line-height: 1; display: inline-block; vertical-align: sub; text-align: right; }
    .mhchem ~ .mhchem-supsub  { font-size: 0.65em; line-height: 1; display: inline-block; vertical-align: sub; }
    .mhchem ~ .mhchem-sup     { font-size: 0.65em; line-height: 1; display: inline-block; vertical-align: 68\%; }
    .mhchem ~ .mhchem-sub     { font-size: 0.65em; line-height: 1; display: inline-block; vertical-align: sub; }
    .mhchem ~ .mhchem-rlap { display: inline-block; width: 0; }
    .mhchem ~ .mhchem-bond-half-top    { vertical-align: 60\%; }
    .mhchem ~ .mhchem-bond-half-middle { vertical-align: 35\%; }
    .mhchem ~ .mhchem-bond-top         { vertical-align: 20\%; }
    .mhchem ~ .mhchem-bond-bottom      { vertical-align: -20\%; }
    .mhchem ~ .mhchem-arrow { display: inline-flex; flex-direction: column; vertical-align: middle; }
    .mhchem ~ .mhchem-arrow > span { line-height: 80\%; text-align: center; }
    .mhchem ~ .mhchem-arrow > .mhchem-above { min-height: 1em; font-size: 60\%; }
    .mhchem ~ .mhchem-arrow > .mhchem-below { min-height: 1em; font-size: 60\%; }
    .mhchem ~ .mhchem-arrow > span.mhchem-arrow-normal { line-height: 40\%; }
    .mhchem ~ .mhchem-arrow > span.mhchem-arrow-larger { line-height: 25\%; font-size: 150\%; }
    .mhchem ~ .mhchem-arrow > span.mhchem-arrow-complement { line-height: 25\%; }
  }

% basic mhchem containers
\NewConfigure{mhchemce}{2}
\NewConfigure{mhchemcf}{2}

\pend:def\__mhchem_output_begin_ce:{\a:mhchemce}
\append:def\__mhchem_output_end_ce:{\b:mhchemce}
\pend:def\__mhchem_output_begin_cf:{\a:mhchemcf}
\append:def\__mhchem_output_end_cf:{\b:mhchemcf}

\Configure{mhchemcf}{\HCode{<span~class="mhchem">}}{\HCode{</span>}}
\Configure{mhchemce}{\HCode{<span~class="mhchem">}}{\HCode{</span>}}


% alternative version of coreFivd

\NewConfigure{mhchemisotope}{3}
\Configure{mhchemisotope}{\HCode{<span~class="mhchem-isotope">}}{\HCode{<br~/>&\#xfeff;}}{\HCode{</span>}}

\NewConfigure{mhchemsub}{2}
\Configure{mhchemsub}{\HCode { <sub~class="mhchem-sub"> }}{\HCode { </sub> } }

\NewConfigure{mhchemsup}{2}
\Configure{mhchemsup}{\HCode { <sup~class="mhchem-sup"> }}{\HCode { </sup> } }

\cs_set_protected:Npn \__mhchem_output_coreFivefourht:nnnnnnn #1#2#3#4#5#6#7
  {
    \bool_if:nT
      { \tl_if_empty_p:n {#7}  &&  ! \tl_if_empty_p:n {#5} }
      { \bool_set_true:N \l__mhchem_option_superscriptsStacked_bool }
      
    \tl_if_empty:nF {#1#2} 
      {
        \a:mhchemisotope
        \__mhchem_output_withFont:n { #1 } 
        \b:mhchemisotope
        \__mhchem_output_withFont:n { #2 }
        \c:mhchemisotope
      }
    \__mhchem_output_withFont:n { #3 } 
    \bool_if:NTF \l__mhchem_option_superscriptsStacked_bool
      {
        \tl_if_empty:nTF {#4#5#7} 
          {
            \tl_if_empty:nF {#6}
              {
                \a:mhchemsub
                \__mhchem_output_withFont:n { #6 }
                \b:mhchemsub
              }
          }
          {
            \tl_if_empty:nTF {#6}
              {
                \a:mhchemsup
                \__mhchem_output_withFont:n { #4#5#7 }
                \b:mhchemsup
              }
              { 
                \HCode { <span~class="mhchem-supsub"> }
                \__mhchem_output_withFont:n { #4#5#7 }
                \HCode { <br~/>&\#xfeff; }
                \__mhchem_output_withFont:n { #6 }
                \HCode { </span> } 
             }
          }
      }
      {
        \tl_if_empty:nF {#4}
          {
            \a:mhchemsup
            \__mhchem_output_withFont:n { #4 }
            \b:mhchemsup
          }
        \tl_if_empty:nF {#6}
          { 
            \a:mhchemsub
            \__mhchem_output_withFont:n { #6 }
            \b:mhchemsub
          }
        \tl_if_empty:nF {#5#7} 
          { 
            \a:mhchemsup
            \__mhchem_output_withFont:n { #5#7 }
            \b:mhchemsup
          }
      }
  }

% replace original coreFive with our alternative version. it will work in picture math
\HLet\__mhchem_output_coreFive:nnnnnnn\__mhchem_output_coreFivefourht:nnnnnnn

\cs_set_protected:Npn \__mhchem_output_withFont:n #1  %. output #1 as math or text
  {
    \bool_if:NTF \l__mhchem_output_isMathMode_bool
      { \mathrm {#1} }
      { \text {#1} }
  }

\NewConfigure{mhchemoperator}{2}
\Configure{mhchemoperator}{\HCode { <span~class="mhchem-operator"> ~ }}{\HCode { ~ </span> }}

% ideally, these should be redefined using \HLet, to support picture math
\cs_set_protected:Npn \__mhchem_output_skipAfterAmount: { \HCode { ~ } }  % space for copy & paste
\cs_set_protected:Npn \__mhchem_output_skipBeforeStateOfAggregation: {}
\cs_set_protected:Npn \__mhchem_output_minus: { \HCode { &minus; } }
\cs_set_protected:Npn \__mhchem_output_operatorPlus:
  { \a:mhchemoperator + \b:mhchemoperator  }
\cs_set_protected:Npn \__mhchem_output_operatorMinus:
  { \a:mhchemoperator\HCode {&minus;} \b:mhchemoperator }
\cs_set_protected:Npn \__mhchem_output_operatorEquals:
  { \a:mhchemoperator =  \b:mhchemoperator }
\cs_set_protected:Npn \__mhchem_output_operatorPlusMinus:
  {\a:mhchemoperator \HCode {&plusmn; } \b:mhchemoperator }
\cs_set_protected:Npn \__mhchem_output_electronDot: { \HCode { &bull; } }
\cs_set_protected:Npn \__mhchem_output_additionCompound: { \HCode { &middot; } }
\cs_set_protected:Npn \__mhchem_output_excited: { \HCode { &\#x2731; } }
\cs_set_protected:Npn \__mhchem_output_commaDecimal: { , }
\cs_set_protected:Npn \__mhchem_output_commaEnumeration: { , \HCode { &thinsp; } }
\cs_set_protected:Npn \__mhchem_output_commaEnumerationSmall: { , \HCode { &thinsp; } }
  
\cs_set_protected:Npn \__mhchem_output_bond_single: { \HCode { &minus; } }
\cs_set_protected:Npn \__mhchem_output_bond_double: { \HCode { &equals; } }
\cs_set_protected:Npn \__mhchem_output_bond_triple: { \HCode { &equiv; } }
% todo: add MathML support for these
\cs_set_protected:Npn \__mhchem_output_bond_half:  % todo: improve
  { \HCode { <span~class="mhchem-bond-half-middle">&\#xfe4d;</span> } }
\cs_set_protected:Npn \__mhchem_output_bond_oneAndHalf:  % todo: improve 
  { \HCode { <span~class="mhchem-rlap">&minus;</span><span~class="mhchem-bond-half-top">&\#xfe4d;</span> } }
\cs_set_protected:Npn \__mhchem_output_bond_twoAndHalf:  % todo: improve
  { \HCode { <span~class="mhchem-rlap">=</span><span~class="mhchem-bond-half-top">&\#xfe4d;</span> } }
\cs_set_protected:Npn \__mhchem_output_bond_twoAndHalff:  % todo: improve
  { \HCode { <span~class="mhchem-rlap~mhchem-bond-top">&minus;</span><span~class="mhchem-rlap~mhchem-bond-bottom">&minus;</span><span~class="mhchem-bond-half-middle">&\#xfe4d;</span> } }
\cs_set_protected:Npn \__mhchem_output_bond_dotdotdot: { \HCode { &middot;&middot;&middot; } }
\cs_set_protected:Npn \__mhchem_output_bond_dotdotdotdot: { \HCode { &middot;&middot;&middot;&middot; } }
\cs_set_protected:Npn \__mhchem_output_bond_rightArrow: { \HCode { &\#xffeb; } }
\cs_set_protected:Npn \__mhchem_output_bond_leftArrow: { \HCode { &\#xffe9; } }

\NewConfigure{mhchemarrow}{2}
\NewConfigure{mhchemarrowabove}{2}

\NewConfigure{mhchemarrowyields}{1}
\NewConfigure{mhchemarrowyieldsLeft}{1}
\NewConfigure{mhchemarrowyieldsLeftRight}{1}
\NewConfigure{mhchemarrowmesomerism}{1}
\NewConfigure{mhchemarrowequilibrium}{1}
\NewConfigure{mhchemarrowequilibriumRight}{1}
\NewConfigure{mhchemarrowequilibriumLeft}{1}

\Configure{mhchemarrow}{\HCode {<span~class="mhchem-arrow">}}{\HCode{</span>}}
\Configure{mhchemarrowabove}{\HCode { <span~class="mhchem-above">}}{\HCode{</span>}}
\Configure{mhchemarrowyields}{ \HCode { <span~class="mhchem-arrow-normal">&\#x27F6;</span> } }
\Configure{mhchemarrowyieldsLeft}{ \HCode { <span~class="mhchem-arrow-normal">&\#x2190;</span> } }
\Configure{mhchemarrowyieldsLeftRight}{ \HCode { <span~class="mhchem-arrow-normal">&\#x21c4;</span> } }  % todo: improve
\Configure{mhchemarrowmesomerism}{ \HCode { <span~class="mhchem-arrow-normal">&\#x2194;</span> } }  % todo: improve
\Configure{mhchemarrowequilibrium}{ \HCode { <span~class="mhchem-arrow-normal">&\#x21cc;</span> } }  % todo: improve
\Configure{mhchemarrowequilibriumRight}{ \HCode { <span~class="mhchem-arrow-larger">&\#x21c0;</span><span~class="mhchem-arrow-complement">&\#x21bd;</span> } }  % todo: improve
\Configure{mhchemarrowequilibriumLeft}{ \HCode { <span~class="mhchem-arrow-complement">&\#x21c0;</span><span~class="mhchem-arrow-larger">&\#x21bd;</span> } }  % todo: improve



\cs_set_protected:Npn \__mhchem_arrow_deployfourht:nnnnn #1#2#3#4#5
  {
    \a:mhchemarrow
    \tl_if_empty:nF {#3#5}
      {
        \a:mhchemarrowabove
        \str_case:nnF {#2}
          {
            {   } { \ce { #3 } }
            { M } { \ensuremath { #3 } }
            { T } { \text { #3 } }
            { C } { \ce { #3 } }
          }
          { \msg_error:nnn { mhchem } { unexpected-arrow-type } {#2} }
          \b:mhchemarrowabove
      }
    \str_case:nnF {#1}
      {
        { yields } {\a:mhchemarrowyields }
        { yieldsLeft } {\a:mhchemarrowyieldsLeft }
        { yieldsLeftRight } {\a:mhchemarrowyieldsLeftRight }  % todo: improve
        { esomerism } {\a:mhchemarrowesomerism }  % todo: improve
        { equilibrium } {\a:mhchemarrowequilibrium }  % todo: improve
        { equilibriumRight } {\a:mhchemarrowequilibriumRight }  % todo: improve
        { equilibriumLeft } {\a:mhchemarrowequilibriumLeft }  % todo: improve
      }
      { \msg_error:nnn { mhchem } { unexpected-arrow-type } {#1} }
    \tl_if_empty:nF {#3#5}
      {
        \a:mhchemarrowabove
        \str_case:nnF {#2}
          {
            {   } { \ce { #5 } }
            { M } { \ensuremath { #5 } }
            { T } { \text { #5 } }
            { C } { \ce { #5 } }
          }
          { \msg_error:nnn { mhchem } { unexpected-arrow-type } {#2} }
        \b:mhchemarrowabove
      }
    \b:mhchemarrow
  }

\HLet\__mhchem_arrow_deploy:nnnnn\__mhchem_arrow_deployfourht:nnnnn
  
\ExplSyntaxOff

% Additional configurations for MathML

% print mathml command or html, depending on if we are inside mathml or not
\newcommand\:mhmathmlorhtml[2]{\ifmathml\a:mathml #1\else #2\fi}
\newcommand\:mhonlyinmathml[1]{\ifmathml #1\fi}
\:CheckOption{mathml}
\if:Option

\Configure{mhchemcf}{\HCode{<\:mhmathmlorhtml{mrow}{span}\space class="mhchem-cf">}}{\HCode{</\:mhmathmlorhtml{mrow}{span}>}}
\Configure{mhchemce}{\HCode{<\:mhmathmlorhtml{mrow}{span}\space class="mhchem-ce">}}{\HCode{</\:mhmathmlorhtml{mrow}{span}>}}

\Configure{mhchemsub}{%
  \:mhmathmlorhtml{%
  \Send{BACK}%
  {<\a:mathml msub><\a:mathml mrow\Hnewline>}%
  \Tg</\a:mathml mrow>\Tg<\a:mathml mrow\Hnewline>\trap:base%
  }{%
  \HCode{<sub>}}%
}{\:mhmathmlorhtml{\Tg</\a:mathml mrow>\TG</\a:mathml msub\Hnewline>}{\HCode{</sub>}}}
\Configure{mhchemsup}{%
  \:mhmathmlorhtml{
  \Send{BACK}
  {<\a:mathml msup><\a:mathml mrow\Hnewline>}%
  \Tg</\a:mathml mrow>\Tg<\a:mathml mrow\Hnewline>\trap:base
  }{%
  \HCode{<sup>}}%
}{\:mhmathmlorhtml{\Tg</\a:mathml mrow>\TG</\a:mathml msup\Hnewline>}{\HCode{</sup>}}}

\Configure{mhchemoperator}{\HCode{<\:mhmathmlorhtml{mo}{span} class="mhchem-operator">}\PauseMathClass}{\EndPauseMathClass\HCode {</\:mhmathmlorhtml{mo}{span}>}}

\Configure{mhchemarrow}{\HCode {<\:mhmathmlorhtml{mrow}{span} class="mhchem-arrow">\:mhonlyinmathml{<mo>}}}{\HCode{\:mhonlyinmathml{</mo>}</\:mhmathmlorhtml{mrow}{span}>}}
\Configure{mhchemarrowabove}{\HCode { <\:mhmathmlorhtml{mrow}{span} class="mhchem-above">\:mhonlyinmathml{<mo>}}}{\HCode{\:mhonlyinmathml{</mo>}</\:mhmathmlorhtml{mrow}{span}>}}
\Configure{mhchemarrowyields}{ \HCode { <\:mhmathmlorhtml{mrow}{span} class="mhchem-arrow-normal">\:mhonlyinmathml{<mo>}&\#x2192;\:mhonlyinmathml{</mo>}</\:mhmathmlorhtml{mrow}{span}> } }
\Configure{mhchemarrowyieldsLeft}{ \HCode { <\:mhmathmlorhtml{mrow}{span} class="mhchem-arrow-normal">\:mhonlyinmathml{<mo>}&\#x2190;\:mhonlyinmathml{</mo>}</\:mhmathmlorhtml{mrow}{span}> } }
\Configure{mhchemarrowyieldsLeftRight}{ \HCode { <\:mhmathmlorhtml{mrow}{span} class="mhchem-arrow-normal">\:mhonlyinmathml{<mo>}&\#x21c4;\:mhonlyinmathml{</mo>}</\:mhmathmlorhtml{mrow}{span}> } }  % todo: improve
\Configure{mhchemarrowmesomerism}{ \HCode { <\:mhmathmlorhtml{mrow}{span} class="mhchem-arrow-normal">\:mhonlyinmathml{<mo>}&\#x2194;\:mhonlyinmathml{</mo>}</\:mhmathmlorhtml{mrow}{span}> } }  % todo: improve
\Configure{mhchemarrowequilibrium}{ \HCode { <\:mhmathmlorhtml{mrow}{span} class="mhchem-arrow-normal">\:mhonlyinmathml{<mo>}&\#x21cc;\:mhonlyinmathml{</mo>}</\:mhmathmlorhtml{mrow}{span}> } }  % todo: improve
\Configure{mhchemarrowequilibriumRight}{ \HCode { <\:mhmathmlorhtml{mrow}{span} class="mhchem-arrow-larger">\:mhonlyinmathml{<mo>}&\#x21c0;\:mhonlyinmathml{</mo>}</\:mhmathmlorhtml{mrow}{span}><\:mhmathmlorhtml{mrow}{span} class="mhchem-arrow-complement">\:mhonlyinmathml{<mo>}&\#x21bd;\:mhonlyinmathml{</mo>}</\:mhmathmlorhtml{mrow}{span}> } }  % todo: improve
\Configure{mhchemarrowequilibriumLeft}{ \HCode { <\:mhmathmlorhtml{mrow}{span} class="mhchem-arrow-complement">\:mhonlyinmathml{<mo>}&\#x21c0;\:mhonlyinmathml{</mo>}</\:mhmathmlorhtml{mrow}{span}><\:mhmathmlorhtml{mrow}{span} class="mhchem-arrow-larger">\:mhonlyinmathml{<mo>}&\#x21bd;\:mhonlyinmathml{</mo>}</\:mhmathmlorhtml{mrow}{span}> } }  % todo: improve
\else
\fi
% }

\Hinput{mhchem}

TeX Live 中包含的此文件版本将命令重定义与 HTML 代码混合在一起。最好不要混合它们,而是使用可配置的钩子。这样,您就可以支持多种输出格式。

您可以将此文件保存到与 TeX 文件相同的目录中,它将被自动使用。

结果如下

 make4ht filename.tex "mathml,mathjax"

在此处输入图片描述

您需要最新版本的 TeX4ht 和开发版本make4ht才能使其工作。

相关内容