summaryrefslogtreecommitdiff
path: root/docutils/utils/math
diff options
context:
space:
mode:
authormilde <milde@929543f6-e4f2-0310-98a6-ba3bd3dd1d04>2015-04-10 23:48:51 +0000
committermilde <milde@929543f6-e4f2-0310-98a6-ba3bd3dd1d04>2015-04-10 23:48:51 +0000
commit820c36ab42a847b231a89ef6431a1fb1859d864b (patch)
tree74344167f2953f720ffecfb0e618a7a67ae9e33e /docutils/utils/math
parent626004e20fb78140d43d423fd710c9cff73e6d38 (diff)
downloaddocutils-820c36ab42a847b231a89ef6431a1fb1859d864b.tar.gz
Support some external TeX math -> MathML converters.
git-svn-id: http://svn.code.sf.net/p/docutils/code/trunk/docutils@7861 929543f6-e4f2-0310-98a6-ba3bd3dd1d04
Diffstat (limited to 'docutils/utils/math')
-rw-r--r--docutils/utils/math/tex2mathml_extern.py147
1 files changed, 147 insertions, 0 deletions
diff --git a/docutils/utils/math/tex2mathml_extern.py b/docutils/utils/math/tex2mathml_extern.py
new file mode 100644
index 000000000..f315977b8
--- /dev/null
+++ b/docutils/utils/math/tex2mathml_extern.py
@@ -0,0 +1,147 @@
+#!/usr/bin/env python
+# -*- coding: utf-8 -*-
+
+# :Id: $Id$
+# :Copyright: © 2015 Günter Milde.
+# :License: Released under the terms of the `2-Clause BSD license`_, in short:
+#
+# Copying and distribution of this file, with or without modification,
+# are permitted in any medium without royalty provided the copyright
+# notice and this notice are preserved.
+# This file is offered as-is, without any warranty.
+#
+# .. _2-Clause BSD license: http://www.spdx.org/licenses/BSD-2-Clause
+
+# Wrappers for TeX->MathML conversion by external tools
+# =====================================================
+
+import subprocess
+
+document_template = r"""\documentclass{article}
+\usepackage{amsmath}
+\begin{document}
+%s
+\end{document}
+"""
+
+def latexml(math_code, reporter=None):
+ """Convert LaTeX math code to MathML with LaTeXML_
+
+ .. _LaTeXML: http://dlmf.nist.gov/LaTeXML/
+ """
+ p = subprocess.Popen(['latexml',
+ '-', # read from stdin
+ # '--preload=amsmath',
+ '--inputencoding=utf8',
+ ],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ close_fds=True)
+ p.stdin.write((document_template % math_code).encode('utf8'))
+ p.stdin.close()
+ latexml_code = p.stdout.read()
+ latexml_err = p.stderr.read().decode('utf8')
+ if reporter and latexml_err.find('Error') >= 0 or not latexml_code:
+ reporter.error(latexml_err)
+
+ post_p = subprocess.Popen(['latexmlpost',
+ '-',
+ '--nonumbersections',
+ '--format=xhtml',
+ # '--linelength=78', # experimental
+ '--'
+ ],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ close_fds=True)
+ post_p.stdin.write(latexml_code)
+ post_p.stdin.close()
+ result = post_p.stdout.read().decode('utf8')
+ post_p_err = post_p.stderr.read().decode('utf8')
+ if reporter and post_p_err.find('Error') >= 0 or not result:
+ reporter.error(post_p_err)
+
+ # extract MathML code:
+ start,end = result.find('<math'), result.find('</math>')+7
+ result = result[start:end]
+ if 'class="ltx_ERROR' in result:
+ raise SyntaxError(result)
+ return result
+
+def ttm(math_code, reporter=None):
+ """Convert LaTeX math code to MathML with TtM_
+
+ .. _TtM: http://hutchinson.belmont.ma.us/tth/mml/
+ """
+ p = subprocess.Popen(['ttm',
+ # '-i', # italic font for equations. Default roman.
+ '-u', # unicode character encoding. (Default iso-8859-1).
+ '-r', # output raw MathML (no preamble or postlude)
+ ],
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ close_fds=True)
+ p.stdin.write((document_template % math_code).encode('utf8'))
+ p.stdin.close()
+ result = p.stdout.read()
+ err = p.stderr.read().decode('utf8')
+ if err.find('**** Unknown') >= 0:
+ msg = '\n'.join([line for line in err.splitlines()
+ if line.startswith('****')])
+ raise SyntaxError('\nMessage from external converter TtM:\n'+ msg)
+ if reporter and err.find('**** Error') >= 0 or not result:
+ reporter.error(err)
+ start,end = result.find('<math'), result.find('</math>')+7
+ result = result[start:end]
+ return result
+
+def blahtexml(math_code, inline=True, reporter=None):
+ """Convert LaTeX math code to MathML with blahtexml_
+
+ .. _blahtexml: http://gva.noekeon.org/blahtexml/
+ """
+ options = ['--mathml',
+ '--indented',
+ '--spacing', 'moderate',
+ '--mathml-encoding', 'raw',
+ '--other-encoding', 'raw',
+ '--doctype-xhtml+mathml',
+ '--annotate-TeX',
+ ]
+ if inline:
+ mathmode_arg = ''
+ else:
+ mathmode_arg = 'mode="display"'
+ options.append('--displaymath')
+
+ p = subprocess.Popen(['blahtexml']+options,
+ stdin=subprocess.PIPE,
+ stdout=subprocess.PIPE,
+ stderr=subprocess.PIPE,
+ close_fds=True)
+ p.stdin.write(math_code.encode('utf8'))
+ p.stdin.close()
+ result = p.stdout.read().decode('utf8')
+ err = p.stderr.read().decode('utf8')
+
+ print err
+ if result.find('<error>') >= 0:
+ raise SyntaxError('\nMessage from external converter blahtexml:\n'
+ +result[result.find('<message>')+9:result.find('</message>')])
+ if reporter and (err.find('**** Error') >= 0 or not result):
+ reporter.error(err)
+ start,end = result.find('<markup>')+9, result.find('</markup>')
+ result = ('<math xmlns="http://www.w3.org/1998/Math/MathML"%s>\n'
+ '%s</math>\n') % (mathmode_arg, result[start:end])
+ return result
+
+# self-test
+
+if __name__ == "__main__":
+ example = ur'\frac{\partial \sin^2(\alpha)}{\partial \vec r} \varpi \, \text{Grüße}'
+ # print latexml(example).encode('utf8')
+ # print ttm(example)#.encode('utf8')
+ print blahtexml(example).encode('utf8')