-
-
Notifications
You must be signed in to change notification settings - Fork 65
MathML tweaks #1661
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
MathML tweaks #1661
Changes from all commits
70f84ed
5b89c3f
e88108d
5295f48
1831e6b
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,30 @@ | |
| Lower-level formatter of Mathics objects as MathML strings. | ||
|
|
||
| MathML formatting is usually initiated in Mathics via MathMLForm[]. | ||
|
|
||
| For readability, and following WMA MathML generated code, tags \ | ||
| containing sub-tags are split on several lines, one by | ||
| sub element. For example, the Box expression | ||
|
|
||
| >> FractionBox[RowBox[{"a", "+", SuperscriptBox["b", "c"]}], "d"] | ||
|
|
||
| produces | ||
| ``` | ||
| <mfrac> | ||
| <mrow> | ||
| <mi>a</mi> | ||
| <mo>+</mo> | ||
| <msup> | ||
| <mi>b</mi> | ||
| <mi>c</mi> | ||
| </msup> | ||
| </mrow> | ||
| <mi>d</mi> | ||
| </mfrac> | ||
| ``` | ||
| In WMA, each line would be also indented adding one space on each \ | ||
| level of indentation. | ||
|
|
||
| """ | ||
|
|
||
| import base64 | ||
|
|
@@ -44,6 +68,7 @@ def encode_mathml(text: str) -> str: | |
| return text | ||
|
|
||
|
|
||
| # "Operators" which are not in display_operators_set | ||
| extra_operators = { | ||
| ",", | ||
| "(", | ||
|
|
@@ -52,15 +77,15 @@ def encode_mathml(text: str) -> str: | |
| "]", | ||
| "{", | ||
| "}", | ||
| "\u301a", | ||
| "\u301b", | ||
| "\u00d7", | ||
| "\u2032", | ||
| "\u2032\u2032", | ||
| " ", | ||
| "\u2062", | ||
| "\u222b", | ||
| "\u2146", | ||
| # TODO: check why the following characters are not in `operators`: | ||
| "\u301a", # [[ | ||
| "\u301b", # ]] | ||
| "\u00d7", # \[Times] | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Why can't this be picked up from character tables?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Good question. I have to check if we are not doing already that. |
||
| "\u2032", # \[RawComma] | ||
| "\u2032\u2032", # \[RawComma]\[RawComma] | ||
| "\u2062", # \[InvisibleTimes] | ||
| "\u222b", # \[Integral] | ||
| "\u2146", # \[DifferentialD] | ||
| } | ||
|
|
||
|
|
||
|
|
@@ -80,13 +105,10 @@ def render(format, string): | |
| return format % encoded_text | ||
|
|
||
| if text.startswith('"') and text.endswith('"'): | ||
| if show_string_characters: | ||
| return render("<ms>%s</ms>", text[1:-1]) | ||
| else: | ||
| outtext = "" | ||
| for line in text[1:-1].split("\n"): | ||
| outtext += render("<mtext>%s</mtext>", line) | ||
| return outtext | ||
| text = text[1:-1] | ||
| if not show_string_characters: | ||
| return render("<mtext>%s</mtext>", text) | ||
| return render("<ms>%s</ms>", text) | ||
| elif ( | ||
| text | ||
| and (number_as_text is SymbolFalse) | ||
|
|
@@ -101,29 +123,47 @@ def render(format, string): | |
| # Mathics-Django: | ||
| if text == "": | ||
| return "" | ||
| if text == "\u2146": | ||
| if text == "\u2146": # DifferentialD | ||
| return render( | ||
| '<mo form="prefix" lspace="0.2em" rspace="0">%s</mo>', text | ||
| ) | ||
| if text == "\u2062": | ||
| if text == "\u2062": # InvisibleTimes | ||
| return render( | ||
| '<mo form="prefix" lspace="0" rspace="0.2em">%s</mo>', text | ||
| ) | ||
| return render("<mo>%s</mo>", text) | ||
| elif is_symbol_name(text): | ||
| return render("<mi>%s</mi>", text) | ||
| else: | ||
| outtext = "" | ||
| for line in text.split("\n"): | ||
| outtext += render("<mtext>%s</mtext>", line) | ||
| return outtext | ||
| return "".join( | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is where getting the proper indent level would be done. |
||
| render("<mtext>%s</mtext>", line) for line in text.split("\n") | ||
| ) | ||
|
|
||
|
|
||
| add_conversion_fn(String, string) | ||
|
|
||
|
|
||
| def interpretation_box(self, **options): | ||
| return lookup_conversion_method(self.boxes, "mathml")(self.boxes, **options) | ||
| boxes = self.boxes | ||
| origin = self.expr | ||
| if origin.has_form("InputForm", None): | ||
| # InputForm produce outputs of the form | ||
| # InterpretationBox[Style[_String, ...], origin_InputForm, opts___] | ||
| assert isinstance(boxes, StyleBox), f"boxes={boxes} are not a StyleBox" | ||
| boxes = boxes.boxes | ||
| options["System`ShowStringCharacters"] = SymbolTrue | ||
| assert isinstance(boxes, String) | ||
| # Remove the outer quotes | ||
| elif origin.has_form("OutputForm", None): | ||
| # OutputForm produce outputs of the form | ||
| # InterpretationBox[PaneBox[_String, ...], origin_OutputForm, opts___] | ||
| assert boxes.has_form("PaneBox", 1, None) | ||
| boxes = boxes.boxes | ||
| assert isinstance(boxes, String) | ||
| # Remove the outer quotes | ||
| boxes = String(boxes.value) | ||
|
|
||
| return lookup_conversion_method(boxes, "mathml")(boxes, **options) | ||
|
|
||
|
|
||
| add_conversion_fn(InterpretationBox, interpretation_box) | ||
|
|
@@ -171,7 +211,7 @@ def fractionbox(self, **options) -> str: | |
| _options = self.box_options.copy() | ||
| _options.update(options) | ||
| options = _options | ||
| return "<mfrac>%s %s</mfrac>" % ( | ||
| return "<mfrac>\n%s\n%s\n</mfrac>" % ( | ||
| lookup_conversion_method(self.num, "mathml")(self.num, **options), | ||
| lookup_conversion_method(self.den, "mathml")(self.den, **options), | ||
| ) | ||
|
|
@@ -231,7 +271,7 @@ def sqrtbox(self, **options): | |
| lookup_conversion_method(self.index, "mathml")(self.index, **options), | ||
| ) | ||
|
|
||
| return "<msqrt> %s </msqrt>" % lookup_conversion_method(self.radicand, "mathml")( | ||
| return "<msqrt>\n%s\n</msqrt>" % lookup_conversion_method(self.radicand, "mathml")( | ||
| self.radicand, **options | ||
| ) | ||
|
|
||
|
|
@@ -243,7 +283,7 @@ def subscriptbox(self, **options): | |
| _options = self.box_options.copy() | ||
| _options.update(options) | ||
| options = _options | ||
| return "<msub>%s %s</msub>" % ( | ||
| return "<msub>\n%s\n%s\n</msub>" % ( | ||
| lookup_conversion_method(self.base, "mathml")(self.base, **options), | ||
| lookup_conversion_method(self.subindex, "mathml")(self.subindex, **options), | ||
| ) | ||
|
|
@@ -256,7 +296,7 @@ def superscriptbox(self, **options): | |
| _options = self.box_options.copy() | ||
| _options.update(options) | ||
| options = _options | ||
| return "<msup>%s %s</msup>" % ( | ||
| return "<msup>\n%s\n%s\n</msup>" % ( | ||
| lookup_conversion_method(self.base, "mathml")(self.base, **options), | ||
| lookup_conversion_method(self.superindex, "mathml")(self.superindex, **options), | ||
| ) | ||
|
|
@@ -270,7 +310,7 @@ def subsuperscriptbox(self, **options): | |
| _options.update(options) | ||
| options = _options | ||
| options["inside_row"] = True | ||
| return "<msubsup>%s %s %s</msubsup>" % ( | ||
| return "<msubsup>\n%s\n%s\n%s\n</msubsup>" % ( | ||
| lookup_conversion_method(self.base, "mathml")(self.base, **options), | ||
| lookup_conversion_method(self.subindex, "mathml")(self.subindex, **options), | ||
| lookup_conversion_method(self.superindex, "mathml")(self.superindex, **options), | ||
|
|
@@ -318,7 +358,7 @@ def is_list_interior(content): | |
|
|
||
| # print(f"mrow: {result}") | ||
|
|
||
| return "<mrow>%s</mrow>" % " ".join(result) | ||
| return "<mrow>\n%s\n</mrow>" % "\n".join(result) | ||
|
|
||
|
|
||
| add_conversion_fn(RowBox, rowbox) | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Recently, RightDoubleBracket and LeftDoubleBracket were tagged as operators. I suspect that these can now be picked up from the character tables.