def test_handle_math_mpointthree_big(self): r"""MPointThree[\big]: commands in arguments""" elem_math = pf.Math(r"\MPointThree[\Big]{\frac{3}{2}}{1}{2}") elem_math_repl = handle_math(elem_math) self.assertEqual( elem_math_repl.text, r"\Big(\frac{3}{2}\coordsep 1\coordsep 2{}\Big)", )
def test_handle_math_mpointtwoas(self): r"""MPointTwoAS: commands in arguments""" elem_math = pf.Math(r"\MPointTwoAS{-\sqrt6}{-\frac12\sqrt6}") elem_math_repl = handle_math(elem_math) self.assertEqual( elem_math_repl.text, r"\left(-\sqrt6\coordsep -\frac12\sqrt6\right)", )
def test_handle_math_mvector(self): """MVector: commands in arguments""" elem_math = pf.Math(r"x^2 \MVector{2\\-\Mtfrac{5}{2}\\-2}") elem_math_repl = handle_math(elem_math) self.assertEqual( elem_math_repl.text, r"x^2 \begin{pmatrix}2\\-\tfrac{5}{2}\\-2\end{pmatrix}", )
def test_handle_math_mpointtwo_parse_bug(self): r"""MPointTwo[\big]: a particular bug""" elem_math = pf.Math(r"\MPointTwo[\Big]{\frac{1}{n}}{0}\MCondSetSep") elem_math_repl = handle_math(elem_math) self.assertEqual( elem_math_repl.text, r"\Big(\frac{1}{n}\coordsep 0{}\Big) {\,}:{\,}", )
def test_handle_math_mpointtwo_big(self): r"""MPointTwo[\big]: commands in arguments""" elem_math = pf.Math( r"\MPointTwo[\Big]{\frac{3}{2}}{1+\frac{\sqrt{3}}{2}}") elem_math_repl = handle_math(elem_math) self.assertEqual( elem_math_repl.text, r"\Big(\frac{3}{2}\coordsep 1+\frac{\sqrt{3}}{2}{}\Big)", )
def test_handle_math_mpointtwo(self): """MPointTwo: commands in arguments""" elem_math = pf.Math(r"\MPointTwo{\frac{3}{2}}{1+\frac{\sqrt{3}}{2}} " "x_2") elem_math_repl = handle_math(elem_math) self.assertEqual( elem_math_repl.text, r"(\frac{3}{2}\coordsep 1+\frac{\sqrt{3}}{2}) x_2", )
def _mymath(elem, doc): text = elem.text latex, *rest = _multisplit(text, "|¬") if doc.format == "latex": return pf.Math(latex, format="InlineMath") else: rest = rest[0] if rest else latex return pf.Str(rest)
def handle_mzxyzhltrennzeichen(self, cmd_args, elem): r"""Handle ``\MZXYZhltrennzeichen`` command. It is transformed to a ``\decmarker`` command and later substituted by MathJax. This is already in math substitions but as it occurs outside of math environments it's defined here too. """ if isinstance(elem, pf.Block): raise ValueError( r"Encountered \MZXYZhltrennzeichen as block element!") return pf.Math(r"\decmarker", format="InlineMath")
def handle_mzahl(self, cmd_args, elem): r"""Handle ``\MZahl`` command. This is a math command but in fact occurs also in text. """ if isinstance(elem, pf.Block): raise ValueError(r"Encountered \MZahl as block element!") return pf.Math( r"\num{{{}.{}}}".format(cmd_args[0], cmd_args[1]), format="InlineMath", )
def test_handle_mcaseenv(self): """MMCaseEnv""" elem_math = pf.Math( r"|x| = \begin{MCaseEnv} x & \text{falls}\;x\geq 0 " r"\\ -x & \text{falls}\;x<0 \MDFPeriod \end{MCaseEnv}") elem_math_repl = handle_math(elem_math) self.assertEqual( elem_math_repl.text, r"|x| = \left\lbrace\begin{array}{rl} x & \text{falls}\;x\geq 0 " r"\\ -x & \text{falls}\;x<0 \, . \end{array}\right.", )
def test_handle_math_mpointthree(self): r"""MPointThree: commands in arguments""" elem_math = pf.Math( r"\MPointThree{x = \Mtfrac{2}{19}}{y = - \Mtfrac{5}{19}}" r"{z = \Mtfrac{2}{19}}") elem_math_repl = handle_math(elem_math) self.assertEqual( elem_math_repl.text, r"(x = \tfrac{2}{19}\coordsep y = - \tfrac{5}{19}\coordsep " r"z = \tfrac{2}{19})", )
def test_handle_math_multiple(self): r"""multiple commands in one math string""" elem_math = pf.Math(r"z=\MPointThree{\frac{1}{2}}{3}{\sqrt{2}};" r"q=\MPointTwoAS{2}{1+\frac{\sqrt{3}}{2}};" r"f(x)=x^2") elem_math_repl = handle_math(elem_math) self.assertEqual( elem_math_repl.text, r"z=(\frac{1}{2}\coordsep 3\coordsep \sqrt{2});" r"q=\left(2\coordsep 1+\frac{\sqrt{3}}{2}\right);" r"f(x)=x^2", )
def test_handle_math_mcases(self): r"""mcases: commands in arguments""" elem_math = pf.Math( r"\MCases{\text{Term} & \text{falls}\;\text{Term}\geq 0\\ " r"-\text{Term} & \text{falls}\;\text{Term}<0}") elem_math_repl = handle_math(elem_math) self.assertEqual( elem_math_repl.text, r"\left\lbrace{\begin{array}{rl} \text{Term} & \text{falls}\;" r"\text{Term}\geq 0\\ -\text{Term} & \text{falls}\;\text{Term}<0 " r"\end{array}}\right.", )
def test_handle_math_function(self): r"""function: commands in arguments""" elem_math = pf.Math( r"\function{h}{(-\frac{\pi}{2}\MIntvlSep \frac{\pi}{2})}" r"{\R}{\alpha}{\tan(\alpha)}") elem_math_repl = handle_math(elem_math) self.assertEqual( elem_math_repl.text, r"h:\;\left\lbrace{\begin{array}{rcl} " r"(-\frac{\pi}{2}; \frac{\pi}{2}) &\longrightarrow &" r" \mathbb{R} \\ \alpha &\longmapsto & \tan(\alpha) " r"\end{array}}\right.", )
def sage(elem, doc): elemtype = type(elem) if elemtype in [pf.Math, pf.RawInline]: contents = replace_sagecommand(elem.text) if elemtype == pf.Math: return pf.Math(contents, format=elem.format) else: return pf.RawInline(contents, format=elem.format) if elemtype == pf.CodeBlock: isSageSilent = 'sagesilent' in elem.classes isSageBlock = 'sageblock' in elem.classes isSagePlot = 'sageplot' in elem.classes code = elem.text if isSageBlock or isSagePlot or isSageSilent: img_file = get_image_output_filename(code) sage_file = get_sage_filename(code) if isSagePlot: code = code.strip("\n") codelist = code.split("\n") plot_cmd = codelist.pop() code = "\n".join(codelist) m = re.search(r"sageplot\[(?P<first_name>.*)\]\((.*)\)", plot_cmd) if m == None: para, cmd = "", plot_cmd else: para, cmd = m.group(1), m.group(2) if len(para) > 0: para = ',' + para code += "\n(%s).save(\"%s\"%s)" % (cmd, img_file, para) out, err = run_sage(code) if isSageSilent: return pf.Plain(pf.RawInline("", "tex")) elif isSageBlock: sys.stderr.write('\n convert markdown \n') return pf.convert_text(out) else: return pf.Para( pf.Image(url=img_file, attributes=elem.attributes)) if 'latex' in elem.classes: out, err, img_file = run_tex(code) return pf.Para(pf.Image(url=img_file, attributes=elem.attributes))
def action(elem, doc): r"""Handles \begin{align} \label \eqref and \ref while converting from LaTeX. Why --- * Pandoc converts \begin{align} -> \begin{aligned} implicitly which does not handle multiple labels * Pandoc does not have a mechanism to handle \eqref or \ref, but pandoc-crossref has one, so we re-engineer an expression which suits the latter """ if isinstance(elem, pf.Math) and elem.format == "DisplayMath": text = pf.stringify(elem) for label in extract_latex_labels(text): if not label.startswith("eq:"): text = text.replace(rf'\label{{{label}}}', rf'\label{{eq:{label}}}') if r"\begin{aligned}" in text: if r"\label" in text: env = "align" else: env = "align*" return pf.RawInline( "\n" + text.replace("{aligned}", f"{{{env}}}") + "\n", format="tex" ) else: return pf.Math(text, format=elem.format) if doc.format.startswith("markdown"): label = "" if isinstance(elem, pf.RawInline) and elem.format == "tex": label = pf.stringify(elem).lstrip(r"\eqref{").rstrip("}") return create_citation(label, 'eq:') elif isinstance(elem, pf.Link) and "reference-type" in elem.attributes: label = elem.url.lstrip("#") if elem.attributes["reference-type"] == "eqref": return create_citation(label, "eq:") elif elem.attributes["reference-type"] == "ref": return create_citation(label)
def handle_mequationitem(self, cmd_args, elem): r"""Handle ``\MEquationItem`` command.""" if len(cmd_args) != 2: raise ValueError( r"\MEquationItem needs 2 arguments. Received: {}".format( cmd_args)) content_left = parse_fragment(cmd_args[0], elem.doc.metadata["lang"].text) content_right = parse_fragment(cmd_args[1], elem.doc.metadata["lang"].text) content = to_inline([ content_left, pf.Math(r"\;\;=\;", format="InlineMath"), content_right ]) if isinstance(elem, pf.Block): return pf.Plain(content) return content
def test_all(): md = 'Some *markdown* **text** ~xyz~' c_md = pf.convert_text(md) b_md = [ pf.Para(pf.Str("Some"), pf.Space, pf.Emph(pf.Str("markdown")), pf.Space, pf.Strong(pf.Str("text")), pf.Space, pf.Subscript(pf.Str("xyz"))) ] print("Benchmark MD:") print(b_md) print("Converted MD:") print(c_md) assert repr(c_md) == repr(b_md) with io.StringIO() as f: doc = pf.Doc(*c_md) pf.dump(doc, f) c_md_dump = f.getvalue() with io.StringIO() as f: doc = pf.Doc(*b_md) pf.dump(doc, f) b_md_dump = f.getvalue() assert c_md_dump == b_md_dump # ---------------------- print() tex = r'Some $x^y$ or $x_n = \sqrt{a + b}$ \textit{a}' c_tex = pf.convert_text(tex) b_tex = [ pf.Para(pf.Str("Some"), pf.Space, pf.Math("x^y", format='InlineMath'), pf.Space, pf.Str("or"), pf.Space, pf.Math(r"x_n = \sqrt{a + b}", format='InlineMath'), pf.Space, pf.RawInline(r"\textit{a}", format='tex')) ] print("Benchmark TEX:") print(b_tex) print("Converted TEX:") print(c_tex) assert repr(c_tex) == repr(b_tex) with io.StringIO() as f: doc = pf.Doc(*c_tex) pf.dump(doc, f) c_tex_dump = f.getvalue() with io.StringIO() as f: doc = pf.Doc(*b_tex) pf.dump(doc, f) b_tex_dump = f.getvalue() assert c_tex_dump == b_tex_dump print("\nBack and forth conversions... md->json->md") md = 'Some *markdown* **text** ~xyz~' print("[MD]", md) md2json = pf.convert_text(md, input_format='markdown', output_format='json') print("[JSON]", md2json) md2json2md = pf.convert_text(md2json, input_format='json', output_format='markdown') print("[MD]", md2json2md) assert md == md2json2md print("\nBack and forth conversions... md->panflute->md") md = 'Some *markdown* **text** ~xyz~' print("[MD]", md) md2panflute = pf.convert_text(md, input_format='markdown', output_format='panflute') print("[PANFLUTE]", md2panflute) md2panflute2md = pf.convert_text(md2panflute, input_format='panflute', output_format='markdown') print("[MD]", md2panflute2md) assert md == md2panflute2md print("\nBack and forth conversions... md->panflute(standalone)->md") md = 'Some *markdown* **text** ~xyz~' print("[MD]", md) md2panflute = pf.convert_text(md, input_format='markdown', output_format='panflute', standalone=True) print("[PANFLUTE]", md2panflute) md2panflute2md = pf.convert_text(md2panflute, input_format='panflute', output_format='markdown') print("[MD]", md2panflute2md) assert md == md2panflute2md print( "\nBack and forth conversions... md table -> json(standalone) -> md table" ) md = """lorem --- --- x y --- --- ipsum""" print("[MD]", repr(md)) md2json = pf.convert_text(md, input_format='markdown', output_format='json', standalone=True) print("[json]", md2json) md2json2md = pf.convert_text(md2json, input_format='json', output_format='markdown') print("[MD]", repr(md2json2md)) assert md == md2json2md print( "\nBack and forth conversions... md table -> panflute(standalone) -> md table" ) print("[MD]", repr(md)) md2panflute = pf.convert_text(md, input_format='markdown', output_format='panflute', standalone=True) print("[PANFLUTE]", md2panflute) md2panflute2md = pf.convert_text(md2panflute, input_format='panflute', output_format='markdown') print("[MD]", repr(md2panflute2md)) assert md == md2panflute2md print( "\nBack and forth conversions... gfm table (empty) -> json(standalone) -> gfm table (empty)" ) md = """lorem | x | y | | - | - | ipsum""" print("[MD]", repr(md)) md2json = pf.convert_text(md, input_format='gfm', output_format='json', standalone=True) print("[json]", md2json) md2json2md = pf.convert_text(md2json, input_format='json', output_format='gfm') print("[MD]", repr(md2json2md)) assert md == md2json2md print( "\nBack and forth conversions... gfm table (empty) -> panflute(standalone) -> gfm table (empty)" ) print("[MD]", repr(md)) md2panflute = pf.convert_text(md, input_format='gfm', output_format='panflute', standalone=True) print("[PANFLUTE]", md2panflute) md2panflute2md = pf.convert_text(md2panflute, input_format='panflute', output_format='gfm') print("[MD]", repr(md2panflute2md)) assert md == md2panflute2md
def test_handle_math_meinheit(self): r"""MEinheit""" elem_math = pf.Math(r"\MEinheit{kg} -58^{\circ}{\MEinheit[]{C}}") elem_math_repl = handle_math(elem_math) self.assertEqual(elem_math_repl.text, r"\, \mathrm{kg} -58^{\circ}{\mathrm{C}}")
def test_math_input(self): """filter() returns Math if given Math element""" elem_math = pf.Math(r"1+2") ret = self._filter_elem([pf.Para(elem_math)], elem_math) self.assertIsInstance(ret, pf.Math)
def test_handle_math_substitutions(self): """Math substitutions should work""" elem_math = pf.Math(r"\N \Q {\R}") elem_math_repl = handle_math(elem_math) self.assertEqual(elem_math_repl.text, r"\mathbb{N} \mathbb{Q} {\mathbb{R}}")