Файловый менеджер - Редактировать - /var/www/html/MMLmappings.zip
Ðазад
PK ! ���"�� �� BaseParsing.phpnu �Iw�� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings; use IntlChar; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\Misc; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\Sizes; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\Tag; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\TexClass; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\Variants; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Util\MMLParsingUtil; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Util\MMLutil; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmenclose; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmerror; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmfrac; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmi; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmmultiscripts; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmo; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmover; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmpadded; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmphantom; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmroot; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmrow; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmspace; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmsqrt; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmstyle; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmsub; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmsup; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmtable; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmtd; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmtext; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmtr; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmunder; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmunderover; use MediaWiki\Extension\Math\WikiTexVC\Nodes\DQ; use MediaWiki\Extension\Math\WikiTexVC\Nodes\FQ; use MediaWiki\Extension\Math\WikiTexVC\Nodes\Fun1; use MediaWiki\Extension\Math\WikiTexVC\Nodes\Fun1nb; use MediaWiki\Extension\Math\WikiTexVC\Nodes\Fun2; use MediaWiki\Extension\Math\WikiTexVC\Nodes\Fun2sq; use MediaWiki\Extension\Math\WikiTexVC\Nodes\Fun4; use MediaWiki\Extension\Math\WikiTexVC\Nodes\Literal; use MediaWiki\Extension\Math\WikiTexVC\Nodes\Matrix; use MediaWiki\Extension\Math\WikiTexVC\Nodes\TexArray; use MediaWiki\Extension\Math\WikiTexVC\Nodes\TexNode; use MediaWiki\Extension\Math\WikiTexVC\Nodes\UQ; use MediaWiki\Extension\Math\WikiTexVC\TexUtil; use MediaWiki\Extension\Math\WikiTexVC\TexVC; /** * 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; } $mrow = new MMLmrow(); $mo = new MMLmo( "", $attrs ); // $passedArgs $mover = new MMLmover(); $ret = $mrow->encapsulateRaw( $mrow->encapsulateRaw( $mover->encapsulateRaw( $node->getArg()->renderMML( $passedArgs ) . $mo->encapsulateRaw( $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 = TexUtil::getInstance()->delimiter( trim( $open ) ) ?? false; if ( $resDelimiter ) { // $retDelim = $bm->checkAndParseDelimiter($open, $node,$passedArgs,true); $moOpen = new MMLmo( TexClass::OPEN ); $output .= $moOpen->encapsulateRaw( $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->encapsulateRaw( $node->getMainarg()->renderMML() ); } if ( $close != null ) { $resDelimiter = TexUtil::getInstance()->delimiter( trim( $close ) ) ?? false; if ( $resDelimiter ) { $moClose = new MMLmo( TexClass::CLOSE ); $output .= $moClose->encapsulateRaw( $resDelimiter[0] ); } } return $output; } public static function alignAt( Matrix $node, $passedArgs, $operatorContent, $name, $smth, $smth2 = null ) { // Parsing is very similar to AmsEQArray, maybe extract function ... tcs: 178 $mrow = new MMLmrow(); $mtable = new MMLmtable( "" ); $mtr = new MMLmtr(); $mtd = new MMLmtd(); $renderedInner = ""; foreach ( $node as $tableRow ) { $renderedInner .= $mtr->getStart(); foreach ( $tableRow->getArgs() as $tableCell ) { $renderedInner .= $mtd->getStart() . $tableCell->renderMML() . $mtd->getEnd(); } $renderedInner .= $mtr->getEnd(); } return $mrow->encapsulateRaw( $mtable->encapsulateRaw( $renderedInner ) ); } public static function amsEqnArray( $node, $passedArgs, $operatorContent, $name, $smth, $smth2 = null ) { $mrow = new MMLmrow(); $mtable = new MMLmtable( '' ); $mtr = new MMLmtr(); $mtd = new MMLmtd(); $renderedInner = ""; foreach ( $node as $tableRow ) { $renderedInner .= $mtr->getStart(); foreach ( $tableRow->getArgs() as $tableCell ) { $renderedInner .= $mtd->encapsulateRaw( $tableCell->renderMML() ); // pass args here ? } $renderedInner .= $mtr->getEnd(); } return $mrow->encapsulateRaw( $mtable->encapsulateRaw( $renderedInner ) ); } public static function boldsymbol( $node, $passedArgs, $operatorContent, $name, $smth = null, $smth2 = null ) { $mrow = new MMLmrow(); $passedArgs = array_merge( [ "mathvariant" => Variants::BOLDITALIC ] ); return $mrow->encapsulateRaw( $node->getArg()->renderMML( $passedArgs ) ); } public static function cancel( Fun1 $node, $passedArgs, $operatorContent, $name, $notation = '' ): string { $outer = new MMLmenclose( '', [ 'notation' => $notation, 'class' => 'menclose' ] ); $bars = ''; foreach ( explode( ' ', $notation ) as $element ) { $bars .= ( new MMLmrow( '', [ 'class' => 'menclose-' . $element ] ) )->getEmpty(); } return $outer->encapsulateRaw( $node->getArg()->renderMML() . $bars ); } 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->encapsulateRaw( $node->getArg2()->renderMML() ) . $mpAdded->encapsulateRaw( $node->getArg1()->renderMML() ); return $mrow->encapsulateRaw( $msup->encapsulateRaw( $inner ) ); } public static function chemCustom( $node, $passedArgs, $operatorContent, $name, $translation = null ) { return $translation ?: 'tbd chemCustom'; } public static function customLetters( $node, $passedArgs, $operatorContent, $name, $char, $isOperator = false ) { $mrow = new MMLmrow(); if ( $isOperator ) { $mo = new MMLmo(); return $mrow->encapsulateRaw( $mo->encapsulateRaw( $char ) ); } $mi = new MMLmi( "", [ "mathvariant" => "normal" ] ); return $mrow->encapsulateRaw( $mi->encapsulateRaw( $char ) ); } 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->encapsulateRaw( $whatIsThis . $mstyle->encapsulateRaw( $mrow->encapsulateRaw( $node->getArg1()->renderMML() ) ) ) . $mrow->encapsulateRaw( $whatIsThis . $mstyle->encapsulateRaw( $mrow->encapsulateRaw( $node->getArg2()->renderMML() ) ) ); return $mrow->encapsulateRaw( $mfrac->encapsulateRaw( $inner ) ); } public static function crLaTeX( $node, $passedArgs, $operatorContent, $name ) { $mspace = new MMLmspace( "", [ "linebreak" => "newline" ] ); return $mspace->getEmpty(); } 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->encapsulateRaw( "…" ); } public static function genFrac( $node, $passedArgs, $operatorContent, $name, $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 ( in_array( $thick, [ 'thin', 'medium', 'thick', '0' ], true ) ) { $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->encapsulateRaw( "Bad math style" ); } if ( $styleAlpha === 'D' ) { // NodeUtil_js_1.default.setProperties(frac, { displaystyle: true, scriptlevel: 0 }); // tbd add props $displayStyle = "true"; $styleAttr = [ "minsize" => "2.047em" ]; } else { $styleAttr = [ "minsize" => "1.2em" ]; } /* @phan-suppress-next-line SecurityCheck-DoubleEscaped */ $frac = new MMLmfrac( '', $attrs ); } else { // NodeUtil_js_1.default.setProperties(frac, { displaystyle: false, // scriptlevel: styleDigit - 1 }); // tbd add props /* @phan-suppress-next-line SecurityCheck-DoubleEscaped */ $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->encapsulateRaw( $moL->encapsulateRaw( $left ) ); } $output .= $frac->encapsulateRaw( $mrow->encapsulateRaw( $node->getArg1()->renderMML() ) . $mrow->encapsulateRaw( $node->getArg2()->renderMML() ) ); if ( $right ) { $mrowClose = new MMLmrow( TexClass::CLOSE ); $moR = new MMLmo( "", $styleAttr ); $output .= $mrowClose->encapsulateRaw( $moR->encapsulateRaw( $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 instanceof Fun2 ) { $inner = $mrow->encapsulateRaw( $node->getArg1()->renderMML() ) . $mrow->encapsulateRaw( $node->getArg2()->renderMML() ); } elseif ( $node instanceof DQ ) { $inner = $mrow->encapsulateRaw( $node->getBase()->renderMML() ) . $mrow->encapsulateRaw( $node->getDown()->renderMML() ); } else { $inner = ""; foreach ( $node->getArgs() as $arg ) { $rendered = is_string( $arg ) ? $arg : $arg->renderMML(); $inner .= $mrow->encapsulateRaw( $rendered ); } } return $mrow->encapsulateRaw( $mfrac->encapsulateRaw( $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->encapsulateRaw( "HLINE TBD" ); } public static function hskip( $node, $passedArgs, $operatorContent, $name ) { if ( $node->getArg()->isCurly() ) { $unit = MMLutil::squashLitsToUnit( $node->getArg() ); if ( !$unit ) { return null; } $em = MMLutil::dimen2em( $unit ); } else { // Prevent parsing in unmapped cases return null; } // Added kern j4t if ( $name == "mskip" || $name == "mkern" || "kern" ) { $args = [ "width" => $em ]; } else { return null; } $mspace = new MMLmspace( "", $args ); return $mspace->encapsulateRaw( "" ); } public static function handleOperatorName( $node, $passedArgs, $operatorContent, $name ) { // In example "\\operatorname{a}" $applyFct = self::getApplyFct( $operatorContent ); $mmlNot = ""; if ( isset( $operatorContent['not'] ) && $operatorContent['not'] ) { $mmlNot = MMLParsingUtil::createNot(); } $passedArgs = array_merge( $passedArgs, [ Tag::CLASSTAG => TexClass::OP, "mathvariant" => Variants::NORMAL ] ); $state = [ 'squashLiterals' => true ]; return $mmlNot . $node->getArg()->renderMML( $passedArgs, $state ) . $applyFct; } public static function lap( $node, $passedArgs, $operatorContent, $name ) { if ( !$node instanceof Fun1 ) { return null; } if ( trim( $name ) === "\\rlap" ) { $args = [ "width" => "0" ]; } elseif ( trim( $name ) === "\\llap" ) { $args = [ "width" => "0", "lspace" => "-1width" ]; } else { return null; } $mrow = new MMLmrow(); $mpAdded = new MMLmpadded( "", $args ); return $mrow->encapsulateRaw( $mpAdded->encapsulateRaw( $node->getArg()->renderMML() ) ); } public static function macro( $node, $passedArgs, $operatorContent, $name, $macro = '', $argcount = null, $def = null ) { // Parse the Macro if ( $macro == "\\text{ }" ) { $mtext = new MMLmtext(); return $mtext->encapsulateRaw( ' ' ); } switch ( trim( $name ) ) { case "\\mod": $mmlRow = new MMLmrow(); $mo = new MMLmo( "", [ "lspace" => "2.5pt", "rspace" => "2.5pt" ] ); // @phan-suppress-next-line PhanUndeclaredMethod $inner = $node->getArg() instanceof TexNode ? $node->getArg()->renderMML() : ""; return $mmlRow->encapsulateRaw( $mo->encapsulate( "mod" ) . $inner ); 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(); // @phan-suppress-next-line PhanUndeclaredMethod $inner = $node->getArg() instanceof TexNode ? $node->getArg()->renderMML() : ""; return $mmlRow->encapsulateRaw( $mspace->encapsulate() . $mo->encapsulate( "(" ) . $mi->encapsulate( "mod" ) . $mspace2->encapsulate() . $inner . $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 ( trim( $name ) === "\\varlimsup" ) { $movu = new MMLmover(); } else { $movu = new MMLmunder(); } $mmlMi = new MMLmi(); $mo = new MMLmo( "", [ "accent" => "true" ] ); return $mmlRow->encapsulateRaw( $movu->encapsulateRaw( $mmlMi->encapsulateRaw( "lim" ) . $mo->encapsulateRaw( "―" ) ) ); case "\\varinjlim": $mmlRow = new MMLmrow( TexClass::OP ); $mmlMunder = new MMLmunder(); $mi = new MMLmi(); $mo = new MMLmo(); return $mmlRow->encapsulateRaw( $mmlMunder->encapsulateRaw( $mi->encapsulateRaw( "lim" ) . $mo->encapsulateRaw( "→" ) ) ); case "\\varprojlim": $mmlRow = new MMLmrow( TexClass::OP ); $mmlMunder = new MMLmunder(); $mi = new MMLmi(); $mo = new MMLmo(); return $mmlRow->encapsulateRaw( $mmlMunder->encapsulateRaw( $mi->encapsulate( "lim" ) . $mo->encapsulateRaw( "←" ) ) ); 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 ); if ( $node instanceof DQ ) { $inner = $mover->encapsulateRaw( $mmlRowArg2->encapsulateRaw( $node->getBase()->renderMML() ) . $mmlRow->encapsulateRaw( $node->getDown()->renderMML() ) ); } else { $inner = $mover->encapsulateRaw( $mmlRowArg2->encapsulateRaw( // @phan-suppress-next-line PhanUndeclaredMethod $node->getArg2()->renderMML() ) . // @phan-suppress-next-line PhanUndeclaredMethod $mmlRow->encapsulateRaw( $node->getArg1()->renderMML() ) ); } return $mmlRow->encapsulateRaw( $mmlRowInner->encapsulateRaw( $inner ) ); case "\\bmod": $mo = new MMLmo( "", [ "lspace" => Sizes::THICKMATHSPACE, "rspace" => Sizes::THICKMATHSPACE ] ); $mmlRow = new MMLmrow( TexClass::ORD ); $mspace = new MMLmspace( "", [ "width" => "0.167em" ] ); // @phan-suppress-next-line PhanUndeclaredMethod $inner = $node->getArg() instanceof TexNode ? // @phan-suppress-next-line PhanUndeclaredMethod $mmlRow->encapsulateRaw( $node->getArg()->renderMML() ) : ""; return $mmlRow->encapsulateRaw( $mo->encapsulate( "mod" ) . $inner . $mmlRow->encapsulateRaw( $mspace->getEmpty() ) ); case "\\implies": $mstyle = new MMLmstyle( "", [ "scriptlevel" => "0" ] ); $mspace = new MMLmspace( "", [ "width" => "0.278em" ] ); $mo = new MMLmo(); return $mstyle->encapsulateRaw( $mspace->getEmpty() ) . $mo->encapsulateRaw( "⟹" ) . $mstyle->encapsulateRaw( $mspace->getEmpty() ); case "\\iff": $mstyle = new MMLmstyle( "", [ "scriptlevel" => "0" ] ); $mspace = new MMLmspace( "", [ "width" => "0.278em" ] ); $mo = new MMLmo(); return $mstyle->encapsulateRaw( $mspace->getEmpty() ) . $mo->encapsulateRaw( "⟺" ) . $mstyle->encapsulateRaw( $mspace->getEmpty() ); case "\\tripledash": // Using emdash for rendering here. $mo = new MMLmo(); return $mo->encapsulateRaw( "—" ); case "\\longrightleftharpoons": case "\\longLeftrightharpoons": case "\\longRightleftharpoons": $texvc = new TexVC(); $warnings = []; $checkRes = $texvc->check( $macro, [ "usemhchem" => true, "usemhchemtexified" => true ], $warnings, true ); return $checkRes["input"]->renderMML(); case "\\longleftrightarrows": // The tex-cmds used in makro are not supported, just use a hardcoded mml macro here. $mtext = new MMLmtext(); $mrowRel = new MMLmrow( TexClass::REL ); $mrowOrd = new MMLmrow( TexClass::ORD ); $mrowOp = new MMLmrow( TexClass::OP ); $mover = new MMLmover(); $mpadded = new MMLmpadded( "", [ "height" => "0", "depth" => "0" ] ); $mo = new MMLmo( "", [ "stretchy" => "false" ] ); $mspace = new MMLmspace( "", [ "width" => "0px", "height" => ".25em", "depth" => "0px", "mathbackground" => "black" ] ); return $mtext->encapsulateRaw( " " ) . $mrowRel->encapsulateRaw( $mover->encapsulateRaw( $mrowOp->encapsulateRaw( $mrowOrd->encapsulateRaw( $mpadded->encapsulateRaw( $mo->encapsulateRaw( "⟵" ) ) ) . $mspace->getEmpty() ) . $mrowOrd->encapsulateRaw( $mo->encapsulateRaw( "⟶" ) ) ) ); } // 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( 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(); $tableArgs = [ "columnspacing" => "1em", "rowspacing" => "4pt" ]; $boarder = $node->getBoarder(); if ( $align ) { $tableArgs['columnalign'] = $align; } elseif ( $node->hasColumnInfo() ) { $tableArgs['columnalign'] = $node->getAlignInfo(); } $rowNo = 0; $lines = $node->getLines(); foreach ( $node as $row ) { $resInner .= $mtr->getStart(); $colNo = 0; foreach ( $row as $cell ) { $usedArg = clone $cell; if ( $usedArg instanceof TexArray && $usedArg->getLength() >= 1 && $usedArg[0] instanceof Literal && $usedArg[0]->getArg() === '\\hline ' ) { $usedArg->pop(); if ( $rowNo === $node->getLength() - 1 && $usedArg->getLength() === 0 ) { // remove the started row $resInner = substr( $resInner, 0, -1 * strlen( $mtr->getStart() ) ); continue 2; } } $mtdAttributes = []; $texclass = $lines[$rowNo] ? TexClass::TOP : ''; $texclass .= $lines[$rowNo + 1] ?? false ? ' ' . TexClass::BOTTOM : ''; $texclass .= $boarder[$colNo] ?? false ? ' ' . TexClass::LEFT : ''; $texclass .= $boarder[$colNo + 1 ] ?? false ? ' ' . TexClass::RIGHT : ''; $texclass = trim( $texclass ); if ( $texclass ) { $mtdAttributes['class'] = $texclass; } $mtd = new MMLmtd( '', $mtdAttributes ); $state = [ 'inMatrix' => true ]; $resInner .= $mtd->encapsulateRaw( $usedArg->renderMML( $passedArgs, $state ) ); $colNo++; } $resInner .= $mtr->getEnd(); $rowNo++; } $mrow = new MMLmrow(); $mtable = new MMLmtable( "", $tableArgs ); if ( $cases || ( $open != null && $close != null ) ) { $bm = new BaseMethods(); $mmlMoOpen = $bm->checkAndParseDelimiter( $open, $node, [], [], true, TexClass::OPEN ); if ( $mmlMoOpen == null ) { $mmlMoOpen = new MMLmo( TexClass::OPEN, [] ); $mmlMoOpen = $mmlMoOpen->encapsulateRaw( $open ?? '' ); } $closeAtts = [ "fence" => "true", "stretchy" => "true", "symmetric" => "true" ]; $mmlMoClose = $bm->checkAndParseDelimiter( $close, $node, $closeAtts, null, true, TexClass::CLOSE ); if ( $mmlMoOpen == null ) { $mmlMoClose = new MMLmo( TexClass::CLOSE, $closeAtts ); $mmlMoClose = $mmlMoClose->encapsulateRaw( $close ); } $resInner = $mmlMoOpen . $mtable->encapsulateRaw( $resInner ) . $mmlMoClose; return $mrow->encapsulateRaw( $resInner ); } return $mtable->encapsulateRaw( $resInner ); } public static function namedOp( $node, $passedArgs, $operatorContent, $name, $id = null ) { /* Determine whether the named function should have an added apply function. The operatorContent is defined as state in parsing of TexArray */ $applyFct = self::getApplyFct( $operatorContent ); if ( $node instanceof Literal ) { $mi = new MMLmi( "", $passedArgs ); return $mi->encapsulateRaw( $id ?? ltrim( $name, '\\' ) ) . $applyFct; } $mrow = new MMLmrow( TexClass::ORD, [] ); $msub = new MMLmsub( "", $passedArgs ); return $msub->encapsulateRaw( $node->getBase()->renderMML() . $applyFct . $mrow->encapsulateRaw( $node->getDown()->renderMML() ) ); } public static function over( $node, $passedArgs, $operatorContent, $name, $id = null ) { $attributes = []; $start = ""; $tail = ""; if ( trim( $name ) === "\\atop" ) { $attributes = [ "linethickness" => "0" ]; } elseif ( trim( $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->encapsulateRaw( $mo->encapsulate( "(" ) ); $tail = $mrowClose->encapsulateRaw( $mo->encapsulate( ")" ) ) . $mrowAll->getEnd(); $attributes = [ "linethickness" => "0" ]; } $mfrac = new MMLmfrac( "", $attributes ); $mrow = new MMLmrow( "", [] ); if ( $node instanceof Fun2 ) { return $start . $mfrac->encapsulateRaw( $mrow->encapsulateRaw( $node->getArg1()->renderMML() ) . $mrow->encapsulateRaw( $node->getArg2()->renderMML() ) ) . $tail; } $inner = ""; foreach ( $node->getArgs() as $arg ) { if ( is_string( $arg ) && str_contains( $arg, $name ) ) { continue; } $rendered = $arg instanceof TexNode ? $arg->renderMML() : $arg; $inner .= $mrow->encapsulateRaw( $rendered ); } return $start . $mfrac->encapsulateRaw( $inner ) . $tail; } public static function oint( $node, $passedArgs, $operatorContent, $name, $uc = null, $attributes = null, $smth2 = null ) { // This is a custom mapping not in js. $mmlText = new MMLmtext( "", $attributes ); $mrow = new MMLmrow(); switch ( trim( $name ) ) { case "\\oint": $mStyle = new MMLmstyle( "", [ "displaystyle" => "true" ] ); $mo = new MMLmo(); return $mStyle->encapsulateRaw( $mo->encapsulateRaw( MMLutil::uc2xNotation( $uc ) ) ); case "\\P": $mo = new MMLmo(); return $mo->encapsulateRaw( MMLutil::uc2xNotation( $uc ) ); case "\\oiint": case "\\oiiint": case "\\ointctrclockwise": case "\\varointclockwise": $mStyle = new MMLmstyle( "", [ "mathsize" => "2.07em" ] ); $mSpace = new MMLmspace( "", [ "width" => Sizes::THINMATHSPACE ] ); return $mrow->encapsulateRaw( $mStyle->encapsulateRaw( $mmlText->encapsulateRaw( MMLutil::uc2xNotation( $uc ) ) . $mSpace->getEmpty() ) ); default: return ( new MMLmerror() )->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( "", [] ); $mover = new MMLmover(); if ( $node instanceof DQ ) { return $mrow->encapsulateRaw( $mover->encapsulateRaw( $mrow2->encapsulateRaw( $node->getDown()->renderMML() . $node->getDown()->renderMML() ) ) ); } else { $inrow = $mrow2->encapsulateRaw( $node->getArg2()->renderMML() ); } return $mrow->encapsulateRaw( $mover->encapsulateRaw( $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->encapsulateRaw( $mrow->encapsulateRaw( $mpadded->encapsulateRaw( $mphantom->encapsulateRaw( $node->getArg()->renderMML() ) ) ) ); } public static function raiseLower( $node, $passedArgs, $operatorContent, $name ) { if ( !$node instanceof Fun2 ) { return null; } $arg1 = $node->getArg1(); // the second check is to avoid a false positive for PhanTypeMismatchArgumentSuperType if ( $arg1->isCurly() && $arg1 instanceof TexArray ) { $unit = MMLutil::squashLitsToUnit( $arg1 ); if ( !$unit ) { return null; } $em = MMLutil::dimen2em( $unit ); if ( !$em ) { return null; } } else { return null; } if ( trim( $name ) === "\\raise" ) { $args = [ "height" => MMLutil::addPreOperator( $em, "+" ), "depth" => MMLutil::addPreOperator( $em, "-" ), "voffset" => MMLutil::addPreOperator( $em, "+" ) ]; } elseif ( trim( $name ) === "\\lower" ) { $args = [ "height" => MMLutil::addPreOperator( $em, "-" ), "depth" => MMLutil::addPreOperator( $em, "+" ), "voffset" => MMLutil::addPreOperator( $em, "-" ) ]; } else { // incorrect name, should not happen, prevent erroneous mappings from getting rendered. return null; } $mrow = new MMLmrow(); $mpAdded = new MMLmpadded( "", $args ); return $mrow->encapsulateRaw( $mpAdded->encapsulateRaw( $node->getArg2()->renderMML() ) ); } public static function underset( $node, $passedArgs, $operatorContent, $name, $smh = null ) { $mrow = new MMLmrow( TexClass::ORD, [] ); $inrow = $node->getArg2()->renderMML(); $arg1 = $node->getArg1()->renderMML(); if ( $inrow && $arg1 ) { $munder = new MMLmunder(); return $mrow->encapsulateRaw( $munder->encapsulateRaw( $inrow . $arg1 ) ); } // If there are no two elements in munder, not render munder return $mrow->encapsulateRaw( $inrow . $arg1 ); } public static function underOver( Fun1 $node, $passedArgs, $operatorContent, $name, $operatorId = null, $stack = null, $nonHex = false ) { // tbd verify if stack interpreted correctly ? $texClass = $stack ? TexClass::OP : TexClass::ORD; // ORD or "" $mrow = new MMLmrow( $texClass ); $fname = $node->getFname(); if ( str_starts_with( $fname, '\\over' ) ) { $movun = new MMLmover(); } elseif ( str_starts_with( $fname, '\\under' ) ) { $movun = new MMLmunder(); } else { // incorrect name, should not happen, prevent erroneous mappings from getting rendered. $merror = new MMLmerror(); return $merror->encapsulateRaw( 'underOver rendering requires macro to start with either \\under or \\over.' ); } if ( $operatorId == 2015 ) { // eventually move such cases to mapping $mo = new MMLmo( "", [ "accent" => "true" ] ); } else { $mo = new MMLmo(); } $inner = $nonHex ? $operatorId : MMLutil::number2xNotation( $operatorId ); return $mrow->encapsulateRaw( $movun->encapsulateRaw( $node->getArg()->renderMML( $passedArgs ) . $mo->encapsulateRaw( $inner ) ) ); } public static function mathFont( $node, $passedArgs, $operatorContent, $name, $mathvariant = null ) { $mrow = new MMLmrow( TexClass::ORD, [] ); $args = MMLParsingUtil::getFontArgs( $name, $mathvariant, $passedArgs ); $state = []; // Unicode fixes for the operators switch ( $mathvariant ) { case Variants::DOUBLESTRUCK: $state = [ "double-struck-literals" => true ]; break; case Variants::CALLIGRAPHIC: $state = [ "calligraphic" => true ]; break; case Variants::BOLDCALLIGRAPHIC: $state = [ "bold-calligraphic" => true ]; break; case Variants::FRAKTUR: $state = [ "fraktur" => true ]; break; case Variants::BOLD: $state = [ "bold" => true ]; break; } if ( $node instanceof Fun1nb ) { // Only one mrow from Fun1nb !? return $mrow->encapsulateRaw( $node->getArg()->renderMML( $args, $state ) ); } return $mrow->encapsulateRaw( $mrow->encapsulateRaw( $node->getArg()->renderMML( $args, $state ) ) ); } public static function mathChoice( $node, $passedArgs, $operatorContent, $name, $smth = null ) { if ( !$node instanceof Fun4 ) { $merror = new MMLmerror(); return $merror->encapsulateRaw( "Wrong node type in mathChoice" ); } /** * Parametrization for mathchoice: * \mathchoice * {<material for display style>} * {<material for text style>} * {<material for script style>} * {<material for scriptscript style>} */ if ( isset( $operatorContent["styleargs"] ) ) { $styleArgs = $operatorContent["styleargs"]; $displayStyle = $styleArgs["displaystyle"] ?? "true"; $scriptLevel = $styleArgs["scriptlevel"] ?? "0"; if ( $displayStyle == "true" && $scriptLevel == "0" ) { // This is displaystyle return $node->getArg1()->renderMML( $passedArgs, $operatorContent ); } elseif ( $displayStyle == "false" && $scriptLevel == "0" ) { // This is textstyle return $node->getArg2()->renderMML( $passedArgs, $operatorContent ); } elseif ( $displayStyle == "false" && $scriptLevel == "1" ) { // This is scriptstyle return $node->getArg3()->renderMML( $passedArgs, $operatorContent ); } elseif ( $displayStyle == "false" && $scriptLevel == "2" ) { // This is scriptscriptstyle return $node->getArg4()->renderMML( $passedArgs, $operatorContent ); } } // By default render displaystyle return $node->getArg1()->renderMML( $passedArgs, $operatorContent ); } 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 "\\|": case "|": $passedArgs = array_merge( $passedArgs, [ "stretchy" => "true", "symmetric" => "true" ] ); break; case "\\uparrow": case "\\downarrow": case "\\Uparrow": case "\\Downarrow": case "\\updownarrow": case "/": case "\\backslash": case "\\Updownarrow": $passedArgs = array_merge( [ "fence" => "true" ], $passedArgs, [ "stretchy" => "true", "symmetric" => "true" ] ); break; } if ( in_array( $name, [ "\\bigl", "\\Bigl", "\\biggl", "\\Biggl" ] ) ) { $passedArgs = array_merge( $passedArgs, [ Tag::CLASSTAG => TexClass::OPEN ] ); } if ( in_array( $name, [ "\\bigr", "\\Bigr", "\\biggr", "\\Biggr" ] ) ) { $passedArgs = array_merge( $passedArgs, [ Tag::CLASSTAG => TexClass::CLOSE ] ); } $ret = $bm->checkAndParseDelimiter( $node->getArg(), $node, $passedArgs, $operatorContent, true ); if ( $ret ) { return $ret; } $argPrep = $node->getArg(); return $mrowOuter->encapsulateRaw( $mrow->encapsulateRaw( $mo->encapsulateRaw( $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->encapsulateRaw( $node->getArg()->renderMML() ); } public static function namedFn( $node, $passedArgs, $operatorContent, $name, $smth = null ) { // Determine wether the named function should have an added apply function. The state is defined in // parsing of TexArray $applyFct = self::getApplyFct( $operatorContent ); if ( $node instanceof Literal ) { $mi = new MMLmi(); return $mi->encapsulateRaw( ltrim( $name, '\\' ) ) . $applyFct; } $mrow = new MMLmrow( TexClass::ORD, [] ); // tbd remove mathjax specifics $msub = new MMLmsub(); return $msub->encapsulateRaw( $node->getBase()->renderMML() . $applyFct . $mrow->encapsulateRaw( $node->getDown()->renderMML() ) ); } public static function limits( $node, $passedArgs, $operatorContent, $name, $smth = null ) { $argsOp = [ 'form' => 'prefix' ]; if ( isset( $operatorContent['styleargs'] ) ) { $displaystyle = $operatorContent['styleargs']['displaystyle'] ?? 'true'; if ( $displaystyle === 'false' ) { $argsOp['movablelimits'] = 'true'; } if ( $node->containsFunc( '\\nolimits' ) ) { $argsOp['movablelimits'] = 'false'; } } $mrow = new MMLmrow( TexClass::ORD, [] ); $opParsed = ( $operatorContent["limits"] ?? false ) ? $operatorContent["limits"]->renderMML( $argsOp ) : ""; if ( $node instanceof DQ ) { $munder = new MMLmunder(); return $munder->encapsulateRaw( $opParsed . $mrow->encapsulateRaw( $node->getDown()->renderMML() ) ); } elseif ( $node instanceof FQ ) { $munderOver = new MMLmunderover(); return $munderOver->encapsulateRaw( $opParsed . $mrow->encapsulateRaw( $node->getDown()->renderMML() ) . $mrow->encapsulateRaw( $node->getUp()->renderMML() ) ); } elseif ( preg_match( '/\s*\\\\?(no)?limits\s*/', $name ) ) { // Don't render limits return ''; } } public static function setFont( $node, $passedArgs, $operatorContent, $name, $variant = null ) { return self::mathFont( $node, $passedArgs, $operatorContent, $name, $variant ); } public static function sideset( $node, $passedArgs, $operatorContent, $name ) { if ( !array_key_exists( "sideset", $operatorContent ) ) { $merror = new MMLmerror(); return $merror->encapsulateRaw( "Error parsing sideset expression, no succeeding operator found" ); } $mmlMrow = new MMLmrow( TexClass::OP ); if ( $operatorContent["sideset"] instanceof Literal ) { $mmlMultiscripts = new MMLmmultiscripts( "", [ Tag::ALIGN => "left" ] ); $bm = new BaseMethods(); $opParsed = $bm->checkAndParseOperator( $operatorContent["sideset"]->getArg(), null, [], [], null ); $in1 = $node->getArg1()->renderMML(); $in2 = $node->getArg2()->renderMML(); return $mmlMrow->encapsulateRaw( $mmlMultiscripts->encapsulateRaw( $opParsed . $in2 . "<mprescripts/>" . $in1 ) ); } if ( $operatorContent["sideset"] instanceof FQ || $operatorContent["sideset"] instanceof DQ || $operatorContent["sideset"] instanceof UQ ) { $mmlMultiscripts = new MMLmmultiscripts( "", [] ); $mmlMunderOver = new MMLmunderover(); $mstyle = new MMLmstyle( "", [ "displaystyle" => "true" ] ); $bm = new BaseMethods(); if ( count( $operatorContent["sideset"]->getBase()->getArgs() ) == 1 ) { $baseOperator = $operatorContent["sideset"]->getBase()->getArgs()[0]; $opParsed = $bm->checkAndParseOperator( $baseOperator, null, [ "largeop" => "true", "movablelimits" => "false", "symmetric" => "true" ], [], null ); if ( $opParsed == null ) { $opParsed = $operatorContent["sideset"]->getBase()->renderMML(); } } else { $merror = new MMLmerror(); $opParsed = $merror->encapsulateRaw( "Sideset operator parsing not implemented yet" ); } $in1 = $node->getArg1()->renderMML(); $in2 = $node->getArg2()->renderMML(); $mrowEnd = new MMLmrow( "", [] ); $down = $operatorContent["sideset"] instanceof UQ ? '<mrow />' : $operatorContent["sideset"]->getDown()->renderMML(); $end1 = $mrowEnd->encapsulateRaw( $down ); $up = $operatorContent["sideset"] instanceof DQ ? '<mrow />' : $operatorContent["sideset"]->getUp()->renderMML(); $end2 = $mrowEnd->encapsulateRaw( $up ); return $mmlMrow->encapsulateRaw( $mmlMunderOver->encapsulateRaw( $mstyle->encapsulateRaw( $mmlMultiscripts->encapsulateRaw( $opParsed . $in2 . "<mprescripts/>" . $in1 ) ) . $end1 . $end2 ) ); } $merror = new MMLmerror(); return $merror->encapsulateRaw( "Error parsing sideset expression, no valid succeeding operator found" ); } public static function spacer( $node, $passedArgs, $operatorContent, $name, $withIn = null, $smth2 = null ) { $width = MMLutil::round2em( $withIn ); $mspace = new MMLmspace( "", [ "width" => $width ] ); return $mspace->encapsulate(); } public static function smash( $node, $passedArgs, $operatorContent, $name ) { $mpArgs = []; $inner = ""; if ( $node instanceof Fun2sq ) { $arg1 = $node->getArg1(); $arg1i = ""; if ( $arg1->isCurly() ) { $arg1i = $arg1->render(); } if ( str_contains( $arg1i, "{b}" ) ) { $mpArgs = [ "depth" => "0" ]; } if ( str_contains( $arg1i, "{t}" ) ) { $mpArgs = [ "height" => "0" ]; } if ( str_contains( $arg1i, "{tb}" ) || str_contains( $arg1i, "{bt}" ) ) { $mpArgs = [ "height" => "0", "depth" => "0" ]; } $inner = $node->getArg2()->renderMML() ?? ""; } elseif ( $node instanceof Fun1 ) { // Implicitly assume "tb" as default mode $mpArgs = [ "height" => "0", "depth" => "0" ]; $inner = $node->getArg()->renderMML() ?? ""; } $mrow = new MMLmrow(); $mpAdded = new MMLmpadded( "", $mpArgs ); return $mrow->encapsulateRaw( $mpAdded->encapsulateRaw( $inner ) ); } 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->encapsulateRaw( $mrow2->encapsulateRaw( $inner ) ); case "mathbin": // no break case "mathop": // no break case "mathrel": $mrow2 = new MMLmrow( $texClass, [] ); $inner = $node->getArg()->renderMML(); return $mrow2->encapsulateRaw( $inner ); default: $mrow = new MMLmrow( TexClass::ORD ); $mrow2 = new MMLmrow( $texClass, [] ); $inner = $node->getArg()->renderMML(); return $mrow->encapsulateRaw( $mrow2->encapsulateRaw( $inner ) ); } } public static function intent( $node, $passedArgs, $operatorContent, $name, $smth = null ) { if ( !$node instanceof Fun2 ) { return null; } // if there is intent annotation add intent to root element // match args in row of subargs, unless an element has explicit annotations // nested annotations ? $arg1 = $node->getArg1(); $arg2 = $node->getArg2(); if ( !$arg2->isCurly() ) { return null; } // tbd refactor intent form and fiddle in mml or tree $intentStr = MMLutil::squashLitsToUnitIntent( $arg2 ); $intentContent = MMLParsingUtil::getIntentContent( $intentStr ); $intentParams = MMLParsingUtil::getIntentParams( $intentContent ); // Sometimes the intent has additioargs = {array[3]} nal args in the same string $intentArg = MMLParsingUtil::getIntentArgs( $intentStr ); if ( !$intentContent && !$intentParams && $intentArg !== null ) { // explicit args annotation parsing in literal // return $arg1->renderMML([],["intent-params-expl"=>$intentArg]); // alternative just add the arg here return $arg1->renderMML( [ "arg" => $intentArg ] ); } $intentContentAtr = [ "intent" => $intentContent ]; if ( $intentArg !== null ) { $intentContentAtr["arg"] = $intentArg; } // tbd refine intent params and operator content merging (does it overwrite ??) $intentParamsState = $intentParams ? [ "intent-params" => $intentParams ] : $operatorContent; // Here are some edge cases, they might go into renderMML in the related element if ( str_contains( $intentContent ?? '', "matrix" ) || ( $arg1->isCurly() && $arg1->getArgs()[0] instanceof Matrix ) ) { $element = $arg1->getArgs()[0]; $rendered = $element->renderMML( [], $intentParamsState ); $hackyXML = MMLParsingUtil::forgeIntentToSpecificElement( $rendered, $intentContentAtr, "mtable" ); return $hackyXML; } elseif ( $arg1->isCurly() && count( $arg1->getArgs() ) >= 2 ) { // Create a surrounding element which holds the intents $mrow = new MMLmrow( "", $intentContentAtr ); return $mrow->encapsulateRaw( $arg1->renderMML( [], $intentParamsState ) ); } elseif ( $arg1->isCurly() && count( $arg1->getArgs() ) >= 1 ) { // Forge the intent attribute to the top-level element after MML rendering $element = $arg1->getArgs()[0]; $rendered = $element->renderMML( [], $intentParamsState ); $hackyXML = MMLParsingUtil::forgeIntentToTopElement( $rendered, $intentContentAtr ); return $hackyXML; } else { // This is the default case return $arg1->renderMML( $intentContentAtr, $intentParamsState ); } } public static function hBox( $node, $passedArgs, $operatorContent, $name, $smth = null ) { switch ( trim( $name ) ) { case "\\mbox": $mo = new MMLmo(); $mmlMrow = new MMLmrow(); if ( isset( $operatorContent['foundOC'] ) ) { $op = $operatorContent['foundOC']; $macro = TexUtil::getInstance()->nullary_macro_in_mbox( $op ) ? /* tested in \MediaWiki\Extension\Math\Tests\WikiTexVC\TexUtilTest::testUnicodeDefined */ [ '&#x' . TexUtil::getInstance()->unicode_char( $op ) . ';' ] : TexUtil::getInstance()->identifier( $op ); $input = $macro[0] ?? $op; // @phan-suppress-next-line PhanTypeMismatchArgumentNullable - false positive see above return $mmlMrow->encapsulateRaw( $mo->encapsulateRaw( MMLutil::uc2xNotation( $input ) ) ); } else { $mmlMrow = new MMLmrow(); $mtext = new MMLmtext(); return $mmlMrow->encapsulateRaw( $mtext->encapsulateRaw( "\mbox" ) ); } case "\\hbox": $mmlMrow = new MMLmrow(); $mstyle = new MMLmstyle( "", [ "displaystyle" => "false", "scriptlevel" => "0" ] ); $mtext = new MMLmtext(); $inner = $node->getArg() instanceof TexNode ? $node->getArg()->renderMML() : $node->getArg(); return $mmlMrow->encapsulateRaw( $mstyle->encapsulateRaw( $mtext->encapsulateRaw( $inner ) ) ); case "\\text": $mmlMrow = new MMLmrow(); $mtext = new MMLmtext(); $inner = $node->getArg() instanceof TexNode ? $node->getArg()->renderMML() : $node->getArg(); return $mmlMrow->encapsulateRaw( $mtext->encapsulateRaw( $inner ) ); 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 ) ); $state = [ "inHBox" => true ]; $inner = $node->getArg()->isCurly() ? $node->getArg()->renderMML( [], $state ) : $node->getArg()->renderMML( [ "fromHBox" => true ] ); return $mmlMrow->encapsulateRaw( $mtext->encapsulateRaw( $inner ) ); } $merror = new MMLmerror(); // $node->getArg1()->renderMML() . $node->getArg2()->renderMML() return $merror->encapsulateRaw( "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 if ( $node instanceof Literal ) { return MMLParsingUtil::createNot(); } else { $mError = new MMLmerror(); return $mError->encapsulateRaw( "TBD implement 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->encapsulateRaw( $char ); } return $mmlMover->encapsulateRaw( $inner ); } $mError = new MMLmerror(); return $mError->encapsulateRaw( "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->encapsulateRaw( $mroot->encapsulateRaw( $arg2Rendered . $mrow->encapsulateRaw( $node->getArg1()->renderMML( $passedArgs ) ) ) ); } $msqrt = new MMLmsqrt(); // Currently this is own implementation from Fun1.php return $mrow->encapsulateRaw( // assuming that this is always encapsulated in mrow $msqrt->encapsulateRaw( $node->getArg()->renderMML( $passedArgs ) ) ); } public static function tilde( $node, $passedArgs, $operatorContent, $name ) { $mspace = new MMLmspace( "", [ "width" => "0.5em" ] ); return $mspace->getEmpty(); } 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->encapsulateRaw( $mmlUnderOver->encapsulateRaw( $mstyle->encapsulateRaw( $moArrow->encapsulateRaw( $char ) ) . $mpadded->encapsulateRaw( $mmlMrow->encapsulateRaw( $node->getArg1()->renderMML() ) . $mspace->encapsulate() ) . $mpadded->encapsulateRaw( $node->getArg2()->renderMML() ) ) ); } return $mover->encapsulateRaw( $mstyle->encapsulateRaw( $moArrow->encapsulateRaw( $char ) ) . $mpadded->encapsulateRaw( $node->getArg()->renderMML() . $mspace->encapsulate() ) ); } private static function getApplyFct( array $operatorContent ): string { $applyFct = ""; if ( array_key_exists( "foundNamedFct", $operatorContent ) ) { $hasNamedFct = $operatorContent['foundNamedFct'][0]; $hasValidParameters = $operatorContent["foundNamedFct"][1]; if ( $hasNamedFct && $hasValidParameters ) { $applyFct = MMLParsingUtil::renderApplyFunction(); } } return $applyFct; } } PK ! � D�~. ~. Util/MMLParsingUtil.phpnu �Iw�� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Util; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\Tag; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\TexClass; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\Variants; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmo; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmpadded; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmrow; use MediaWiki\Extension\Math\WikiTexVC\MMLnodes\MMLmtext; /** * This class contains functionalities for MML-node * parsing which can be extracted and are used * for multiple functions. */ class MMLParsingUtil { public static function renderApplyFunction() { $mo = new MMLmo(); return $mo->encapsulateRaw( "⁡" ); } public static function getFontArgs( string $name, ?string $variant, ?array $passedArgs ): array { $args = []; switch ( $name ) { case "cal": case "mathcal": $args = [ Tag::MJXVARIANT => "-tex-calligraphic", "mathvariant" => Variants::SCRIPT ]; break; case "it": case "mathit": $args = [ Tag::MJXVARIANT => $variant, "mathvariant" => Variants::ITALIC ]; break; case "bf": case "mathbf": $args = [ "mathvariant" => $variant ]; break; // Sstatements from here come from other fct ok ? otherwise create second fct case "textit": $args = [ "mathvariant" => Variants::ITALIC ]; break; case "textbf": $args = [ "mathvariant" => Variants::BOLD ]; break; case "textsf": $args = [ "mathvariant" => Variants::SANSSERIF ]; break; case "texttt": $args = [ "mathvariant" => Variants::MONOSPACE ]; break; case "textrm": break; case "emph": // Toggle by passed args in emph if ( isset( $passedArgs["mathvariant"] ) ) { if ( $passedArgs["mathvariant"] === Variants::ITALIC ) { $args = [ "mathvariant" => Variants::NORMAL ]; } } else { $args = [ "mathvariant" => Variants::ITALIC ]; } break; default: $args = [ "mathvariant" => $variant ]; } return $args; } /** * Parses an expression that defines a color; this is usually an argument in Literal. * Example expression is: "\definecolor {ultramarine}{rgb}{0,0.12549019607843,0.37647058823529}" * @param string $input tex-string, which contains the expression * @return array|null either an array which contains hex of parsed expression or null if not parsable */ public static function parseDefineColorExpression( string $input ): ?array { $returnObj = null; $matches = []; $matched = preg_match_all( '/\{(.*?)\}/', $input, $matches ); if ( !$matched ) { return null; } $ctr = count( $matches[1] ?? [] ); if ( $ctr == 3 && $matches[1][1] === "rgb" ) { $returnObj = []; $rgbValues = explode( ",", $matches[1][2] ); $r = round( floatval( $rgbValues[0] ) * 255 ); $g = round( floatval( $rgbValues[1] ) * 255 ); $b = round( floatval( $rgbValues[2] ) * 255 ); $color = sprintf( "#%02x%02x%02x", $r, $g, $b ); $returnObj["name"] = $matches[1][0]; $returnObj["type"] = "rgb"; $returnObj["hex"] = $color; } return $returnObj; } /** * Creates a negation block in MathML, usually preceding the negated statement * @return string negation block as MathML */ public static function createNot() { $mmlMrow = new MMLmrow( TexClass::REL ); $mpadded = new MMLmpadded( "", [ "width" => "0" ] ); $mtext = new MMLmtext(); return $mmlMrow->encapsulateRaw( $mpadded->encapsulateRaw( $mtext->encapsulateRaw( "⧸" ) ) ); } public static function mapToDoubleStruckUnicode( string $inputString ): string { $map = [ '0' => '𝟘', '1' => '𝟙', '2' => '𝟚', '3' => '𝟛', '4' => '𝟜', '5' => '𝟝', '6' => '𝟞', '7' => '𝟟', '8' => '𝟠', '9' => '𝟡', 'A' => '𝔸', 'B' => '𝔹', 'C' => 'ℂ', 'D' => '𝔻', 'E' => '𝔼', 'F' => '𝔽', 'G' => '𝔾', 'H' => 'ℍ', 'I' => '𝕀', 'J' => '𝕁', 'K' => '𝕂', 'L' => '𝕃', 'M' => '𝕄', 'N' => 'ℕ', 'O' => '𝕆', 'P' => 'ℙ', 'Q' => 'ℚ', 'R' => 'ℝ', 'S' => '𝕊', 'T' => '𝕋', 'U' => '𝕌', 'V' => '𝕍', 'W' => '𝕎', 'X' => '𝕏', 'Y' => '𝕐', 'Z' => 'ℤ', 'a' => '𝕒', 'b' => '𝕓', 'c' => '𝕔', 'd' => '𝕕', 'e' => '𝕖', 'f' => '𝕗', 'g' => '𝕘', 'h' => '𝕙', 'i' => '𝕚', 'j' => '𝕛', 'k' => '𝕜', 'l' => '𝕝', 'm' => '𝕞', 'n' => '𝕟', 'o' => '𝕠', 'p' => '𝕡', 'q' => '𝕢', 'r' => '𝕣', 's' => '𝕤', 't' => '𝕥', 'u' => '𝕦', 'v' => '𝕧', 'w' => '𝕨', 'x' => '𝕩', 'y' => '𝕪', 'z' => '𝕫' ]; return self::matchAlphanumeric( $inputString, $map ); } public static function mapToCaligraphicUnicode( string $inputString ): string { $map = [ '0' => '𝟎', '1' => '𝟏', '2' => '𝟐', '3' => '𝟑', '4' => '𝟒', '5' => '𝟓', '6' => '𝟔', '7' => '𝟕', '8' => '𝟖', '9' => '𝟗', 'A' => '𝒜', 'B' => 'ℬ', 'C' => '𝒞', 'D' => '𝒟', 'E' => 'ℰ', 'F' => 'ℱ', 'G' => '𝒢', 'H' => 'ℋ', 'I' => 'ℐ', 'J' => '𝒥', 'K' => '𝒦', 'L' => 'ℒ', 'M' => 'ℳ', 'N' => '𝒩', 'O' => '𝒪', 'P' => '𝒫', 'Q' => '𝒬', 'R' => 'ℛ', 'S' => '𝒮', 'T' => '𝒯', 'U' => '𝒰', 'V' => '𝒱', 'W' => '𝒲', 'X' => '𝒳', 'Y' => '𝒴', 'Z' => '𝒵', 'a' => '𝒶', 'b' => '𝒷', 'c' => '𝒸', 'd' => '𝒹', 'e' => 'ℯ', 'f' => '𝒻', 'g' => 'ℊ', 'h' => '𝒽', 'i' => '𝒾', 'j' => '𝒿', 'k' => '𝓀', 'l' => '𝓁', 'm' => '𝓂', 'n' => '𝓃', 'o' => 'ℴ', 'p' => '𝓅', 'q' => '𝓆', 'r' => '𝓇', 's' => '𝓈', 't' => '𝓉', 'u' => '𝓊', 'v' => '𝓋', 'w' => '𝓌', 'x' => '𝓍', 'y' => '𝓎', 'z' => '𝓏' ]; return self::matchAlphanumeric( $inputString, $map ); } public static function mapToFrakturUnicode( string $inputString ): string { $res = ''; $specialCases = [ 'C' => 'ℭ', 'H' => 'ℌ', 'I' => 'ℑ', 'R' => 'ℜ', 'Z' => 'ℤ' ]; foreach ( mb_str_split( $inputString ) as $chr ) { // see https://www.w3.org/TR/mathml-core/#fraktur-mappings if ( isset( $specialCases[$chr] ) ) { $res .= $specialCases[$chr]; continue; } if ( $chr >= 'A' && $chr <= 'Z' ) { $code = self::addToChr( $chr, '1D4C3' ); $res .= '&#x' . $code . ';'; } elseif ( $chr >= 'a' && $chr <= 'z' ) { $code = self::addToChr( $chr, '1D4BD' ); $res .= '&#x' . $code . ';'; } else { $res .= $chr; } } return $res; } public static function mapToBoldUnicode( string $inputString ): string { $res = ''; foreach ( mb_str_split( $inputString ) as $chr ) { // see https://www.w3.org/TR/mathml-core/#bold-mappings if ( $chr >= 'A' && $chr <= 'Z' ) { $code = self::addToChr( $chr, '1D3BF' ); $res .= '&#x' . $code . ';'; } elseif ( $chr >= 'a' && $chr <= 'z' ) { $code = self::addToChr( $chr, '1D3B9' ); $res .= '&#x' . $code . ';'; } elseif ( $chr >= '0' && $chr <= '9' ) { $code = self::addToChr( $chr, '1D79E' ); $res .= '&#x' . $code . ';'; } else { $res .= $chr; } } return $res; } private static function addToChr( string $chr, string $base ): string { return strtoupper( dechex( mb_ord( $chr ) + hexdec( $base ) ) ); } public static function matchAlphanumeric( string $inputString, array $map ): string { // Replace each character in the input string with its caligraphic Unicode equivalent return preg_replace_callback( '/[A-Za-z0-9]/u', static function ( $matches ) use ( $map ) { return $map[$matches[0]] ?? $matches[0]; }, $inputString ); } public static function getIntentContent( ?string $input ): ?string { if ( !$input ) { return null; } $matchesInt = []; $matchInt = preg_match( "/intent=[\'\"](.*)[\'\"]/", $input, $matchesInt ); if ( $matchInt && count( $matchesInt ) >= 2 ) { return $matchesInt[1]; } return null; } public static function getIntentParams( ?string $intentContent ): ?array { if ( !$intentContent ) { return null; } $matchesParams = []; // tbd eventually not only alphanumerical chars valid in intent params $matchParams = preg_match_all( "/\\\$([a-zA-Z]+)/", $intentContent, $matchesParams ); if ( $matchParams && count( $matchesParams ) >= 2 ) { return $matchesParams[1]; } return null; } public static function getIntentArgs( ?string $input ): ?string { if ( !$input ) { return null; } $matchesArgs = []; $matchArg = preg_match( "/arg\s*=\s*[\'\"](.*?)[\'\"]/", $input, $matchesArgs ); if ( $matchArg && count( $matchesArgs ) >= 2 ) { return $matchesArgs[1]; } return null; } /** * Converts a rendered MathML string to a XML tree and adds the attributes from input * to the top-level element.Valid attributes for adding are "arg" and "intent. * It overwrites pre-existing attributes in the top-level element. * TBD: currently contains a hacky way to remove xml header in the output string * example:" <msup intent="_($op,_of,$arg)">" intent attributes comes from input variables * @param string $renderedMML defines input MathML string * @param array $intentContentAtr defines attributes to add * @return string MML with added attributes */ public static function forgeIntentToTopElement( string $renderedMML, $intentContentAtr ) { if ( !$intentContentAtr || !$renderedMML ) { return $renderedMML; } return self::addAttributesToMML( $renderedMML, $intentContentAtr, "" ); } /** * Add parameters from aattributes to the MML string * @param string $renderedMML defines input MathML string * @param array $intentContentAtr defines attributes to add * @param string $elementTag element tag when using foundNodes * @param bool $useFoundNodes use found nodes * @return string MML with added attributes */ public static function addAttributesToMML( string $renderedMML, array $intentContentAtr, string $elementTag, bool $useFoundNodes = false ): string { $xml = simplexml_load_string( $renderedMML ); if ( !$xml ) { return ""; } if ( $useFoundNodes ) { $foundNodes = $xml->xpath( $elementTag ); if ( !( $foundNodes !== null && count( $foundNodes ) >= 1 ) ) { return $renderedMML; } } if ( isset( $intentContentAtr["intent"] ) ) { if ( isset( $xml["intent"] ) ) { $xml["intent"] = $intentContentAtr["intent"]; } elseif ( $intentContentAtr["intent"] != null && is_string( $intentContentAtr["intent"] ) ) { $xml->addAttribute( "intent", $intentContentAtr["intent"] ); } } if ( isset( $intentContentAtr["arg"] ) ) { if ( isset( $xml["arg"] ) ) { $xml["arg"] = $intentContentAtr["arg"]; } elseif ( $intentContentAtr["arg"] != null && is_string( $intentContentAtr["arg"] ) ) { $xml->addAttribute( "arg", $intentContentAtr["arg"] ); } } $hackyXML = str_replace( "<?xml version=\"1.0\"?>", "", $xml->asXML() ); return str_replace( "\n", "", $hackyXML ); } public static function forgeIntentToSpecificElement( string $renderedMML, array $intentContentAtr, string $elementTag ): string { if ( !$intentContentAtr || !$renderedMML || !$elementTag ) { return $renderedMML; } return self::addAttributesToMML( $elementTag, $intentContentAtr, $elementTag, true ); } } PK ! ȣtO� � Util/MMLutil.phpnu �Iw�� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Util; use IntlChar; use MediaWiki\Extension\Math\WikiTexVC\Nodes\DQ; use MediaWiki\Extension\Math\WikiTexVC\Nodes\Literal; use MediaWiki\Extension\Math\WikiTexVC\Nodes\TexArray; use MediaWiki\Extension\Math\WikiTexVC\Nodes\TexNode; /** * Utility Methods for parsing Tex to MathML * @author Johannes Stegmüller */ class MMLutil { /** * Splits a regular expression in the form '\operatorname {someparams} * Also recognizes succeeding parentheses '\operatorname (' as params * @param string $input tex expression * @return array|null found groups or null */ public static function initalParseLiteralExpression( $input ): ?array { $pattern = "/([\\a-zA-Z\s]+)\{([^}]+)\}/"; $matches = []; $matched = preg_match_all( $pattern, $input, $matches ); return $matched ? $matches : null; } /** * Recognize if input is a unicode string "\\u1235" * If yes converts it to notation "ģ", if no just returns the input. * @param string $input input to be checked * @return string modified input or input */ public static function uc2xNotation( string $input ): string { if ( str_starts_with( $input, "\\u" ) ) { return str_replace( "\\u", "&#x", $input ) . ";"; } return $input; } /** * If an input string is in "..:" notation * then convert it to a string of notation \\u12.. * @param string $input input to be checked * @return string modified input or input */ public static function x2uNotation( string $input ): string { if ( str_starts_with( $input, "&#x" ) ) { return rtrim( str_replace( "&#x", "\\u", $input ), ";" ); } return $input; } public static function number2xNotation( string $input ): string { return "&#x" . $input . ";"; } /** * Rounds a floating point input to three digits precision * and returns it as string with succeeding "em". * @param float $size input to be processed * @return string rounded digits with em */ public static function round2em( float $size ) { $rounded = round( $size, 3 ); return $rounded . "em"; } /** * In a floating point digit as string, set input to precision of three digits * without rounding. * @param string $size input to be checked * @return string digits of precision three with em */ public static function size2em( string $size ): string { return preg_replace( "/(\.\d\d\d).+/", '$1', $size ) . "em"; } /** * Assumes the input curly contains an TexArray of literals, squashes the TexArray characters to a string. * @param TexArray $node TexArray of literals * @return ?string squashed string in example "2mu", "-3mu" etc. Null if no TexArray inside curly. */ public static function squashLitsToUnit( TexArray $node ): ?string { $unit = ""; foreach ( $node as $literal ) { if ( !$literal instanceof Literal ) { continue; } $unit .= $literal->getArg(); } return $unit; } /** * em or other dimensional unit gets multiplied by pre-operator. * @param string $size input size i.e-123em * @param string $operator "plus (+) or minus (-) * @return string ++ => + , -- => +, -+ => - */ public static function addPreOperator( string $size, string $operator ): string { $emtr = trim( $size ); $ok = preg_match( "/^([+\-])$/", $operator ); if ( !$ok ) { return ''; } switch ( $emtr[0] ) { case "-": if ( $operator == "+" ) { return $emtr; } elseif ( $operator == "-" ) { $emtr[0] = "+"; return $emtr; } break; case "+": if ( $operator == "+" ) { return $emtr; } elseif ( $operator == "-" ) { $emtr[0] = "-"; return $emtr; } break; default: return $operator . $emtr; } return $emtr; } /** * Convert a length dimension to em format * currently supports "mu: math unit and forwards em" * @param string $dimen input for length dimension like "-2mu" or "3 em" * @return string|null converted string i.e. "0.333em" or null if error */ public static function dimen2em( string $dimen ): ?string { $matches = []; $matched = preg_match( '/([+-]?)(\d*\.*\d+)\s*(mu|em)/', $dimen, $matches ); if ( !$matched ) { return null; } if ( $matches[3] == "mu" ) { $ret = self::size2em( strval( intval( $matches[2] ) / 18 ) ); } elseif ( $matches[3] == "em" ) { $ret = $matches[2] . "em"; } else { return null; } return ( $matches[1] == "-" ? "-" : "" ) . $ret; } public static function createEntity( string $code ): ?string { return IntlChar::chr( intval( $code, 16 ) ); } /** * From a defined mapping table get the value by key. * Do some optional common conversion steps for the values. * @param string $key key to find entry in table * @param array $mappingTable table which the value is found by key * @param bool $convertUc2X convert first value of the found entry in array to specific "ģ" notation * @param bool $addSlashes add a backslash to the key * @return mixed|string[]|null the found entry in the table */ public static function getMappingByKey( string $key, array $mappingTable, bool $convertUc2X = false, bool $addSlashes = false ) { if ( $addSlashes ) { if ( !str_starts_with( $key, "\\" ) ) { return null; } $key = trim( substr( $key, 1 ) ); } if ( isset( $mappingTable[$key] ) ) { $found = $mappingTable[$key]; if ( is_string( $found ) ) { $found = [ $found ]; } if ( $convertUc2X ) { $found[0] = self::uc2xNotation( $found[0] ); } return $found; } return null; } /** * From a defined mapping table get the value by key. * @param string $key key to find entry in table * @param array $mappingTable table which the value is found by key * @return mixed|string[]|null the found entry in the table */ public static function getMappingByKeySimple( string $key, array $mappingTable, bool $addSlashes = false ) { if ( $addSlashes && !str_starts_with( $key, "\\" ) ) { return null; } $key = $addSlashes ? trim( substr( $key, 1 ) ) : $key; if ( isset( $mappingTable[$key] ) ) { return $mappingTable[$key]; } return null; } /** * Assumes the input curly contains an TexArray of literals, squashes the TexArray characters to a string. * It checks for dollar escaping and removes a backslash, also renders DQ args with underscores * @param TexNode $node curly containing a TexArray of literals * @return ?string squashed string in example "2mu", "-3mu" etc. Null if no TexArray inside curly. */ public static function squashLitsToUnitIntent( TexNode $node ): ?string { if ( !$node->isCurly() ) { return null; } $unit = ""; foreach ( $node->getArgs() as $literal ) { if ( $literal instanceof DQ ) { $args = $literal->getArgs(); if ( !$args[0] instanceof Literal || !$args[1] instanceof Literal ) { continue; } $arg = self::removeDollarEscaping( $args[0]->getArgs()[0] ) . "_" . self::removeDollarEscaping( $args[1]->getArgs()[0] ); } else { if ( !$literal instanceof Literal ) { continue; } $arg = self::removeDollarEscaping( $literal->getArg() ); } $unit .= $arg; } return $unit; } public static function removeDollarEscaping( string $input ): string { if ( $input == "\\$" ) { return "\$"; } return $input; } } PK ! `���: �: AMSMappings.phpnu �[��� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Lengths\MathSpace; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\Align; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\TexClass; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\Variants; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Util\MMLutil; /** * Based on AMSMappings.js in MML3 * Only importing infix atm * Singleton * */ class AMSMappings { /** @var self|null */ private static $instance = null; private const AMSMACROS = [ "mathring" => [ 'accent', '02DA' ], "nobreakspace" => 'Tilde', "negmedspace" => [ 'spacer', MathSpace::NEGATIVEMEDIUMMATHSPACE ], "negthickspace" => [ 'spacer', MathSpace::NEGATIVETHICKMATHSPACE ], "idotsint" => [ 'MultiIntegral', '\\int\\cdots\\int' ], "dddot" => [ 'accent', '20DB' ], "ddddot" => [ 'accent', '20DC' ], "sideset" => 'SideSet', "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}}}' ], // replaced underrightarrow here not supported "varinjlim" => [ 'macro', '\\mathop{\\xrightarrow{\\mmlToken{mi}{lim}}}' ], // replaced underleftarrow here not supported "varprojlim" => [ 'macro', '\\mathop{\\xleftarrow{\\mmlToken{mi}{lim}}}' ], "DeclareMathOperator" => 'HandleDeclareOp', "operatorname" => 'handleOperatorName', "genfrac" => 'genFrac', "frac" => [ 'genFrac', '', '', '', '' ], "tfrac" => [ 'genFrac', '', '', '', '1' ], "dfrac" => [ 'genFrac', '', '', '', '0' ], "binom" => [ 'genFrac', '(', ')', '0', '0' ], "tbinom" => [ 'genFrac', '(', ')', '0', '1' ], "dbinom" => [ 'genFrac', '(', ')', '0', '0' ], "cfrac" => 'cFrac', "shoveleft" => [ 'HandleShove', Align::LEFT ], "shoveright" => [ 'HandleShove', Align::RIGHT ], "xrightarrow" => [ 'xArrow', 0x2192, 5, 10 ], "xleftarrow" => [ 'xArrow', 0x2190, 10, 5 ] ]; private const AMSMATHCHAR0MI = [ "digamma" => '\u03DD', "varkappa" => '\u03F0', "varGamma" => [ '\u0393', [ "mathvariant" => Variants::ITALIC ] ], "varDelta" => [ '\u0394', [ "mathvariant" => Variants::ITALIC ] ], "varTheta" => [ '\u0398', [ "mathvariant" => Variants::ITALIC ] ], "varLambda" => [ '\u039B', [ "mathvariant" => Variants::ITALIC ] ], "varXi" => [ '\u039E', [ "mathvariant" => Variants::ITALIC ] ], "varPi" => [ '\u03A0', [ "mathvariant" => Variants::ITALIC ] ], "varSigma" => [ '\u03A3', [ "mathvariant" => Variants::ITALIC ] ], "varStigma" => [ '\u03DB', [ "mathvariant" => Variants::ITALIC ] ], "varUpsilon" => [ '\u03A5', [ "mathvariant" => Variants::ITALIC ] ], "varPhi" => [ '\u03A6', [ "mathvariant" => Variants::ITALIC ] ], "varPsi" => [ '\u03A8', [ "mathvariant" => Variants::ITALIC ] ], "varOmega" => [ '\u03A9', [ "mathvariant" => Variants::ITALIC ] ], "beth" => '\u2136', "gimel" => '\u2137', "daleth" => '\u2138', "backprime" => [ '\u2035', [ "variantForm" => "True" ] ], // actually: "variantForm" => "True" "hslash" => '\u210F', "varnothing" => [ '\u2205', [ "variantForm" => "True" ] ], // actually: "variantForm" => "True" "blacktriangle" => '\u25B4', "triangledown" => [ '\u25BD', [ "variantForm" => "True" ] ], // actually: "variantForm" => "True" "blacktriangledown" => '\u25BE', "square" => '\u25FB', "Box" => '\u25FB', "blacksquare" => '\u25FC', "lozenge" => '\u25CA', "Diamond" => '\u25CA', "blacklozenge" => '\u29EB', "circledS" => [ '\u24C8', [ "mathvariant" => Variants::NORMAL ] ], "bigstar" => '\u2605', "sphericalangle" => '\u2222', "measuredangle" => '\u2221', "nexists" => '\u2204', "complement" => '\u2201', "mho" => '\u2127', "eth" => [ '\u00F0', [ "mathvariant" => Variants::NORMAL ] ], "Finv" => '\u2132', "diagup" => '\u2571', "Game" => '\u2141', "diagdown" => '\u2572', "Bbbk" => [ '\u006B', [ "mathvariant" => Variants::DOUBLESTRUCK ] ], "yen" => '\u00A5', "circledR" => '\u00AE', "checkmark" => '\u2713', "maltese" => '\u2720' ]; private const AMSMATHCHAR0MO = [ "iiiint" => [ '\u2A0C', [ "texClass" => TexClass::OP ] ], // added this mapping from other array "dotplus" => '\u2214', "ltimes" => '\u22C9', "smallsetminus" => [ '\u2216', [ "variantForm" => "True" ] ], // actually: "variantForm" => "True" "rtimes" => '\u22CA', "Cap" => '\u22D2', "doublecap" => '\u22D2', "leftthreetimes" => '\u22CB', "Cup" => '\u22D3', "doublecup" => '\u22D3', "rightthreetimes" => '\u22CC', "barwedge" => '\u22BC', "curlywedge" => '\u22CF', "veebar" => '\u22BB', "curlyvee" => '\u22CE', "doublebarwedge" => '\u2A5E', "boxminus" => '\u229F', "circleddash" => '\u229D', "boxtimes" => '\u22A0', "circledast" => '\u229B', "boxdot" => '\u22A1', "circledcirc" => '\u229A', "boxplus" => '\u229E', "centerdot" => [ '\u22C5', [ "variantForm" => "True" ] ], // actually: "variantForm" => "True" "divideontimes" => '\u22C7', "intercal" => '\u22BA', "leqq" => '\u2266', "geqq" => '\u2267', "leqslant" => '\u2A7D', "geqslant" => '\u2A7E', "eqslantless" => '\u2A95', "eqslantgtr" => '\u2A96', "lesssim" => '\u2272', "gtrsim" => '\u2273', "lessapprox" => '\u2A85', "gtrapprox" => '\u2A86', "approxeq" => '\u224A', "lessdot" => '\u22D6', "gtrdot" => '\u22D7', "lll" => '\u22D8', "llless" => '\u22D8', "ggg" => '\u22D9', "gggtr" => '\u22D9', "lessgtr" => '\u2276', "gtrless" => '\u2277', "lesseqgtr" => '\u22DA', "gtreqless" => '\u22DB', "lesseqqgtr" => '\u2A8B', "gtreqqless" => '\u2A8C', "doteqdot" => '\u2251', "Doteq" => '\u2251', "eqcirc" => '\u2256', "risingdotseq" => '\u2253', "circeq" => '\u2257', "fallingdotseq" => '\u2252', "triangleq" => '\u225C', "backsim" => '\u223D', "thicksim" => [ '\u223C', [ "variantForm" => "True" ] ], // actually: "variantForm" => "True" "backsimeq" => '\u22CD', "thickapprox" => [ '\u2248', [ "variantForm" => "True" ] ], // actually: "variantForm" => "True" "subseteqq" => '\u2AC5', "supseteqq" => '\u2AC6', "Subset" => '\u22D0', "Supset" => '\u22D1', "sqsubset" => '\u228F', "sqsupset" => '\u2290', "preccurlyeq" => '\u227C', "succcurlyeq" => '\u227D', "curlyeqprec" => '\u22DE', "curlyeqsucc" => '\u22DF', "precsim" => '\u227E', "succsim" => '\u227F', "precapprox" => '\u2AB7', "succapprox" => '\u2AB8', "vartriangleleft" => '\u22B2', "lhd" => '\u22B2', "vartriangleright" => '\u22B3', "rhd" => '\u22B3', "trianglelefteq" => '\u22B4', "unlhd" => '\u22B4', "trianglerighteq" => '\u22B5', "unrhd" => '\u22B5', "vDash" => [ '\u22A8', [ "variantForm" => true ] ], "Vdash" => '\u22A9', "Vvdash" => '\u22AA', "smallsmile" => [ '\u2323', [ "variantForm" => true ] ], "shortmid" => [ '\u2223', [ "variantForm" => true ] ], "smallfrown" => [ '\u2322', [ "variantForm" => true ] ], "shortparallel" => [ '\u2225', [ "variantForm" => true ] ], "bumpeq" => '\u224F', "between" => '\u226C', "Bumpeq" => '\u224E', "pitchfork" => '\u22D4', "varpropto" => [ '\u221D', [ "variantForm" => true ] ], "backepsilon" => '\u220D', "blacktriangleleft" => '\u25C2', "blacktriangleright" => '\u25B8', "therefore" => '\u2234', "because" => '\u2235', "eqsim" => '\u2242', "vartriangle" => [ '\u25B3', [ "variantForm" => true ] ], "Join" => '\u22C8', "nless" => '\u226E', "ngtr" => '\u226F', "nleq" => '\u2270', "ngeq" => '\u2271', "nleqslant" => [ '\u2A87', [ "variantForm" => true ] ], "ngeqslant" => [ '\u2A88', [ "variantForm" => true ] ], "nleqq" => [ '\u2270', [ "variantForm" => true ] ], "ngeqq" => [ '\u2271', [ "variantForm" => true ] ], "lneq" => '\u2A87', "gneq" => '\u2A88', "lneqq" => '\u2268', "gneqq" => '\u2269', "lvertneqq" => [ '\u2268', [ "variantForm" => true ] ], "gvertneqq" => [ '\u2269', [ "variantForm" => true ] ], "lnsim" => '\u22E6', "gnsim" => '\u22E7', "lnapprox" => '\u2A89', "gnapprox" => '\u2A8A', "nprec" => '\u2280', "nsucc" => '\u2281', "npreceq" => [ '\u22E0', [ "variantForm" => true ] ], "nsucceq" => [ '\u22E1', [ "variantForm" => true ] ], "precneqq" => '\u2AB5', "succneqq" => '\u2AB6', "precnsim" => '\u22E8', "succnsim" => '\u22E9', "precnapprox" => '\u2AB9', "succnapprox" => '\u2ABA', "nsim" => '\u2241', "ncong" => '\u2246', "nshortmid" => [ '\u2224', [ "variantForm" => true ] ], "nshortparallel" => [ '\u2226', [ "variantForm" => true ] ], "nmid" => '\u2224', "nparallel" => '\u2226', "nvdash" => '\u22AC', "nvDash" => '\u22AD', "nVdash" => '\u22AE', "nVDash" => '\u22AF', "ntriangleleft" => '\u22EA', "ntriangleright" => '\u22EB', "ntrianglelefteq" => '\u22EC', "ntrianglerighteq" => '\u22ED', "nsubseteq" => '\u2288', "nsupseteq" => '\u2289', "nsubseteqq" => [ '\u2288', [ "variantForm" => true ] ], "nsupseteqq" => [ '\u2289', [ "variantForm" => true ] ], "subsetneq" => '\u228A', "supsetneq" => '\u228B', "varsubsetneq" => [ '\u228A', [ "variantForm" => true ] ], "varsupsetneq" => [ '\u228B', [ "variantForm" => true ] ], "subsetneqq" => '\u2ACB', "supsetneqq" => '\u2ACC', "varsubsetneqq" => [ '\u2ACB', [ "variantForm" => true ] ], "varsupsetneqq" => [ '\u2ACC', [ "variantForm" => true ] ], "leftleftarrows" => '\u21C7', "rightrightarrows" => '\u21C9', "leftrightarrows" => '\u21C6', "rightleftarrows" => '\u21C4', "Lleftarrow" => '\u21DA', "Rrightarrow" => '\u21DB', "twoheadleftarrow" => '\u219E', "twoheadrightarrow" => '\u21A0', "leftarrowtail" => '\u21A2', "rightarrowtail" => '\u21A3', "looparrowleft" => '\u21AB', "looparrowright" => '\u21AC', "leftrightharpoons" => '\u21CB', "rightleftharpoons" => [ '\u21CC', [ "variantForm" => true ] ], "curvearrowleft" => '\u21B6', "curvearrowright" => '\u21B7', "circlearrowleft" => '\u21BA', "circlearrowright" => '\u21BB', "Lsh" => '\u21B0', "Rsh" => '\u21B1', "upuparrows" => '\u21C8', "downdownarrows" => '\u21CA', "upharpoonleft" => '\u21BF', "upharpoonright" => '\u21BE', "downharpoonleft" => '\u21C3', "restriction" => '\u21BE', "multimap" => '\u22B8', "downharpoonright" => '\u21C2', "leftrightsquigarrow" => '\u21AD', "rightsquigarrow" => '\u21DD', "leadsto" => '\u21DD', "dashrightarrow" => '\u21E2', "dashleftarrow" => '\u21E0', "nleftarrow" => '\u219A', "nrightarrow" => '\u219B', "nLeftarrow" => '\u21CD', "nRightarrow" => '\u21CF', "nleftrightarrow" => '\u21AE', "nLeftrightarrow" => '\u21CE' ]; private const AMSMATHENVIRONMENT = [ 'equation*' => [ 'Equation', null, false ], 'eqnarray*' => [ 'EqnArray', null, false, true, 'rcl', null, '.5em' ], 'align' => [ 'EqnArray', null, true, true, 'rl', 'ParseUtil_js_1.default.cols(0, 2)' ], 'align*' => [ 'EqnArray', null, false, true, 'rl', "ParseUtil_js_1.default.cols(0, 2)" ], "multline" => [ 'Multline', null, true ], 'multline*' => [ 'Multline', null, false ], "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' ], "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)", '.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' => [ 'matrix', '{', '', 'left left', null, '.1em', null, true ], 'array' => [ 'matrix' ] ]; private const AMSSYMBOLDELIMITERS = [ 'ulcorner' => '\u231C', 'urcorner' => '\u231D', 'llcorner' => '\u231E', 'lrcorner' => '\u231F' ]; private const AMSSYMBOLMACROS = [ "implies" => [ 'macro', '\\;\\Longrightarrow\\;' ], "impliedby" => [ 'macro', '\\;\\Longleftarrow\\;' ] ]; private const AMSMATHDELIMITERS = [ 'lvert' => [ '\u007C', [ "texClass" => TexClass::OPEN ] ], 'rvert' => [ '\u007C', [ "texClass" => TexClass::CLOSE ] ], 'lVert' => [ '\u2016', [ "texClass" => TexClass::OPEN ] ], 'rVert' => [ '\u2016', [ "texClass" => TexClass::CLOSE ] ] ]; private const ALL = [ "amsmathchar0mo" => self::AMSMATHCHAR0MO, "amsmathchar0mi" => self::AMSMATHCHAR0MI, "amsmacros" => self::AMSMACROS, "amssymbolmacros" => self::AMSSYMBOLMACROS, "amsdelimiters" => self::AMSSYMBOLDELIMITERS, "amsmathenvironment" => self::AMSMATHENVIRONMENT ]; private function __construct() { // Just an empty private constructor, for singleton pattern } public static function getAll(): array { return self::ALL; } public static function getInstance() { self::$instance ??= new AMSMappings(); return self::$instance; } public static function getOperatorByKey( $key ) { // √ to \\u.... this is only temporary probably entities.php will be refactored with \u vals again $key = MMLutil::x2uNotation( $key ); return MMLutil::getMappingByKey( $key, self::AMSMATHCHAR0MO, true, true ); } public static function getIdentifierByKey( $key ) { return MMLutil::getMappingByKey( $key, self::AMSMATHCHAR0MI, true, true ); } public static function getSymbolDelimiterByKey( $key ) { return MMLutil::getMappingByKey( $key, self::AMSSYMBOLDELIMITERS, true, true ); } public static function getMathDelimiterByKey( $key ) { return MMLutil::getMappingByKey( $key, self::AMSMATHDELIMITERS, true, true ); } public static function getMacroByKey( $key ) { $ret = MMLutil::getMappingByKey( $key, self::AMSMACROS, false, true ); if ( $ret != null ) { return $ret; } return MMLutil::getMappingByKey( $key, self::AMSSYMBOLMACROS, true, true ); } public static function getEnvironmentByKey( $key ) { return MMLutil::getMappingByKey( $key, self::AMSMATHENVIRONMENT ); } } PK ! +lr�o �o BaseMappings.phpnu �[��� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Lengths\MathSpace; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\Tag; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\TexClass; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants\Variants; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Util\MMLutil; use MediaWiki\Extension\Math\WikiTexVC\TexUtil; /** * Based on BaseMappings.js in MML3 * Singleton */ class BaseMappings { /** @var self|null */ private static $instance = null; // Macro Map 'special' private const SPECIAL = [ '{' => 'open', '}' => 'close', '~' => [ 'tilde', true ], '^' => 'superscript', '_' => 'subscript', ' ' => 'space', '\t' => 'space', '\r' => 'space', '\n' => 'space', '\\' => 'prime', '%' => 'comment', '&' => 'entry', '#' => 'hash', '\u00A0' => 'space', '\u2019' => 'prime' ]; private const MATHCHAR0MI = [ "alpha" => '\u03B1', "beta" => '\u03B2', "gamma" => '\u03B3', "delta" => '\u03B4', "epsilon" => '\u03F5', "zeta" => '\u03B6', "eta" => '\u03B7', "theta" => '\u03B8', "iota" => '\u03B9', "kappa" => '\u03BA', "lambda" => '\u03BB', "mu" => '\u03BC', "nu" => '\u03BD', "xi" => '\u03BE', "omicron" => '\u03BF', "pi" => '\u03C0', "rho" => '\u03C1', "sigma" => '\u03C3', "tau" => '\u03C4', "upsilon" => '\u03C5', "phi" => '\u03D5', "chi" => '\u03C7', "psi" => '\u03C8', "omega" => '\u03C9', "varepsilon" => '\u03B5', "vartheta" => '\u03D1', "varpi" => '\u03D6', "varrho" => '\u03F1', "varsigma" => '\u03C2', "varphi" => '\u03C6', "S" => [ '\u00A7', [ "mathvariant" => Variants::NORMAL ] ], "aleph" => [ '\u2135', [ "mathvariant" => Variants::NORMAL ] ], "hbar" => [ '\u210F', [ Tag::ALTERNATE => "1" ] ], // actually: "variantForm" => "True" "imath" => '\u0131', "jmath" => '\u0237', "ell" => '\u2113', "wp" => [ '\u2118', [ "mathvariant" => Variants::NORMAL ] ], "Re" => [ '\u211C', [ "mathvariant" => Variants::NORMAL ] ], "Im" => [ '\u2111', [ "mathvariant" => Variants::NORMAL ] ], "partial" => [ '\u2202', [] ], // "mathvariant" => Variants::ITALIC ] this leads to 'wrong' output "infty" => [ '\u221E', [ "mathvariant" => Variants::NORMAL ] ], "prime" => [ '\u2032', [ Tag::ALTERNATE => "1" ] ], // actually: "variantForm" => "True" "emptyset" => [ '\u2205', [ "mathvariant" => Variants::NORMAL ] ], "nabla" => [ '\u2207', [ "mathvariant" => Variants::NORMAL ] ], "top" => [ '\u22A4', [ "mathvariant" => Variants::NORMAL ] ], "bot" => [ '\u22A5', [ "mathvariant" => Variants::NORMAL ] ], "angle" => [ '\u2220', [ "mathvariant" => Variants::NORMAL ] ], "triangle" => [ '\u25B3', [ "mathvariant" => Variants::NORMAL ] ], "backslash" => [ '\u2216', [ "mathvariant" => Variants::NORMAL ] ], "forall" => [ '\u2200', [ "mathvariant" => Variants::NORMAL ] ], "exists" => [ '\u2203', [ "mathvariant" => Variants::NORMAL ] ], "neg" => [ '\u00AC', [ "mathvariant" => Variants::NORMAL ] ], "lnot" => [ '\u00AC', [ "mathvariant" => Variants::NORMAL ] ], "flat" => [ '\u266D', [ "mathvariant" => Variants::NORMAL ] ], "natural" => [ '\u266E', [ "mathvariant" => Variants::NORMAL ] ], "sharp" => [ '\u266F', [ "mathvariant" => Variants::NORMAL ] ], "clubsuit" => [ '\u2663', [ "mathvariant" => Variants::NORMAL ] ], "diamondsuit" => [ '\u2662', [ "mathvariant" => Variants::NORMAL ] ], "heartsuit" => [ '\u2661', [ "mathvariant" => Variants::NORMAL ] ], "spadesuit" => [ '\u2660', [ "mathvariant" => Variants::NORMAL ] ] ]; private const MATHCHAR0MO = [ "surd" => '\u221A', "coprod" => [ '\u2210', [ "texClass" => TexClass::OP, "movesupsub" => true ] ], "bigvee" => [ '\u22C1', [ "texClass" => TexClass::OP, "movesupsub" => true ] ], "bigwedge" => [ '\u22C0', [ "texClass" => TexClass::OP, "movesupsub" => true ] ], "biguplus" => [ '\u2A04', [ "texClass" => TexClass::OP, "movesupsub" => true ] ], "bigcap" => [ '\u22C2', [ "texClass" => TexClass::OP, "movesupsub" => true ] ], "bigcup" => [ '\u22C3', [ "texClass" => TexClass::OP, "movesupsub" => true ] ], "int" => [ '\u222B', [ "texClass" => TexClass::OP ] ], "intbar" => [ '\u2A0D', [ "texClass" => TexClass::OP ] ], "intBar" => [ '\u2A0E', [ "texClass" => TexClass::OP ] ], "intop" => [ '\u222B', [ "texClass" => TexClass::OP, "movesupsub" => true, "movablelimits" => true ] ], "iint" => [ '\u222C', [ "texClass" => TexClass::OP ] ], "iiint" => [ '\u222D', [ "texClass" => TexClass::OP ] ], "prod" => [ '\u220F', [ "texClass" => TexClass::OP, "movesupsub" => true ] ], "sum" => [ '\u2211', [ "texClass" => TexClass::OP, "movesupsub" => true ] ], "bigotimes" => [ '\u2A02', [ "texClass" => TexClass::OP, "movesupsub" => true ] ], "bigoplus" => [ '\u2A01', [ "texClass" => TexClass::OP, "movesupsub" => true ] ], "bigodot" => [ '\u2A00', [ "texClass" => TexClass::OP, "movesupsub" => true ] ], "bigsqcup" => [ '\u2A06', [ "texClass" => TexClass::OP, "movesupsub" => true ] ], "smallint" => [ '\u222B', [ "largeop" => false ] ], "triangleleft" => '\u25C3', "triangleright" => '\u25B9', "bigtriangleup" => '\u25B3', "bigtriangledown" => '\u25BD', "wedge" => '\u2227', "land" => '\u2227', "vee" => '\u2228', "lor" => '\u2228', "cap" => '\u2229', "cup" => '\u222A', "ddagger" => '\u2021', "dagger" => '\u2020', "sqcap" => '\u2293', "sqcup" => '\u2294', "uplus" => '\u228E', "amalg" => '\u2A3F', "diamond" => '\u22C4', "bullet" => '\u2219', "wr" => '\u2240', "div" => '\u00F7', "divsymbol" => '\u00F7', "odot" => [ '\u2299', [ "largeop" => false ] ], "oslash" => [ '\u2298', [ "largeop" => false ] ], "otimes" => [ '\u2297', [ "largeop" => false ] ], "ominus" => [ '\u2296', [ "largeop" => false ] ], "oplus" => [ '\u2295', [ "largeop" => false ] ], "mp" => '\u2213', "pm" => '\u00B1', "circ" => '\u2218', "bigcirc" => '\u25EF', "setminus" => '\u2216', "cdot" => '\u22C5', "ast" => '\u2217', "times" => '\u00D7', "star" => '\u22C6', "propto" => '\u221D', "sqsubseteq" => '\u2291', "sqsupseteq" => '\u2292', "parallel" => '\u2225', "mid" => '\u2223', "dashv" => '\u22A3', "vdash" => '\u22A2', "leq" => '\u2264', "le" => '\u2264', "geq" => '\u2265', "ge" => '\u2265', "lt" => '\u003C', "gt" => '\u003E', "succ" => '\u227B', "prec" => '\u227A', "approx" => '\u2248', "succeq" => '\u2AB0', "preceq" => '\u2AAF', "supset" => '\u2283', "subset" => '\u2282', "supseteq" => '\u2287', "subseteq" => '\u2286', "in" => '\u2208', "ni" => '\u220B', "notin" => '\u2209', "owns" => '\u220B', "gg" => '\u226B', "ll" => '\u226A', "sim" => '\u223C', "simeq" => '\u2243', "perp" => '\u22A5', "equiv" => '\u2261', "asymp" => '\u224D', "smile" => '\u2323', "frown" => '\u2322', "ne" => '\u2260', "neq" => '\u2260', "cong" => '\u2245', "doteq" => '\u2250', "bowtie" => '\u22C8', "models" => '\u22A8', "notChar" => '\u29F8', "Leftrightarrow" => '\u21D4', "Leftarrow" => '\u21D0', "Rightarrow" => '\u21D2', "leftrightarrow" => '\u2194', "leftarrow" => '\u2190', "gets" => '\u2190', "rightarrow" => '\u2192', "to" => [ '\u2192', [ "accent" => "false" ] ], "mapsto" => [ '\u21A6', [ "stretchy" => "false" ] ], // added stretchy for tests "leftharpoonup" => '\u21BC', "leftharpoondown" => '\u21BD', "rightharpoonup" => '\u21C0', "rightharpoondown" => '\u21C1', "nearrow" => '\u2197', "searrow" => '\u2198', "nwarrow" => '\u2196', "swarrow" => '\u2199', "rightleftharpoons" => '\u21CC', "hookrightarrow" => '\u21AA', "hookleftarrow" => '\u21A9', "longleftarrow" => '\u27F5', "Longleftarrow" => '\u27F8', "longrightarrow" => '\u27F6', "Longrightarrow" => '\u27F9', "Longleftrightarrow" => '\u27FA', "longleftrightarrow" => '\u27F7', "longmapsto" => [ '\u27FC', [ "stretchy" => "false" ] ], // added stretchy for test "ldots" => '\u2026', "cdots" => '\u22EF', // "cdots" => '\u2026', // fallback "vdots" => '\u22EE', "ddots" => '\u22F1', "dotsc" => '\u2026', "dotsb" => '\u22EF', // "dotsb" => '\u2026', // fallback "dotsm" => '\u22EF', // "dotsm" => '\u2026', // fallback "dotsi" => '\u22EF', // "dotsi" => '\u2026', // fallback "dotso" => '\u2026', "ldotp" => [ '\u002E', [ "texClass" => TexClass::PUNCT ] ], "cdotp" => [ '\u22C5', [ "texClass" => TexClass::PUNCT ] ], "colon" => [ '\u003A', [ "texClass" => TexClass::PUNCT ] ] ]; private const MATCHAR7 = [ "Gamma" => '\u0393', "Delta" => '\u0394', "Theta" => '\u0398', "Lambda" => '\u039B', "Xi" => '\u039E', "Pi" => '\u03A0', "Sigma" => '\u03A3', "Upsilon" => '\u03A5', "Phi" => '\u03A6', "Psi" => '\u03A8', "Omega" => '\u03A9', '_' => '\u005F', '#' => '\u0023', '$' => '\u0024', '%' => '\u0025', '&' => '\u0026', 'And' => '\u0026' ]; private const DELIMITER = [ '(' => [ '(', [ "stretchy" => "false" ] ], // added this additionally for running all tc ')' => [ ')', [ "stretchy" => "false" ] ], // added this additionally for running all tc '[' => [ '[', [ "stretchy" => "false" ] ], // added this additionally for running all tc ']' => [ ']', [ "stretchy" => "false" ] ], // added this additionally for running all tc '<' => '\u27E8', '>' => '\u27E9', '\\lt' => '\u27E8', '\\gt' => '\u27E9', '/' => '/', '|' => [ '|', [ "texClass" => TexClass::ORD ] ], '.' => '', '\\\\' => '\\', '\\lmoustache' => '\u23B0', '\\rmoustache' => '\u23B1', '\\lgroup' => '\u27EE', '\\rgroup' => '\u27EF', '\\arrowvert' => '\u23D0', '\\Arrowvert' => '\u2016', '\\bracevert' => '\u23AA', '\\Vert' => [ '\u2016', [ "texClass" => TexClass::ORD ] ], '\\|' => [ '\u2016', [ "texClass" => TexClass::ORD ] ], '\\vert' => [ '|', [ "texClass" => TexClass::ORD ] ], '\\uparrow' => '\u2191', '\\downarrow' => '\u2193', '\\updownarrow' => '\u2195', '\\Uparrow' => '\u21D1', '\\Downarrow' => '\u21D3', '\\Updownarrow' => '\u21D5', '\\backslash' => '\\', "\\rangle" => '\u27E9', '\\langle' => '\u27E8', '\\rbrace' => '}', '\\lbrace' => '{', // added this attrs additionally for running all tc: '\\}' => [ '}', [ "fence" => "false", "stretchy" => "false" ] ], // added this attrs additionally for running all tc: '\\{' => [ '{', [ "fence" => "false", "stretchy" => "false" ] ], '\\rceil' => '\u2309', '\\lceil' => '\u2308', '\\rfloor' => '\u230B', '\\lfloor' => '\u230A', '\\lbrack' => '[', '\\rbrack' => ']' ]; 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 ], "tiny" => [ 'SetSize', 0.5 ], "Tiny" => [ 'SetSize', 0.6 ], "scriptsize" => [ 'SetSize', 0.7 ], "small" => [ 'SetSize', 0.85 ], "normalsize" => [ 'SetSize', 1.0 ], "large" => [ 'SetSize', 1.2 ], "Large" => [ 'SetSize', 1.44 ], "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', '203E' ], "underline" => [ 'underOver', '_', null, true ], "overarc" => [ 'underOver', '23DC', 1 ], "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', "root" => 'Root', "uproot" => [ 'MoveRoot', 'upRoot' ], "leftroot" => [ 'MoveRoot', 'leftRoot' ], "left" => 'LeftRight', "right" => 'LeftRight', "middle" => 'LeftRight', "llap" => 'lap', "rlap" => 'lap', "raise" => 'raiseLower', "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 ], "hskip" => 'hskip', "hspace" => 'hskip', "kern" => 'hskip', "mskip" => 'hskip', "mspace" => 'hskip', "mkern" => 'hskip', "rule" => 'rule', "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 ], "mathord" => [ 'TeXAtom', TexClass::ORD ], "mathop" => [ 'TeXAtom', TexClass::OP ], "mathopen" => [ 'TeXAtom', TexClass::OPEN ], "mathclose" => [ 'TeXAtom', TexClass::CLOSE ], "mathbin" => [ 'TeXAtom', TexClass::BIN ], "mathrel" => [ 'TeXAtom', TexClass::REL ], "mathpunct" => [ 'TeXAtom', TexClass::PUNCT ], "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 "fbox" => 'FBox', "boxed" => [ 'macro', '\\fbox{$\\displaystyle{#1}$}', 1 ], "framebox" => 'FrameBox', "strut" => 'Strut', "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, true ], "eqalign" => [ 'matrix', null, null, 'right left', "(0, lengths_js_1.em)(MathSpace::thickmathspace)", '.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', "(0, lengths_js_1.em)(MathSpace::thickmathspace)", '.5em', 'D', null, 'right' ], "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="0.2777777777777778em"' . // "0.2777777777777778em" is equivlent to thickmathspace T320910 ' rspace="0.2777777777777778em"]{mod}' ], "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}' . '{\\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' . '{\\scriptstyle{A}}\\kern-.17em\\TeX' ], ' ' => [ 'macro', '\\text{ }' ], "not" => 'not', "dots" => 'dots', "space" => 'Tilde', '\u00A0' => 'Tilde', "begin" => 'BeginEnd', "end" => 'BeginEnd', "label" => 'HandleLabel', "ref" => 'HandleRef', "nonumber" => 'HandleNoTag', "mathchoice" => 'mathChoice', "mmlToken" => 'MmlToken', "intent" => 'intent' ]; private const ENVIRONMENT = [ "array" => [ 'AlignedArray' ], "equation" => [ 'Equation', null, true ], "eqnarray" => [ 'EqnArray', null, true, true, 'rcl', null, '.5em' ] ]; private const COLORS = [ 'Apricot' => '#FBB982', 'Aquamarine' => '#00B5BE', 'Bittersweet' => '#C04F17', 'Black' => '#221E1F', 'Blue' => '#2D2F92', 'BlueGreen' => '#00B3B8', 'BlueViolet' => '#473992', 'BrickRed' => '#B6321C', 'Brown' => '#792500', 'BurntOrange' => '#F7921D', 'CadetBlue' => '#74729A', 'CarnationPink' => '#F282B4', 'Cerulean' => '#00A2E3', 'CornflowerBlue' => '#41B0E4', 'Cyan' => '#00AEEF', 'Dandelion' => '#FDBC42', 'DarkOrchid' => '#A4538A', 'Emerald' => '#00A99D', 'ForestGreen' => '#009B55', 'Fuchsia' => '#8C368C', 'Goldenrod' => '#FFDF42', 'Gray' => '#949698', 'Green' => '#00A64F', 'GreenYellow' => '#DFE674', 'JungleGreen' => '#00A99A', 'Lavender' => '#F49EC4', 'LimeGreen' => '#8DC73E', 'Magenta' => '#EC008C', 'Mahogany' => '#A9341F', 'Maroon' => '#AF3235', 'Melon' => '#F89E7B', 'MidnightBlue' => '#006795', 'Mulberry' => '#A93C93', 'NavyBlue' => '#006EB8', 'OliveGreen' => '#3C8031', 'Orange' => '#F58137', 'OrangeRed' => '#ED135A', 'Orchid' => '#AF72B0', 'Peach' => '#F7965A', 'Periwinkle' => '#7977B8', 'PineGreen' => '#008B72', 'Plum' => '#92268F', 'ProcessBlue' => '#00B0F0', 'Purple' => '#99479B', 'RawSienna' => '#974006', 'Red' => '#ED1B23', 'RedOrange' => '#F26035', 'RedViolet' => '#A1246B', 'Rhodamine' => '#EF559F', 'RoyalBlue' => '#0071BC', 'RoyalPurple' => '#613F99', 'RubineRed' => '#ED017D', 'Salmon' => '#F69289', 'SeaGreen' => '#3FBC9D', 'Sepia' => '#671800', 'SkyBlue' => '#46C5DD', 'SpringGreen' => '#C6DC67', 'Tan' => '#DA9D76', 'TealBlue' => '#00AEB3', 'Thistle' => '#D883B7', 'Turquoise' => '#00B4CE', 'Violet' => '#58429B', 'VioletRed' => '#EF58A0', 'White' => '#FFFFFF', 'WildStrawberry' => '#EE2967', 'Yellow' => '#FFF200', 'YellowGreen' => '#98CC70', 'YellowOrange' => '#FAA21A', ]; // They are currently from mhchemConfiguration.js private const MHCHEM = [ "ce" => [ 'machine', 'ce' ], "pu" => [ 'machine', 'pu' ], "longrightleftharpoons" => [ 'macro', '\\stackrel{\\textstyle{-}\\!\\!{\\rightharpoonup}}{\\smash{{\\leftharpoondown}\\!\\!{-}}}' ], "longRightleftharpoons" => [ 'macro', '\\stackrel{\\textstyle{-}\\!\\!{\\rightharpoonup}}{\\smash{\\leftharpoondown}}' ], "longLeftrightharpoons" => [ 'macro', '\\stackrel{\\textstyle\\vphantom{{-}}{\\rightharpoonup}}{\\smash{{\\leftharpoondown}\\!\\!{-}}}' ], "longleftrightarrows" => [ 'macro', '\\stackrel{\\longrightarrow}{\\smash{\\longleftarrow}\\Rule{0px}{.25em}{0px}}' ], "tripledash" => [ 'macro', '\\vphantom{-}\\raise{2mu}\\\kern{2mu}\\tiny\\text{-}\\kern{1mu}\\text{-}\\kern{1mu}\\text{-}\\kern{2mu}}' ], "xleftrightarrow" => [ 'xArrow', 0x2194, 6, 6 ], "xrightleftharpoons" => [ 'xArrow', 0x21CC, 5, 7 ], "xRightleftharpoons" => [ 'xArrow', 0x21CC, 5, 7 ], "xLeftrightharpoons" => [ 'xArrow', 0x21CC, 5, 7 ], "bond" => [ "chemCustom", "\\bond" ], ]; // These are some mappings which are created customly for this private const CUSTOM = [ "boldsymbol" => [ 'boldsymbol', '' ], // see boldsymbolConfiguration.js "oint" => [ 'oint', '\u222E', [ "texClass" => TexClass::OP ] ], "oiint" => [ 'oint', '\u222F', [ "texClass" => TexClass::OP ] ], "oiiint" => [ 'oint', '\u2230', [ "texClass" => TexClass::OP ] ], "ointctrclockwise" => [ 'oint', '\u2233', [ "texClass" => TexClass::OP ] ], "varointclockwise" => [ 'oint', '\u2232', [ "texClass" => TexClass::OP ] ], "P" => [ 'oint', '\u00B6', [ "texClass" => TexClass::OP ] ], 'textvisiblespace' => [ 'Insert', '\u2423' ], // From TextCompMappings.js (only makro it seems) "Alpha" => [ 'customLetters', "A" ], "Beta" => [ 'customLetters', "B" ], "Chi" => [ 'customLetters', "X" ], "Epsilon" => [ 'customLetters', "E" ], "Eta" => [ 'customLetters', "H" ], "Iota" => [ 'customLetters', "I" ], "Kappa" => [ 'customLetters', "K" ], "Mu" => [ 'customLetters', "M" ], "Nu" => [ 'customLetters', "N" ], "Omicron" => [ 'customLetters', "O" ], "Rho" => [ 'customLetters', "P" ], "Tau" => [ 'customLetters', "T" ], "Zeta" => [ 'customLetters', "Z" ], "ca" => [ "customLetters", "∼", true ] ]; private const ALL = [ "special" => self::SPECIAL, "macros" => self::MACROS, "delimiter" => self::DELIMITER, "mathchar7" => self::MATCHAR7, "mathchar0mi" => self::MATHCHAR0MI, "mathchar0mo" => self::MATHCHAR0MO, "environment" => self::ENVIRONMENT, "colors" => self::COLORS, "mhchem" => self::MHCHEM, "custom" => self::CUSTOM ]; private function __construct() { // Just an empty private constructor, for singleton pattern } public static function getAll(): array { $cancelElements = TexUtil::getInstance()->getBaseElements()['cancel_required']; $cancel = []; foreach ( $cancelElements as $name => $value ) { // PhanTypeVoidAssignment Cannot assign void return value // @phan-suppress-next-line PhanCoalescingNeverUndefined $cancel[$name] = TexUtil::getInstance()->callback( $name ) ?? null; } return self::ALL + [ 'cancel' => $cancel ]; } public static function getInstance(): BaseMappings { self::$instance ??= new BaseMappings(); return self::$instance; } public static function getOperatorByKey( $key ) { if ( $key === '-' ) { return MMLutil::uc2xNotation( '\u2212' ); // added this additionally for running all tests } return MMLutil::getMappingByKey( $key, self::MATHCHAR0MO, true, true ); } public static function getIdentifierByKey( $key ) { return MMLutil::getMappingByKey( $key, self::MATHCHAR0MI, true, true ); } public static function getMacroByKey( $key ) { return MMLutil::getMappingByKeySimple( $key, self::MACROS, true ); } public static function getSpecialByKey( $key ) { $ret = MMLutil::getMappingByKeySimple( $key, self::SPECIAL ); // Only activated elements get found in this mapping currently. if ( is_array( $ret ) && count( $ret ) >= 2 && $ret[1] ) { return $ret; } return null; } public static function getCancelByKey( $key ) { if ( !TexUtil::getInstance()->cancel_required( $key ) ) { return null; } return TexUtil::getInstance()->callback( $key ); } public static function getCharacterByKey( $key ) { return MMLutil::getMappingByKeySimple( $key, self::MATCHAR7, true ); } public static function getCustomByKey( $key ) { return MMLutil::getMappingByKeySimple( $key, self::CUSTOM, true ); } public static function getMhChemByKey( $key ) { return MMLutil::getMappingByKeySimple( $key, self::MHCHEM, true ); } public static function getColorByKey( $key ) { // Cast to uppercase first letter since mapping is structured that way. $key = ucfirst( $key ); return MMLutil::getMappingByKey( $key, self::COLORS ); } public static function getDelimiterByKey( $key ) { return MMLutil::getMappingByKey( $key, self::DELIMITER, true ); } } PK ! '�0z z OperatorDictionary.phpnu �Iw�� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings; use MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Util\MMLutil; /** * Based on OperatorDictionary.js in MML3 * Only importing infix atm * Singleton * * Some of the entries are commented since they parse to mi elements, values are not used atm. */ class OperatorDictionary { private const INFIX = [ // Implemented elements have [something, true] for custom parsing '!' => [ "1, 0, TEXCLASS.CLOSE, null" ], // exclamation mark '!=' => [ " exports.MO.BIN4" ], '#' => [ " exports.MO.ORD" ], '$' => [ " exports.MO.ORD" ], '%' => [ " [3, 3, MmlNode_js_1.TEXCLASS.ORD], null]" ], '&&' => [ " exports.MO.BIN4" ], '' => [ " exports.MO.ORD" ], '*' => [ " exports.MO.BIN3" ], '**' => [ " OPDEF(1\"], 1)" ], '*=' => [ " exports.MO.BIN4" ], '+' => [ " exports.MO.BIN4" ], '+=' => [ " exports.MO.BIN4" ], ',' => [ " [0, 3], MmlNode_js_1.TEXCLASS.PUNCT\"]," . "{ linebreakstyle=> [\" 'after'\"], separator=> [\" true }]", true ], '-' => [ " exports.MO.BIN4" ], '-=' => [ " exports.MO.BIN4" ], '->' => [ " exports.MO.BIN5" ], '.' => [ " [0, 3], MmlNode_js_1.TEXCLASS.PUNCT\"], { separator=> [ true }]" ], ':' => [ " [1, 2], MmlNode_js_1.TEXCLASS.REL\"], null]" ], '/' => [ " exports.MO.ORD11", true ], '//' => [ " OPDEF(1\"], 1)" ], '/=' => [ " exports.MO.BIN4" ], '=>' => [ " [1, 2], MmlNode_js_1.TEXCLASS.REL\"], null]" ], '=>=' => [ " exports.MO.BIN4" ], ';' => [ " [0, 3], MmlNode_js_1.TEXCLASS.PUNCT]," . "{ linebreakstyle=> ['after'], separator=> [ true }]", true ], '<' => [ " exports.MO.REL", true ], '<=' => [ " exports.MO.BIN5" ], '<>' => [ " OPDEF(1, 1)" ], '=' => [ " exports.MO.REL" ], '==' => [ " exports.MO.BIN4" ], '>' => [ " exports.MO.REL", true ], '>=' => [ " exports.MO.BIN5" ], '?' => [ " [1, 1], MmlNode_js_1.TEXCLASS.CLOSE], null]" ], '@' => [ " exports.MO.ORD11" ], '\\' => [ " exports.MO.ORD", true ], '^' => [ " exports.MO.ORD11" ], '_' => [ " exports.MO.ORD11" ], '|' => [ " [2, 2], MmlNode_js_1.TEXCLASS.ORD]," . "{ fence=> [\"true\"], stretchy=> [\"true\"], symmetric=> [\" true }]" ], '||' => [ " [2, 2], MmlNode_js_1.TEXCLASS.ORD]," . "{ fence=> [\"true\"], stretchy=> [\"true\"], symmetric=> [\" true }]" ], '|||' => [ " [2, 2], MmlNode_js_1.TEXCLASS.ORD]," . "{ fence=> [\"true\"], stretchy=> [\"true\"], symmetric=> [\" true }]" ] ]; private function __construct() { // Just an empty private constructor, for singleton pattern } public static function getOperatorByKey( string $key ) { $key = MMLutil::uc2xNotation( $key ); return MMLutil::getMappingByKey( $key, self::INFIX ); } } PK ! �to� � Lengths/Units.phpnu �Iw�� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Lengths; class Units { public const PX = 1; public const IN = 96; public const CM = 96 / 2.54; public const MM = 96 / 25.; } PK ! ��� � Lengths/RelUnits.phpnu �Iw�� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Lengths; class RelUnits { public const EM = 1; public const EX = 0.431; public const PT = 1 / 10; public const PC = 12 / 10; public const MU = 1 / 18; } PK ! C�[x� � Lengths/MathSpace.phpnu �Iw�� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings\Lengths; class MathSpace { public const VERYVERYTHINMATHSPACE = 1 / 18; public const VERYTHINMATHSPACE = 2 / 18; public const THINMATHSPACE = 3 / 18; public const MEDIUMMATHSPACE = 4 / 18; public const THICKMATHSPACE = 5 / 18; public const VERYTHICKMATHSPACE = 6 / 18; public const VERYVERYTHICKMATHSPACE = 7 / 18; public const NEGATIVEVERYVERYTHINMATHSPACE = -1 / 18; public const NEGATIVEVERYTHINMATHSPACE = -2 / 18; public const NEGATIVETHINMATHSPACE = -3 / 18; public const NEGATIVEMEDIUMMATHSPACE = -4 / 18; public const NEGATIVETHICKMATHSPACE = -5 / 18; public const NEGATIVEVERYTHICKMATHSPACE = -6 / 18; public const NEGATIVEVERYVERYTHICKMATHSPACE = -7 / 18; public const THIN = 0.04; public const MEDIUM = 0.06; public const THICK = 0.1; public const NORMAL = 1; public const BIG = 2; public const SMALL = 1 / M_PI; public const INFINITY = INF; // PREV "EXPORTS.BIGDIMEN"; } PK ! ��$ $ TexConstants/Variants.phpnu �Iw�� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants; class Variants { public const NORMAL = 'normal'; public const BOLD = 'bold'; public const ITALIC = 'italic'; public const BOLDITALIC = 'bold-italic'; public const DOUBLESTRUCK = 'double-struck'; public const FRAKTUR = 'fraktur'; public const BOLDFRAKTUR = 'bold-fraktur'; public const SCRIPT = 'script'; public const BOLDSCRIPT = 'bold-script'; public const SANSSERIF = 'sans-serif'; public const BOLDSANSSERIF = 'bold-sans-serif'; public const SANSSERIFITALIC = 'sans-serif-italic'; public const SANSSERIFBOLDITALIC = 'sans-serif-bold-italic'; public const MONOSPACE = 'monospace'; public const INITIAL = 'inital'; public const TAILED = 'tailed'; public const LOOPED = 'looped'; public const STRETCHED = 'stretched'; public const CALLIGRAPHIC = '-tex-calligraphic'; public const BOLDCALLIGRAPHIC = '-tex-bold-calligraphic'; public const OLDSTYLE = '-tex-oldstyle'; public const BOLDOLDSTYLE = '-tex-bold-oldstyle'; public const MATHITALIC = '-tex-mathit'; } PK ! G[��9 9 TexConstants/Align.phpnu �Iw�� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants; class Align { public const TOP = 'top'; public const BOTTOM = 'bottom'; public const CENTER = 'center'; public const BASELINE = 'baseline'; public const AXIS = 'axis'; public const LEFT = 'left'; public const RIGHT = 'right'; } PK ! ����1 1 TexConstants/Notation.phpnu �Iw�� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants; class Notation { public const LONGDIV = 'longdiv'; public const ACTUARIAL = 'actuarial'; public const PHASORANGLE = 'phasorangle'; public const RADICAL = 'radical'; public const BOX = 'box'; public const ROUNDEDBOX = 'roundedbox'; public const CIRCLE = 'circle'; public const LEFT = 'left'; public const RIGHT = 'right'; public const TOP = 'top'; public const BOTTOM = 'bottom'; public const UPDIAGONALSTRIKE = 'updiagonalstrike'; public const DOWNDIAGONALSTRIKE = 'downdiagonalstrike'; public const VERTICALSTRIKE = 'verticalstrike'; public const HORIZONTALSTRIKE = 'horizontalstrike'; public const NORTHEASTARROW = 'northeastarrow'; public const MADRUWB = 'madruwb'; public const UPDIAGONALARROW = 'updiagonalarrow'; } PK ! ��D|O O TexConstants/Sizes.phpnu �Iw�� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants; class Sizes { public const VERYVERYTHINMATHSPACE = 1 / 18 . "em"; public const VERYTHINMATHSPACE = 2 / 18 . "em"; public const THINMATHSPACE = 3 / 18 . "em"; public const MEDIUMMATHSPACE = 4 / 18 . "em"; public const THICKMATHSPACE = 5 / 18 . "em"; public const VERYTHICKMATHSPACE = 6 / 18 . "em"; public const VERYVERYTHICKMATHSPACE = 7 / 18 . "em"; public const NEGATIVEVERYVERYTHINMATHSPACE = -1 / 18 . "em"; public const NEGATIVEVERYTHINMATHSPACE = -2 / 18 . "em"; public const NEGATIVETHINMATHSPACE = -3 / 18 . "em"; public const NEGATIVEMEDIUMMATHSPACE = -4 / 18 . "em"; public const NEGATIVETHICKMATHSPACE = -5 / 18 . "em"; public const NEGATIVEVERYTHICKMATHSPACE = -6 / 18 . "em"; public const NEGATIVEVERYVERYTHICKMATHSPACE = -7 / 18 . "em"; } PK ! Gc:� TexConstants/Tag.phpnu �Iw�� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants; /** * This class contains the string how tags are written * Changing this will remove mathjax specifics. */ class Tag { public const ALIGN = "data-mjx-script-align"; public const ALTERNATE = "data-mjx-alternate"; public const SCRIPTTAG = "data-mjx-pseudoscript"; // Example exchange value: "texClass" public const CLASSTAG = "data-mjx-texclass"; // This is some tag in addition to mathvariant public const MJXVARIANT = "data-mjx-variant"; } PK ! �cu�< < TexConstants/TexClass.phpnu �Iw�� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants; class TexClass { public const ORD = "ORD"; public const OP = "OP"; public const BIN = "BIN"; public const REL = "REL"; public const OPEN = "OPEN"; public const CLOSE = "CLOSE"; public const PUNCT = "PUNCT"; public const INNER = "INNER"; public const VCENTER = "VCENTER"; public const NONE = "-1"; public const TOP = "mwe-math-matrix-top"; public const BOTTOM = "mwe-math-matrix-bottom"; public const LEFT = "mwe-math-matrix-left"; public const RIGHT = "mwe-math-matrix-right"; } PK ! Y�C� � TexConstants/Misc.phpnu �Iw�� <?php namespace MediaWiki\Extension\Math\WikiTexVC\MMLmappings\TexConstants; class Misc { public const P_HEIGHT = 1.2 / 0.85; } PK ! 4� �v"