我正在编写一篇化学含量较高的文本,我注意到 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 { − } }
\cs_set_protected:Npn \__mhchem_output_operatorPlus:
{ \a:mhchemoperator + \b:mhchemoperator }
\cs_set_protected:Npn \__mhchem_output_operatorMinus:
{ \a:mhchemoperator\HCode {−} \b:mhchemoperator }
\cs_set_protected:Npn \__mhchem_output_operatorEquals:
{ \a:mhchemoperator = \b:mhchemoperator }
\cs_set_protected:Npn \__mhchem_output_operatorPlusMinus:
{\a:mhchemoperator \HCode {± } \b:mhchemoperator }
\cs_set_protected:Npn \__mhchem_output_electronDot: { \HCode { • } }
\cs_set_protected:Npn \__mhchem_output_additionCompound: { \HCode { · } }
\cs_set_protected:Npn \__mhchem_output_excited: { \HCode { &\#x2731; } }
\cs_set_protected:Npn \__mhchem_output_commaDecimal: { , }
\cs_set_protected:Npn \__mhchem_output_commaEnumeration: { , \HCode {   } }
\cs_set_protected:Npn \__mhchem_output_commaEnumerationSmall: { , \HCode {   } }
\cs_set_protected:Npn \__mhchem_output_bond_single: { \HCode { − } }
\cs_set_protected:Npn \__mhchem_output_bond_double: { \HCode { = } }
\cs_set_protected:Npn \__mhchem_output_bond_triple: { \HCode { ≡ } }
% 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">−</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">−</span><span~class="mhchem-rlap~mhchem-bond-bottom">−</span><span~class="mhchem-bond-half-middle">&\#xfe4d;</span> } }
\cs_set_protected:Npn \__mhchem_output_bond_dotdotdot: { \HCode { ··· } }
\cs_set_protected:Npn \__mhchem_output_bond_dotdotdotdot: { \HCode { ···· } }
\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
才能使其工作。