Update visitor functions and add parsing methods (MMLGen)

Bug: T302628

Change-Id: I5374a831cf74a6eb3bf3165abe3ad0661ec07f5f
This commit is contained in:
Stegmujo 2022-12-23 11:34:16 +00:00
parent a692599224
commit f8e25f5dce
No known key found for this signature in database
GPG key ID: FEFA628F883FAE29
21 changed files with 1871 additions and 259 deletions

View file

@ -17,37 +17,37 @@ class AMSMappings {
private static $instance = null;
private const AMSMACROS = [
"mathring" => [ 'Accent', '02DA' ],
"mathring" => [ 'accent', '02DA' ],
"nobreakspace" => 'Tilde',
"negmedspace" => [ 'Spacer', MathSpace::NEGATIVEMEDIUMMATHSPACE ],
"negthickspace" => [ 'Spacer', MathSpace::NEGATIVETHICKMATHSPACE ],
"negmedspace" => [ 'spacer', MathSpace::NEGATIVEMEDIUMMATHSPACE ],
"negthickspace" => [ 'spacer', MathSpace::NEGATIVETHICKMATHSPACE ],
"idotsint" => [ 'MultiIntegral', '\\int\\cdots\\int' ],
"dddot" => [ 'Accent', '20DB' ],
"ddddot" => [ 'Accent', '20DC' ],
"dddot" => [ 'accent', '20DB' ],
"ddddot" => [ 'accent', '20DC' ],
"sideset" => 'SideSet',
"boxed" => [ 'Macro', '\\fbox{$\\displaystyle{#1}$}', 1 ],
"boxed" => [ 'macro', '\\fbox{$\\displaystyle{#1}$}', 1 ],
"tag" => 'HandleTag',
"notag" => 'HandleNoTag',
"eqref" => [ 'HandleRef', true ],
"substack" => [ 'Macro', '\\begin{subarray}{c}#1\\end{subarray}', 1 ],
"injlim" => [ 'NamedOp', 'inj lim' ],
"projlim" => [ 'NamedOp', 'proj lim' ],
"varliminf" => [ 'Macro', '\\mathop{\\underline{\\mmlToken{mi}{lim}}}' ],
"varlimsup" => [ 'Macro', '\\mathop{\\overline{\\mmlToken{mi}{lim}}}' ],
"substack" => [ 'macro', '\\begin{subarray}{c}#1\\end{subarray}', 1 ],
"injlim" => [ 'namedOp', 'inj lim' ],
"projlim" => [ 'namedOp', 'proj lim' ],
"varliminf" => [ 'macro', '\\mathop{\\underline{\\mmlToken{mi}{lim}}}' ],
"varlimsup" => [ 'macro', '\\mathop{\\overline{\\mmlToken{mi}{lim}}}' ],
// replaced underrightarrow here not supported
"varinjlim" => [ 'Macro', '\\mathop{\\xrightarrow{\\mmlToken{mi}{lim}}}' ],
"varinjlim" => [ 'macro', '\\mathop{\\xrightarrow{\\mmlToken{mi}{lim}}}' ],
// replaced underleftarrow here not supported
"varprojlim" => [ 'Macro', '\\mathop{\\xleftarrow{\\mmlToken{mi}{lim}}}' ],
"varprojlim" => [ 'macro', '\\mathop{\\xleftarrow{\\mmlToken{mi}{lim}}}' ],
"DeclareMathOperator" => 'HandleDeclareOp',
"operatorname" => 'HandleOperatorName',
"genfrac" => 'Genfrac',
"frac" => [ 'Genfrac', '', '', '', '' ],
"tfrac" => [ 'Genfrac', '', '', '', '1' ],
"dfrac" => [ 'Genfrac', '', '', '', '0' ],
"binom" => [ 'Genfrac', '(', ')', '0', '' ],
"tbinom" => [ 'Genfrac', '(', ')', '0', '1' ],
"dbinom" => [ 'Genfrac', '(', ')', '0', '0' ],
"cfrac" => 'CFrac',
"operatorname" => 'handleOperatorName',
"genfrac" => 'genFrac',
"frac" => [ 'genFrac', '', '', '', '' ],
"tfrac" => [ 'genFrac', '', '', '', '1' ],
"dfrac" => [ 'genFrac', '', '', '', '0' ],
"binom" => [ 'genFrac', '(', ')', '0', '' ],
"tbinom" => [ 'genFrac', '(', ')', '0', '1' ],
"dbinom" => [ 'genFrac', '(', ')', '0', '0' ],
"cfrac" => 'cFrac',
"shoveleft" => [ 'HandleShove', Align::LEFT ],
"shoveright" => [ 'HandleShove', Align::RIGHT ],
"xrightarrow" => [ 'xArrow', 0x2192, 5, 10 ],
@ -309,26 +309,26 @@ class AMSMappings {
"split" => [ 'EqnArray', null, false, false, 'rl', "ParseUtil_js_1.default.cols(0)" ],
"gather" => [ 'EqnArray', null, true, true, 'c' ],
'gather*' => [ 'EqnArray', null, false, true, 'c' ],
"alignat" => [ 'AlignAt', null, true, true ],
'alignat*' => [ 'AlignAt', null, false, true ],
"alignedat" => [ 'AlignAt', null, false, false ],
"aligned" => [ 'AmsEqnArray', null, null, null, 'rl', "ParseUtil_js_1.default.cols(0, 2)", '.5em', 'D' ],
"gathered" => [ 'AmsEqnArray', null, null, null, 'c', null, '.5em', 'D' ],
"alignat" => [ 'alignAt', null, true, true ],
'alignat*' => [ 'alignAt', null, false, true ],
"alignedat" => [ 'alignAt', null, false, false ],
"aligned" => [ 'amsEqnArray', null, null, null, 'rl', "ParseUtil_js_1.default.cols(0, 2)", '.5em', 'D' ],
"gathered" => [ 'amsEqnArray', null, null, null, 'c', null, '.5em', 'D' ],
"xalignat" => [ 'XalignAt', null, true, true ],
'xalignat*' => [ 'XalignAt', null, false, true ],
"xxalignat" => [ 'XalignAt', null, false, false ],
"flalign" => [ 'FlalignArray', null, true, false, true, 'rlc', 'auto auto fit' ],
'flalign*' => [ 'FlalignArray', null, false, false, true, 'rlc', 'auto auto fit' ],
"subarray" => [ 'Array', null, null, null, null, "ParseUtil_js_1.default.cols(0)", '0.1em', 'S', 1 ],
"smallmatrix" => [ 'Array', null, null, null, 'c', "ParseUtil_js_1.default.cols(1 / 3)",
"subarray" => [ 'array', null, null, null, null, "ParseUtil_js_1.default.cols(0)", '0.1em', 'S', 1 ],
"smallmatrix" => [ 'array', null, null, null, 'c', "ParseUtil_js_1.default.cols(1 / 3)",
'.2em', 'S', 1 ],
"matrix" => [ 'Array', null, null, null, 'c' ],
"pmatrix" => [ 'Array', null, '(', ')', 'c' ],
"bmatrix" => [ 'Array', null, '[', ']', 'c' ],
"Bmatrix" => [ 'Array', null, '\\{', '\\}', 'c' ],
"vmatrix" => [ 'Array', null, '\\vert', '\\vert', 'c' ],
"Vmatrix" => [ 'Array', null, '\\Vert', '\\Vert', 'c' ],
"cases" => [ 'Array', null, '\\{', '.', 'll', null, '.2em', 'T' ]
"matrix" => [ 'array', null, null, null, 'c' ],
"pmatrix" => [ 'array', null, '(', ')', 'c' ],
"bmatrix" => [ 'array', null, '[', ']', 'c' ],
"Bmatrix" => [ 'array', null, '\\{', '\\}', 'c' ],
"vmatrix" => [ 'array', null, '\\vert', '\\vert', 'c' ],
"Vmatrix" => [ 'array', null, '\\Vert', '\\Vert', 'c' ],
"cases" => [ 'array', null, '\\{', '.', 'll', null, '.2em', 'T' ]
];
private const AMSSYMBOLDELIMITERS = [
'ulcorner' => '\u231C',
@ -338,8 +338,8 @@ class AMSMappings {
];
private const AMSSYMBOLMACROS = [
"implies" => [ 'Macro', '\\;\\Longrightarrow\\;' ],
"impliedby" => [ 'Macro', '\\;\\Longleftarrow\\;' ]
"implies" => [ 'macro', '\\;\\Longrightarrow\\;' ],
"impliedby" => [ 'macro', '\\;\\Longleftarrow\\;' ]
];
private const AMSMATHDELIMITERS = [

View file

@ -323,72 +323,72 @@ class BaseMappings {
];
private const MACROS = [
"displaystyle" => [ 'SetStyle', 'D', true, 0 ],
"textstyle" => [ 'SetStyle', 'T', false, 0 ],
"scriptstyle" => [ 'SetStyle', 'S', false, 1 ],
"scriptscriptstyle" => [ 'SetStyle', 'SS', false, 2 ],
"rm" => [ 'SetFont', Variants::NORMAL ],
"mit" => [ 'SetFont', Variants::ITALIC ],
"oldstyle" => [ 'SetFont', Variants::OLDSTYLE ],
"cal" => [ 'SetFont', Variants::CALLIGRAPHIC ],
"it" => [ 'SetFont', Variants::MATHITALIC ],
"bf" => [ 'SetFont', Variants::BOLD ],
"bbFont" => [ 'SetFont', Variants::DOUBLESTRUCK ],
"scr" => [ 'SetFont', Variants::SCRIPT ],
"frak" => [ 'SetFont', Variants::FRAKTUR ],
"sf" => [ 'SetFont', Variants::SANSSERIF ],
"tt" => [ 'SetFont', Variants::MONOSPACE ],
"mathrm" => [ 'MathFont', Variants::NORMAL ],
"mathup" => [ 'MathFont', Variants::NORMAL ],
"mathnormal" => [ 'MathFont', '' ],
"mathbf" => [ 'MathFont', Variants::BOLD ],
"mathbfup" => [ 'MathFont', Variants::BOLD ],
"mathit" => [ 'MathFont', Variants::MATHITALIC ],
"mathbfit" => [ 'MathFont', Variants::BOLDITALIC ],
"mathbb" => [ 'MathFont', Variants::DOUBLESTRUCK ],
"Bbb" => [ 'MathFont', Variants::DOUBLESTRUCK ],
"mathfrak" => [ 'MathFont', Variants::FRAKTUR ],
"mathbffrak" => [ 'MathFont', Variants::BOLDFRAKTUR ],
"mathscr" => [ 'MathFont', Variants::SCRIPT ],
"mathbfscr" => [ 'MathFont', Variants::BOLDSCRIPT ],
"mathsf" => [ 'MathFont', Variants::SANSSERIF ],
"mathsfup" => [ 'MathFont', Variants::SANSSERIF ],
"mathbfsf" => [ 'MathFont', Variants::BOLDSANSSERIF ],
"mathbfsfup" => [ 'MathFont', Variants::BOLDSANSSERIF ],
"mathsfit" => [ 'MathFont', Variants::SANSSERIFITALIC ],
"mathbfsfit" => [ 'MathFont', Variants::SANSSERIFBOLDITALIC ],
"mathtt" => [ 'MathFont', Variants::MONOSPACE ],
"mathcal" => [ 'MathFont', Variants::CALLIGRAPHIC ],
"mathbfcal" => [ 'MathFont', Variants::BOLDCALLIGRAPHIC ],
"emph" => [ 'MathFont', Variants::ITALIC ], // added this specific case, toggles roman/italic fonts
"symrm" => [ 'MathFont', Variants::NORMAL ],
"symup" => [ 'MathFont', Variants::NORMAL ],
"symnormal" => [ 'MathFont', '' ],
"symbf" => [ 'MathFont', Variants::BOLD ],
"symbfup" => [ 'MathFont', Variants::BOLD ],
"symit" => [ 'MathFont', Variants::ITALIC ],
"symbfit" => [ 'MathFont', Variants::BOLDITALIC ],
"symbb" => [ 'MathFont', Variants::DOUBLESTRUCK ],
"symfrak" => [ 'MathFont', Variants::FRAKTUR ],
"symbffrak" => [ 'MathFont', Variants::BOLDFRAKTUR ],
"symscr" => [ 'MathFont', Variants::SCRIPT ],
"symbfscr" => [ 'MathFont', Variants::BOLDSCRIPT ],
"symsf" => [ 'MathFont', Variants::SANSSERIF ],
"symsfup" => [ 'MathFont', Variants::SANSSERIF ],
"symbfsf" => [ 'MathFont', Variants::BOLDSANSSERIF ],
"symbfsfup" => [ 'MathFont', Variants::BOLDSANSSERIF ],
"symsfit" => [ 'MathFont', Variants::SANSSERIFITALIC ],
"symbfsfit" => [ 'MathFont', Variants::SANSSERIFBOLDITALIC ],
"symtt" => [ 'MathFont', Variants::MONOSPACE ],
"symcal" => [ 'MathFont', Variants::CALLIGRAPHIC ],
"symbfcal" => [ 'MathFont', Variants::BOLDCALLIGRAPHIC ],
"textrm" => [ 'HBox', null, Variants::NORMAL ],
"textup" => [ 'HBox', null, Variants::NORMAL ],
"textnormal" => [ 'HBox' ],
"textit" => [ 'HBox', null, Variants::ITALIC ],
"textbf" => [ 'HBox', null, Variants::BOLD ],
"textsf" => [ 'HBox', null, Variants::SANSSERIF ],
"texttt" => [ 'HBox', null, Variants::MONOSPACE ],
"displaystyle" => [ 'setStyle', 'D', true, 0 ],
"textstyle" => [ 'setStyle', 'T', false, 0 ],
"scriptstyle" => [ 'setStyle', 'S', false, 1 ],
"scriptscriptstyle" => [ 'setStyle', 'SS', false, 2 ],
"rm" => [ 'setFont', Variants::NORMAL ],
"mit" => [ 'setFont', Variants::ITALIC ],
"oldstyle" => [ 'setFont', Variants::OLDSTYLE ],
"cal" => [ 'setFont', Variants::CALLIGRAPHIC ],
"it" => [ 'setFont', Variants::MATHITALIC ],
"bf" => [ 'setFont', Variants::BOLD ],
"bbFont" => [ 'setFont', Variants::DOUBLESTRUCK ],
"scr" => [ 'setFont', Variants::SCRIPT ],
"frak" => [ 'setFont', Variants::FRAKTUR ],
"sf" => [ 'setFont', Variants::SANSSERIF ],
"tt" => [ 'setFont', Variants::MONOSPACE ],
"mathrm" => [ 'mathFont', Variants::NORMAL ],
"mathup" => [ 'mathFont', Variants::NORMAL ],
"mathnormal" => [ 'mathFont', '' ],
"mathbf" => [ 'mathFont', Variants::BOLD ],
"mathbfup" => [ 'mathFont', Variants::BOLD ],
"mathit" => [ 'mathFont', Variants::MATHITALIC ],
"mathbfit" => [ 'mathFont', Variants::BOLDITALIC ],
"mathbb" => [ 'mathFont', Variants::DOUBLESTRUCK ],
"Bbb" => [ 'mathFont', Variants::DOUBLESTRUCK ],
"mathfrak" => [ 'mathFont', Variants::FRAKTUR ],
"mathbffrak" => [ 'mathFont', Variants::BOLDFRAKTUR ],
"mathscr" => [ 'mathFont', Variants::SCRIPT ],
"mathbfscr" => [ 'mathFont', Variants::BOLDSCRIPT ],
"mathsf" => [ 'mathFont', Variants::SANSSERIF ],
"mathsfup" => [ 'mathFont', Variants::SANSSERIF ],
"mathbfsf" => [ 'mathFont', Variants::BOLDSANSSERIF ],
"mathbfsfup" => [ 'mathFont', Variants::BOLDSANSSERIF ],
"mathsfit" => [ 'mathFont', Variants::SANSSERIFITALIC ],
"mathbfsfit" => [ 'mathFont', Variants::SANSSERIFBOLDITALIC ],
"mathtt" => [ 'mathFont', Variants::MONOSPACE ],
"mathcal" => [ 'mathFont', Variants::CALLIGRAPHIC ],
"mathbfcal" => [ 'mathFont', Variants::BOLDCALLIGRAPHIC ],
"emph" => [ 'mathFont', Variants::ITALIC ], // added this specific case, toggles roman/italic fonts
"symrm" => [ 'mathFont', Variants::NORMAL ],
"symup" => [ 'mathFont', Variants::NORMAL ],
"symnormal" => [ 'mathFont', '' ],
"symbf" => [ 'mathFont', Variants::BOLD ],
"symbfup" => [ 'mathFont', Variants::BOLD ],
"symit" => [ 'mathFont', Variants::ITALIC ],
"symbfit" => [ 'mathFont', Variants::BOLDITALIC ],
"symbb" => [ 'mathFont', Variants::DOUBLESTRUCK ],
"symfrak" => [ 'mathFont', Variants::FRAKTUR ],
"symbffrak" => [ 'mathFont', Variants::BOLDFRAKTUR ],
"symscr" => [ 'mathFont', Variants::SCRIPT ],
"symbfscr" => [ 'mathFont', Variants::BOLDSCRIPT ],
"symsf" => [ 'mathFont', Variants::SANSSERIF ],
"symsfup" => [ 'mathFont', Variants::SANSSERIF ],
"symbfsf" => [ 'mathFont', Variants::BOLDSANSSERIF ],
"symbfsfup" => [ 'mathFont', Variants::BOLDSANSSERIF ],
"symsfit" => [ 'mathFont', Variants::SANSSERIFITALIC ],
"symbfsfit" => [ 'mathFont', Variants::SANSSERIFBOLDITALIC ],
"symtt" => [ 'mathFont', Variants::MONOSPACE ],
"symcal" => [ 'mathFont', Variants::CALLIGRAPHIC ],
"symbfcal" => [ 'mathFont', Variants::BOLDCALLIGRAPHIC ],
"textrm" => [ 'hBox', null, Variants::NORMAL ],
"textup" => [ 'hBox', null, Variants::NORMAL ],
"textnormal" => [ 'hBox' ],
"textit" => [ 'hBox', null, Variants::ITALIC ],
"textbf" => [ 'hBox', null, Variants::BOLD ],
"textsf" => [ 'hBox', null, Variants::SANSSERIF ],
"texttt" => [ 'hBox', null, Variants::MONOSPACE ],
"tiny" => [ 'SetSize', 0.5 ],
"Tiny" => [ 'SetSize', 0.6 ],
"scriptsize" => [ 'SetSize', 0.7 ],
@ -399,68 +399,68 @@ class BaseMappings {
"LARGE" => [ 'SetSize', 1.73 ],
"huge" => [ 'SetSize', 2.07 ],
"Huge" => [ 'SetSize', 2.49 ],
"arcsin" => 'NamedFn',
"arccos" => 'NamedFn',
"arctan" => 'NamedFn',
"arg" => 'NamedFn',
"cos" => 'NamedFn',
"cosh" => 'NamedFn',
"cot" => 'NamedFn',
"coth" => 'NamedFn',
"csc" => 'NamedFn',
"deg" => 'NamedFn',
"det" => 'NamedOp',
"dim" => 'NamedFn',
"exp" => 'NamedFn',
"gcd" => 'NamedOp',
"hom" => 'NamedFn',
"inf" => 'NamedOp',
"ker" => 'NamedFn',
"lg" => 'NamedFn',
"lim" => 'NamedOp',
"liminf" => [ 'NamedOp', 'lim inf' ],
"limsup" => [ 'NamedOp', 'lim sup' ],
"ln" => 'NamedFn',
"log" => 'NamedFn',
"max" => 'NamedOp',
"min" => 'NamedOp',
"Pr" => 'NamedOp',
"sec" => 'NamedFn',
"sin" => 'NamedFn',
"sinh" => 'NamedFn',
"sup" => 'NamedOp',
"tan" => 'NamedFn',
"tanh" => 'NamedFn',
"limits" => [ 'Limits', 1 ],
"nolimits" => [ 'Limits', 0 ],
"overline" => [ 'UnderOver', '2015' ],
"underline" => [ 'UnderOver', '2015' ],
"overbrace" => [ 'UnderOver', '23DE', 1 ],
"underbrace" => [ 'UnderOver', '23DF', 1 ],
"overparen" => [ 'UnderOver', '23DC' ],
"underparen" => [ 'UnderOver', '23DD' ],
"overrightarrow" => [ 'UnderOver', '2192' ],
"underrightarrow" => [ 'UnderOver', '2192' ],
"overleftarrow" => [ 'UnderOver', '2190' ],
"underleftarrow" => [ 'UnderOver', '2190' ],
"overleftrightarrow" => [ 'UnderOver', '2194' ],
"underleftrightarrow" => [ 'UnderOver', '2194' ],
"overset" => 'Overset',
"underset" => 'Underset',
"arcsin" => 'namedFn',
"arccos" => 'namedFn',
"arctan" => 'namedFn',
"arg" => 'namedFn',
"cos" => 'namedFn',
"cosh" => 'namedFn',
"cot" => 'namedFn',
"coth" => 'namedFn',
"csc" => 'namedFn',
"deg" => 'namedFn',
"det" => 'namedOp',
"dim" => 'namedFn',
"exp" => 'namedFn',
"gcd" => 'namedOp',
"hom" => 'namedFn',
"inf" => 'namedOp',
"ker" => 'namedFn',
"lg" => 'namedFn',
"lim" => 'namedOp',
"liminf" => [ 'namedOp', 'lim inf' ],
"limsup" => [ 'namedOp', 'lim sup' ],
"ln" => 'namedFn',
"log" => 'namedFn',
"max" => 'namedOp',
"min" => 'namedOp',
"Pr" => 'namedOp',
"sec" => 'namedFn',
"sin" => 'namedFn',
"sinh" => 'namedFn',
"sup" => 'namedOp',
"tan" => 'namedFn',
"tanh" => 'namedFn',
"limits" => [ 'limits', 1 ],
"nolimits" => [ 'limits', 0 ],
"overline" => [ 'underOver', '2015' ],
"underline" => [ 'underOver', '2015' ],
"overbrace" => [ 'underOver', '23DE', 1 ],
"underbrace" => [ 'underOver', '23DF', 1 ],
"overparen" => [ 'underOver', '23DC' ],
"underparen" => [ 'underOver', '23DD' ],
"overrightarrow" => [ 'underOver', '2192' ],
"underrightarrow" => [ 'underOver', '2192' ],
"overleftarrow" => [ 'underOver', '2190' ],
"underleftarrow" => [ 'underOver', '2190' ],
"overleftrightarrow" => [ 'underOver', '2194' ],
"underleftrightarrow" => [ 'underOver', '2194' ],
"overset" => 'overset',
"underset" => 'underset',
"overunderset" => 'Overunderset',
"stackrel" => [ 'Macro', '\\mathrel{\\mathop{#2}\\limits^{#1}}', 2 ],
"stackbin" => [ 'Macro', '\\mathbin{\\mathop{#2}\\limits^{#1}}', 2 ],
"over" => 'Over',
"overwithdelims" => 'Over',
"atop" => 'Over',
"atopwithdelims" => 'Over',
"above" => 'Over',
"abovewithdelims" => 'Over',
"brace" => [ 'Over', '{', '}' ],
"brack" => [ 'Over', '[', ']' ],
"choose" => [ 'Over', '(', ')' ],
"frac" => 'Frac',
"sqrt" => 'Sqrt',
"stackrel" => [ 'macro', '\\mathrel{\\mathop{#2}\\limits^{#1}}', 2 ],
"stackbin" => [ 'macro', '\\mathbin{\\mathop{#2}\\limits^{#1}}', 2 ],
"over" => 'over',
"overwithdelims" => 'over',
"atop" => 'over',
"atopwithdelims" => 'over',
"above" => 'over',
"abovewithdelims" => 'over',
"brace" => [ 'over', '{', '}' ],
"brack" => [ 'over', '[', ']' ],
"choose" => [ 'over', '(', ')' ],
"frac" => 'frac',
"sqrt" => 'sqrt',
"root" => 'Root',
"uproot" => [ 'MoveRoot', 'upRoot' ],
"leftroot" => [ 'MoveRoot', 'leftRoot' ],
@ -473,16 +473,16 @@ class BaseMappings {
"lower" => 'RaiseLower',
"moveleft" => 'MoveLeftRight',
"moveright" => 'MoveLeftRight',
',' => [ 'Spacer', MathSpace::THINMATHSPACE ],
"'" => [ 'Spacer', MathSpace::MEDIUMMATHSPACE ],
'>' => [ 'Spacer', MathSpace::MEDIUMMATHSPACE ],
';' => [ 'Spacer', MathSpace::THICKMATHSPACE ],
'!' => [ 'Spacer', MathSpace::NEGATIVETHINMATHSPACE ],
"enspace" => [ 'Spacer', 0.5 ],
"quad" => [ 'Spacer', 1 ],
"qquad" => [ 'Spacer', 2 ],
"thinspace" => [ 'Spacer', MathSpace::THINMATHSPACE ],
"negthinspace" => [ 'Spacer', MathSpace::NEGATIVETHINMATHSPACE ],
',' => [ 'spacer', MathSpace::THINMATHSPACE ],
"'" => [ 'spacer', MathSpace::MEDIUMMATHSPACE ],
'>' => [ 'spacer', MathSpace::MEDIUMMATHSPACE ],
';' => [ 'spacer', MathSpace::THICKMATHSPACE ],
'!' => [ 'spacer', MathSpace::NEGATIVETHINMATHSPACE ],
"enspace" => [ 'spacer', 0.5 ],
"quad" => [ 'spacer', 1 ],
"qquad" => [ 'spacer', 2 ],
"thinspace" => [ 'spacer', MathSpace::THINMATHSPACE ],
"negthinspace" => [ 'spacer', MathSpace::NEGATIVETHINMATHSPACE ],
"hskip" => 'Hskip',
"hspace" => 'Hskip',
"kern" => 'Hskip',
@ -493,22 +493,22 @@ class BaseMappings {
"Rule" => [ 'Rule' ],
"Space" => [ 'Rule', 'blank' ],
"nonscript" => 'Nonscript',
"big" => [ 'MakeBig', TexClass::ORD, 0.85 ],
"Big" => [ 'MakeBig', TexClass::ORD, 1.15 ],
"bigg" => [ 'MakeBig', TexClass::ORD, 1.45 ],
"Bigg" => [ 'MakeBig', TexClass::ORD, 1.75 ],
"bigl" => [ 'MakeBig', TexClass::OPEN, 0.85 ],
"Bigl" => [ 'MakeBig', TexClass::OPEN, 1.15 ],
"biggl" => [ 'MakeBig', TexClass::OPEN, 1.45 ],
"Biggl" => [ 'MakeBig', TexClass::OPEN, 1.75 ],
"bigr" => [ 'MakeBig', TexClass::CLOSE, 0.85 ],
"Bigr" => [ 'MakeBig', TexClass::CLOSE, 1.15 ],
"biggr" => [ 'MakeBig', TexClass::CLOSE, 1.45 ],
"Biggr" => [ 'MakeBig', TexClass::CLOSE, 1.75 ],
"bigm" => [ 'MakeBig', TexClass::REL, 0.85 ],
"Bigm" => [ 'MakeBig', TexClass::REL, 1.15 ],
"biggm" => [ 'MakeBig', TexClass::REL, 1.45 ],
"Biggm" => [ 'MakeBig', TexClass::REL, 1.75 ],
"big" => [ 'makeBig', TexClass::ORD, 0.85 ],
"Big" => [ 'makeBig', TexClass::ORD, 1.15 ],
"bigg" => [ 'makeBig', TexClass::ORD, 1.45 ],
"Bigg" => [ 'makeBig', TexClass::ORD, 1.75 ],
"bigl" => [ 'makeBig', TexClass::OPEN, 0.85 ],
"Bigl" => [ 'makeBig', TexClass::OPEN, 1.15 ],
"biggl" => [ 'makeBig', TexClass::OPEN, 1.45 ],
"Biggl" => [ 'makeBig', TexClass::OPEN, 1.75 ],
"bigr" => [ 'makeBig', TexClass::CLOSE, 0.85 ],
"Bigr" => [ 'makeBig', TexClass::CLOSE, 1.15 ],
"biggr" => [ 'makeBig', TexClass::CLOSE, 1.45 ],
"Biggr" => [ 'makeBig', TexClass::CLOSE, 1.75 ],
"bigm" => [ 'makeBig', TexClass::REL, 0.85 ],
"Bigm" => [ 'makeBig', TexClass::REL, 1.15 ],
"biggm" => [ 'makeBig', TexClass::REL, 1.45 ],
"Biggm" => [ 'makeBig', TexClass::REL, 1.75 ],
"mathord" => [ 'TeXAtom', TexClass::ORD ],
"mathop" => [ 'TeXAtom', TexClass::OP ],
"mathopen" => [ 'TeXAtom', TexClass::OPEN ],
@ -519,70 +519,70 @@ class BaseMappings {
"mathinner" => [ 'TeXAtom', TexClass::INNER ],
"vcenter" => [ 'TeXAtom', TexClass::VCENTER ],
"buildrel" => 'BuildRel',
"hbox" => [ 'HBox', 0 ],
"text" => 'HBox',
"mbox" => [ 'HBox', 0 ],
"vbox" => [ 'VBox', 0 ], // added this here in addition
"hbox" => [ 'hBox', 0 ],
"text" => 'hBox',
"mbox" => [ 'hBox', 0 ],
"vbox" => [ 'vbox', 0 ], // added this here in addition
"fbox" => 'FBox',
"boxed" => [ 'Macro', '\\fbox{$\\displaystyle{#1}$}', 1 ],
"boxed" => [ 'macro', '\\fbox{$\\displaystyle{#1}$}', 1 ],
"framebox" => 'FrameBox',
"strut" => 'Strut',
"mathstrut" => [ 'Macro', '\\vphantom{(}' ],
"phantom" => 'Phantom',
"vphantom" => [ 'Phantom', 1, 0 ],
"hphantom" => [ 'Phantom', 0, 1 ],
"mathstrut" => [ 'macro', '\\vphantom{(}' ],
"phantom" => 'phantom',
"vphantom" => [ 'phantom', 1, 0 ],
"hphantom" => [ 'phantom', 0, 1 ],
"smash" => 'Smash',
"acute" => [ 'Accent', '00B4' ],
"grave" => [ 'Accent', '0060' ],
"ddot" => [ 'Accent', '00A8' ],
"tilde" => [ 'Accent', '007E' ],
"bar" => [ 'Accent', '00AF' ],
"breve" => [ 'Accent', '02D8' ],
"check" => [ 'Accent', '02C7' ],
"hat" => [ 'Accent', '005E' ],
"vec" => [ 'Accent', '2192' ],
"dot" => [ 'Accent', '02D9' ],
"widetilde" => [ 'Accent', '007E', 1 ],
"widehat" => [ 'Accent', '005E', 1 ],
"matrix" => 'Matrix',
"array" => 'Matrix',
"pmatrix" => [ 'Matrix', '(', ')' ],
"cases" => [ 'Matrix', '{', '', 'left left', null, '.1em', null,
"acute" => [ 'accent', '00B4' ],
"grave" => [ 'accent', '0060' ],
"ddot" => [ 'accent', '00A8' ],
"tilde" => [ 'accent', '007E' ],
"bar" => [ 'accent', '00AF' ],
"breve" => [ 'accent', '02D8' ],
"check" => [ 'accent', '02C7' ],
"hat" => [ 'accent', '005E' ],
"vec" => [ 'accent', '2192' ],
"dot" => [ 'accent', '02D9' ],
"widetilde" => [ 'accent', '007E', 1 ],
"widehat" => [ 'accent', '005E', 1 ],
"matrix" => 'matrix',
"array" => 'matrix',
"pmatrix" => [ 'matrix', '(', ')' ],
"cases" => [ 'matrix', '{', '', 'left left', null, '.1em', null,
true ],
"eqalign" => [ 'Matrix', null, null, 'right left',
"eqalign" => [ 'matrix', null, null, 'right left',
"(0, lengths_js_1.em)(MathSpace::thickmathspace)", '.5em', 'D' ],
"displaylines" => [ 'Matrix', null, null, 'center', null, '.5em', 'D' ],
"displaylines" => [ 'matrix', null, null, 'center', null, '.5em', 'D' ],
"cr" => 'Cr',
'\\' => 'CrLaTeX',
"newline" => [ 'CrLaTeX', true ],
"hline" => [ 'HLine', 'solid' ],
"hdashline" => [ 'HLine', 'dashed' ],
"eqalignno" => [ 'Matrix', null, null, 'right left',
"hline" => [ 'hline', 'solid' ],
"hdashline" => [ 'hline', 'dashed' ],
"eqalignno" => [ 'matrix', null, null, 'right left',
"(0, lengths_js_1.em)(MathSpace::thickmathspace)", '.5em', 'D', null,
'right' ],
"leqalignno" => [ 'Matrix', null, null, 'right left',
"leqalignno" => [ 'matrix', null, null, 'right left',
"(0, lengths_js_1.em)(MathSpace::thickmathspace)", '.5em', 'D', null,
'left' ],
"hfill" => 'HFill',
"hfil" => 'HFill',
"hfilll" => 'HFill',
"bmod" => [ 'Macro', '\\mmlToken{mo}[lspace="thickmathspace"' .
"bmod" => [ 'macro', '\\mmlToken{mo}[lspace="thickmathspace"' .
' rspace="thickmathspace"]{mod}' ],
"pmod" => [ 'Macro', '\\pod{\\mmlToken{mi}{mod}\\kern 6mu #1}', 1 ],
"mod" => [ 'Macro', '\\mathchoice{\\kern18mu}{\\kern12mu}' .
"pmod" => [ 'macro', '\\pod{\\mmlToken{mi}{mod}\\kern 6mu #1}', 1 ],
"mod" => [ 'macro', '\\mathchoice{\\kern18mu}{\\kern12mu}' .
'{\\kern12mu}{\\kern12mu}\\mmlToken{mi}{mod}\\,\\,#1',
1 ],
"pod" => [ 'Macro', '\\mathchoice{\\kern18mu}{\\kern8mu}' .
"pod" => [ 'macro', '\\mathchoice{\\kern18mu}{\\kern8mu}' .
'{\\kern8mu}{\\kern8mu}(#1)', 1 ],
"iff" => [ 'Macro', '\\;\\Longleftrightarrow\\;' ],
"skew" => [ 'Macro', '{{#2{#3\\mkern#1mu}\\mkern-#1mu}{}}', 3 ],
"pmb" => [ 'Macro', '\\rlap{#1}\\kern1px{#1}', 1 ],
"TeX" => [ 'Macro', 'T\\kern-.14em\\lower.5ex{E}\\kern-.115em X' ],
"LaTeX" => [ 'Macro', 'L\\kern-.325em\\raise.21em' .
"iff" => [ 'macro', '\\;\\Longleftrightarrow\\;' ],
"skew" => [ 'macro', '{{#2{#3\\mkern#1mu}\\mkern-#1mu}{}}', 3 ],
"pmb" => [ 'macro', '\\rlap{#1}\\kern1px{#1}', 1 ],
"TeX" => [ 'macro', 'T\\kern-.14em\\lower.5ex{E}\\kern-.115em X' ],
"LaTeX" => [ 'macro', 'L\\kern-.325em\\raise.21em' .
'{\\scriptstyle{A}}\\kern-.17em\\TeX' ],
' ' => [ 'Macro', '\\text{ }' ],
"not" => 'Not',
"dots" => 'Dots',
' ' => [ 'macro', '\\text{ }' ],
"not" => 'not',
"dots" => 'dots',
"space" => 'Tilde',
'\u00A0' => 'Tilde',
"begin" => 'BeginEnd',
@ -603,9 +603,9 @@ class BaseMappings {
// Mathtools environment actually from Mathtools mappings tbd refactor
private const ENVIRONMNENTMT = [
'dcases' => [ 'Array', null, '\\{', '', 'll', null, '.2em', 'D' ],
'rcases' => [ 'Array', null, '', '\\}', 'll', null, '.2em' ],
'drcases' => [ 'Array', null, '', '\\}', 'll', null, '.2em', 'D' ],
'dcases' => [ 'array', null, '\\{', '', 'll', null, '.2em', 'D' ],
'rcases' => [ 'array', null, '', '\\}', 'll', null, '.2em' ],
'drcases' => [ 'array', null, '', '\\}', 'll', null, '.2em', 'D' ],
'dcases*' => [ 'Cases', null, '{', '', 'D' ],
'rcases*' => [ 'Cases', null, '', '}' ],
'drcases*' => [ 'Cases', null, '', '}', 'D' ],
@ -627,11 +627,11 @@ class BaseMappings {
'vsmallmatrix*' => [ 'MtSmallMatrix', null, '\\vert', '\\vert' ],
'Vsmallmatrix' => [ 'MtSmallMatrix', null, '\\Vert', '\\Vert', 'c' ],
'Vsmallmatrix*' => [ 'MtSmallMatrix', null, '\\Vert', '\\Vert' ],
'crampedsubarray' => [ 'Array', null, null, null, null, '0em', '0.1em', 'S\'', 1 ],
'crampedsubarray' => [ 'array', null, null, null, null, '0em', '0.1em', 'S\'', 1 ],
'multlined' => 'MtMultlined',
'spreadlines' => [ 'SpreadLines', true ],
'lgathered' => [ 'AmsEqnArray', null, null, null, 'l', null, '.5em', 'D' ],
'rgathered' => [ 'AmsEqnArray', null, null, null, 'r', null, '.5em', 'D' ],
'lgathered' => [ 'amsEqnArray', null, null, null, 'l', null, '.5em', 'D' ],
'rgathered' => [ 'amsEqnArray', null, null, null, 'r', null, '.5em', 'D' ],
];
private const COLORS = [
@ -705,37 +705,37 @@ class BaseMappings {
'YellowOrange' => '#FAA21A',
];
// This is from CancelConfiguration.js
// This is from cancelConfiguration.js
private const CANCEL = [
"cancel" => [ 'Cancel', Notation::UPDIAGONALSTRIKE ],
"bcancel" => [ 'Cancel', Notation::DOWNDIAGONALSTRIKE ],
"xcancel" => [ 'Cancel', Notation::UPDIAGONALSTRIKE . ' ' .
"cancel" => [ 'cancel', Notation::UPDIAGONALSTRIKE ],
"bcancel" => [ 'cancel', Notation::DOWNDIAGONALSTRIKE ],
"xcancel" => [ 'cancel', Notation::UPDIAGONALSTRIKE . ' ' .
Notation::DOWNDIAGONALSTRIKE ],
"cancelto" => [ 'CancelTo', Notation::UPDIAGONALSTRIKE . " " . Notation::UPDIAGONALARROW .
"cancelto" => [ 'cancelTo', Notation::UPDIAGONALSTRIKE . " " . Notation::UPDIAGONALARROW .
" " . Notation::NORTHEASTARROW ]
];
// They are currently from mhchemConfiguration.js
private const MHCHEM = [
"ce" => [ 'Machine', 'ce' ],
"pu" => [ 'Machine', 'pu' ],
"ce" => [ 'machine', 'ce' ],
"pu" => [ 'machine', 'pu' ],
"longrightleftharpoons" => [
'Macro',
'macro',
'\\stackrel{\\textstyle{-}\\!\\!{\\rightharpoonup}}{\\smash{{\\leftharpoondown}\\!\\!{-}}}'
],
"longRightleftharpoons" => [
'Macro',
'macro',
'\\stackrel{\\textstyle{-}\\!\\!{\\rightharpoonup}}{\\smash{\\leftharpoondown}}'
],
"longLeftrightharpoons" => [
'Macro',
'macro',
'\\stackrel{\\textstyle\\vphantom{{-}}{\\rightharpoonup}}{\\smash{{\\leftharpoondown}\\!\\!{-}}}'
],
"longleftrightarrows" => [
'Macro',
'macro',
'\\stackrel{\\longrightarrow}{\\smash{\\longleftarrow}\\Rule{0px}{.25em}{0px}}'
],
"tripledash" => [
'Macro',
'macro',
'\\vphantom{-}\\raise2mu{\\kern2mu\\tiny\\text{-}\\kern1mu\\text{-}\\kern1mu\\text{-}\\kern2mu}'
],
"xleftrightarrow" => [ 'xArrow', 0x2194, 6, 6 ],
@ -743,17 +743,17 @@ class BaseMappings {
"xRightleftharpoons" => [ 'xArrow', 0x21CC, 5, 7 ],
"xLeftrightharpoons" => [ 'xArrow', 0x21CC, 5, 7 ],
"bond" => [ "ChemCustom", "\\bond" ],
"bond" => [ "chemCustom", "\\bond" ],
];
// These are some mappings which are created customly for this
private const CUSTOM = [
"boldsymbol" => [ 'Boldsymbol','' ], // see BoldsymbolConfiguration.js
"oiint" => [ 'Oint', '\u222F', [ "texClass" => TexClass::OP ] ],
"oiiint" => [ 'Oint', '\u2230', [ "texClass" => TexClass::OP ] ],
"ointctrclockwise" => [ 'Oint', '?', [ "texClass" => TexClass::OP ] ],
"boldsymbol" => [ 'boldsymbol','' ], // see boldsymbolConfiguration.js
"oiint" => [ 'oint', '\u222F', [ "texClass" => TexClass::OP ] ],
"oiiint" => [ 'oint', '\u2230', [ "texClass" => TexClass::OP ] ],
"ointctrclockwise" => [ 'oint', '?', [ "texClass" => TexClass::OP ] ],
// \varointclockwise
"varointclockwise" => [ 'Oint', '?', [ "texClass" => TexClass::OP ] ],
"P" => [ 'Oint', '?', [ "texClass" => TexClass::OP ] ], // not correct but same mapping
"varointclockwise" => [ 'oint', '?', [ "texClass" => TexClass::OP ] ],
"P" => [ 'oint', '?', [ "texClass" => TexClass::OP ] ], // not correct but same mapping
'textvisiblespace' => [ 'Insert', '\u2423' ], // From TextCompMappings.js (only makro it seems)
];

View file

@ -0,0 +1,256 @@
<?php
namespace MediaWiki\Extension\Math\TexVC\MMLmappings;
use ArgumentCountError;
use MediaWiki\Extension\Math\TexVC\MMLmappings\TexConstants\Variants;
use MediaWiki\Extension\Math\TexVC\MMLmappings\Util\MMLutil;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmi;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmo;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmrow;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmspace;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmstyle;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmtext;
/**
* This contains the basic parsing methods for tex elements, which get invoked
* to check if there is a specific parsing function defined in the mappings
* and then forward to the parsing function.
*
* Much of this is WIP since there are many cases.
* @author Johannes Stegmüller
*/
class BaseMethods {
public function checkAndParse( $input, $node, $passedArgs, $operatorContent ) {
if ( !is_string( $input ) ) {
// just discard these elements, sometimes empty TexArray
return null;
}
$input = trim( $input );
if ( str_starts_with( $input, "\\" ) ) {
$input = substr( $input, 1 );
}
// Checking for a named parsing function
$resFct = BaseMappings::getMacroByKey( $input );
if ( $resFct == null ) {
$resFct = AMSMappings::getMacroByKey( $input );
if ( $resFct == null ) {
// Also check for mathtools environment, this is currently done to find some form of matrices,
// probably refactored later
$resFct = AMSMappings::getEnvironmentByKey( $input );
if ( $resFct == null ) {
$resFct = BaseMappings::getcancelByKey( $input );
if ( $resFct == null ) {
$resFct = BaseMappings::getCustomByKey( $input );
if ( $resFct == null ) {
$resFct = BaseMappings::getMhChemByKey( $input );
}
}
}
}
}
if ( $resFct == null ) {
return null;
}
// If the function has been found, dynamically call the associated parsing function.
if ( is_string( $resFct ) ) {
$resFct = [ $resFct ];
}
try {
// Passing resolved function as param without first id
if ( count( $resFct ) > 1 ) {
$shifted = array_shift( $resFct );
return BaseParsing::{$shifted}( $node, $passedArgs, $operatorContent, $input, ...$resFct );
} else {
return BaseParsing::{$resFct[0]}( $node, $passedArgs, $operatorContent, $input );
}
} catch ( \Exception $exception ) {
return null;
}
}
public function checkAndParseOperator( $input, $node, $passedArgs, $operatorContent ) {
$input = MMLutil::inputPreparation( $input );
$resOperator = BaseMappings::getOperatorByKey( $input );
if ( $resOperator == null ) {
$resOperator = AMSMappings::getOperatorByKey( $input );
if ( $resOperator == null ) {
$resOperator = OperatorDictionary::getOperatorByKey( $input );
if ( $resOperator ) {
if ( isset( $resOperator[1] ) ) {
// custom parsing here
return $this->parseOperatorDict( $node, $passedArgs, $operatorContent, $input, false );
}
// Atm just do simple parsing for elements in operator dictionary
$mmlMo = new MMLmo();
return $mmlMo->encapsulate( $input );
}
}
}
// If the macro has been found, dynamically call the associated parsing function.
if ( is_string( $resOperator ) ) {
$resOperator = [ $resOperator ];
}
if ( $resOperator == null ) {
return null;
}
try {
return $this->parseOperator( $node, $passedArgs, $operatorContent, $input, ...$resOperator );
} catch ( ArgumentCountError $errArgcount ) {
return null;
}
}
public function parseOperatorDict( $node, $passedArgs, $operatorContent, $input, $uc = null, $attrs = [] ) {
// Some custom parsing from operatorDict
switch ( $input ) {
case ";":
$mmlMStyle = new MMLmstyle( "", [ "scriptlevel" => "0" ] );
$mSpace = new MMLmspace( "", [ "width" => "0.278em" ] );
return $mmlMStyle->encapsulate( $mSpace->encapsulate( "" ) );
case ",":
// this maybe just a default case, this is not rendered when it is the last in row
$mmlMo = new MMLmo();
return $mmlMo->encapsulate( "," );
}
return $input;
}
public function parseOperator( $node, $passedArgs, $operatorContent, $name, $uc = null, $attrs = [] ) {
// if($name == "equiv" || $name == "dotplus" || $name == "mp" || $name == "pm"){
$attrs = array_merge( $passedArgs, $attrs ); // this is rather a workaround
$mo = new MMLmo( "", $attrs );
$text = $mo->encapsulate( $uc );
// Some attributes are nnot used which come from the mapping, tbd refactor this
$text = str_replace( " largeop=\"\"", "", $text );
$text = str_replace( "variantForm=\"True\"", "data-mjx-alternate=\"1\"", $text );
$text = str_replace( "variantForm=\"1\"", "data-mjx-alternate=\"1\"", $text );
$text = str_replace( " movesupsub=\"1\"", "", $text );
return str_replace( "texClass", "data-mjx-texclass", $text );
}
public function checkAndParseIdentifier( $input, $node, $passedArgs, $operatorContent ) {
$input = MMLutil::inputPreparation( $input );
$resIdentifier = BaseMappings::getIdentifierByKey( $input );
if ( $resIdentifier == null ) {
$resIdentifier = AMSMappings::getIdentifierByKey( $input );
}
// If the macro has been found, dynamically call the associated parsing function.
if ( is_string( $resIdentifier ) ) {
$resIdentifier = [ $resIdentifier ];
}
if ( $resIdentifier == null ) {
return null;
}
try {
return $this->parseIdentifier( $node, $passedArgs, $operatorContent, $input, ...$resIdentifier );
} catch ( ArgumentCountError $errArgcount ) {
return null;
}
}
public function parseIdentifier( $node, $passedArgs, $operatorContent, $name, $uc = null, $attrs = [] ) {
// tbd verify rule: Lowercase name ("operator" instead "Operator") seems to
// indicate additional italic mathvariant when bold already
if ( !ctype_upper( $name ) ) {
if ( isset( $passedArgs["mathvariant"] ) && $passedArgs["mathvariant"] ) {
$passedArgs["mathvariant"] = $passedArgs["mathvariant"] . "-" . Variants::ITALIC;
}
}
$args = array_merge( $passedArgs, $attrs );
$mi = new MMLmi( "", $args );
$text = $mi->encapsulate( $uc );
// TODO refactor just for test
$text = str_replace( "variantForm=\"True\"", "data-mjx-alternate=\"1\"", $text );
$text = str_replace( "variantForm=\"1\"", "data-mjx-alternate=\"1\"", $text );
return str_replace( "texClass", "data-mjx-texclass", $text );
}
public function checkAndParseDelimiter( $input, $node, $passedArgs,
$operatorContent, $noargs = false, $texClass = "" ) {
$resDelimiter = BaseMappings::getDelimiterByKey( trim( $input ) );
if ( $resDelimiter == null ) {
$input = MMLutil::inputPreparation( $input );
$resDelimiter = AMSMappings::getSymbolDelimiterByKey( $input );
if ( $resDelimiter == null ) {
$resDelimiter = AMSMappings::getMathDelimiterByKey( $input );
if ( $resDelimiter == null ) {
return null;
}
}
}
if ( is_string( $resDelimiter ) ) {
$resDelimiter = [ $resDelimiter ];
} else {
if ( isset( $resDelimiter[1] ) && is_array( $resDelimiter[1] ) && !$noargs ) {
$passedArgs = array_merge( $resDelimiter[1], $passedArgs );
}
}
$mo = new MMLmo( $texClass, $passedArgs );
return $mo->encapsulate( $resDelimiter[0] );
}
public function checkAndParseMathCharacter( $input, $node, $passedArgs, $operatorContent ) {
$inputP = MMLutil::inputPreparation( $input );
$resChar = BaseMappings::getCharacterByKey( $inputP );
if ( $resChar == null ) {
return null;
}
// Maybe move this to the mapping
$args = [ "mathvariant" => "normal" ];
$mi = new MMLmi( "", $args );
$enc = MMLutil::uc2xNotation( $resChar );
return $mi->encapsulate( $enc );
}
public function checkAndParseColor( $input, $node, $passedArgs, $operatorContent ) {
// tbd usually this encapsulates the succeeding box element
if ( $operatorContent == null ) {
return null;
}
$input = MMLutil::inputPreparation( $input );
if ( !( $input === 'color' || $input === 'pagecolor' ) ) {
return null;
}
$resColor = BaseMappings::getColorByKey( $operatorContent );
if ( $resColor == null ) {
return null;
}
if ( is_array( $resColor ) ) {
$resColor = $resColor[0]; // tbd refactor or correct mappings
}
if ( $input === 'color' ) {
$mstyle = new MMLmstyle( "", [ "mathcolor" => $resColor ] );
return $mstyle->encapsulate( "" );
} else {
// Input is 'pagecolor'
$mtext = new MMLmtext( "", [ "mathcolor" => $resColor ] );
$mrow = new MMLmrow();
$mi = new MMLmi();
// Mj3 does this, probably not necessary
$innerRow = "";
foreach ( str_split( $operatorContent ) as $char ) {
$innerRow .= $mi->encapsulate( $char );
}
if ( $innerRow !== "" ) {
return $mtext->encapsulate( "\\pagecolor" ) . $mrow->encapsulate( $innerRow );
} else {
return $mtext->encapsulate( "\\pagecolor" );
}
}
}
}

View file

@ -0,0 +1,929 @@
<?php
namespace MediaWiki\Extension\Math\TexVC\MMLmappings;
use IntlChar;
use MediaWiki\Extension\Math\TexVC\MMLmappings\TexConstants\Misc;
use MediaWiki\Extension\Math\TexVC\MMLmappings\TexConstants\Tag;
use MediaWiki\Extension\Math\TexVC\MMLmappings\TexConstants\TexClass;
use MediaWiki\Extension\Math\TexVC\MMLmappings\TexConstants\Variants;
use MediaWiki\Extension\Math\TexVC\MMLmappings\Util\MMLParsingUtil;
use MediaWiki\Extension\Math\TexVC\MMLmappings\Util\MMLutil;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmenclose;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmfrac;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmi;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmmultiscripts;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmo;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmover;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmpadded;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmphantom;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmroot;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmrow;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmspace;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmsqrt;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmstyle;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmsub;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmsubsup;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmsup;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmtable;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmtd;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmtext;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmtr;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmunder;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmunderover;
use MediaWiki\Extension\Math\TexVC\Nodes\Curly;
use MediaWiki\Extension\Math\TexVC\Nodes\DQ;
use MediaWiki\Extension\Math\TexVC\Nodes\Fun1nb;
use MediaWiki\Extension\Math\TexVC\Nodes\Fun2sq;
use MediaWiki\Extension\Math\TexVC\Nodes\Literal;
use MediaWiki\Extension\Math\TexVC\Nodes\TexArray;
/**
* Parsing functions for specific recognized mappings.
* Usually the parsing functions are invoked from the BaseMethods classes.
*/
class BaseParsing {
public static function accent( $node, $passedArgs, $name, $operatorContent, $accent, $stretchy = null ) {
// Currently this is own implementation from Fun1.php
// TODO The first if-clause is mathjax specific (and not necessary by generic parsers)
// and will most probably removed (just for running all tc atm)
if ( $accent == "00B4" || $accent == "0060" ) {
$attrs = [ Tag::SCRIPTTAG => "true" ];
} else {
if ( $stretchy == null ) {
// $attrs = [ "stretchy" => "false" ]; // not mention explicit stretchy
$attrs = [];
} else {
$attrs = [ "stretchy" => "true" ];
}
}
// Fetching entity from $accent key tbd
$entity = MMLutil::createEntity( $accent );
if ( !$entity ) {
$entity = $accent;
}
if ( $node->getArg() instanceof Curly && $node->getArg()->getArg() instanceof TexArray
&& count( $node->getArg()->getArg()->getArgs() ) > 1 ) {
$mrow = new MMLmrow();
$renderedArg = $mrow->encapsulate( $node->getArg()->renderMML() );
} else {
$renderedArg = $node->getArg()->renderMML();
}
$mrow = new MMLmrow();
$mo = new MMLmo( "", $attrs ); // $passedArgs
$mover = new MMLmover();
$ret = $mrow->encapsulate(
$mrow->encapsulate(
$mover->encapsulate(
$renderedArg .
$mo->encapsulate( $entity )
)
)
);
return $ret;
}
public static function array( $node, $passedArgs, $operatorContent, $name, $begin = null, $open = null,
$close = null, $align = null, $spacing = null,
$vspacing = null, $style = null, $raggedHeight = null ) {
$output = "";
$mrow = new MMLmrow();
if ( $open != null ) {
$resDelimiter = BaseMappings::getDelimiterByKey( trim( $open ) );
if ( $resDelimiter ) {
// $retDelim = $bm->checkAndParseDelimiter($open, $node,$passedArgs,true);
$moOpen = new MMLmo( TexClass::OPEN );
$output .= $moOpen->encapsulate( $resDelimiter[0] );
}
}
if ( $name == "Bmatrix" || $name == "bmatrix" || $name == "Vmatrix"
|| $name == "vmatrix" || $name == "smallmatrix" || $name == "pmatrix" || $name == "matrix" ) {
// This is a workaround and might be improved mapping BMatrix to Matrix directly instead of array
return self::matrix( $node, $passedArgs, $operatorContent, $name,
$open, $close, null, null, null, null, true );
} else {
$output .= $mrow->encapsulate( $node->getMainarg()->renderMML() );
}
if ( $close != null ) {
$resDelimiter = BaseMappings::getDelimiterByKey( trim( $close ) );
if ( $resDelimiter ) {
// $retDelim = $bm->checkAndParseDelimiter($open, $node,$passedArgs,true);
$moClose = new MMLmo( TexClass::CLOSE );
$output .= $moClose->encapsulate( $resDelimiter[0] );
}
}
return $output;
}
public static function alignAt( $node, $passedArgs, $operatorContent, $name, $smth, $smth2 = null ) {
// Parsing is very similar to AmsEQArray, maybe extract function ... tcs: 178
$mrow = new MMLmrow();
// tbd how are the table args composed ?
$tableArgs = [ "columnalign" => "right",
"columnspacing" => "", "displaystyle" => "true", "rowspacing" => "3pt" ];
$mtable = new MMLmtable( "", $tableArgs );
$mtr = new MMLmtr();
$mtd = new MMLmtd();
$renderedInner = "";
$tableElements = array_slice( $node->getArgs(), 1 )[0];
$discarded = false;
foreach ( $tableElements->getArgs() as $tableRow ) {
$renderedInner .= $mtr->getStart();
foreach ( $tableRow->getArgs() as $tableCell ) {
$renderedInner .= $mtd->getStart();
foreach ( $tableCell->getArgs() as $cellItem ) {
if ( !$discarded && $cellItem instanceof Curly ) {
$discarded = true;
// Just discard the number of rows atm, it is in the first Curly
} else {
$renderedInner .= $cellItem->renderMML(); // pass args here ?
}
}
$renderedInner .= $mtd->getEnd();
}
$renderedInner .= $mtr->getEnd();
}
return $mrow->encapsulate( $mtable->encapsulate( $renderedInner ) );
}
public static function amsEqnArray( $node, $passedArgs, $operatorContent, $name, $smth, $smth2 = null ) {
// this goes for name =="aligned" ... tcs: 358 420 421
$mrow = new MMLmrow();
// tbd how are the table args composed ?
$tableArgs = [ "columnalign" => "right",
"columnspacing" => "", "displaystyle" => "true", "rowspacing" => "3pt" ];
$mtable = new MMLmtable( "", $tableArgs );
$mtr = new MMLmtr();
$mtd = new MMLmtd();
$renderedInner = "";
$tableElements = array_slice( $node->getArgs(), 1 )[0];
foreach ( $tableElements->getArgs() as $tableRow ) {
$renderedInner .= $mtr->getStart();
foreach ( $tableRow->getArgs() as $tableCell ) {
$renderedInner .= $mtd->encapsulate( $tableCell->renderMML() ); // pass args here ?
}
$renderedInner .= $mtr->getEnd();
}
return $mrow->encapsulate( $mtable->encapsulate( $renderedInner ) );
}
public static function boldsymbol( $node, $passedArgs, $operatorContent, $name, $smth = null, $smth2 = null ) {
$mrow = new MMLmrow();
$passedArgs = array_merge( [ "mathvariant" => Variants::BOLDITALIC ] );
return $mrow->encapsulate( $node->getArg()->renderMML( $passedArgs ) );
}
public static function cancel( $node, $passedArgs, $operatorContent, $name, $notation = null, $smth2 = null ) {
$mrow = new MMLmrow();
$menclose = new MMLmenclose( "", [ "notation" => $notation ] );
return $mrow->encapsulate( $menclose->encapsulate( $node->getArg()->renderMML() ) );
}
public static function cancelTo( $node, $passedArgs, $operatorContent, $name, $notation = null ) {
$mrow = new MMLmrow();
$msup = new MMLmsup();
$mpAdded = new MMLmpadded( "", [ "depth" => "-.1em" ,"height" => "+.1em" ,"voffset" => ".1em" ] );
$menclose = new MMLmenclose( "", [ "notation" => $notation ] );
$inner = $menclose->encapsulate(
$node->getArg2()->renderMML() ) . $mpAdded->encapsulate( $node->getArg1()->renderMML() );
return $mrow->encapsulate( $msup->encapsulate( $inner ) );
}
public static function chemCustom( $node, $passedArgs, $operatorContent, $name, $translation = null ) {
if ( $translation ) {
return $translation;
}
return "tbd chemCustom";
}
public static function cFrac( $node, $passedArgs, $operatorContent, $name ) {
$mrow = new MMLmrow();
$mfrac = new MMLmfrac();
$mstyle = new MMLmstyle( "", [ "displaystyle" => "false", "scriptlevel" => "0" ] );
$mpAdded = new MMLmpadded( "", [ "depth" => "3pt","height" => "8.6pt","width" => "0" ] );
// See TexUtilMMLTest testcase 81
// (mml3 might be erronous here, but this element seems to be rendered correctly)
$whatIsThis = $mrow->getStart() . $mpAdded->getStart() . $mpAdded->getEnd() . $mrow->getEnd();
$inner = $mrow->encapsulate( $whatIsThis .
$mstyle->encapsulate( $mrow->encapsulate( $node->getArg1()->renderMML() ) ) ) .
$mrow->encapsulate( $whatIsThis . $mstyle->encapsulate(
$mrow->encapsulate( $node->getArg2()->renderMML() ) ) );
return $mrow->encapsulate( $mfrac->encapsulate( $inner ) );
}
public static function dots( $node, $passedArgs, $operatorContent, $name, $smth = null, $smth2 = null ) {
// lowerdots || centerdots seems aesthetical, just using lowerdots atm s
$mo = new MMLmo( "", $passedArgs );
return $mo->encapsulate( "&#x2026;" );
}
public function genFrac( $node, $passedArgs, $name, $operatorContent,
$left = null, $right = null, $thick = null, $style = null ) {
// Actually this is in AMSMethods, consider refactoring left, right, thick, style
$bm = new BaseMethods();
$ret = $bm->checkAndParseDelimiter( $name, $node, $passedArgs, $operatorContent, true );
if ( $ret ) {
// TBD
if ( $left == null ) {
$left = $ret;
}
if ( $right == null ) {
$right = $ret;
}
if ( $thick == null ) {
$thick = $ret;
}
if ( $style == null ) {
$style = trim( $ret );
}
}
$attrs = [];
$fract = null;
$styleAttr = [];
$displayStyle = "false";
if ( $thick !== "" ) {
$attrs = array_merge( $attrs, [ "linethickness" => $thick ] );
}
if ( $style !== '' ) {
$styleDigit = intval( $style, 10 );
$styleAlpha = [ 'D', 'T', 'S', 'SS' ][$styleDigit];
if ( $styleAlpha == null ) {
$mrow = new MMLmrow();
return $mrow->encapsulate( "Bad math style" );
}
if ( $styleAlpha === 'D' ) {
// NodeUtil_js_1.default.setProperties(frac, { displaystyle: true, scriptlevel: 0 });
// tbd add props
$displayStyle = "true";
$styleAttr = [ "maxsize" => "2.047em", "minsize" => "2.047em" ];
} else {
$styleAttr = [ "maxsize" => "1.2em", "minsize" => "1.2em" ];
}
$frac = new MMLmfrac( "", $attrs );
} else {
// NodeUtil_js_1.default.setProperties(frac, { displaystyle: false,
// scriptlevel: styleDigit - 1 });
// tbd add props
$frac = new MMLmfrac( "", $attrs );
$styleAttr = [ "maxsize" => "1.2em", "minsize" => "1.2em" ];
}
$mrow = new MMLmrow();
$mstyle = new MMLmstyle( "", [ "displaystyle" => $displayStyle, "scriptlevel" => "0" ] );
$output = $mrow->getStart();
if ( $style !== '' ) {
$output .= $mstyle->getStart();
}
$output .= $mrow->getStart();
if ( $left ) {
$mrowOpen = new MMLmrow( TexClass::OPEN );
$moL = new MMLmo( "", $styleAttr );
$output .= $mrowOpen->encapsulate( $moL->encapsulate( $left ) );
}
// when is mrow encapsulating and when not ?
//$output .= $frac->encapsulate(
// $mrow->encapsulate($node->getArg1()->renderMML()) .$mrow->encapsulate( $node->getArg2()->renderMML() ));
$output .= $frac->encapsulate( $node->getArg1()->renderMML() . $node->getArg2()->renderMML() );
if ( $right ) {
$mrowClose = new MMLmrow( TexClass::CLOSE );
$moR = new MMLmo( "", $styleAttr );
$output .= $mrowClose->encapsulate( $moR->encapsulate( $right ) );
}
$output .= $mrow->getEnd();
if ( $style !== '' ) {
$output .= $mstyle->getEnd();
}
$output .= $mrow->getEnd();
return $output;
}
public static function frac( $node, $passedArgs, $operatorContent, $name ) {
$mrow = new MMLmrow();
$mfrac = new MMLmfrac();
// if node is Fun1
$inner = $mrow->encapsulate( $node->getArg1()->renderMML() ) .
$mrow->encapsulate( $node->getArg2()->renderMML() );
return $mrow->encapsulate( $mfrac->encapsulate( $inner ) );
}
public static function hline( $node, $passedArgs, $operatorContent, $name,
$smth1 = null, $smth2 = null, $smth3 = null, $smth4 = null ) {
// HLine is most probably not parsed this way, since only parsed in Matrix context
$mmlRow = new MMLmrow( "tbd" );
return $mmlRow->encapsulate( "HLINE TBD" );
}
public static function handleOperatorName( $node, $passedArgs, $operatorContent, $name,
$smth1 = null, $smth2 = null, $smth3 = null, $smth4 = null ) {
// \\operatorname{a}
$passedArgs = array_merge( $passedArgs, [ Tag::CLASSTAG => TexClass::OP, "mathvariant" => Variants::NORMAL ] );
return $node->getArg()->renderMML( $passedArgs );
}
public static function macro( $node, $passedArgs, $operatorContent, $name, $macro, $argcount = null, $def = null ) {
// Parse the Macro
switch ( $name ) {
case "mod":
$mmlRow = new MMLmrow();
$mspace = new MMLmspace( "", [ "width" => "0.444em" ] );
$mspace2 = new MMLmspace( "", [ "width" => "0.333em" ] );
$mo = new MMLmo( "", [ "stretchy" => "false" ] );
$mi = new MMLmi();
return $mmlRow->encapsulate(
$mspace->encapsulate( "" ) . $mo->encapsulate( "(" ) .
$mi->encapsulate( "mod" ) . $mspace2->encapsulate( "" ) .
$mo->encapsulate( ")" ) );
case "pmod":
// tbd indicate in mapping that this is composed within php
$mmlRow = new MMLmrow();
$mspace = new MMLmspace( "", [ "width" => "0.444em" ] );
$mspace2 = new MMLmspace( "", [ "width" => "0.333em" ] );
$mo = new MMLmo( "", [ "stretchy" => "false" ] );
$mi = new MMLmi();
return $mmlRow->encapsulate( $mspace->encapsulate( "" ) .
$mo->encapsulate( "(" ) . $mi->encapsulate( "mod" ) .
$mspace2->encapsulate( "" ) . $node->getArg()->renderMML() . $mo->encapsulate( ")" ) );
case "varlimsup":
case "varliminf":
// hardcoded macro in php (there is also a dynamic mapping which is not completely resolved atm)
$mmlRow = new MMLmrow( TexClass::OP );
if ( $name === "varlimsup" ) {
$movu = new MMLmover();
} else {
$movu = new MMLmunder();
}
$mmlMi = new MMLmi();
$mo = new MMLmo( "", [ "accent" => "true" ] );
return $mmlRow->encapsulate( $movu->encapsulate(
$mmlMi->encapsulate( "lim" ) . $mo->encapsulate( "&#x2015;" ) ) );
case "varinjlim":
$mmlRow = new MMLmrow( TexClass::OP );
$mmlMunder = new MMLmunder();
$mi = new MMLmi();
$mo = new MMLmo();
return $mmlRow->encapsulate( $mmlMunder->encapsulate(
$mi->encapsulate( "lim" ) .
$mo->encapsulate( "&#x2192;" ) )
);
case "varprojlim":
$mmlRow = new MMLmrow( TexClass::OP );
$mmlMunder = new MMLmunder();
$mi = new MMLmi();
$mo = new MMLmo();
return $mmlRow->encapsulate( $mmlMunder->encapsulate(
$mi->encapsulate( "lim" ) .
$mo->encapsulate( "&#x2190;" )
) );
case "stackrel":
// hardcoded macro in php (there is also a dynamic mapping which is not not completely resolved atm)
$mmlRow = new MMLmrow();
$mmlRowInner = new MMLmrow( TexClass::REL );
$mover = new MMLmover();
$mmlRowArg2 = new MMLmrow( TexClass::OP );
$inner = $mover->encapsulate( $mmlRowArg2->encapsulate(
$node->getArg2()->renderMML() ) .
$mmlRow->encapsulate( $node->getArg1()->renderMML() )
);
return $mmlRow->encapsulate( $mmlRowInner->encapsulate( $inner ) );
case "bmod":
$mo = new MMLmo( "", [ "lspace" => "thickmathspace", "rspace" => "thickmathspace" ] );
$mmlRow = new MMLmrow( TexClass::ORD );
$mstyle = new MMLmstyle( "", [ "scriptlevel" => "0" ] );
$mspace = new MMLmspace( "", [ "width" => "0.167em" ] );
return $mmlRow->encapsulate( $mo->encapsulate( "mod" ) .
$mmlRow->encapsulate( $mstyle->encapsulate( $mspace->getEmpty() ) ) );
case "implies":
$mstyle = new MMLmstyle( "", [ "scriptlevel" => "0" ] );
$mspace = new MMLmspace( "", [ "width" => "0.278em" ] );
$mo = new MMLmo();
return $mstyle->encapsulate( $mspace->getEmpty() ) . $mo->encapsulate( "&#x27F9;" ) .
$mstyle->encapsulate( $mspace->getEmpty() );
case "iff":
$mstyle = new MMLmstyle( "", [ "scriptlevel" => "0" ] );
$mspace = new MMLmspace( "", [ "width" => "0.278em" ] );
$mo = new MMLmo();
return $mstyle->encapsulate( $mspace->getEmpty() ) . $mo->encapsulate( "&#x27FA;" ) .
$mstyle->encapsulate( $mspace->getEmpty() );
}
// Removed all token based parsing, since macro resolution for the supported macros can be hardcoded in php
$mmlMrow = new MMLmrow();
return $mmlMrow->encapsulate( "macro not resolved: " . $macro );
}
public static function matrix( $node, $passedArgs, $operatorContent,
$name, $open = null, $close = null, $align = null, $spacing = null,
$vspacing = null, $style = null, $cases = null, $numbered = null ) {
$resInner = "";
$mtr = new MMLmtr();
$mtd = new MMLmtd();
$addHlines = false;
$columnInfo = [];
// tbd hline element is the first literal element within second texarray -> resolve
foreach ( $node->getMainarg()->getArgs() as $mainarg ) {
$resInner .= $mtr->getStart();
foreach ( $mainarg->getArgs() as $arg ) {
$usedArg = clone $arg;
if ( count( $arg->getArgs() ) >= 1 && $arg->getArgs()[0] instanceof Literal ) {
// Discarding the column information Curly at the moment
if ( $arg->getArgs()[0]->getArg() == "\\hline " ) {
// discarding the hline
// $usedArg->args[0] = null; // this does no work tbd
$usedArg->pop();
$addHlines = true;
}
}
if ( count( $arg->getArgs() ) >= 1 && $arg->getArgs()[0] instanceof Curly ) {
// Discarding the column information Curly at the moment
// $usedArg->getArgs()[0] = null;
$columnInfo = $usedArg->getArgs()[0]->render();
$usedArg->pop();
}
$resInner .= $mtd->encapsulate( $usedArg->renderMML( $passedArgs ) );
}
$resInner .= $mtr->getEnd();
}
$mrow = new MMLmrow();
$tableArgs = [ "columnspacing" => "1em", "rowspacing" => "4pt" ];
$mencloseArgs = null;
if ( $addHlines ) {
// TBD this is just simple check, create a parsing function for hlines when there are more cases
// solid as first val: hline for header row
// none as second val: no hlines for follow up rows
$tableArgs = array_merge( $tableArgs, [ "rowlines" => "solid none" ] );
}
if ( $columnInfo ) {
// TBD this is just simple check, create a parsing function for hlines when there are more cases
if ( str_contains( $columnInfo, "|" ) ) {
$mencloseArgs = [ "data-padding" => "0","notation" => "left right" ];
// it seems this is creted when left and right is solely coming from columninfo
$tableArgs = array_merge( $tableArgs, [ "columnlines" => "solid" ] );
}
}
$mtable = new MMLmtable( "", $tableArgs );
if ( $cases || ( $open != null && $close != null ) ) {
$bm = new BaseMethods();
$mmlMoOpen = $bm->checkAndParseDelimiter( $open, $node, [], [],
true, TexClass::OPEN );
if ( $mmlMoOpen == null ) {
$open = MMLutil::inputPreparation( $open );
$mmlMoOpen = new MMLmo( TexClass::OPEN, [] );
$mmlMoOpen = $mmlMoOpen->encapsulate( $open );
}
$closeAtts = [ "fence" => "true","stretchy" => "true","symmetric" => "true" ];
$mmlMoClose = $bm->checkAndParseDelimiter( $close, $node, $closeAtts,
null, true, TexClass::CLOSE );
if ( $mmlMoOpen == null ) {
$close = MMLutil::inputPreparation( $close );
$mmlMoClose = new MMLmo( TexClass::CLOSE, $closeAtts );
$mmlMoClose = $mmlMoClose->encapsulate( $close );
}
$resInner = $mmlMoOpen . $mtable->encapsulate( $resInner ) . $mmlMoClose;
} else {
$resInner = $mtable->encapsulate( $resInner );
}
if ( $mencloseArgs ) {
$menclose = new MMLmenclose( "", $mencloseArgs );
$matrix = $mrow->encapsulate( $menclose->encapsulate( $resInner ) );
} else {
$matrix = $mrow->encapsulate( $resInner );
}
return $matrix;
}
public static function namedOp( $node, $passedArgs, $operatorContent, $name, $id = null ) {
if ( !$id ) {
// $id = substr($name,1); eventually change how name is passed
$id = $name;
}
// This id statement probably wont work atm:
// lim&#x2006;inf
$id = str_replace( "&thinsp;", '&#x2006;', $id );
$mo = new MMLmo( TexClass::OP, [ "movablelimits" => "true" ] );
// "movesupsub"=>"true" activate this also as attribute ?
return $mo->encapsulate( $id );
}
public static function over( $node, $passedArgs, $operatorContent, $name, $id = null ) {
$attributes = [];
$start = "";
$tail = "";
if ( $name === "atop" ) {
$attributes = [ "linethickness" => "0" ];
} elseif ( $name == "choose" ) {
$mrowAll = new MMLmrow( TexClass::ORD );
$mrowOpen = new MMLmrow( TexClass::OPEN );
$mrowClose = new MMLmrow( TexClass::CLOSE );
$mo = new MMLmo( "", [ "maxsize" => "1.2em","minsize" => "1.2em" ] );
$start = $mrowAll->getStart() . $mrowOpen->encapsulate( $mo->encapsulate( "(" ) );
$tail = $mrowClose->encapsulate( $mo->encapsulate( ")" ) ) . $mrowAll->getEnd();
$attributes = [ "linethickness" => "0" ];
}
$mfrac = new MMLmfrac( "", $attributes ); // "movesupsub"=>"true" activate this also as attribute ?
$mrow = new MMLmrow( "", [] ); // tbd remove mathjax specifics,
// tbd added a getArg2 mrow which seems correct, consider removiing in some cases ?
return $start . $mfrac->encapsulate( $mrow->encapsulate(
$node->getArg1()->renderMML() ) . $mrow->encapsulate( $node->getArg2()->renderMML() ) ) . $tail;
}
public static function oint( $node, $passedArgs, $operatorContent,
$name, $uc = null, $smth1 = null, $smth2 = null ) {
// This is a custom mapping not in js.
$mmlText = new MMLmtext( "", [ "mathcolor" => "red" ] );
switch ( $name ) {
case "oiiint":
case "oiint":
case "ointctrclockwise":
case "varointclockwise":
case "P":
return $mmlText->encapsulate( "\\" . $name );
default:
return $mmlText->encapsulate( "not found in OintMethod" );
}
}
public static function overset( $node, $passedArgs, $operatorContent, $name, $id = null ) {
$mrow = new MMLmrow( TexClass::ORD, [] ); // tbd remove mathjax specifics
$mrow2 = new MMLmrow( "", [] );
$inrow = $mrow2->encapsulate( $node->getArg2()->renderMML() );
$mover = new MMLmover();
return $mrow->encapsulate( $mover->encapsulate( $inrow . $node->getArg1()->renderMML() ) );
}
public static function phantom( $node, $passedArgs, $operatorContent,
$name, $vertical = null, $horizontal = null, $smh3 = null ) {
$mrow = new MMLmrow( TexClass::ORD, [] );
$attrs = [];
if ( $vertical ) {
$attrs = array_merge( $attrs, [ "width" => "0" ] );
}
if ( $horizontal ) {
$attrs = array_merge( $attrs, [ "depth" => "0", "height" => "0" ] );
}
$mpadded = new MMLmpadded( "", $attrs );
$mphantom = new MMLmphantom();
return $mrow->encapsulate( $mrow->encapsulate(
$mpadded->encapsulate( $mphantom->encapsulate( $node->getArg()->renderMML() ) ) ) );
}
public static function underset( $node, $passedArgs, $operatorContent, $name, $smh = null ) {
$mrow = new MMLmrow( TexClass::ORD, [] ); // tbd remove mathjax specifics
$mrow2 = new MMLmrow( "", [] );
$inrow = $node->getArg2()->renderMML();
$munder = new MMLmunder();
// Some cases encapsulate getArg1 in Mrow ??
return $mrow->encapsulate( $munder->encapsulate( $inrow . $node->getArg1()->renderMML() ) );
}
public static function underOver( $node, $passedArgs, $operatorContent,
$name, $operatorId = null, $stack = null ) {
// tbd verify if stack interpreted correctly ?
$texClass = $stack ? TexClass::OP : TexClass::ORD; // ORD or ""
$mrow = new MMLmrow( $texClass );
if ( $name[0] === 'o' ) {
$movun = new MMLmover();
} else {
$movun = new MMLmunder();
}
if ( $operatorId == 2015 ) { // eventually move such cases to mapping
$mo = new MMLmo( "", [ "accent" => "true" ] );
} else {
$mo = new MMLmo();
}
if ( $node instanceof DQ ) {
$mrowI = new MMLmrow();
return $movun->encapsulate(
$node->getBase()->renderMML() .
$mrowI->encapsulate( $node->getDown()->renderMML() )
);
}
// TBD: Export this check to utility function it seems to be used multiple times
$renderedArg = "";
$check = method_exists( $node, "getArg" ); // this was to prevent crash if DQ, might be refactored
if ( $check ) {
if ( $node->getArg() instanceof Curly && $node->getArg()->getArg() instanceof TexArray
&& count( $node->getArg()->getArg()->getArgs() ) > 1 ) {
$mrowI = new MMLmrow();
$renderedArg = $mrowI->encapsulate( $node->getArg()->renderMML() );
} else {
$renderedArg = $node->getArg()->renderMML();
}
}
return $mrow->encapsulate( $movun->encapsulate(
$renderedArg . $mo->encapsulate( MMLutil::number2xNotation( $operatorId ) )
) );
}
public static function mathFont( $node, $passedArgs, $operatorContent, $name, $mathvariant = null ) {
$mrow = new MMLmrow( TexClass::ORD, [] );
$mi = new MMLmi();
$args = MMLParsingUtil::getFontArgs( $name, $mathvariant, $passedArgs );
if ( $node instanceof Fun1nb ) {
// Only one mrow from Fun1nb !?
return $mrow->encapsulate( $node->getArg()->renderMML( $args ) );
}
return $mrow->encapsulate( $mrow->encapsulate( $node->getArg()->renderMML( $args ) ) );
}
public static function makeBig( $node, $passedArgs, $operatorContent, $name, $texClass = null, $size = null ) {
// Create the em format and shorten commas
$size *= Misc::P_HEIGHT;
$sizeShortened = MMLutil::size2em( strval( $size ) );
$mrowOuter = new MMLmrow( TexClass::ORD, [] );
$mrow = new MMLmrow( $texClass, [] );
$passedArgs = array_merge( $passedArgs, [ "maxsize" => $sizeShortened, "minsize" => $sizeShortened ] );
$mo = new MMLmo( "", $passedArgs );
// Sieve arg if it is a delimiter (it seems args are not applied here
$bm = new BaseMethods();
$argcurrent = trim( $node->getArg() );
switch ( $argcurrent ) {
case "\\|":
$passedArgs = array_merge( $passedArgs, [ "symmetric" => "true" ] );
break;
case "\\uparrow":
case "\\downarrow":
case "\\Uparrow":
case "\\Downarrow":
case "\\updownarrow":
case "\\Updownarrow":
$passedArgs = array_merge( [ "fence" => "true" ], $passedArgs, [ "symmetric" => "true" ] );
break;
case "\\backslash":
case "/":
$passedArgs = array_merge( [ "fence" => "true" ],
$passedArgs, [ "stretchy" => "true", "symmetric" => "true" ] );
break;
}
$ret = $bm->checkAndParseDelimiter( $node->getArg(), $node, $passedArgs, $operatorContent, true );
if ( $ret ) {
return $mrowOuter->encapsulate( $mrow->encapsulate( $ret ) );
}
$argPrep = MMLutil::inputPreparation( $node->getArg() );
return $mrowOuter->encapsulate( $mrow->encapsulate( $mo->encapsulate( $argPrep ) ) );
}
public static function machine( $node, $passedArgs, $operatorContent, $name, $type = null ) {
// this could also be shifted to MhChem.php renderMML for ce
// For parsing chem (ce) or ??? (pu)
$mmlMrow = new MMLmrow();
return $mmlMrow->encapsulate( $node->getArg()->renderMML() );
}
public static function namedFn( $node, $passedArgs, $operatorContent, $name, $smth = null ) {
if ( $node instanceof Literal ) {
$mi = new MMLmi();
return $mi->encapsulate( $name );
}
$mrow = new MMLmrow( TexClass::ORD, [] ); // tbd remove mathjax specifics
$msub = new MMLmsub();
return $msub->encapsulate( $node->getBase()->renderMML() .
$mrow->encapsulate( $node->getDown()->renderMML() ) );
}
public static function limits( $node, $passedArgs, $operatorContent, $name, $smth = null ) {
// not completely done, has preceding lits
$mrow = new MMLmrow( TexClass::ORD, [] ); // tbd remove mathjax specifics
$munder = new MMLmunder();
if ( $node instanceof Literal ) {
// Workaround currently
return $munder->encapsulate( $mrow->encapsulate( $node->getArg() ) );
}
return $munder->encapsulate( $mrow->encapsulate( $node->getDown()->renderMML() ) );
}
public static function setFont( $node, $passedArgs, $operatorContent, $name, $variant = null ) {
$mrow = new MMLmrow();
$args = MMLParsingUtil::getFontArgs( $name, $variant, $passedArgs );
return $mrow->encapsulate( $mrow->encapsulate( $node->getArg()->renderMML( $args ) ) );
}
public static function sideset( $node, $passedArgs, $operatorContent, $name,
$smth1 = null, $smth2 = null, $smth3 = null ) {
// Sideset parsing is not completed yet (Waiting for MML)
$mmlMrow = new MMLmrow( TexClass::OP );
$mmlMultiscripts = new MMLmmultiscripts( "", [ Tag::ALIGN => "left" ] );
$in1 = $node->getArg1()->renderMML();
$in2 = $node->getArg2()->renderMML();
return $mmlMrow->encapsulate( $mmlMultiscripts->encapsulate( $in2 . "<mprescripts/>" . $in1 ) );
}
public static function spacer( $node, $passedArgs, $operatorContent, $name, $withIn = null, $smth2 = null ) {
// var node = parser.create('node', 'mspace', [], { width: (0, lengths_js_1.em)(space) });
$mstyle = new MMLmstyle( "", [ "scriptlevel" => "0" ] );
$width = MMLutil::round2em( $withIn );
$mspace = new MMLmspace( "", [ "width" => $width ] );
return $mstyle->encapsulate( $mspace->encapsulate( "" ) );
}
public static function texAtom( $node, $passedArgs, $operatorContent, $name, $texClass = null ) {
switch ( $name ) {
case "mathclose":
$mrow = new MMLmrow();
$mrow2 = new MMLmrow( $texClass, [] );
$inner = $node->getArg()->renderMML();
return $mrow->encapsulate( $mrow2->encapsulate( $inner ) );
case "mathbin":
// no break
case "mathop":
// no break
case "mathrel":
$mrow2 = new MMLmrow( $texClass, [] );
$inner = $node->getArg()->renderMML();
return $mrow2->encapsulate( $inner );
default:
$mrow = new MMLmrow( TexClass::ORD );
$mrow2 = new MMLmrow( $texClass, [] );
$inner = $node->getArg()->renderMML();
return $mrow->encapsulate( $mrow2->encapsulate( $inner ) );
}
}
public static function hBox( $node, $passedArgs, $operatorContent, $name, $smth = null ) {
switch ( $name ) {
case "mbox":
// These seem special case for mbox, otherwise mbox parsed like hbox
if ( $operatorContent == "\\textvisiblespace" ) {
// there is also custom mapping for now to that,
// for TexUtilMMLTest this seems to only occur here though
$mmlMrow = new MMLmrow();
$mtext = new MMLmtext();
return $mmlMrow->encapsulate( $mtext->encapsulate( "&#x2423;" ) );
} elseif ( $operatorContent != null ) { // ok ?? \\AA \\Coppa ....
$mmlMrow = new MMLmrow();
$mtext = new MMLmtext( "", [ "mathcolor" => "red" ] );
return $mmlMrow->encapsulate( $mtext->encapsulate( $operatorContent ) );
}
// no break
case "hbox":
$mmlMrow = new MMLmrow();
$mstyle = new MMLmstyle( "", [ "displaystyle" => "false", "scriptlevel" => "0" ] );
$mtext = new MMLmtext();
return $mmlMrow->encapsulate( $mstyle->encapsulate(
$mtext->encapsulate( $node->getArg() ) ) ); // renderMML for arg ?
case "text":
$mmlMrow = new MMLmrow();
$mtext = new MMLmtext();
return $mmlMrow->encapsulate( $mtext->encapsulate( $node->getArg() ) ); // renderMML for arg ?
case "textbf":
// no break
case "textit":
// no break
case "textrm":
// no break
case "textsf":
// no break
case "texttt":
$mmlMrow = new MMLmrow();
$mtext = new MMLmtext( "", MMLParsingUtil::getFontArgs( $name, null, null ) );
return $mmlMrow->encapsulate( $mtext->encapsulate( $node->getArg()->renderMML() ) );
}
$msubsup = new MMLmsubsup( "tbd HBox" );
// $node->getArg1()->renderMML() . $node->getArg2()->renderMML()
return $msubsup->encapsulate( "undefined hbox" );
}
public static function setStyle( $node, $passedArgs, $operatorContent, $name,
$smth = null, $smth1 = null, $smth2 = null ) {
// Just discard setstyle since they are captured in TexArray now}
return " ";
}
public static function not( $node, $passedArgs, $operatorContent, $name, $smth = null,
$smth1 = null, $smth2 = null ) {
// This is only tested for \not statement without follow-up parameters
$mmlMrow = new MMLmrow( TexClass::REL );
if ( $node instanceof Literal ) {
$mpadded = new MMLmpadded( "", [ "width" => "0" ] );
$mtext = new MMLmtext();
return $mmlMrow->encapsulate( $mpadded->encapsulate( $mtext->encapsulate( "&#x29F8;" ) ) );
} else {
$mmlMrow->encapsulate( "TBD Not" );
}
}
public static function vbox( $node, $passedArgs, $operatorContent, $name, $smth = null ) {
// This is only example functionality for vbox("ab").
// TBD: it should be discussed if vbox is supported since it
// does not seem to be supported by mathjax
if ( is_string( $node->getArg() ) ) {
$mmlMover = new MMLmover();
$mmlmrow = new MMLmrow();
$arr1 = str_split( $node->getArg() );
$inner = "";
foreach ( $arr1 as $char ) {
$inner .= $mmlmrow->encapsulate( $char );
}
return $mmlMover->encapsulate( $inner );
}
$mmr = new MMLmrow();
return $mmr->encapsulate( "no implemented vbox" );
}
public static function sqrt( $node, $passedArgs, $operatorContent, $name ) {
$mrow = new MMLmrow();
// There is an additional argument for the root
if ( $node instanceof Fun2sq ) {
$mroot = new MMLmroot();
// In case of an empty curly add an mrow
$arg2Rendered = $node->getArg2()->renderMML( $passedArgs );
if ( trim( $arg2Rendered ) === "" ) {
$arg2Rendered = $mrow->getEmpty();
}
return $mrow->encapsulate(
$mroot->encapsulate(
$arg2Rendered .
$mrow->encapsulate(
$node->getArg1()->renderMML( $passedArgs )
)
)
);
}
$msqrt = new MMLmsqrt();
// Currently this is own implementation from Fun1.php
return $mrow->encapsulate( // assuming that this is always encapsulated in mrow
$msqrt->encapsulate(
$node->getArg()->renderMML( $passedArgs )
)
);
}
public static function xArrow( $node, $passedArgs, $operatorContent, $name, $chr = null, $l = null, $r = null ) {
$defWidth = "+" . MMLutil::round2em( ( $l + $r ) / 18 );
$defLspace = MMLutil::round2em( $l / 18 );
$mover = new MMLmover();
$mstyle = new MMLmstyle( "", [ "scriptlevel" => "0" ] );
$moArrow = new MMLmo( Texclass::REL, [] );
$char = IntlChar::chr( $chr );
$mpaddedArgs = [ "height" => "-.2em", "lspace" => $defLspace, "voffset" => "-.2em", "width" => $defWidth ];
$mpadded = new MMLmpadded( "", $mpaddedArgs );
$mspace = new MMLmspace( "", [ "depth" => ".25em" ] );
if ( $node instanceof Fun2sq ) {
$mmlMrow = new MMLmrow();
$mmlUnderOver = new MMLmunderover();
return $mmlMrow->encapsulate( $mmlUnderOver->encapsulate(
$mstyle->encapsulate( $moArrow->encapsulate( $char ) ) .
$mpadded->encapsulate(
$mmlMrow->encapsulate(
$node->getArg1()->renderMML()
) .
$mspace->encapsulate( "" )
) .
$mpadded->encapsulate(
$node->getArg2()->renderMML()
)
) );
}
return $mover->encapsulate(
$mstyle->encapsulate( $moArrow->encapsulate( $char ) ) .
$mpadded->encapsulate(
$node->getArg()->renderMML() .
$mspace->encapsulate( "" )
)
);
}
}

View file

@ -4,6 +4,8 @@ declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\TexVC\Nodes;
use MediaWiki\Extension\Math\TexVC\MMLmappings\BaseMethods;
class Big extends TexNode {
/** @var string */
@ -39,6 +41,16 @@ class Big extends TexNode {
return '{' . $this->fname . ' ' . $this->arg . '}';
}
public function renderMML( $arguments = [] ) {
$bm = new BaseMethods();
$res = $bm->checkAndParse( $this->fname, $this, $arguments, null );
if ( $res ) {
return $res;
} else {
return "Not Implemented Big for: " . $this->getArgs()[0];
}
}
public function extractIdentifiers( $args = null ) {
return [];
}

View file

@ -4,6 +4,8 @@ declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\TexVC\Nodes;
use MediaWiki\Extension\Math\TexVC\MMLmappings\BaseMethods;
class Box extends TexNode {
/** @var string */
@ -39,6 +41,30 @@ class Box extends TexNode {
return '{' . $this->fname . '{' . $this->arg . '}}';
}
public function renderMML( $arguments = [] ) {
$bm = new BaseMethods();
$res = $bm->checkAndParse( $this->getArgs()[0], $this, $arguments, null );
if ( $res ) {
return $res;
} else {
return "Not Implemented Box for: " . $this->getArgs()[0];
}
/**
* $mrow = new MMLmrow();
* $mtext = new MMLmtext();
*
* $renderedMML = $mrow->encapsulate(
* $mtext->encapsulate( $this->arg )
* );
* $color = BaseMappings::getColorByKey($this->arg);
* if($color){
* $mstyle = new MMLmstyle();
* $renderedMML = $renderedMML . $mstyle->getEnd();
* }
* return $renderedMML;
*/
}
public function extractIdentifiers( $args = null ) {
return [];
}

View file

@ -4,6 +4,9 @@ declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\TexVC\Nodes;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmrow;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmtext;
class ChemWord extends TexNode {
/** @var TexNode */
@ -39,6 +42,16 @@ class ChemWord extends TexNode {
return $this->left->render() . $this->right->render();
}
public function renderMML( $arguments = [] ) {
$mmlMrow = new MMLmrow();
$mtextLeft = new MMLmtext( "", [ "mathcolor" => "red" ] );
$mtextRight = new MMLmtext();
// If right has empty literal content is resolved as dash
$right = $this->getRight()->getArgs()[0] == "" ? "-" : $this->getRight()->renderMML();
return $mmlMrow->encapsulate( $mmlMrow->encapsulate(
$mtextLeft->encapsulate( $this->getLeft()->renderMML() ) . $mtextRight->encapsulate( $right ) ) );
}
public function extractIdentifiers( $args = null ) {
return [];
}

View file

@ -25,6 +25,13 @@ class Curly extends TexNode {
return $this->arg->inCurlies();
}
public function renderMML( $arguments = [] ) {
// J4T set17
//$mmlRow = new MMLmrow();
//return $mmlRow->encapsulate(parent::renderMML($arguments));
return parent::renderMML( $arguments );
}
public function inCurlies() {
return $this->render();
}

View file

@ -4,6 +4,10 @@ declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\TexVC\Nodes;
use MediaWiki\Extension\Math\TexVC\MMLmappings\BaseMethods;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmrow;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmsub;
class DQ extends TexNode {
/** @var TexNode */
private $base;
@ -34,6 +38,20 @@ class DQ extends TexNode {
return $this->base->render() . '_' . $this->down->inCurlies();
}
public function renderMML( $arguments = [] ) {
// Check if there is a specific parsing in BaseMethods
$bm = new BaseMethods();
$res = $bm->checkAndParse( $this->base->getArgs()[0], $this, $arguments, null );
if ( $res ) {
return $res;
} else {
// Otherwise use default fallback
$mmlMrow = new MMLmrow();
$msub = new MMLmsub();
return $msub->encapsulate( $this->base->renderMML() . $mmlMrow->encapsulate( $this->down->renderMML() ) );
}
}
public function extractIdentifiers( $args = null ) {
$d = $this->down->extractSubscripts();
$b = $this->base->extractIdentifiers();

View file

@ -4,6 +4,8 @@ declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\TexVC\Nodes;
use MediaWiki\Extension\Math\TexVC\MMLmappings\BaseMethods;
class Declh extends TexNode {
/** @var string */
@ -39,6 +41,16 @@ class Declh extends TexNode {
return '{' . $this->fname . ' ' . $this->arg->inCurlies() . '}';
}
public function renderMML( $arguments = [] ) {
$bm = new BaseMethods();
$res = $bm->checkAndParse( $this->fname, $this, $arguments, null );
if ( $res ) {
return $res;
} else {
return "not implemented yet Declh parsing";
}
}
public function extractIdentifiers( $args = null ) {
if ( $args == null ) {
$args = [ $this->arg ];

View file

@ -4,6 +4,11 @@ declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\TexVC\Nodes;
use MediaWiki\Extension\Math\TexVC\MMLmappings\BaseMethods;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmrow;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmsubsup;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmunderover;
class FQ extends TexNode {
/** @var TexNode */
@ -45,6 +50,40 @@ class FQ extends TexNode {
return $this->base->render() . '_' . $this->down->inCurlies() . '^' . $this->up->inCurlies();
}
public function renderMML( $arguments = [] ) {
$bm = new BaseMethods();
if ( $this->getArgs()[0]->getLength() == 0 ) {
// this happens when FQ is located in Sideset (is this a common parsing way?)
$mrow = new MMLmrow();
return $mrow->encapsulate( $this->getDown()->renderMML() ) .
$mrow->encapsulate( $this->getUp()->renderMML() );
}
// Not sure if this case is necessary ..
if ( is_string( $this->getArgs()[0] ) ) {
$res = $bm->checkAndParse( $this->getArgs()[0], $this, $arguments, null );
if ( $res ) {
return $res;
} else {
return "Not Implemented FQ for: " . $this->getArgs()[0];
}
}
$melement = new MMLmsubsup();
// tbd check for more such cases like TexUtilTest 317
$base = $this->getBase();
if ( $base instanceof Literal ) {
if ( trim( $this->getBase()->getArgs()[0] ) === "\\sum" ) {
$melement = new MMLmunderover();
}
}
// This seems to be the common case
$mrow = new MMLmrow();
return $melement->encapsulate( $this->getBase()->renderMML() .
$mrow->encapsulate( $this->getDown()->renderMML() ) . $mrow->encapsulate( $this->getUp()->renderMML() ) );
}
public function name() {
return 'FQ';
}

View file

@ -4,6 +4,10 @@ declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\TexVC\Nodes;
use MediaWiki\Extension\Math\TexVC\MMLmappings\BaseMethods;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmo;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmover;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmrow;
use MediaWiki\Extension\Math\TexVC\TexUtil;
class Fun1 extends TexNode {
@ -44,6 +48,31 @@ class Fun1 extends TexNode {
return '{' . $this->fname . ' ' . $this->arg->inCurlies() . '}';
}
public function renderMML( $arguments = [] ) {
$bm = new BaseMethods();
$res = $bm->checkAndParse( $this->fname, $this, $arguments, null );
if ( $res ) {
return $res;
} else {
return "Not Implemented Fun1 for: " . $this->fname;
}
}
public function createMover( $inner, $moArgs = [] ): string {
$mrow = new MMLmrow();
$mo = new MMLmo( "", $moArgs );
$mover = new MMLmover();
$ret = $mrow->encapsulate(
$mrow->encapsulate(
$mover->encapsulate(
$this->args[1]->renderMML() .
$mo->encapsulate( $inner )
)
)
);
return $ret;
}
public function extractIdentifiers( $args = null ) {
if ( $args == null ) {
$args = [ $this->arg ];
@ -85,4 +114,5 @@ class Fun1 extends TexNode {
public function name() {
return 'FUN1';
}
}

View file

@ -4,6 +4,8 @@ declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\TexVC\Nodes;
use MediaWiki\Extension\Math\TexVC\MMLmappings\BaseMethods;
class Fun1nb extends Fun1 {
public function name() {
@ -17,4 +19,38 @@ class Fun1nb extends Fun1 {
public function render() {
return $this->fname . ' ' . $this->arg->inCurlies() . ' ';
}
public function renderMML( $arguments = [] ) {
$bm = new BaseMethods();
$res = $bm->checkAndParse( $this->fname, $this, $arguments, null );
if ( $res ) {
return $res;
} else {
return "Not Implemented Fun1nb for: " . $this->fname;
}
// This is very preliminary and should most probably be synced with the mappings from time to time
// this might move to Fun1.php
/**
* $mrow = new MMLmrow();
* $mo = new MMLmo();
* switch($this->fname) {
* case "\\mathrm":
*
* $diff = $this->arg->getArg()->mmlSquash(true, false);
* if($diff<=0){
* $arguments = array_merge([ "mathvariant"=>"normal"], $arguments);
* }
* return $mrow->encapsulate($this->arg->renderMML($arguments));
*
* case "\\operatorname":
* // Very experimental rule here, squashed elements with 'd' are without args, others with 'd' have
* $diff = $this->arg->getArg()->mmlSquash(true, false);
* if($diff<=0){
* $arguments = array_merge(["data-mjx-texclass"=>"OP", "mathvariant"=>"normal"], $arguments);
* }
* return $this->arg->renderMML($arguments);
* };
* return parent::renderMML($arguments); // TODO: Change the autogenerated stub
*/
}
}

View file

@ -4,6 +4,8 @@ declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\TexVC\Nodes;
use MediaWiki\Extension\Math\TexVC\MMLmappings\BaseMethods;
class Fun2 extends TexNode {
/** @var string */
@ -49,6 +51,16 @@ class Fun2 extends TexNode {
return '{' . $this->fname . ' ' . $this->arg1->inCurlies() . $this->arg2->inCurlies() . '}';
}
public function renderMML( $arguments = [] ) {
$bm = new BaseMethods();
$res = $bm->checkAndParse( $this->fname, $this, $arguments, null );
if ( $res ) {
return $res;
} else {
return "NotImplemented Fun2 for: " . $this->fname;
}
}
public function extractIdentifiers( $args = null ) {
if ( $args == null ) {
$args = [ $this->arg1, $this->arg2 ];

View file

@ -4,6 +4,8 @@ declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\TexVC\Nodes;
use MediaWiki\Extension\Math\TexVC\MMLmappings\BaseMethods;
class Infix extends TexNode {
/** @var string */
@ -51,6 +53,16 @@ class Infix extends TexNode {
$this->arg2->render() . '}';
}
public function renderMML( $arguments = [] ) {
$bm = new BaseMethods();
$res = $bm->checkAndParse( $this->op, $this, $arguments, null );
if ( $res ) {
return $res;
} else {
return "Not Implemented Infix for: " . $this->getArgs()[0];
}
}
public function extractIdentifiers( $args = null ) {
if ( $args == null ) {
$args = [ $this->arg1, $this->arg2 ];

View file

@ -4,6 +4,10 @@ declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\TexVC\Nodes;
use MediaWiki\Extension\Math\TexVC\MMLmappings\BaseMethods;
use MediaWiki\Extension\Math\TexVC\MMLmappings\Util\MMLutil;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmi;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmn;
use MediaWiki\Extension\Math\TexVC\TexUtil;
class Literal extends TexNode {
@ -21,6 +25,67 @@ class Literal extends TexNode {
array_push( $this->extendedLiterals, '\\infty', '\\emptyset' );
}
public function renderMML( $arguments = [] ) {
if ( is_numeric( $this->arg ) ) {
$mn = new MMLmn( "", $arguments );
return $mn->encapsulate( $this->arg );
}
// is important to split and find chars within curly and differentiate, see tc 459
$foundOperatorContent = MMLutil::initalParseLiteralExpression( $this->arg );
if ( !$foundOperatorContent ) {
$input = $this->arg;
$operatorContent = null;
} else {
$input = $foundOperatorContent[1][0];
$operatorContent = $foundOperatorContent[2][0];
}
// This is rather a workaround:
// Sometimes literals from TexVC contain complete \\operatorname {asd} hinted as bug tex-2-mml.json
if ( str_contains( $input, "\\operatorname" ) ) {
$mi = new MMLmi();
return $mi->encapsulate( $operatorContent );
}
// Sieve for Operators
$bm = new BaseMethods();
$ret = $bm->checkAndParseOperator( $input, $this, $arguments, $operatorContent );
if ( $ret ) {
return $ret;
}
// Sieve for mathchar07 chars
$bm = new BaseMethods();
$ret = $bm->checkAndParseMathCharacter( $input, $this, $arguments, $operatorContent );
if ( $ret ) {
return $ret;
}
// Sieve for Identifiers
$ret = $bm->checkAndParseIdentifier( $input, $this, $arguments, $operatorContent );
if ( $ret ) {
return $ret;
}
// Sieve for Delimiters
$ret = $bm->checkAndParseDelimiter( $input, $this, $arguments, $operatorContent );
if ( $ret ) {
return $ret;
}
// Sieve for Colors
$ret = $bm->checkAndParseColor( $input, $this, $arguments, $operatorContent );
if ( $ret ) {
return $ret;
}
// Sieve for Makros
$ret = $bm->checkAndParse( $input, $this, $arguments, $operatorContent );
if ( $ret ) {
return $ret;
}
// If falling through all sieves just create an MI element
$mi = new MMLmi( "", $arguments );
return $mi->encapsulate( $input ); // $this->arg
}
/**
* @return string
*/
@ -28,6 +93,10 @@ class Literal extends TexNode {
return $this->arg;
}
public function setArg( $arg ) {
$this->arg = $arg;
}
/**
* @return int[]|string[]
*/

View file

@ -4,6 +4,11 @@ declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\TexVC\Nodes;
use MediaWiki\Extension\Math\TexVC\MMLmappings\BaseMethods;
use MediaWiki\Extension\Math\TexVC\MMLmappings\TexConstants\TexClass;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmo;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmrow;
class Lr extends TexNode {
/** @var string */
@ -49,6 +54,44 @@ class Lr extends TexNode {
return '\\left' . $this->left . $this->arg->render() . '\\right' . $this->right;
}
public function renderMML( $arguments = [] ) {
// TBD set attributes for right AND left correctly
$rightAttrs = [];
if ( $this->right == "." ) {
$rightAttrs = [ "fence" => "true", "stretchy" => "true", "symmetric" => "true" ];
}
$bm = new BaseMethods();
$left = $bm->checkAndParseDelimiter( $this->left, $this, [], null, false,
TexClass::OPEN );
if ( !$left ) {
$moLeft = new MMLmo( TexClass::OPEN, [] );
$left = $moLeft->encapsulate( $this->right );
}
$right = $bm->checkAndParseDelimiter( $this->right, $this, $rightAttrs, null, false,
TexClass::CLOSE );
if ( !$right ) {
$moRight = new MMLmo( TexClass::CLOSE, $rightAttrs );
$right = $moRight->encapsulate( $this->right );
}
$inner = $this->getArg()->renderMML();
$mrow = new MMLmrow( TexClass::INNER );
return $mrow->encapsulate(
$left . $inner .
$right
);
}
private function mmlTranslate( $input ) {
switch ( trim( $input ) ) {
case "\\vert":
return "|";
default:
return $input;
}
}
public function containsFunc( $target, $args = null ) {
if ( $args == null ) {
$args = [ '\\left','\\right', $this->arg ];

View file

@ -5,6 +5,7 @@ declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\TexVC\Nodes;
use InvalidArgumentException;
use MediaWiki\Extension\Math\TexVC\MMLmappings\BaseMethods;
class Matrix extends TexNode {
@ -62,6 +63,16 @@ class Matrix extends TexNode {
return '{\\begin{' . $this->top . '}' . $this->renderMatrix( $this->mainarg ) . '\\end{' . $this->top . '}}';
}
public function renderMML( $arguments = [] ) {
$bm = new BaseMethods();
$res = $bm->checkAndParse( $this->getTop(), $this, $arguments, null );
if ( $res ) {
return $res;
} else {
return "Not Implemented Matrix for: " . $this->getArgs()[0];
}
}
private function renderMatrix( $matrix ) {
$mapped = array_map( [ self::class, 'renderLine' ], $matrix->args );
return implode( '\\\\', $mapped );

View file

@ -5,6 +5,7 @@ declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\TexVC\Nodes;
use InvalidArgumentException;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmstyle;
class TexArray extends TexNode {
@ -21,6 +22,56 @@ class TexArray extends TexNode {
parent::__construct( ...$nargs );
}
public function checkForStyleArgs( $node ) {
if ( $node instanceof Literal ) {
$name = trim( $node->getArg() );
switch ( $name ) {
case "\\displaystyle":
return [ "displaystyle" => "true", "scriptlevel" => "0" ];
case "\\scriptstyle":
return [ "displaystyle" => "false", "scriptlevel" => "1" ];
case "\\scriptscriptstyle":
return [ "displaystyle" => "false", "scriptlevel" => "2" ];
case "\\textstyle":
return [ "displaystyle" => "false", "scriptlevel" => "0" ];
}
}
return null;
}
public function renderMML( $arguments = [] ) {
// Everything here is for parsing displaystyle, probably refactored to TexVC grammar later
$fullRenderedArray = "";
$mmlStyle = null;
for ( $i = 0, $count = count( $this->args ); $i < $count; $i++ ) {
$current = $this->args[$i];
if ( isset( $this->args[$i + 1] ) ) {
$next = $this->args[$i + 1];
} else {
$next = null;
}
$styleArguments = $this->checkForStyleArgs( $current );
// For cases with "displaystyle{someargs} otherargs"
if ( $styleArguments ) {
$mmlStyle = new MMLmstyle( "", $styleArguments );
$fullRenderedArray .= $mmlStyle->getStart();
if ( $next instanceof Curly ) {
$fullRenderedArray .= $next->renderMML( $arguments );
$fullRenderedArray .= $mmlStyle->getEnd();
$mmlStyle = null;
$i++;
}
} else {
$fullRenderedArray .= $current->renderMML( $arguments );
}
}
if ( $mmlStyle ) {
$fullRenderedArray .= $mmlStyle->getEnd();
}
return $fullRenderedArray;
}
public function inCurlies() {
if ( isset( $this->args[0] ) && count( $this->args ) == 1 ) {
return $this->args[0]->inCurlies();
@ -97,6 +148,10 @@ class TexArray extends TexNode {
array_push( $this->args, ...$elements );
}
public function pop() {
array_splice( $this->args, 0, 1 );
}
/**
* @return TexNode|string|null first value
*/

View file

@ -39,6 +39,19 @@ class TexNode {
return $out;
}
public function renderMML( $arguments = [] ) {
return array_reduce( $this->args, function ( $out, $child ) use ( $arguments ) {
return $out . $this->renderChildMML( $child, $arguments );
}, '' );
}
public function renderChildMML( $child, $arguments ) {
if ( $child instanceof TexNode ) {
return $child->renderMML( $arguments );
}
return $child;
}
public function getLength(): ?int {
if ( isset( $this->args[0] ) ) {
return count( $this->args );

View file

@ -4,6 +4,10 @@ declare( strict_types = 1 );
namespace MediaWiki\Extension\Math\TexVC\Nodes;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmover;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmrow;
use MediaWiki\Extension\Math\TexVC\MMLnodes\MMLmsup;
class UQ extends TexNode {
/** @var TexNode */
@ -35,6 +39,21 @@ class UQ extends TexNode {
return $this->base->render() . '^' . $this->up->inCurlies();
}
public function renderMML( $arguments = [] ) {
$mrow = new MMLmrow();
$mmlBase = new MMLmsup();
// Sometimes 'overbrace' or similar seems to determine the wrapping element here.
if ( $this->getBase() instanceof Fun1nb && str_starts_with( $this->getBase()->getArgs()[0], "\\o" ) ) {
$mmlBase = new MMLmover();
}
return $mmlBase->encapsulate(
$this->base->renderMML( $arguments ) .
$mrow->getStart() . // up is inferring a new mrow
$this->up->renderMML( $arguments ) .
$mrow->getEnd()
);
}
public function name() {
return 'UQ';
}