|
From: <mi...@us...> - 2024-01-13 09:50:23
|
Revision: 9512
http://sourceforge.net/p/docutils/code/9512
Author: milde
Date: 2024-01-13 09:50:21 +0000 (Sat, 13 Jan 2024)
Log Message:
-----------
Simplify HTML math handling.
Define new function `utils.math.wrap_math_code()`.
Use it to simplify the `HTMLTranslator.visit_math()` method.
Modified Paths:
--------------
trunk/docutils/docutils/utils/math/__init__.py
trunk/docutils/docutils/utils/math/tex2mathml_extern.py
trunk/docutils/docutils/writers/_html_base.py
trunk/docutils/test/functional/expected/math_output_html.html
trunk/docutils/test/test_utils.py
Modified: trunk/docutils/docutils/utils/math/__init__.py
===================================================================
--- trunk/docutils/docutils/utils/math/__init__.py 2024-01-13 09:50:07 UTC (rev 9511)
+++ trunk/docutils/docutils/utils/math/__init__.py 2024-01-13 09:50:21 UTC (rev 9512)
@@ -61,3 +61,12 @@
if not numbered:
env += '*'
return env
+
+
+def wrap_math_code(code, as_block):
+ # Wrap math-code in mode-switching TeX command/environment.
+ # If `as_block` is True, use environment for displayed equation(s).
+ if as_block:
+ env = pick_math_environment(code)
+ return '\\begin{%s}\n%s\n\\end{%s}' % (env, code, env)
+ return '$%s$' % code
Modified: trunk/docutils/docutils/utils/math/tex2mathml_extern.py
===================================================================
--- trunk/docutils/docutils/utils/math/tex2mathml_extern.py 2024-01-13 09:50:07 UTC (rev 9511)
+++ trunk/docutils/docutils/utils/math/tex2mathml_extern.py 2024-01-13 09:50:21 UTC (rev 9512)
@@ -18,7 +18,7 @@
import subprocess
from docutils import nodes
-from docutils.utils.math import MathError, pick_math_environment
+from docutils.utils.math import MathError, wrap_math_code
# `latexml` expects a complete document:
document_template = r"""\documentclass{article}
@@ -59,11 +59,13 @@
'--doctype-xhtml+mathml',
'--annotate-TeX',
]
+ # "blahtexml" expects LaTeX code without math-mode-switch.
+ # We still need to tell it about displayed equation(s).
mathml_args = ' display="block"' if as_block else ''
+ _wrapped = wrap_math_code(math_code, as_block)
+ if '{align*}' in _wrapped:
+ math_code = _wrapped.replace('{align*}', '{aligned}')
- if pick_math_environment(math_code).startswith('align'):
- math_code = r'\begin{aligned}%s\end{aligned}' % math_code
-
result = subprocess.run(args, input=math_code,
capture_output=True, text=True)
@@ -100,7 +102,9 @@
'--inputencoding=utf8',
'--',
]
- result1 = subprocess.run(args1, input=document_template % math_code,
+ math_code = document_template % wrap_math_code(math_code, as_block)
+
+ result1 = subprocess.run(args1, input=math_code,
capture_output=True, text=True)
if result1.stdout:
result1.stderr = '\n'.join(line for line in result1.stderr.splitlines()
@@ -154,7 +158,7 @@
'--mathml',
'--from=latex',
]
- result = subprocess.run(args, input=math_code,
+ result = subprocess.run(args, input=wrap_math_code(math_code, as_block),
capture_output=True, text=True)
result.stdout = result.stdout[result.stdout.find('<math'):
@@ -187,12 +191,14 @@
args = ['ttm',
'-L', # source is LaTeX snippet
'-r'] # output MathML snippet
+ math_code = wrap_math_code(math_code, as_block)
- # Supports only ASCII and "latin extended" characters (Docutils converts
- # most math characters to LaTeX commands before calling ttm).
+ # "ttm" does not support UTF-8 input. (Docutils converts most math
+ # characters to LaTeX commands before calling this function.)
try:
- result = subprocess.run(args, input=math_code, capture_output=True,
- text=True, encoding='ISO-8859-1')
+ result = subprocess.run(args, input=math_code,
+ capture_output=True, text=True,
+ encoding='ISO-8859-1')
except UnicodeEncodeError as err:
raise MathError(err)
@@ -213,12 +219,33 @@
if __name__ == "__main__":
example = (r'\frac{\partial \sin^2(\alpha)}{\partial \vec r}'
r'\varpi \mathbb{R} \, \text{Grüße}')
- # print(blahtexml(example, as_block=True))
- # print(blahtexml(example))
- # print(latexml('$'+example+'$'))
- print(pandoc('$'+example+'$'))
- # print(ttm('$'+example.replace(r'\mathbb', r'\mathbf')+'$'))
+ print("""<!DOCTYPE html>
+<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
+<head>
+<title>test external mathml converters</title>
+</head>
+<body>
+<p>Test external converters</p>
+<p>
+""")
+ print(f'latexml: {latexml(example)},')
+ print(f'ttm: {ttm(example.replace("mathbb", "mathbf"))},')
+ print(f'blahtexml: {blahtexml(example)},')
+ print(f'pandoc: {pandoc(example)}.')
+ print('</p>')
+
+ print('<p>latexml:</p>')
+ print(latexml(example, as_block=True))
+ print('<p>ttm:</p>')
+ print(ttm(example.replace('mathbb', 'mathbf'), as_block=True))
+ print('<p>blahtexml:</p>')
+ print(blahtexml(example, as_block=True))
+ print('<p>pandoc:</p>')
+ print(pandoc(example, as_block=True))
+
+ print('</main>\n</body>\n</html>')
+
buggy = r'\sinc \phy'
# buggy = '\sqrt[e]'
try:
Modified: trunk/docutils/docutils/writers/_html_base.py
===================================================================
--- trunk/docutils/docutils/writers/_html_base.py 2024-01-13 09:50:07 UTC (rev 9511)
+++ trunk/docutils/docutils/writers/_html_base.py 2024-01-13 09:50:21 UTC (rev 9512)
@@ -30,9 +30,8 @@
from docutils.parsers.rst.directives import length_or_percentage_or_unitless
from docutils.parsers.rst.directives.images import PIL
from docutils.transforms import writer_aux
-from docutils.utils.math import (MathError, math2html, latex2mathml,
- pick_math_environment,
- tex2mathml_extern, unichar2tex)
+from docutils.utils.math import (latex2mathml, math2html, tex2mathml_extern,
+ unichar2tex, wrap_math_code, MathError)
class Writer(writers.Writer):
@@ -1281,31 +1280,11 @@
'problematic': ('span', 'pre', ['math', 'problematic']),
}
- def visit_math(self, node, math_env=''):
- # Also called from `visit_math_block()` (with math_env != '').
+ def visit_math(self, node):
+ # Also called from `visit_math_block()`:
is_block = isinstance(node, nodes.math_block)
format = self.math_output
- # LaTeX container
- wrappers = {
- # math_mode: (inline, block)
- 'html': ('$%s$', '\\begin{%s}\n%s\n\\end{%s}'),
- 'latex': (None, None),
- 'mathml': ('$%s$', '\\begin{%s}\n%s\n\\end{%s}'),
- 'mathjax': (r'\(%s\)', '\\begin{%s}\n%s\n\\end{%s}'),
- 'problematic': (None, None),
- }
- wrapper = wrappers[self.math_output][math_env != '']
- if (self.math_output == 'mathml'
- and (not self.math_options
- or self.math_options == 'blahtexml')):
- wrapper = None
- # get and wrap content
math_code = node.astext().translate(unichar2tex.uni2tex_table)
- if wrapper:
- try: # wrapper with three "%s"
- math_code = wrapper % (math_env, math_code, math_env)
- except TypeError: # wrapper with one "%s"
- math_code = wrapper % math_code
# preamble code and conversion
if format == 'html':
@@ -1314,8 +1293,9 @@
self.stylesheet_call(utils.find_file_in_dirs(
s, self.settings.stylesheet_dirs), adjust_path=True)
for s in self.math_options.split(',')]
+ math2html.DocumentParameters.displaymode = is_block
# TODO: fix display mode in matrices and fractions
- math2html.DocumentParameters.displaymode = is_block
+ math_code = wrap_math_code(math_code, is_block)
math_code = math2html.math2html(math_code)
elif format == 'latex':
math_code = self.encode(math_code)
@@ -1332,6 +1312,10 @@
if '?' not in self.mathjax_url:
self.mathjax_url += '?config=TeX-AMS_CHTML'
self.math_header = [self.mathjax_script % self.mathjax_url]
+ if is_block:
+ math_code = wrap_math_code(math_code, is_block)
+ else:
+ math_code = rf'\({math_code}\)'
math_code = self.encode(math_code)
elif format == 'mathml':
if 'XHTML 1' in self.doctype:
@@ -1372,8 +1356,7 @@
pass
def visit_math_block(self, node):
- math_env = pick_math_environment(node.astext())
- self.visit_math(node, math_env=math_env)
+ self.visit_math(node)
def depart_math_block(self, node):
self.report_messages(node)
Modified: trunk/docutils/test/functional/expected/math_output_html.html
===================================================================
--- trunk/docutils/test/functional/expected/math_output_html.html 2024-01-13 09:50:07 UTC (rev 9511)
+++ trunk/docutils/test/functional/expected/math_output_html.html 2024-01-13 09:50:21 UTC (rev 9512)
@@ -68,7 +68,7 @@
directives:</p>
<p>The Schrödinger equation</p>
<div class="formula" id="eq-schrodinger">
-<i>i</i><i>ħ</i><span class="fraction"><span class="ignored">(</span><span class="numerator">∂</span><span class="ignored">)/(</span><span class="denominator">∂<i>t</i></span><span class="ignored">)</span></span>Ψ = <i>Ĥ</i>Ψ,
+<i>i</i><i>ℏ</i><span class="fraction"><span class="ignored">(</span><span class="numerator">∂</span><span class="ignored">)/(</span><span class="denominator">∂<i>t</i></span><span class="ignored">)</span></span>Ψ = <i>Ĥ</i>Ψ,
</div>
<p>with the <em>wave function</em> <span class="formula">Ψ</span>, describes how the quantum state of a
physical system changes in time.</p>
Modified: trunk/docutils/test/test_utils.py
===================================================================
--- trunk/docutils/test/test_utils.py 2024-01-13 09:50:07 UTC (rev 9511)
+++ trunk/docutils/test/test_utils.py 2024-01-13 09:50:21 UTC (rev 9512)
@@ -20,7 +20,8 @@
sys.path.insert(0, str(Path(__file__).resolve().parents[1]))
import docutils
-from docutils import utils, nodes
+from docutils import nodes, utils
+import docutils.utils.math
TEST_ROOT = Path(__file__).parent # ./test/ from the docutils root
@@ -417,5 +418,26 @@
utils.get_stylesheet_list(self)
+class MathTests(unittest.TestCase):
+
+ tests = [('a + b = c', 'equation*'),
+ (r'x = \begin{cases} -1&x<0 \\ 1&x>0 \end{cases}', 'equation*'),
+ (r'a + 2b = c \\ 3a + b = 2c', 'align*'),
+ ]
+
+ def test_pick_math_environment(self):
+ for sample, result in self.tests:
+ self.assertEqual(utils.math.pick_math_environment(sample), result)
+
+ def test_wrap_math_code(self):
+ for sample, env in self.tests:
+ self.assertEqual(utils.math.wrap_math_code(sample, as_block=False),
+ f'${sample}$')
+ self.assertEqual(utils.math.wrap_math_code(sample, as_block=True),
+ f'\\begin{{{env}}}\n'
+ f'{sample}\n'
+ f'\\end{{{env}}}')
+
+
if __name__ == '__main__':
unittest.main()
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
|